From bd391b422a1a94785b59c73c11ffea857ae02b18 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Thu, 24 May 2018 09:57:06 -0400 Subject: [PATCH 1/8] presentation first pass First pass at project page design using actual assets from Carl, and matching styles with current design. Includes a (negative margin) hack to line up the stage. see https://github.com/LLK/scratch-gui/issues/2132 --- src/components/forms/inplace-input.scss | 16 +- src/redux/preview.js | 61 ++++-- src/views/preview/presentation.jsx | 256 +++++++++++++++------- src/views/preview/preview.jsx | 62 +++++- src/views/preview/preview.scss | 212 ++++++++++++------ static/svgs/project/copy-link-gray.svg | 10 + static/svgs/project/copy-link-white.svg | 10 + static/svgs/project/delete-gray.svg | 17 ++ static/svgs/project/fav-gray.svg | 10 + static/svgs/project/fav-yellow.svg | 10 + static/svgs/project/love-gray.svg | 10 + static/svgs/project/love-red.svg | 10 + static/svgs/project/remix-gray.svg | 10 + static/svgs/project/remix-white.svg | 10 + static/svgs/project/report-gray.svg | 10 + static/svgs/project/report-white.svg | 10 + static/svgs/project/restore-gray.svg | 10 + static/svgs/project/revised-date-gray.svg | 13 ++ static/svgs/project/scripts-gray.svg | 10 + static/svgs/project/see-inside-white.svg | 10 + static/svgs/project/share-white.svg | 10 + static/svgs/project/studio-add-white.svg | 10 + static/svgs/project/views-gray.svg | 13 ++ 23 files changed, 626 insertions(+), 174 deletions(-) create mode 100644 static/svgs/project/copy-link-gray.svg create mode 100644 static/svgs/project/copy-link-white.svg create mode 100644 static/svgs/project/delete-gray.svg create mode 100644 static/svgs/project/fav-gray.svg create mode 100644 static/svgs/project/fav-yellow.svg create mode 100644 static/svgs/project/love-gray.svg create mode 100644 static/svgs/project/love-red.svg create mode 100644 static/svgs/project/remix-gray.svg create mode 100644 static/svgs/project/remix-white.svg create mode 100644 static/svgs/project/report-gray.svg create mode 100644 static/svgs/project/report-white.svg create mode 100644 static/svgs/project/restore-gray.svg create mode 100644 static/svgs/project/revised-date-gray.svg create mode 100644 static/svgs/project/scripts-gray.svg create mode 100644 static/svgs/project/see-inside-white.svg create mode 100644 static/svgs/project/share-white.svg create mode 100644 static/svgs/project/studio-add-white.svg create mode 100644 static/svgs/project/views-gray.svg diff --git a/src/components/forms/inplace-input.scss b/src/components/forms/inplace-input.scss index 46deab4b9..a0a6ae845 100644 --- a/src/components/forms/inplace-input.scss +++ b/src/components/forms/inplace-input.scss @@ -3,8 +3,8 @@ .inplace-input { transition: all .5s ease; - border: 2px dashed $ui-dark-gray; - border-radius: 5px; + border: 2px dashed $ui-blue; + border-radius: 8px; background-color: transparent; padding: 0 1rem; color: $type-gray; @@ -31,13 +31,12 @@ .inplace-textarea { transition: all 1s ease; - margin-bottom: .75rem; - border: 2px dashed $ui-dark-gray; - border-radius: 5px; + box-sizing: border-box; + border: 2px dashed $ui-blue; + border-radius: 8px; background-color: $ui-light-gray; padding: .75rem 1rem; - width: calc(100% - 2.25rem); - min-height: 20rem; + width: 100%; line-height: 1.75em; color: $type-gray; font-size: .875rem; @@ -46,7 +45,8 @@ &:focus { transition: all 1s ease; outline: none; - border: 1px solid $ui-blue; + border: 2px solid $ui-blue; + box-shadow: 0 0 0 4px rgba(76,151,255,0.25); } &.fail { diff --git a/src/redux/preview.js b/src/redux/preview.js index 92c5a6c20..151993408 100644 --- a/src/redux/preview.js +++ b/src/redux/preview.js @@ -13,19 +13,21 @@ module.exports.Status = keyMirror({ module.exports.getInitialState = () => ({ status: { project: module.exports.Status.NOT_FETCHED, - credit: module.exports.Status.NOT_FETCHED, comments: module.exports.Status.NOT_FETCHED, faved: module.exports.Status.NOT_FETCHED, loved: module.exports.Status.NOT_FETCHED, + original: module.exports.Status.NOT_FETCHED, + parent: module.exports.Status.NOT_FETCHED, remixes: module.exports.Status.NOT_FETCHED, studios: module.exports.Status.NOT_FETCHED }, projectInfo: {}, remixes: [], - credit: {}, comments: [], faved: false, loved: false, + original: {}, + parent: {}, studios: [] }); @@ -43,14 +45,18 @@ module.exports.previewReducer = (state, action) => { return Object.assign({}, state, { remixes: action.items }); + case 'SET_ORIGINAL': + return Object.assign({}, state, { + original: action.info + }); + case 'SET_PARENT': + return Object.assign({}, state, { + parent: action.info + }); case 'SET_STUDIOS': return Object.assign({}, state, { studios: action.items }); - case 'SET_CREDIT': - return Object.assign({}, state, { - credit: action.info - }); case 'SET_COMMENTS': return Object.assign({}, state, { comments: action.items @@ -85,8 +91,13 @@ module.exports.setProjectInfo = info => ({ info: info }); -module.exports.setCreditInfo = info => ({ - type: 'SET_CREDIT', +module.exports.setOriginalInfo = info => ({ + type: 'SET_ORIGINAL', + info: info +}); + +module.exports.setParentInfo = info => ({ + type: 'SET_PARENT', info: info }); @@ -140,23 +151,43 @@ module.exports.getProjectInfo = (id, token) => (dispatch => { }); }); -module.exports.getCreditInfo = id => (dispatch => { - dispatch(module.exports.setFetchStatus('credit', module.exports.Status.FETCHING)); +module.exports.getOriginalInfo = id => (dispatch => { + dispatch(module.exports.setFetchStatus('original', module.exports.Status.FETCHING)); api({ uri: `/projects/${id}` }, (err, body) => { if (err) { - dispatch(module.exports.setFetchStatus('credit', module.exports.Status.ERROR)); + dispatch(module.exports.setFetchStatus('original', module.exports.Status.ERROR)); dispatch(module.exports.setError(err)); return; } if (typeof body === 'undefined') { - dispatch(module.exports.setFetchStatus('credit', module.exports.Status.ERROR)); - dispatch(module.exports.setError('No credit info')); + dispatch(module.exports.setFetchStatus('original', module.exports.Status.ERROR)); + dispatch(module.exports.setError('No original info')); return; } - dispatch(module.exports.setFetchStatus('credit', module.exports.Status.FETCHED)); - dispatch(module.exports.setCreditInfo(body)); + dispatch(module.exports.setFetchStatus('original', module.exports.Status.FETCHED)); + dispatch(module.exports.setOriginalInfo(body)); + }); +}); + +module.exports.getParentInfo = id => (dispatch => { + dispatch(module.exports.setFetchStatus('parent', module.exports.Status.FETCHING)); + api({ + uri: `/projects/${id}` + }, (err, body) => { + if (err) { + dispatch(module.exports.setFetchStatus('parent', module.exports.Status.ERROR)); + dispatch(module.exports.setError(err)); + return; + } + if (typeof body === 'undefined') { + dispatch(module.exports.setFetchStatus('parent', module.exports.Status.ERROR)); + dispatch(module.exports.setError('No parent info')); + return; + } + dispatch(module.exports.setFetchStatus('parent', module.exports.Status.FETCHED)); + dispatch(module.exports.setParentInfo(body)); }); }); diff --git a/src/views/preview/presentation.jsx b/src/views/preview/presentation.jsx index b4f5f0165..1e2832831 100644 --- a/src/views/preview/presentation.jsx +++ b/src/views/preview/presentation.jsx @@ -12,6 +12,7 @@ const IntlGUI = injectIntl(GUI); const sessionActions = require('../../redux/session.js'); const decorateText = require('../../lib/decorate-text.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); +const Button = require('../../components/forms/button.jsx'); const Avatar = require('../../components/avatar/avatar.jsx'); const CappedNumber = require('../../components/cappednumber/cappednumber.jsx'); const ShareBanner = require('../../components/share-banner/share-banner.jsx'); @@ -22,7 +23,6 @@ require('./preview.scss'); const PreviewPresentation = props => { const { - creditInfo, editable, faved, favoriteCount, @@ -30,6 +30,8 @@ const PreviewPresentation = props => { isFullScreen, loved, loveCount, + originalInfo, + parentInfo, projectId, projectInfo, remixes, @@ -45,16 +47,19 @@ const PreviewPresentation = props => { const shareDate = (projectInfo.history && projectInfo.history.shared) ? projectInfo.history.shared : ''; return (
- - - - This project is not shared — so only you can see it. Click share to let everyone see it! - - - - + {projectInfo.history && shareDate === '' && + + + + This project is not shared — so only you can see it. Click share to let everyone see it! + + + + + } + { projectInfo && projectInfo.author && projectInfo.author.id && (
@@ -94,84 +99,129 @@ const PreviewPresentation = props => { {sessionStatus === sessionActions.Status.FETCHED && Object.keys(user).length > 0 && user.id !== projectInfo.author.id && - + } - +
- +
+ +
- {shareDate && ( -
-
©
- {' '} - {/* eslint-disable react/jsx-sort-props */} - - {/* eslint-enable react/jsx-sort-props */} -
- )} - {creditInfo && creditInfo.author && creditInfo.id && ( + {parentInfo && parentInfo.author && parentInfo.id && ( - ) - } - {editable ? - : -
- {decorateText(projectInfo.description)} + )} + {originalInfo && originalInfo.author && originalInfo.id && ( + + + + + )} + + +
+ Instructions
- } + {editable ? + : +
+ {decorateText(projectInfo.instructions)} +
+ } +
+ +
+ Notes and Credits +
+ {editable ? + : +
+ {decorateText(projectInfo.description)} +
+ } +
@@ -203,23 +253,36 @@ const PreviewPresentation = props => {
- - -
  • + +
    +
    ©
    + {' '} + {/* eslint-disable react/jsx-sort-props */} + {shareDate === null ? + 'Unshared' : + + } + {/* eslint-enable react/jsx-sort-props */} +
    + + +
  • -
    - -
  • - Social -
  • -
    - -
  • + + +
  • -
    + +
    +
    @@ -275,7 +338,38 @@ const PreviewPresentation = props => { }; PreviewPresentation.propTypes = { - creditInfo: PropTypes.shape({ + editable: PropTypes.bool, + faved: PropTypes.bool, + favoriteCount: PropTypes.number, + intl: intlShape, + isFullScreen: PropTypes.bool, + loveCount: PropTypes.number, + loved: PropTypes.bool, + onFavoriteClicked: PropTypes.func, + onLoveClicked: PropTypes.func, + onSeeInside: PropTypes.func, + onUpdate: PropTypes.func, + originalInfo: PropTypes.shape({ + id: PropTypes.number, + title: PropTypes.string, + description: PropTypes.string, + author: PropTypes.shape({id: PropTypes.number}), + history: PropTypes.shape({ + created: PropTypes.string, + modified: PropTypes.string, + shared: PropTypes.string + }), + stats: PropTypes.shape({ + views: PropTypes.number, + loves: PropTypes.number, + favorites: PropTypes.number + }), + remix: PropTypes.shape({ + parent: PropTypes.number, + root: PropTypes.number + }) + }), + parentInfo: PropTypes.shape({ id: PropTypes.number, title: PropTypes.string, description: PropTypes.string, diff --git a/src/views/preview/preview.jsx b/src/views/preview/preview.jsx index 1c68caf84..fe0ac2b9e 100644 --- a/src/views/preview/preview.jsx +++ b/src/views/preview/preview.jsx @@ -53,8 +53,13 @@ class Preview extends React.Component { if (this.props.projectInfo.id !== prevProps.projectInfo.id) { this.initCounts(this.props.projectInfo.stats.favorites, this.props.projectInfo.stats.loves); this.handlePermissions(); - if (this.props.projectInfo.remix.root !== null) { - this.props.getCreditInfo(this.props.projectInfo.remix.root); + if (this.props.projectInfo.remix.parent !== null) { + this.props.getParentInfo(this.props.projectInfo.remix.parent); + } + if (this.props.projectInfo.remix.root !== null && + this.props.projectInfo.remix.root !== this.props.projectInfo.remix.parent + ) { + this.props.getOriginalInfo(this.props.projectInfo.remix.root); } } if (this.props.playerMode !== prevProps.playerMode || this.props.fullScreen !== prevProps.fullScreen) { @@ -179,13 +184,14 @@ class Preview extends React.Component { ({ projectInfo: state.preview.projectInfo, - credit: state.preview.credit, comments: state.preview.comments, faved: state.preview.faved, loved: state.preview.loved, + original: state.preview.original, + parent: state.preview.parent, remixes: state.preview.remixes, sessionStatus: state.session.status, studios: state.preview.studios, @@ -306,8 +344,11 @@ const mapStateToProps = state => ({ const mapDispatchToProps = dispatch => ({ - getCreditInfo: id => { - dispatch(previewActions.getCreditInfo(id)); + getOriginalInfo: id => { + dispatch(previewActions.getOriginalInfo(id)); + }, + getParentInfo: id => { + dispatch(previewActions.getParentInfo(id)); }, getProjectInfo: (id, token) => { dispatch(previewActions.getProjectInfo(id, token)); @@ -333,8 +374,11 @@ const mapDispatchToProps = dispatch => ({ refreshSession: () => { dispatch(sessionActions.refreshSession()); }, - setCreditInfo: info => { - dispatch(previewActions.setCreditInfo(info)); + setOriginalInfo: info => { + dispatch(previewActions.setOriginalInfo(info)); + }, + setParentInfo: info => { + dispatch(previewActions.setParentInfo(info)); }, updateProject: (id, formData, username, token) => { dispatch(previewActions.updateProject(id, formData, username, token)); diff --git a/src/views/preview/preview.scss b/src/views/preview/preview.scss index 921749f8d..d5eb834fd 100644 --- a/src/views/preview/preview.scss +++ b/src/views/preview/preview.scss @@ -1,6 +1,15 @@ @import "../../colors"; @import "../../frameless"; +/* stage size contants + * this is a hack right now - stage includes padding of .5rem (8px) for alignment in gui + * in www the player is placed with margin -.5rem to align the edge. + * the height is calculated from the actual height on the page (404) - .5rem +*/ +$gui-width: 496px; +$stage-width: 480px; +$stage-height: 406px; + /* override view padding for share banner */ #view { padding: 0 0 20px 0; @@ -15,8 +24,6 @@ height: 100%; } -// .gui * { box-sizing: border-box; } - .preview { .project-title { @@ -137,7 +144,7 @@ background-color: $ui-orange; &:before { - background-image: url("/svgs/favorite/favorite_type-gray.svg"); + background-image: url("/svgs/project/share-white.svg"); } } @@ -145,14 +152,14 @@ background-color: $ui-green; &:before { - background-image: url("/svgs/remix/remix_type-gray.svg"); + background-image: url("/svgs/project/remix-white.svg"); } } .see-inside-button { &:before { - background-image: url("/images/emoji/cool-cat.png"); + background-image: url("/svgs/project/see-inside-white.svg"); } } @@ -164,19 +171,30 @@ .guiPlayer { display: inline-block; - width: 480px; + width: $gui-width; + margin-left: -.5rem; } .project-notes { - width: 45%; - height: 404px; + height: $stage-height; + flex: 1; + // not 1.5rem because of stage padding + margin-left: 1rem; + margin-bottom: .75rem; flex-flow: column; - align-items: left; + align-items: flex-start; } .share-date { - height: 2.5rem; vertical-align: middle; + font-size: .875rem; + color: $type-gray; + } + + .subactions { + justify-content: space-between; + flex: 1; + margin-left: 1.5rem; } .remix-credit { @@ -185,7 +203,7 @@ border-radius: 8px; background-color: $ui-blue-10percent; padding: .5rem; - width: 100%; + width: calc(100% - 1rem); flex-wrap: nowrap; align-items: flex-start; } @@ -194,8 +212,37 @@ font-size: .875rem; flex-shrink: 1; } + + .description-block { + flex-direction: column; + align-items: flex-start; + width: 100%; + flex-grow: 1; + } + + .project-textlabel { + font-weight: bold; + margin: 0 0 .5rem 0; + } .project-description { + border: 1px solid $ui-blue-10percent; + border-radius: 8px; + background-color: $ui-blue-10percent; + padding: .5rem; + width: calc(100% - (1rem + 2px)); + margin-bottom: .75rem; + white-space: pre-line; + overflow-y: auto; + // flex-grow + flex: 1; + } + + .project-description.last { + margin-bottom: 0; + } + + .project-description-edit { border: 1px solid $ui-blue-10percent; border-radius: 8px; background-color: $ui-blue-10percent; @@ -203,13 +250,14 @@ width: 100%; white-space: pre-line; overflow-y: scroll; + // flex-grow flex: 1; &.textarea-row { border: 0; background-color: inherit; padding: 0; - overflow: visible; + overflow: hidden; } &.has-error { @@ -217,6 +265,14 @@ transform: translate(26rem, 0); } } + + .inplace-textarea { + height: 172px; + } + } + + .project-description-edit.remixes .inplace-textarea { + height: 130px; } .copyleft { @@ -227,7 +283,7 @@ } .stats { - width: 480px; + width: $stage-width; justify-content: flex-start; } @@ -258,14 +314,14 @@ cursor: pointer; &:before { - background-image: url("/svgs/love/love_type-gray.svg"); + background-image: url("/svgs/project/love-gray.svg"); } } .project-loves.loved { &:before { - background-image: url("/svgs/messages/love.svg"); + background-image: url("/svgs/project/love-red.svg"); } } @@ -274,85 +330,119 @@ cursor: pointer; &:before { - background-image: url("/svgs/favorite/favorite_type-gray.svg"); + background-image: url("/svgs/project/fav-gray.svg"); } } .project-favorites.favorited { &:before { - background-image: url("/svgs/messages/favorite.svg"); + background-image: url("/svgs/project/fav-yellow.svg"); } } .project-remixes { &:before { - background-image: url("/svgs/remix/remix_type-gray.svg"); + background-image: url("/svgs/project/remix-gray.svg"); } } .project-views { &:before { - background-image: url("/svgs/view/view_type-gray.svg"); + background-image: url("/svgs/project/views-gray.svg"); } } .action-buttons { display: flex; - width: 40%; color: $type-white; font-size: .8rem; font-weight: 500; justify-content: flex-end; flex-wrap: wrap; + } + + .action-button { + margin-left: .5rem; + height: 2rem; + border-radius: 19px; + background-color: $ui-blue; + padding: 0 .5rem; + text-decoration: none; + font-size: .75rem; + line-height: .875rem; + font-weight: normal; + - - li { + // &:hover { + // transition: background-color .25s ease; + // border-color: transparent; + // background-color: $active-gray; + // } + // + // &:active { + // border: 0 solid transparent; + // box-shadow: inset 0 0 5px $box-shadow-gray; + // background-color: $active-dark-gray; + // padding: calc(.75em + 1px) calc(1.5em + 1px); + // } + // + // &.report { + // border: 1px solid $ui-coral; + // background-color: $ui-coral; + // + // &:hover { + // transition: background-color .25s ease; + // border-color: transparent; + // background-color: $active-gray; + // } + // + // &:active { + // border: 0 solid transparent; + // box-shadow: inset 0 0 5px $box-shadow-gray; + // background-color: $active-dark-gray; + // padding: calc(.75em + 1px) calc(1.5em + 1px); + // } + // } + } + + .studio-button, + .copy-link-button, + .report-button { + &:before { display: inline-block; - margin: 0 5px; - border: 1px solid $ui-blue; - border-radius: 50px; - background-color: $ui-blue; - padding: .5em .75em .5em 1.5em; - text-decoration: none; - color: $type-white; - list-style-type: none; - - &:hover { - transition: background-color .25s ease; - border-color: transparent; - background-color: $active-gray; - } - - &:active { - border: 0 solid transparent; - box-shadow: inset 0 0 5px $box-shadow-gray; - background-color: $active-dark-gray; - padding: calc(.75em + 1px) calc(1.5em + 1px); - } - - &.report { - border: 1px solid $ui-coral; - background-color: $ui-coral; - - &:hover { - transition: background-color .25s ease; - border-color: transparent; - background-color: $active-gray; - } - - &:active { - border: 0 solid transparent; - box-shadow: inset 0 0 5px $box-shadow-gray; - background-color: $active-dark-gray; - padding: calc(.75em + 1px) calc(1.5em + 1px); - } - } + margin-right: .125rem; + background-repeat: no-repeat; + background-position: center center; + background-size: contain; + width: 1rem; + height: 1rem; + vertical-align: bottom; + content: ""; + } + } + .studio-button { + &:before { + background-image: url("/svgs/project/studio-add-white.svg"); } } + .copy-link-button { + &:before { + background-image: url("/svgs/project/copy-link-white.svg"); + } + } + + .report-button { + background-color: $ui-coral; + + &:before { + background-image: url("/svgs/project/report-white.svg"); + } + } + .remix-list, .studio-list { flex-direction: column; diff --git a/static/svgs/project/copy-link-gray.svg b/static/svgs/project/copy-link-gray.svg new file mode 100644 index 000000000..6e4571720 --- /dev/null +++ b/static/svgs/project/copy-link-gray.svg @@ -0,0 +1,10 @@ + + + + copy-link-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/copy-link-white.svg b/static/svgs/project/copy-link-white.svg new file mode 100644 index 000000000..b175b51d6 --- /dev/null +++ b/static/svgs/project/copy-link-white.svg @@ -0,0 +1,10 @@ + + + + copy-link-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/delete-gray.svg b/static/svgs/project/delete-gray.svg new file mode 100644 index 000000000..a13aef811 --- /dev/null +++ b/static/svgs/project/delete-gray.svg @@ -0,0 +1,17 @@ + + + + delete-gray + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/static/svgs/project/fav-gray.svg b/static/svgs/project/fav-gray.svg new file mode 100644 index 000000000..40fff7b6d --- /dev/null +++ b/static/svgs/project/fav-gray.svg @@ -0,0 +1,10 @@ + + + + fav-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/fav-yellow.svg b/static/svgs/project/fav-yellow.svg new file mode 100644 index 000000000..32c1c25d0 --- /dev/null +++ b/static/svgs/project/fav-yellow.svg @@ -0,0 +1,10 @@ + + + + fav-yellow + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/love-gray.svg b/static/svgs/project/love-gray.svg new file mode 100644 index 000000000..fe6a0ec3d --- /dev/null +++ b/static/svgs/project/love-gray.svg @@ -0,0 +1,10 @@ + + + + love-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/love-red.svg b/static/svgs/project/love-red.svg new file mode 100644 index 000000000..c1e9457cf --- /dev/null +++ b/static/svgs/project/love-red.svg @@ -0,0 +1,10 @@ + + + + love-red + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/remix-gray.svg b/static/svgs/project/remix-gray.svg new file mode 100644 index 000000000..0701630be --- /dev/null +++ b/static/svgs/project/remix-gray.svg @@ -0,0 +1,10 @@ + + + + remix-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/remix-white.svg b/static/svgs/project/remix-white.svg new file mode 100644 index 000000000..a82c1bf6d --- /dev/null +++ b/static/svgs/project/remix-white.svg @@ -0,0 +1,10 @@ + + + + remix-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/report-gray.svg b/static/svgs/project/report-gray.svg new file mode 100644 index 000000000..3e16a28d3 --- /dev/null +++ b/static/svgs/project/report-gray.svg @@ -0,0 +1,10 @@ + + + + report-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/report-white.svg b/static/svgs/project/report-white.svg new file mode 100644 index 000000000..e3ac6b7bb --- /dev/null +++ b/static/svgs/project/report-white.svg @@ -0,0 +1,10 @@ + + + + report-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/restore-gray.svg b/static/svgs/project/restore-gray.svg new file mode 100644 index 000000000..724a2aae1 --- /dev/null +++ b/static/svgs/project/restore-gray.svg @@ -0,0 +1,10 @@ + + + + restore-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/revised-date-gray.svg b/static/svgs/project/revised-date-gray.svg new file mode 100644 index 000000000..6f9decfeb --- /dev/null +++ b/static/svgs/project/revised-date-gray.svg @@ -0,0 +1,13 @@ + + + + revised-date-gray + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/static/svgs/project/scripts-gray.svg b/static/svgs/project/scripts-gray.svg new file mode 100644 index 000000000..92551136a --- /dev/null +++ b/static/svgs/project/scripts-gray.svg @@ -0,0 +1,10 @@ + + + + scripts-gray + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/see-inside-white.svg b/static/svgs/project/see-inside-white.svg new file mode 100644 index 000000000..104cbd330 --- /dev/null +++ b/static/svgs/project/see-inside-white.svg @@ -0,0 +1,10 @@ + + + + see-inside-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/share-white.svg b/static/svgs/project/share-white.svg new file mode 100644 index 000000000..f1ae61a59 --- /dev/null +++ b/static/svgs/project/share-white.svg @@ -0,0 +1,10 @@ + + + + share-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/studio-add-white.svg b/static/svgs/project/studio-add-white.svg new file mode 100644 index 000000000..35142d5c9 --- /dev/null +++ b/static/svgs/project/studio-add-white.svg @@ -0,0 +1,10 @@ + + + + studio-add-white + Created with Sketch. + + + + + \ No newline at end of file diff --git a/static/svgs/project/views-gray.svg b/static/svgs/project/views-gray.svg new file mode 100644 index 000000000..e159580e4 --- /dev/null +++ b/static/svgs/project/views-gray.svg @@ -0,0 +1,13 @@ + + + + views-gray + Created with Sketch. + + + + + + + + \ No newline at end of file From 34042c9e8e7c5ae0754fbd68e659d1ef9a025c28 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Thu, 24 May 2018 13:47:31 -0400 Subject: [PATCH 2/8] Report first pass Report button opens a modal with the report project form. All the content is currently in `preview/presentation` because components cannot have their own l10n files. --- src/_colors.scss | 5 +- src/components/modal/report/modal.jsx | 34 ++ src/components/modal/report/modal.scss | 41 ++ src/views/preview/presentation.jsx | 784 +++++++++++++++---------- src/views/preview/preview.jsx | 35 +- src/views/preview/preview.scss | 5 + 6 files changed, 568 insertions(+), 336 deletions(-) create mode 100644 src/components/modal/report/modal.jsx create mode 100644 src/components/modal/report/modal.scss diff --git a/src/_colors.scss b/src/_colors.scss index f1fcf7fa5..9dd1d0e89 100644 --- a/src/_colors.scss +++ b/src/_colors.scss @@ -18,8 +18,9 @@ $ui-border: hsla(0, 0, 85, 1); //#D9D9D9 /* 3.0 colors */ /* Using www naming convention for now, should be consistent with gui */ -$ui-green: hsla(163, 83, 40, 1); //#0fbd8c Pen Primary -$ui-coral: hsla(350, 100, 70, 1); //#FF6680 More Priamry +$ui-green: hsla(163, 83, 40, 1); // #0fbd8c Pen Primary +$ui-coral: hsla(350, 100, 70, 1); // #FF6680 More Primary +$ui-coral-dark: hsla(350, 100, 60, 1); // #FF3355 More tertiary $ui-blue-10percent: hsla(215, 100, 65, .1); $ui-orange-25percent: hsla(35, 90, 55, .25); diff --git a/src/components/modal/report/modal.jsx b/src/components/modal/report/modal.jsx new file mode 100644 index 000000000..840b123e8 --- /dev/null +++ b/src/components/modal/report/modal.jsx @@ -0,0 +1,34 @@ +const PropTypes = require('prop-types'); +const React = require('react'); +const Modal = require('../base/modal.jsx'); + +require('../../forms/button.scss'); +require('./modal.scss'); + +const ReportModal = props => ( + +
    +
    +
    + {props.contentLabel} +
    +
    + +
    + {props.children} +
    +
    + +
    +); + +ReportModal.propTypes = { + children: PropTypes.node, + contentLabel: PropTypes.string, + onRequestClose: PropTypes.func +}; + +module.exports = ReportModal; diff --git a/src/components/modal/report/modal.scss b/src/components/modal/report/modal.scss new file mode 100644 index 000000000..df9cb3149 --- /dev/null +++ b/src/components/modal/report/modal.scss @@ -0,0 +1,41 @@ +@import "../../../colors"; +@import "../../../frameless"; + +.mod-report * { + box-sizing: border-box; +} + +.mod-report { + margin: 100px auto; + width: 30rem; + outline: none; + padding: 0; + user-select: none; + + overflow: hidden; +} + +.report-modal-header { + height: 3rem; + padding-top: .75rem; + + box-sizing: border-box; + width: 100%; + background-color: $ui-coral; + box-shadow: inset 0 -1px 0 0 $ui-coral-dark; +} + +.report-content-label { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 1rem; + font-weight: bold; + color: $type-white; + text-align: center; +} + +.report-modal-content { + width: 80%; + margin: 1rem auto; + font-size: .875rem; + line-height: 1.5rem; +} diff --git a/src/views/preview/presentation.jsx b/src/views/preview/presentation.jsx index 1e2832831..a468d228f 100644 --- a/src/views/preview/presentation.jsx +++ b/src/views/preview/presentation.jsx @@ -1,3 +1,4 @@ +const bindAll = require('lodash.bindall'); const FormattedDate = require('react-intl').FormattedDate; const injectIntl = require('react-intl').injectIntl; const intlShape = require('react-intl').intlShape; @@ -13,329 +14,499 @@ const sessionActions = require('../../redux/session.js'); const decorateText = require('../../lib/decorate-text.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); const Button = require('../../components/forms/button.jsx'); +const Form = require('../../components/forms/form.jsx'); +const Input = require('../../components/forms/input.jsx'); +const Select = require('../../components/forms/select.jsx'); +const Spinner = require('../../components/spinner/spinner.jsx'); +const TextArea = require('../../components/forms/textarea.jsx'); const Avatar = require('../../components/avatar/avatar.jsx'); const CappedNumber = require('../../components/cappednumber/cappednumber.jsx'); const ShareBanner = require('../../components/share-banner/share-banner.jsx'); const ThumbnailColumn = require('../../components/thumbnailcolumn/thumbnailcolumn.jsx'); const InplaceInput = require('../../components/forms/inplace-input.jsx'); +const ReportModal = require('../../components/modal/report/modal.jsx'); + require('./preview.scss'); -const PreviewPresentation = props => { - const { - editable, - faved, - favoriteCount, - intl, - isFullScreen, - loved, - loveCount, - originalInfo, - parentInfo, - projectId, - projectInfo, - remixes, - sessionStatus, - studios, - user, - onFavoriteClicked, - onLoveClicked, - onSeeInside, - onUpdate - // ...otherProps TBD - } = props; - const shareDate = (projectInfo.history && projectInfo.history.shared) ? projectInfo.history.shared : ''; - return ( -
    - {projectInfo.history && shareDate === '' && - - - - This project is not shared — so only you can see it. Click share to let everyone see it! - - - - - } - - { projectInfo && projectInfo.author && projectInfo.author.id && ( -
    - +class PreviewPresentation extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleReportClick', + 'handleReportClose', + 'handleReportReasonSelect', + 'handleReportSubmit' + ]); + this.state = { + reportOpen: false, + reportPrompt: 'Select a reason why above.', + reportReason: '' + }; + } + handleReportClick (e) { + e.preventDefault(); + this.setState({reportOpen: true}); + } + handleReportClose () { + this.setState({reportOpen: false}); + } + handleReportReasonSelect (name, value) { + const prompts = [ + 'Please provide a link to the original project', + 'Please provide links to the uncredited content', + 'Please say why the project is too violent or scary', + 'Please say where the inappropriate language occurs in the project (For example: Notes & Credits, sprite name, project text, etc.)', + 'Please say the name of the audio file with the inappropriate music', + 'Please say where the personal contact information is shared (For example: Notes & Credits, sprite name, project text, etc.)', + 'Please be specific about why this project does not follow our Community Guidelines', + 'not used', + 'Please say the name of the sprite or the backdrop with the inappropriate image' + ]; + this.setState({reportPrompt: prompts[value]}); + } + handleReportSubmit (formData) { + console.log('submit report data', formData); + this.setState({reportOpen: false}); + } + render () { + const { + editable, + faved, + favoriteCount, + intl, + isFullScreen, + loved, + loveCount, + originalInfo, + parentInfo, + projectId, + projectInfo, + remixes, + sessionStatus, + studios, + user, + onFavoriteClicked, + onLoveClicked, + onSeeInside, + onUpdate + // ...otherProps TBD + } = this.props; + const shareDate = (projectInfo.history && projectInfo.history.shared) ? projectInfo.history.shared : ''; + return ( +
    + {projectInfo.history && shareDate === '' && + - - -
    - {editable ? - - : -
    {projectInfo.title}
    + + This project is not shared — so only you can see it. Click share to let everyone see it! + + + + + } + + { projectInfo && projectInfo.author && projectInfo.author.id && ( +
    + + + + +
    + {editable ? + + : +
    {projectInfo.title}
    + } + {`${intl.formatMessage({id: 'thumbnail.by'})} `} + + {projectInfo.author.username} + +
    +
    +
    + {sessionStatus === sessionActions.Status.FETCHED && + Object.keys(user).length > 0 && + user.id !== projectInfo.author.id && + } - {`${intl.formatMessage({id: 'thumbnail.by'})} `} - - {projectInfo.author.username} - -
    -
    -
    - {sessionStatus === sessionActions.Status.FETCHED && - Object.keys(user).length > 0 && - user.id !== projectInfo.author.id && - - } - -
    - - -
    - -
    - - {parentInfo && parentInfo.author && parentInfo.id && ( - - -
    - Thanks to - {parentInfo.author.username} - for the original project - {parentInfo.title} - . -
    -
    - )} - {originalInfo && originalInfo.author && originalInfo.id && ( - - - - - )} - - -
    - Instructions -
    - {editable ? - : -
    - {decorateText(projectInfo.instructions)} -
    - } -
    - -
    - Notes and Credits -
    - {editable ? - : -
    - {decorateText(projectInfo.description)} -
    - } -
    -
    -
    - - -
    - {loveCount} -
    -
    - {favoriteCount} -
    -
    - {projectInfo.remix.count} -
    -
    -
    - -
    -
    ©
    - {' '} - {/* eslint-disable react/jsx-sort-props */} - {shareDate === null ? - 'Unshared' : - - } - {/* eslint-enable react/jsx-sort-props */} + +
    +
    + + {parentInfo && parentInfo.author && parentInfo.id && ( + + +
    + Thanks to + {parentInfo.author.username} + for the original project + {parentInfo.title} + . +
    +
    + )} + {originalInfo && originalInfo.author && originalInfo.id && ( + + + + + )} + + +
    + Instructions +
    + {editable ? + : +
    + {decorateText(projectInfo.instructions)} +
    + } +
    + +
    + Notes and Credits +
    + {editable ? + : +
    + {decorateText(projectInfo.description)} +
    + } +
    +
    +
    + + +
    + {loveCount} +
    +
    + {favoriteCount} +
    +
    + {projectInfo.remix.count} +
    +
    + +
    +
    + +
    +
    ©
    + {' '} + {/* eslint-disable react/jsx-sort-props */} + {shareDate === null ? + 'Unshared' : + + } + {/* eslint-enable react/jsx-sort-props */} +
    - - - - + + + + { + sessionStatus === sessionActions.Status.FETCHED && + Object.keys(user).length > 0 && + user.id !== projectInfo.author.id && [ + , + + From the dropdown below, please select the reason why you feel this project is disrespectful or inappropriate or otherwise breaks the Scratch Community Guidelines. +
    + + +