mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-17 00:21:20 -05:00
only show studios user can manipulate in add to studio modal
Refactored studio list consolidation code for add to studio; set canAdd, canRemove flags directly on each studio. pass flag userOwnsProject through to add to studio modal and its buttons. pass flag isAdmin through to add to studio and its buttons. set flags in add to studio buttons for whether user has permission to add project to studio, remove project from studio. Set user ability/inability to click add to studio buttons using permissions flags and css
This commit is contained in:
parent
db6e0ed88f
commit
ab82d37720
7 changed files with 76 additions and 19 deletions
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -3,26 +3,52 @@ 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 = (consolidatedStudios, 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
|
||||
});
|
||||
consolidatedStudios.push(consolidatedStudio);
|
||||
}
|
||||
};
|
||||
|
||||
// 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));
|
||||
showStudio(consolidatedStudios, projectStudio, currentStudioIds, userIsCurator, userOwnsProject, isAdmin);
|
||||
});
|
||||
|
||||
// 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);
|
||||
showStudio(consolidatedStudios, curatedStudio, currentStudioIds, true, userOwnsProject, isAdmin);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -32,16 +58,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 = () => ({});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue