mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 09:35:56 -05:00
Revert "Revert "Add to studio modal should only show studios user can actually change""
This commit is contained in:
parent
ecad945ead
commit
4d3e46e40b
7 changed files with 83 additions and 19 deletions
|
@ -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;
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 = () => ({});
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue