mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-25 05:44:13 -05:00
Merge pull request #5432 from paulkaplan/studio-curator-invite
Update the curator invitation component to spec
This commit is contained in:
commit
35f9f92cea
6 changed files with 85 additions and 16 deletions
|
@ -47,7 +47,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.",
|
||||
|
|
|
@ -167,7 +167,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,14 +8,13 @@ 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';
|
||||
import AlertProvider from '../../components/alert/alert-provider.jsx';
|
||||
import Alert from '../../components/alert/alert.jsx';
|
||||
|
||||
const StudioCurators = ({
|
||||
canInviteCurators, showCuratorInvite, items, error, loading, moreToLoad, onLoadMore
|
||||
canInviteCurators, items, error, loading, moreToLoad, onLoadMore
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
if (items.length === 0) onLoadMore();
|
||||
|
@ -29,7 +28,6 @@ const StudioCurators = ({
|
|||
<h2><FormattedMessage id="studio.curatorsHeader" /></h2>
|
||||
</div>
|
||||
{canInviteCurators && <CuratorInviter />}
|
||||
{showCuratorInvite && <CuratorInvite />}
|
||||
{error && <Debug
|
||||
label="Error"
|
||||
data={error}
|
||||
|
@ -93,7 +91,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,
|
||||
|
@ -103,8 +100,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 StudioMeta from './studio-meta.jsx';
|
||||
import StudioAdminPanel from './studio-admin-panel.jsx';
|
||||
|
||||
|
@ -61,6 +62,7 @@ const StudioShell = ({showCuratorMuteError, muteExpiresAtMs, studioLoadFailed})
|
|||
<div>
|
||||
<Switch>
|
||||
<Route path={`${match.path}/curators`}>
|
||||
<StudioCuratorInvite />
|
||||
{showCuratorMuteError &&
|
||||
<CommentingStatus>
|
||||
<p>
|
||||
|
|
|
@ -60,6 +60,9 @@ $radius: 8px;
|
|||
margin-top: .5rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.studio-info-footer {
|
||||
|
@ -438,8 +441,38 @@ $radius: 8px;
|
|||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
.studio-thumb-edit-button {
|
||||
|
|
Loading…
Reference in a new issue