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;
}
.studio-selector-button-enabled {
pointer-events: auto;
}
.studio-selector-button-disabled {
pointer-events: none;
}
.studio-status-icon {
position: absolute;
right: .625rem;

View file

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

View file

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

View file

@ -3,26 +3,59 @@ const connect = require('react-redux').connect;
const previewActions = require('../../redux/preview.js');
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.
// We add flags to indicate whether the project is currently in the studio,
// 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 = [];
// for each studio the project is in, include it if user can add or remove project from it.
projectStudios.forEach(projectStudio => {
const includesProject = (currentStudioIds.indexOf(projectStudio.id) !== -1);
const consolidatedStudio =
Object.assign({}, projectStudio, {includesProject: includesProject});
consolidatedStudios.push(consolidatedStudio);
const userIsCurator = curatedStudios.some(curatedStudio => (curatedStudio.id === projectStudio.id));
const studioToShow = showStudio(projectStudio, currentStudioIds, userIsCurator, userOwnsProject, isAdmin);
if (studioToShow) {
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 => {
if (!projectStudios.some(projectStudio => (projectStudio.id === curatedStudio.id))) {
const includesProject = (currentStudioIds.indexOf(curatedStudio.id) !== -1);
const consolidatedStudio =
Object.assign({}, curatedStudio, {includesProject: includesProject});
consolidatedStudios.push(consolidatedStudio);
const studioToShow = showStudio(curatedStudio, currentStudioIds, true, userOwnsProject, isAdmin);
if (studioToShow) {
consolidatedStudios.push(studioToShow);
}
}
});
@ -32,16 +65,16 @@ const consolidateStudiosInfo = (curatedStudios, projectStudios, currentStudioIds
const id = consolidatedStudio.id;
consolidatedStudio.hasRequestOutstanding =
((id in studioRequests) &&
(studioRequests[id] === previewActions.Status.FETCHING));
(studioRequests[id] === previewActions.Status.FETCHING));
});
return consolidatedStudios;
};
const mapStateToProps = state => ({
studios: consolidateStudiosInfo(state.preview.curatedStudios,
state.preview.projectStudios, state.preview.currentStudioIds,
state.preview.status.studioRequests)
const mapStateToProps = (state, ownProps) => ({
studios: consolidateStudiosInfo(ownProps.userOwnsProject, ownProps.isAdmin,
state.preview.curatedStudios, state.preview.projectStudios,
state.preview.currentStudioIds, state.preview.status.studioRequests)
});
const mapDispatchToProps = () => ({});

View file

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

View file

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

View file

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