mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-30 19:08:03 -05:00
Update the curator invitation component
This commit is contained in:
parent
8984f2cedc
commit
168cd5a01b
6 changed files with 84 additions and 14 deletions
|
@ -39,7 +39,10 @@
|
|||
"studio.inviteCuratorsHeader": "Invite Curators",
|
||||
"studio.inviteCurator": "Invite",
|
||||
"studio.inviteCuratorPlaceholder": "Scratch Username",
|
||||
"studio.curatorInvitationAccepted": "Congratulations! You are now a curator of this studio.",
|
||||
"studio.curatorInvitation": "You’ve been invited to become a curator of this studio.",
|
||||
"studio.curatorAcceptInvite": "Accept Invite",
|
||||
"studio.curatorInvitationError": "Something went wrong, try again later.",
|
||||
"studio.curatorsEmptyCanAdd1": "You don’t have curators right now.",
|
||||
"studio.curatorsEmptyCanAdd2": "Add some curators to collaborate with!",
|
||||
"studio.curatorsEmpty1": "This studio has no curators right now.",
|
||||
|
|
|
@ -168,7 +168,9 @@ const acceptInvitation = () => ((dispatch, getState) => new Promise((resolve, re
|
|||
// Note: this assumes that the user items from the curator endpoint
|
||||
// are the same structure as the single user data returned from /users/:username
|
||||
dispatch(curators.actions.create(userBody, true));
|
||||
dispatch(setRoles({invited: false, curator: true}));
|
||||
setTimeout(() => {
|
||||
dispatch(setRoles({invited: false, curator: true}));
|
||||
}, 5 * 1000);
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,15 +6,42 @@ import classNames from 'classnames';
|
|||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import {acceptInvitation} from './lib/studio-member-actions';
|
||||
import {selectShowCuratorInvite} from '../../redux/studio-permissions';
|
||||
|
||||
const StudioCuratorInvite = ({onSubmit}) => {
|
||||
const StudioCuratorInvite = ({showCuratorInvite, onSubmit}) => {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [accepted, setAccepted] = useState(false);
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
if (!showCuratorInvite) return null;
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="studio-invitation studio-info-box studio-info-box-error">
|
||||
<div className="studio-invitation-msg">
|
||||
<FormattedMessage id="studio.curatorInvitationError" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (accepted) {
|
||||
return (
|
||||
<div className="studio-invitation studio-info-box studio-info-box-success">
|
||||
<div className="studio-invitation-msg">
|
||||
<FormattedMessage id="studio.curatorInvitationAccepted" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="studio-invitation studio-info-box">
|
||||
<div className="studio-invitation-msg">
|
||||
<FormattedMessage id="studio.curatorInvitation" />
|
||||
</div>
|
||||
<button
|
||||
className={classNames('button', {
|
||||
className={classNames('studio-invitation-button button', {
|
||||
'mod-mutating': submitting
|
||||
})}
|
||||
disabled={submitting}
|
||||
|
@ -22,22 +49,28 @@ const StudioCuratorInvite = ({onSubmit}) => {
|
|||
setSubmitting(true);
|
||||
setError(null);
|
||||
onSubmit()
|
||||
.then(() => {
|
||||
setSubmitting(false);
|
||||
setAccepted(true);
|
||||
})
|
||||
.catch(e => {
|
||||
setError(e);
|
||||
setSubmitting(false);
|
||||
});
|
||||
}}
|
||||
><FormattedMessage id="studio.curatorAcceptInvite" /></button>
|
||||
{error && <div>{error}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
StudioCuratorInvite.propTypes = {
|
||||
showCuratorInvite: PropTypes.func,
|
||||
onSubmit: PropTypes.func
|
||||
};
|
||||
|
||||
const mapStateToProps = () => ({});
|
||||
const mapStateToProps = state => ({
|
||||
showCuratorInvite: selectShowCuratorInvite(state)
|
||||
});
|
||||
|
||||
const mapDispatchToProps = ({
|
||||
onSubmit: acceptInvitation
|
||||
|
|
|
@ -8,12 +8,11 @@ import {curators} from './lib/redux-modules';
|
|||
import Debug from './debug.jsx';
|
||||
import {CuratorTile} from './studio-member-tile.jsx';
|
||||
import CuratorInviter from './studio-curator-inviter.jsx';
|
||||
import CuratorInvite from './studio-curator-invite.jsx';
|
||||
import {loadCurators} from './lib/studio-member-actions';
|
||||
import {selectCanInviteCurators, selectShowCuratorInvite} from '../../redux/studio-permissions';
|
||||
import {selectCanInviteCurators} from '../../redux/studio-permissions';
|
||||
|
||||
const StudioCurators = ({
|
||||
canInviteCurators, showCuratorInvite, items, error, loading, moreToLoad, onLoadMore
|
||||
canInviteCurators, items, error, loading, moreToLoad, onLoadMore
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
if (items.length === 0) onLoadMore();
|
||||
|
@ -24,7 +23,6 @@ const StudioCurators = ({
|
|||
<h2><FormattedMessage id="studio.curatorsHeader" /></h2>
|
||||
</div>
|
||||
{canInviteCurators && <CuratorInviter />}
|
||||
{showCuratorInvite && <CuratorInvite />}
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
|
@ -87,7 +85,6 @@ StudioCurators.propTypes = {
|
|||
})
|
||||
})),
|
||||
canInviteCurators: PropTypes.bool,
|
||||
showCuratorInvite: PropTypes.bool,
|
||||
loading: PropTypes.bool,
|
||||
error: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||
moreToLoad: PropTypes.bool,
|
||||
|
@ -97,8 +94,7 @@ StudioCurators.propTypes = {
|
|||
export default connect(
|
||||
state => ({
|
||||
...curators.selector(state),
|
||||
canInviteCurators: selectCanInviteCurators(state),
|
||||
showCuratorInvite: selectShowCuratorInvite(state)
|
||||
canInviteCurators: selectCanInviteCurators(state)
|
||||
}),
|
||||
{
|
||||
onLoadMore: loadCurators
|
||||
|
|
|
@ -22,6 +22,7 @@ import StudioManagers from './studio-managers.jsx';
|
|||
import StudioCurators from './studio-curators.jsx';
|
||||
import StudioComments from './studio-comments.jsx';
|
||||
import StudioActivity from './studio-activity.jsx';
|
||||
import StudioCuratorInvite from './studio-curator-invite.jsx';
|
||||
|
||||
import {
|
||||
projects,
|
||||
|
@ -53,6 +54,7 @@ const StudioShell = ({studioLoadFailed}) => {
|
|||
<div>
|
||||
<Switch>
|
||||
<Route path={`${match.path}/curators`}>
|
||||
<StudioCuratorInvite />
|
||||
<StudioManagers />
|
||||
<StudioCurators />
|
||||
</Route>
|
||||
|
|
|
@ -349,6 +349,40 @@ $radius: 8px;
|
|||
}
|
||||
}
|
||||
|
||||
.studio-invitation {
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
min-height: 85px; /* So the box doesn't change height after being accepted */
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@media #{$intermediate-and-smaller} {
|
||||
flex-direction: column;
|
||||
.studio-invitation-msg {
|
||||
margin-top: .5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.studio-info-box {
|
||||
border-radius: 4px;
|
||||
background: $ui-blue-10percent;
|
||||
border: 1px solid $ui-blue-25percent;
|
||||
|
||||
&.studio-info-box-success {
|
||||
background: #CEF2E8;
|
||||
border: 1px solid rgba(15, 189, 140, 0.5);
|
||||
}
|
||||
&.studio-info-box-error {
|
||||
background: #FFF0DF;
|
||||
border: 1px solid $ui-dark-orange;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modification classes for different interaction states */
|
||||
.mod-fetching { /* When a field has no content to display yet */
|
||||
position: relative;
|
||||
|
|
Loading…
Reference in a new issue