Unverified Commit d4680725 authored by Sarah Otts's avatar Sarah Otts Committed by GitHub

Merge pull request #5573 from seotts/muted-add-proj-via-proj-page

Muted users can’t add projects to studio via project page
parents 469878a2 a0ab492b
...@@ -145,6 +145,8 @@ module.exports.selectProjectCommentsGloballyEnabled = state => ...@@ -145,6 +145,8 @@ module.exports.selectProjectCommentsGloballyEnabled = state =>
module.exports.selectMuteStatus = state => get(state, ['session', 'session', 'permissions', 'mute_status'], module.exports.selectMuteStatus = state => get(state, ['session', 'session', 'permissions', 'mute_status'],
{muteExpiresAt: 0, offenses: [], showWarning: false}); {muteExpiresAt: 0, offenses: [], showWarning: false});
module.exports.selectIsMuted = state => (module.exports.selectMuteStatus(state).muteExpiresAt || 0) * 1000 > Date.now(); module.exports.selectIsMuted = state => (module.exports.selectMuteStatus(state).muteExpiresAt || 0) * 1000 > Date.now();
module.exports.selectNewStudiosLaunched = state => get(state, ['session', 'session', 'flags', 'new_studios_launched'],
false);
module.exports.selectHasFetchedSession = state => state.session.status === module.exports.Status.FETCHED; module.exports.selectHasFetchedSession = state => state.session.status === module.exports.Status.FETCHED;
......
...@@ -46,5 +46,6 @@ ...@@ -46,5 +46,6 @@
"project.cloudVariables": "Cloud Variables", "project.cloudVariables": "Cloud Variables",
"project.cloudDataLink": "See Data", "project.cloudDataLink": "See Data",
"project.usernameBlockAlert": "This project can detect who is using it, through the \"username\" block. To hide your identity, sign out before using the project.", "project.usernameBlockAlert": "This project can detect who is using it, through the \"username\" block. To hide your identity, sign out before using the project.",
"project.inappropriateUpdate": "Hmm...the bad word detector thinks there is a problem with your text. Please change it and remember to be respectful." "project.inappropriateUpdate": "Hmm...the bad word detector thinks there is a problem with your text. Please change it and remember to be respectful.",
"project.mutedAddToStudio": "You will be able to add to studios again {inDuration}."
} }
...@@ -160,7 +160,6 @@ $stage-width: 480px; ...@@ -160,7 +160,6 @@ $stage-width: 480px;
margin-top: $arrow-border-width; margin-top: $arrow-border-width;
border: 1px solid $active-gray; border: 1px solid $active-gray;
border-radius: 5px; border-radius: 5px;
background-color: $ui-orange;
padding: 1rem; padding: 1rem;
max-width: 18.75rem; max-width: 18.75rem;
min-height: 1rem; min-height: 1rem;
...@@ -185,7 +184,6 @@ $stage-width: 480px; ...@@ -185,7 +184,6 @@ $stage-width: 480px;
border-left: 1px solid $active-gray; border-left: 1px solid $active-gray;
border-radius: 5px; border-radius: 5px;
background-color: $ui-orange;
width: $arrow-border-width; width: $arrow-border-width;
height: $arrow-border-width; height: $arrow-border-width;
......
...@@ -8,90 +8,133 @@ const Button = require('../../components/forms/button.jsx'); ...@@ -8,90 +8,133 @@ const Button = require('../../components/forms/button.jsx');
const AddToStudioModal = require('./add-to-studio.jsx'); const AddToStudioModal = require('./add-to-studio.jsx');
const SocialModal = require('../../components/modal/social/container.jsx'); const SocialModal = require('../../components/modal/social/container.jsx');
const ReportModal = require('../../components/modal/report/modal.jsx'); const ReportModal = require('../../components/modal/report/modal.jsx');
const {connect} = require('react-redux');
const {selectShowProjectMuteError} = require('../../redux/studio-permissions.js');
const {useState} = require('react');
const projectShape = require('./projectshape.jsx').projectShape; const projectShape = require('./projectshape.jsx').projectShape;
import {selectNewStudiosLaunched} from '../../redux/session.js';
import StudioMuteEditMessage from '../studio/studio-mute-edit-message.jsx';
require('./subactions.scss'); require('./subactions.scss');
const Subactions = props => ( const Subactions = ({
<FlexRow className="subactions"> addToStudioOpen,
<div className="share-date"> canAddToStudio,
<div className="copyleft">&copy;</div> canReport,
{' '} isAdmin,
{/* eslint-disable react/jsx-sort-props */} isShared,
{props.shareDate ? ( onAddToStudioClicked,
<FormattedDate onAddToStudioClosed,
value={Date.parse(props.shareDate)} onReportClicked,
day="2-digit" onReportClose,
month="short" onReportSubmit,
year="numeric" onSocialClicked,
/> onSocialClosed,
) : 'Unshared'} onToggleStudio,
{/* eslint-enable react/jsx-sort-props */} projectInfo,
</div> reportOpen,
<FlexRow className="action-buttons"> shareDate,
{(props.canReport) && showAddToStudioMuteError,
<React.Fragment> socialOpen,
<Button userOwnsProject
className="action-button report-button" }) => {
key="report-button" const [showMuteMessage, setShowMuteMessage] = useState(false);
onClick={props.onReportClicked}
> return (
<FormattedMessage id="general.report" /> <FlexRow className="subactions">
</Button> <div className="share-date">
{props.reportOpen && ( <div className="copyleft">&copy;</div>
<ReportModal {' '}
isOpen {/* eslint-disable react/jsx-sort-props */}
key="report-modal" {shareDate ? (
type="project" <FormattedDate
onReport={props.onReportSubmit} value={Date.parse(shareDate)}
onRequestClose={props.onReportClose} day="2-digit"
/> month="short"
)} year="numeric"
</React.Fragment> />
} ) : 'Unshared'}
{props.canAddToStudio && {/* eslint-enable react/jsx-sort-props */}
<React.Fragment> </div>
<Button <FlexRow className="action-buttons">
className="action-button studio-button" {(canReport) &&
key="add-to-studio-button" <React.Fragment>
onClick={props.onAddToStudioClicked} <Button
> className="action-button report-button"
<FormattedMessage id="addToStudio.title" /> key="report-button"
</Button> onClick={onReportClicked}
{props.addToStudioOpen && ( >
<AddToStudioModal <FormattedMessage id="general.report" />
isOpen </Button>
isAdmin={props.isAdmin} {reportOpen && (
key="add-to-studio-modal" <ReportModal
userOwnsProject={props.userOwnsProject} isOpen
onRequestClose={props.onAddToStudioClosed} key="report-modal"
onToggleStudio={props.onToggleStudio} type="project"
/> onReport={onReportSubmit}
)} onRequestClose={onReportClose}
</React.Fragment> />
} )}
{/* only show copy link button, modal if project is shared */} </React.Fragment>
{props.isShared && props.projectInfo && props.projectInfo.id && ( }
<React.Fragment> {canAddToStudio &&
<Button <React.Fragment>
className="action-button copy-link-button" <div
onClick={props.onSocialClicked} style={{position: 'relative'}}
> /* eslint-disable react/jsx-no-bind */
<FormattedMessage id="general.copyLink" /> onMouseEnter={() => showAddToStudioMuteError && setShowMuteMessage(true)}
</Button> onMouseLeave={() => showAddToStudioMuteError && setShowMuteMessage(false)}
{props.socialOpen && ( /* eslint-enable react/jsx-no-bind */
<SocialModal >
isOpen <Button
key="social-modal" className="action-button studio-button"
projectId={props.projectInfo && props.projectInfo.id} disabled={showAddToStudioMuteError}
onRequestClose={props.onSocialClosed} key="add-to-studio-button"
/> onClick={showMuteMessage ? null : onAddToStudioClicked}
)} >
</React.Fragment> <FormattedMessage id="addToStudio.title" />
)} </Button>
{showMuteMessage && <StudioMuteEditMessage
className="studio-button-error"
messageId="project.mutedAddToStudio"
/>}
</div>
{addToStudioOpen && (
<AddToStudioModal
isOpen
isAdmin={isAdmin}
key="add-to-studio-modal"
userOwnsProject={userOwnsProject}
onRequestClose={onAddToStudioClosed}
onToggleStudio={onToggleStudio}
/>
)}
</React.Fragment>
}
{/* only show copy link button, modal if project is shared */}
{isShared && projectInfo && projectInfo.id && (
<React.Fragment>
<Button
className="action-button copy-link-button"
onClick={onSocialClicked}
>
<FormattedMessage id="general.copyLink" />
</Button>
{socialOpen && (
<SocialModal
isOpen
key="social-modal"
projectId={projectInfo && projectInfo.id}
onRequestClose={onSocialClosed}
/>
)}
</React.Fragment>
)}
</FlexRow>
</FlexRow> </FlexRow>
</FlexRow> );
); };
Subactions.propTypes = { Subactions.propTypes = {
addToStudioOpen: PropTypes.bool, addToStudioOpen: PropTypes.bool,
...@@ -110,8 +153,13 @@ Subactions.propTypes = { ...@@ -110,8 +153,13 @@ Subactions.propTypes = {
projectInfo: projectShape, projectInfo: projectShape,
reportOpen: PropTypes.bool, reportOpen: PropTypes.bool,
shareDate: PropTypes.string, shareDate: PropTypes.string,
showAddToStudioMuteError: PropTypes.bool,
socialOpen: PropTypes.bool, socialOpen: PropTypes.bool,
userOwnsProject: PropTypes.bool userOwnsProject: PropTypes.bool
}; };
module.exports = Subactions; module.exports = connect(
state => ({
showAddToStudioMuteError: selectShowProjectMuteError(state) && selectNewStudiosLaunched(state)
})
)(Subactions);
...@@ -109,3 +109,10 @@ ...@@ -109,3 +109,10 @@
} }
} }
} }
.studio-button-error {
top: auto;
transform: none;
width: 100%;
margin-left: 0;
}
...@@ -9,12 +9,15 @@ import {selectMuteStatus} from '../../redux/session'; ...@@ -9,12 +9,15 @@ import {selectMuteStatus} from '../../redux/session';
import {formatRelativeTime} from '../../lib/format-time.js'; import {formatRelativeTime} from '../../lib/format-time.js';
const StudioMuteEditMessage = ({ const StudioMuteEditMessage = ({
className,
messageId,
muteExpiresAtMs muteExpiresAtMs
}) => ( }) => (
<ValidationMessage <ValidationMessage
className={className}
mode="info" mode="info"
message={<FormattedMessage message={<FormattedMessage
id="studio.mutedEdit" id={messageId}
values={{ values={{
inDuration: formatRelativeTime(muteExpiresAtMs, window._locale) inDuration: formatRelativeTime(muteExpiresAtMs, window._locale)
}} }}
...@@ -24,9 +27,15 @@ const StudioMuteEditMessage = ({ ...@@ -24,9 +27,15 @@ const StudioMuteEditMessage = ({
StudioMuteEditMessage.propTypes = { StudioMuteEditMessage.propTypes = {
className: PropTypes.string,
messageId: PropTypes.string,
muteExpiresAtMs: PropTypes.number muteExpiresAtMs: PropTypes.number
}; };
StudioMuteEditMessage.defaultProps = {
messageId: 'studio.mutedEdit'
};
export default connect( export default connect(
state => ({ state => ({
muteExpiresAtMs: (selectMuteStatus(state).muteExpiresAt * 1000 || 0) muteExpiresAtMs: (selectMuteStatus(state).muteExpiresAt * 1000 || 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment