Skip to content
3 changes: 3 additions & 0 deletions src/_colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ $ui-border: hsla(0, 0%, 85%, 1); //#D9D9D9
$ui-border-light-blue: hsla(215, 50%, 90%, 1); //#D9E3F2
$ui-border-orange: hsla(37, 96%, 55%, 1); // #FAA51D

$ui-text-disabled: hsla(227, 15%, 70%, 1); //#A7ACBE
$ui-background-disabled: hsla(231, 14%, 90%, 1); //#E2E3E9

/* modals */
$ui-mint-green: hsl(163, 69%, 44%);
$ui-light-mint: hsl(163, 53%, 67%);
Expand Down
4 changes: 4 additions & 0 deletions src/components/overflow-menu/overflow-icon-disabled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions src/components/overflow-menu/overflow-menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,29 @@ import classNames from 'classnames';

import Dropdown from '../dropdown/dropdown.jsx';
import overflowIcon from './overflow-icon.svg';
import overflowIconDisabled from './overflow-icon-disabled.svg';

import './overflow-menu.scss';

const OverflowMenu = ({
children,
dropdownAs = 'ul',
className
className,
disabled
}) => {
const [open, setOpen] = useState(false);
const iconSrc = disabled ? overflowIconDisabled : overflowIcon;

return (
<div className={classNames('overflow-menu-container', className)}>
<button
className={classNames('overflow-menu-trigger', {
'ignore-react-onclickoutside': open
})}
onClick={() => setOpen(!open)}
disabled={disabled}
>
<img src={overflowIcon} />
<img src={iconSrc} />
</button>
{open && <Dropdown
isOpen
Expand All @@ -39,7 +44,8 @@ const OverflowMenu = ({
OverflowMenu.propTypes = {
children: PropTypes.node,
dropdownAs: PropTypes.string,
className: PropTypes.string
className: PropTypes.string,
disabled: PropTypes.bool
};

export default OverflowMenu;
14 changes: 11 additions & 3 deletions src/views/preview/banner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@ const Button = require('../../components/forms/button.jsx');

require('./banner.scss');

const Banner = ({className, message, actionMessage, onAction}) => (
const Banner = ({
className,
message,
actionMessage,
onAction,
buttonDisabled
}) => (
<div className={classNames('banner-outer', className)}>
<FlexRow className="inner banner-inner">
<span className="banner-text">
{message}
</span>
{actionMessage && onAction && (
<Button
className="banner-button"
className={classNames('banner-button', {'banner-button-disabled': buttonDisabled})}
disabled={buttonDisabled}
onClick={onAction}
>
{actionMessage}
Expand All @@ -28,7 +35,8 @@ Banner.propTypes = {
actionMessage: PropTypes.node,
className: PropTypes.string,
message: PropTypes.node.isRequired,
onAction: PropTypes.func
onAction: PropTypes.func,
buttonDisabled: PropTypes.bool
};

module.exports = Banner;
5 changes: 5 additions & 0 deletions src/views/preview/banner.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,8 @@ $navigation-height: 50px;
.banner-danger .banner-button {
background-color: colors.$ui-red;
}

.banner-button-disabled {
color: colors.$ui-text-disabled;
background-color: colors.$ui-background-disabled;
}
3 changes: 3 additions & 0 deletions src/views/preview/presentation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ const PreviewPresentation = ({
actionMessage={<FormattedMessage id="project.share.shareButton" />}
message={<FormattedMessage id="project.share.notShared" />}
onAction={canShare ? onShare : onShareAttempt}
buttonDisabled={process.env.READ_ONLY_MODE === 'true'}
/>);
}
}
Expand Down Expand Up @@ -443,6 +444,7 @@ const PreviewPresentation = ({
projectInfo={projectInfo}
onFavoriteClicked={onFavoriteClicked}
onLoveClicked={onLoveClicked}
disabled={process.env.READ_ONLY_MODE === 'true'}
/>
</div>
<div className="wrappable-item">
Expand Down Expand Up @@ -593,6 +595,7 @@ const PreviewPresentation = ({
projectInfo={projectInfo}
onFavoriteClicked={onFavoriteClicked}
onLoveClicked={onLoveClicked}
disabled={process.env.READ_ONLY_MODE === 'true'}
/>
<Subactions
addToStudioOpen={addToStudioOpen}
Expand Down
21 changes: 12 additions & 9 deletions src/views/preview/project-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ class Preview extends React.Component {
}
}
handleFavoriteToggle () {
if (!this.props.favedLoaded) return;
if (!this.props.favedLoaded || process.env.READ_ONLY_MODE === 'true') return;

this.props.setFavedStatus(
!this.props.faved,
Expand Down Expand Up @@ -784,7 +784,7 @@ class Preview extends React.Component {
);
}
handleLoveToggle () {
if (!this.props.lovedLoaded) return;
if (!this.props.lovedLoaded || process.env.READ_ONLY_MODE === 'true') return;

this.props.setLovedStatus(
!this.props.loved,
Expand Down Expand Up @@ -1014,6 +1014,8 @@ class Preview extends React.Component {
const canManuallySaveThumbnails = process.env.MANUALLY_SAVE_THUMBNAILS === 'true' &&
(process.env.READ_ONLY_MODE !== 'true' || !this.props.isShared);

const canModifyProject = process.env.READ_ONLY_MODE !== 'true' || !this.props.isShared;

if (!this.props.playerMode && shouldDisplayBlockingPage) {
// The Page components will display the blocking ToS page in this case
return (
Expand Down Expand Up @@ -1195,10 +1197,10 @@ class Preview extends React.Component {
basePath="/"
canCreateCopy={this.props.canCreateCopy}
canCreateNew={this.props.canCreateNew}
canEditTitle={this.props.canEditTitleInEditor}
canEditTitle={this.props.canEditTitleInEditor && canModifyProject}
canRemix={this.props.canRemix}
canSave={this.props.canSave}
canShare={this.props.canShare}
canSave={this.props.canSave && canModifyProject}
canShare={this.props.canShare && process.env.READ_ONLY_MODE !== 'true'}
className="gui"
cloudHost={this.props.cloudHost}
enableCommunity={this.props.enableCommunity}
Expand Down Expand Up @@ -1400,7 +1402,11 @@ const mapStateToProps = state => {
const authorAvatarBadge = authorPresent && author.profile.membership_avatar_badge;
const userOwnsProject = isLoggedIn && authorPresent &&
state.session.session.user.id.toString() === authorId;
const isEditable = isLoggedIn &&

// if we don't have projectInfo, assume it's shared until we know otherwise
const isShared = !projectInfoPresent || state.preview.projectInfo.is_published;

const isEditable = isLoggedIn && (process.env.READ_ONLY_MODE !== 'true' || !isShared) &&
(authorUsername === state.session.session.user.username ||
state.permissions.admin === true);
const areCommentsOn = state.session.session.flags && selectProjectCommentsGloballyEnabled(state);
Expand All @@ -1415,9 +1421,6 @@ const mapStateToProps = state => {
const acceptedTermsOfService = state.session.session.flags?.accepted_terms_of_service;
const isStudent = state.session.session.permissions?.student;

// if we don't have projectInfo, assume it's shared until we know otherwise
const isShared = !projectInfoPresent || state.preview.projectInfo.is_published;

return {
authorId: authorId,
authorThumbnailUrl: thumbnailUrl(authorId),
Expand Down
5 changes: 3 additions & 2 deletions src/views/preview/stats.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const projectShape = require('./projectshape.jsx').projectShape;
require('./stats.scss');

const Stats = props => (
<FlexRow className="stats noselect">
<FlexRow className={classNames('stats noselect', {disabled: props.disabled})}>
<div
className={classNames('project-loves', {loved: props.loved})}
key="loves"
Expand Down Expand Up @@ -45,7 +45,8 @@ Stats.propTypes = {
loved: PropTypes.bool,
onFavoriteClicked: PropTypes.func,
onLoveClicked: PropTypes.func,
projectInfo: projectShape
projectInfo: projectShape,
disabled: PropTypes.bool
};

module.exports = Stats;
20 changes: 20 additions & 0 deletions src/views/preview/stats.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,26 @@
}
}

.disabled {
pointer-events: none;
}

.disabled .project-loves:not(.loved):before {
background-image: url("/svgs/project/love-read-only-not-loved.svg");
}

.disabled .project-loves.loved:before {
background-image: url("/svgs/project/love-read-only-loved.svg");
}

.disabled .project-favorites:not(.favorited):before {
background-image: url("/svgs/project/fav-read-only-not-favorited.svg");
}

.disabled .project-favorites.favorited:before {
background-image: url("/svgs/project/fav-read-only-favorited.svg");
}

.project-remixes {

&:before {
Expand Down
2 changes: 1 addition & 1 deletion src/views/preview/subactions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const Subactions = ({
>
<Button
className="action-button studio-button"
disabled={showAddToStudioMuteError}
disabled={showAddToStudioMuteError || process.env.READ_ONLY_MODE === 'true'}
key="add-to-studio-button"
onClick={showMuteMessage ? null : onAddToStudioClicked}
>
Expand Down
10 changes: 10 additions & 0 deletions src/views/preview/subactions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@
}
}

.subactions .action-buttons .action-button.studio-button:disabled {
background-color: colors.$ui-background-disabled;
color: colors.$ui-text-disabled;
pointer-events: none;

&:before {
background-image: url("/svgs/project/studio-add-gray.svg");
}
}

.studio-button-error {
top: auto;
transform: none;
Expand Down
7 changes: 5 additions & 2 deletions src/views/studio/studio-curator-invite.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {FormattedMessage} from 'react-intl';
import {acceptInvitation} from './lib/studio-member-actions';
import {selectShowCuratorInvite} from '../../redux/studio-permissions';


const StudioCuratorInvite = ({showCuratorInvite, onSubmit}) => {
const [submitting, setSubmitting] = useState(false);
const [accepted, setAccepted] = useState(false);
Expand Down Expand Up @@ -42,10 +43,12 @@ const StudioCuratorInvite = ({showCuratorInvite, onSubmit}) => {
</div>
<button
className={classNames('studio-invitation-button button', {
'mod-mutating': submitting
'mod-mutating': submitting,
'studio-disabled': process.env.READ_ONLY_MODE === 'true'
})}
disabled={submitting}
disabled={submitting || process.env.READ_ONLY_MODE === 'true'}
onClick={() => {
if (submitting || process.env.READ_ONLY_MODE === 'true') return;
setSubmitting(true);
setError(null);
onSubmit()
Expand Down
13 changes: 9 additions & 4 deletions src/views/studio/studio-curator-inviter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {Errors, inviteCurator} from './lib/studio-member-actions';
import intlShape from '../../lib/intl-shape';
import ValidationMessage from '../../components/forms/validation-message.jsx';


const errorToMessageId = error => {
switch (error) {
case Errors.NETWORK: return 'studio.curatorErrors.generic';
Expand Down Expand Up @@ -65,8 +66,11 @@ const StudioCuratorInviter = ({intl, onSubmit}) => {
/>
</div>}
<input
className={classNames({'mod-form-error': error})}
disabled={submitting}
className={classNames({
'mod-form-error': error,
'studio-disabled': process.env.READ_ONLY_MODE === 'true'
})}
disabled={submitting || process.env.READ_ONLY_MODE === 'true'}
type="text"
placeholder={intl.formatMessage({id: 'studio.inviteCuratorPlaceholder'})}
value={value}
Expand All @@ -75,9 +79,10 @@ const StudioCuratorInviter = ({intl, onSubmit}) => {
/>
<button
className={classNames('button', {
'mod-mutating': submitting
'mod-mutating': submitting,
'studio-disabled': process.env.READ_ONLY_MODE === 'true'
})}
disabled={submitting || value === ''}
disabled={submitting || value === '' || process.env.READ_ONLY_MODE === 'true'}
onClick={submit}
><FormattedMessage id="studio.inviteCurator" /></button>
</div>
Expand Down
11 changes: 8 additions & 3 deletions src/views/studio/studio-description.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ValidationMessage from '../../components/forms/validation-message.jsx';
import decorateText from '../../lib/decorate-text.jsx';
import StudioMuteEditMessage from './studio-mute-edit-message.jsx';


const errorToMessageId = error => {
switch (error) {
case Errors.INAPPROPRIATE: return 'studio.updateErrors.inappropriate';
Expand Down Expand Up @@ -53,12 +54,16 @@ const StudioDescription = ({
onMouseLeave={() => isMutedEditor && setShowMuteMessage(false)}
ref={ref}
>
{canEditInfo || isMutedEditor ? (
{(canEditInfo || isMutedEditor) ? (
<React.Fragment>
<textarea
rows="20"
className={classNames('inplace-textarea', fieldClassName)}
disabled={isMutating || isFetching || isMutedEditor}
className={classNames(
'inplace-textarea',
fieldClassName,
{'studio-disabled': process.env.READ_ONLY_MODE === 'true'}
)}
disabled={isMutating || isFetching || isMutedEditor || process.env.READ_ONLY_MODE === 'true'}
defaultValue={description}
onBlur={e => {
if (e.target.value !== description) handleUpdate(e.target.value);
Expand Down
5 changes: 3 additions & 2 deletions src/views/studio/studio-follow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import classNames from 'classnames';
import ValidationMessage from '../../components/forms/validation-message.jsx';


const errorToMessageId = (error, userUsesParentEmail) => {
switch (error) {
case Errors.PERMISSION: return userUsesParentEmail ?
Expand Down Expand Up @@ -50,8 +51,8 @@ const StudioFollow = ({
ref={ref}
>
<button
className={fieldClassName}
disabled={isMutating}
className={classNames(fieldClassName, {'studio-disabled': process.env.READ_ONLY_MODE === 'true'})}
disabled={isMutating || process.env.READ_ONLY_MODE === 'true'}
onClick={() => {
setHideValidationMessage(false);
handleFollow(!isFollowing);
Expand Down
Loading
Loading