Revert "Revert "Add to studio modal should only show studios user can actually change""

This commit is contained in:
Benjamin Wheeler 2019-01-22 17:07:52 -05:00 committed by GitHub
parent ecad945ead
commit 4d3e46e40b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 19 deletions

View file

@ -134,6 +134,14 @@
color: $type-gray; color: $type-gray;
} }
.studio-selector-button-enabled {
pointer-events: auto;
}
.studio-selector-button-disabled {
pointer-events: none;
}
.studio-status-icon { .studio-status-icon {
position: absolute; position: absolute;
right: .625rem; right: .625rem;

View file

@ -26,6 +26,8 @@ const AddToStudioModalPresentation = ({
const contentLabel = intl.formatMessage({id: 'addToStudio.title'}); const contentLabel = intl.formatMessage({id: 'addToStudio.title'});
const studioButtons = studios.map(studio => ( const studioButtons = studios.map(studio => (
<StudioButton <StudioButton
canAdd={studio.canAdd}
canRemove={studio.canRemove}
hasRequestOutstanding={studio.hasRequestOutstanding} hasRequestOutstanding={studio.hasRequestOutstanding}
id={studio.id} id={studio.id}
includesProject={studio.includesProject} includesProject={studio.includesProject}

View file

@ -8,6 +8,8 @@ const AnimateHOC = require('./animate-hoc.jsx');
require('./modal.scss'); require('./modal.scss');
const StudioButton = ({ const StudioButton = ({
canAdd,
canRemove,
hasRequestOutstanding, hasRequestOutstanding,
includesProject, includesProject,
title, title,
@ -38,9 +40,12 @@ const StudioButton = ({
<div <div
className={classNames( className={classNames(
'studio-selector-button', 'studio-selector-button',
{'studio-selector-button-waiting': hasRequestOutstanding}, {
{'studio-selector-button-selected': 'studio-selector-button-waiting': hasRequestOutstanding,
includesProject && !hasRequestOutstanding} 'studio-selector-button-selected': includesProject && !hasRequestOutstanding,
'studio-selector-button-enabled': includesProject ? canRemove : canAdd,
'studio-selector-button-disabled': includesProject ? !canRemove : !canAdd
}
)} )}
onClick={onClick} onClick={onClick}
> >
@ -69,6 +74,8 @@ const StudioButton = ({
}; };
StudioButton.propTypes = { StudioButton.propTypes = {
canAdd: PropTypes.bool,
canRemove: PropTypes.bool,
hasRequestOutstanding: PropTypes.bool, hasRequestOutstanding: PropTypes.bool,
includesProject: PropTypes.bool, includesProject: PropTypes.bool,
onClick: PropTypes.func, onClick: PropTypes.func,

View file

@ -3,26 +3,59 @@ const connect = require('react-redux').connect;
const previewActions = require('../../redux/preview.js'); const previewActions = require('../../redux/preview.js');
const AddToStudioModal = require('../../components/modal/addtostudio/container.jsx'); const AddToStudioModal = require('../../components/modal/addtostudio/container.jsx');
// user can add project to studio if studio is open to all, or user is a curator of studio
const canAdd = (studio, userIsCurator) => (
studio.open_to_all || userIsCurator
);
// user can remove project from studio if user owns project or is admin or user is a curator of studio
const canRemove = (userOwnsProject, isAdmin, userIsCurator) => (
userOwnsProject || isAdmin || userIsCurator
);
// include a given studio in the list to show in add to studio modal.
// only include it if user has the ability to remove the project from this studio.
const showStudio = (studio, currentStudioIds, userIsCurator, userOwnsProject, isAdmin) => {
const includesProject = (currentStudioIds.indexOf(studio.id) !== -1);
const canAddToThisStudio = canAdd(studio, userIsCurator);
const canRemoveFromThisStudio = canRemove(userOwnsProject, isAdmin, userIsCurator);
if (canRemoveFromThisStudio) { // power to remove matches set of studios we want to show
// include the current status of whether the project is in the studio,
// and what privileges the user has to change that.
const consolidatedStudio = Object.assign({}, studio, {
includesProject: includesProject,
canAdd: canAddToThisStudio,
canRemove: canRemoveFromThisStudio
});
return consolidatedStudio;
}
return null;
};
// Build consolidated curatedStudios object from all studio info. // Build consolidated curatedStudios object from all studio info.
// We add flags to indicate whether the project is currently in the studio, // We add flags to indicate whether the project is currently in the studio,
// and the status of requests to join/leave studios. // and the status of requests to join/leave studios.
const consolidateStudiosInfo = (curatedStudios, projectStudios, currentStudioIds, studioRequests) => { const consolidateStudiosInfo = (userOwnsProject, isAdmin, curatedStudios, projectStudios,
currentStudioIds, studioRequests) => {
const consolidatedStudios = []; const consolidatedStudios = [];
// for each studio the project is in, include it if user can add or remove project from it.
projectStudios.forEach(projectStudio => { projectStudios.forEach(projectStudio => {
const includesProject = (currentStudioIds.indexOf(projectStudio.id) !== -1); const userIsCurator = curatedStudios.some(curatedStudio => (curatedStudio.id === projectStudio.id));
const consolidatedStudio = const studioToShow = showStudio(projectStudio, currentStudioIds, userIsCurator, userOwnsProject, isAdmin);
Object.assign({}, projectStudio, {includesProject: includesProject}); if (studioToShow) {
consolidatedStudios.push(consolidatedStudio); consolidatedStudios.push(studioToShow);
}
}); });
// copy the curated studios that project is not in // for each curated studio, if it was not already added to consolidatedStudios above, add it now.
curatedStudios.forEach(curatedStudio => { curatedStudios.forEach(curatedStudio => {
if (!projectStudios.some(projectStudio => (projectStudio.id === curatedStudio.id))) { if (!projectStudios.some(projectStudio => (projectStudio.id === curatedStudio.id))) {
const includesProject = (currentStudioIds.indexOf(curatedStudio.id) !== -1); const studioToShow = showStudio(curatedStudio, currentStudioIds, true, userOwnsProject, isAdmin);
const consolidatedStudio = if (studioToShow) {
Object.assign({}, curatedStudio, {includesProject: includesProject}); consolidatedStudios.push(studioToShow);
consolidatedStudios.push(consolidatedStudio); }
} }
}); });
@ -38,10 +71,10 @@ const consolidateStudiosInfo = (curatedStudios, projectStudios, currentStudioIds
return consolidatedStudios; return consolidatedStudios;
}; };
const mapStateToProps = state => ({ const mapStateToProps = (state, ownProps) => ({
studios: consolidateStudiosInfo(state.preview.curatedStudios, studios: consolidateStudiosInfo(ownProps.userOwnsProject, ownProps.isAdmin,
state.preview.projectStudios, state.preview.currentStudioIds, state.preview.curatedStudios, state.preview.projectStudios,
state.preview.status.studioRequests) state.preview.currentStudioIds, state.preview.status.studioRequests)
}); });
const mapDispatchToProps = () => ({}); const mapDispatchToProps = () => ({});

View file

@ -67,6 +67,7 @@ const PreviewPresentation = ({
faved, faved,
favoriteCount, favoriteCount,
intl, intl,
isAdmin,
isFullScreen, isFullScreen,
isLoggedIn, isLoggedIn,
isNewScratcher, isNewScratcher,
@ -122,6 +123,7 @@ const PreviewPresentation = ({
showAdminPanel, showAdminPanel,
showModInfo, showModInfo,
singleCommentId, singleCommentId,
userOwnsProject,
visibilityInfo visibilityInfo
}) => { }) => {
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : ''; const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';
@ -344,9 +346,11 @@ const PreviewPresentation = ({
<Subactions <Subactions
addToStudioOpen={addToStudioOpen} addToStudioOpen={addToStudioOpen}
canReport={canReport} canReport={canReport}
isAdmin={isAdmin}
projectInfo={projectInfo} projectInfo={projectInfo}
reportOpen={reportOpen} reportOpen={reportOpen}
shareDate={shareDate} shareDate={shareDate}
userOwnsProject={userOwnsProject}
onAddToStudioClicked={onAddToStudioClicked} onAddToStudioClicked={onAddToStudioClicked}
onAddToStudioClosed={onAddToStudioClosed} onAddToStudioClosed={onAddToStudioClosed}
onCopyProjectLink={onCopyProjectLink} onCopyProjectLink={onCopyProjectLink}
@ -469,9 +473,11 @@ const PreviewPresentation = ({
addToStudioOpen={addToStudioOpen} addToStudioOpen={addToStudioOpen}
canAddToStudio={canAddToStudio} canAddToStudio={canAddToStudio}
canReport={canReport} canReport={canReport}
isAdmin={isAdmin}
projectInfo={projectInfo} projectInfo={projectInfo}
reportOpen={reportOpen} reportOpen={reportOpen}
shareDate={shareDate} shareDate={shareDate}
userOwnsProject={userOwnsProject}
onAddToStudioClicked={onAddToStudioClicked} onAddToStudioClicked={onAddToStudioClicked}
onAddToStudioClosed={onAddToStudioClosed} onAddToStudioClosed={onAddToStudioClosed}
onCopyProjectLink={onCopyProjectLink} onCopyProjectLink={onCopyProjectLink}
@ -626,6 +632,7 @@ PreviewPresentation.propTypes = {
faved: PropTypes.bool, faved: PropTypes.bool,
favoriteCount: PropTypes.number, favoriteCount: PropTypes.number,
intl: intlShape, intl: intlShape,
isAdmin: PropTypes.bool,
isFullScreen: PropTypes.bool, isFullScreen: PropTypes.bool,
isLoggedIn: PropTypes.bool, isLoggedIn: PropTypes.bool,
isNewScratcher: PropTypes.bool, isNewScratcher: PropTypes.bool,
@ -684,6 +691,7 @@ PreviewPresentation.propTypes = {
showModInfo: PropTypes.bool, showModInfo: PropTypes.bool,
showUsernameBlockAlert: PropTypes.bool, showUsernameBlockAlert: PropTypes.bool,
singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]), singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
userOwnsProject: PropTypes.bool,
visibilityInfo: PropTypes.shape({ visibilityInfo: PropTypes.shape({
censored: PropTypes.bool, censored: PropTypes.bool,
message: PropTypes.string, message: PropTypes.string,

View file

@ -641,6 +641,7 @@ class Preview extends React.Component {
extensions={this.state.extensions} extensions={this.state.extensions}
faved={this.state.clientFaved} faved={this.state.clientFaved}
favoriteCount={this.state.favoriteCount} favoriteCount={this.state.favoriteCount}
isAdmin={this.props.isAdmin}
isFullScreen={this.props.fullScreen} isFullScreen={this.props.fullScreen}
isLoggedIn={this.props.isLoggedIn} isLoggedIn={this.props.isLoggedIn}
isNewScratcher={this.props.isNewScratcher} isNewScratcher={this.props.isNewScratcher}
@ -668,6 +669,7 @@ class Preview extends React.Component {
showModInfo={this.props.isAdmin} showModInfo={this.props.isAdmin}
showUsernameBlockAlert={this.state.showUsernameBlockAlert} showUsernameBlockAlert={this.state.showUsernameBlockAlert}
singleCommentId={this.state.singleCommentId} singleCommentId={this.state.singleCommentId}
userOwnsProject={this.props.userOwnsProject}
visibilityInfo={this.props.visibilityInfo} visibilityInfo={this.props.visibilityInfo}
onAddComment={this.handleAddComment} onAddComment={this.handleAddComment}
onAddToStudioClicked={this.handleAddToStudioClick} onAddToStudioClicked={this.handleAddToStudioClick}

View file

@ -39,7 +39,9 @@ const Subactions = props => (
{props.addToStudioOpen && ( {props.addToStudioOpen && (
<AddToStudioModal <AddToStudioModal
isOpen isOpen
isAdmin={props.isAdmin}
key="add-to-studio-modal" key="add-to-studio-modal"
userOwnsProject={props.userOwnsProject}
onRequestClose={props.onAddToStudioClosed} onRequestClose={props.onAddToStudioClosed}
onToggleStudio={props.onToggleStudio} onToggleStudio={props.onToggleStudio}
/> />
@ -80,6 +82,7 @@ Subactions.propTypes = {
addToStudioOpen: PropTypes.bool, addToStudioOpen: PropTypes.bool,
canAddToStudio: PropTypes.bool, canAddToStudio: PropTypes.bool,
canReport: PropTypes.bool, canReport: PropTypes.bool,
isAdmin: PropTypes.bool,
onAddToStudioClicked: PropTypes.func, onAddToStudioClicked: PropTypes.func,
onAddToStudioClosed: PropTypes.func, onAddToStudioClosed: PropTypes.func,
onCopyProjectLink: PropTypes.func, onCopyProjectLink: PropTypes.func,
@ -88,7 +91,8 @@ Subactions.propTypes = {
onReportSubmit: PropTypes.func.isRequired, onReportSubmit: PropTypes.func.isRequired,
onToggleStudio: PropTypes.func, onToggleStudio: PropTypes.func,
reportOpen: PropTypes.bool, reportOpen: PropTypes.bool,
shareDate: PropTypes.string shareDate: PropTypes.string,
userOwnsProject: PropTypes.bool
}; };
module.exports = Subactions; module.exports = Subactions;