Commit 6872cfc5 authored by chrisgarrity's avatar chrisgarrity

FIxing PR #1900 comments

addresses most comments except modal refactor, and error response from sumitting report.
* restore gui as a dev dependency
* better separation of view container/presentation
* replace absolute heights for textareas with making all sub components `display: flex`
* start to make presentation more modular added subcomponents to the view folder:
  * share-banner (moved from components)
  * remix-credit
  * remix-list
  * studio-list
parent 5124c613
......@@ -38,6 +38,8 @@ class InplaceInput extends React.Component {
<FRCTextarea
className="inplace-textarea"
componentRef={this.setRef}
elementWrapperClassName="grow"
label={null}
rowClassName={classNames('textarea-row no-label', className)}
onBlur={this.handleBlur}
{...props}
......
const classNames = require('classnames');
const PropTypes = require('prop-types');
const React = require('react');
require('./share-banner.scss');
const ShareBanner = props => (
<div className={classNames('shareBanner', props.className)}>
<div className="inner">
{props.children}
</div>
</div>
);
ShareBanner.propTypes = {
children: PropTypes.node,
className: PropTypes.string
};
module.exports = ShareBanner;
@import "../../colors";
$navigation-height: 50px;
.shareBanner {
background-color: $ui-orange-25percent;
width: 100%;
overflow: hidden;
color: $ui-orange;
}
......@@ -14,7 +14,7 @@ const ThumbnailColumn = props => (
if (props.itemType === 'preview') {
return (
<Thumbnail
avatar={`https://cdn2.scratch.mit.edu/get_image/user/${item.author.i}_32x32.png`}
avatar={`https://cdn2.scratch.mit.edu/get_image/user/${item.author.id}_32x32.png`}
creator={item.author.username}
favorites={item.stats.favorites}
href={href}
......
This diff is collapsed.
......@@ -24,12 +24,28 @@ class Preview extends React.Component {
'handleLoveToggle',
'handlePermissions',
'handlePopState',
'handleReportClick',
'handleReportClose',
'handleReportSubmit',
'handleSeeInside',
'handleUpdate',
'initCounts',
'pushHistory'
'isShared',
'pushHistory',
'userOwnsProject'
]);
this.state = this.initState();
const pathname = window.location.pathname.toLowerCase();
const parts = pathname.split('/').filter(Boolean);
// parts[0]: 'preview'
// parts[1]: either :id or 'editor'
// parts[2]: undefined if no :id, otherwise either 'editor' or 'fullscreen'
this.state = {
editable: false,
favoriteCount: 0,
loveCount: 0,
projectId: parts[1] === 'editor' ? 0 : parts[1],
reportOpen: false
};
this.addEventListeners();
}
componentDidUpdate (prevProps) {
......@@ -89,6 +105,21 @@ class Preview extends React.Component {
removeEventListeners () {
window.removeEventListener('popstate', this.handlePopState);
}
handleReportClick () {
this.setState({reportOpen: true});
}
handleReportClose () {
this.setState({reportOpen: false});
}
handleReportSubmit (formData) {
const data = {
...formData,
id: this.state.projectId,
username: this.props.user.username
};
console.log('submit report data', data); // eslint-disable-line no-console
this.setState({reportOpen: false});
}
handlePopState () {
const path = window.location.pathname.toLowerCase();
const playerMode = path.indexOf('editor') === -1;
......@@ -179,6 +210,23 @@ class Preview extends React.Component {
loveCount: loves
});
}
isShared () {
return (
// if we don't have projectInfo assume shared until we know otherwise
Object.keys(this.props.projectInfo).length === 0 || (
this.props.projectInfo.history &&
this.props.projectInfo.history.shared.length > 0
)
);
}
userOwnsProject () {
return (
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length > 0 &&
Object.keys(this.props.projectInfo).length > 0 &&
this.props.user.id === this.props.projectInfo.author.id
);
}
render () {
return (
this.props.playerMode ?
......@@ -189,6 +237,8 @@ class Preview extends React.Component {
faved={this.props.faved}
favoriteCount={this.state.favoriteCount}
isFullScreen={this.state.isFullScreen}
isReportOpen={this.state.reportOpen}
isShared={this.isShared()}
loveCount={this.state.loveCount}
loved={this.props.loved}
originalInfo={this.props.original}
......@@ -196,11 +246,14 @@ class Preview extends React.Component {
projectId={this.state.projectId}
projectInfo={this.props.projectInfo}
remixes={this.props.remixes}
sessionStatus={this.props.sessionStatus}
studios={this.props.studios}
user={this.props.user}
userOwnsProject={this.userOwnsProject()}
onFavoriteClicked={this.handleFavoriteToggle}
onLoveClicked={this.handleLoveToggle}
onReportClicked={this.handleReportClick}
onReportClose={this.handleReportClose}
onReportSubmit={this.handleReportSubmit}
onSeeInside={this.handleSeeInside}
onUpdate={this.handleUpdate}
/>
......
@import "../../colors";
@import "../../frameless";
/* stage size contants
/* stage size constants
* 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)
......@@ -10,13 +10,6 @@ $gui-width: 496px;
$stage-width: 480px;
$stage-height: 404px;
// remix credit height: 52px
// project text label line-height + margin-bottom .5rem: 19px + 8px = 27px
// Formsy wrapper adds 3px to the input height for
$description-input: 166px; // $stage-height / 2 - $project-label - $wrapper - margin
$description-input-small: 120px; // normal $description-input - $remix-credit
/* override view padding for share banner */
#view {
padding: 0 0 20px 0;
......@@ -138,7 +131,6 @@ $description-input-small: 120px; // normal $description-input - $remix-credit
width: 60%;
}
.share-button,
.remix-button,
.see-inside-button {
margin-top: 0;
......@@ -158,18 +150,6 @@ $description-input-small: 120px; // normal $description-input - $remix-credit
}
}
.shareText {
align-self: center;
}
.share-button {
background-color: $ui-orange;
&:before {
background-image: url("/svgs/project/share-white.svg");
}
}
.remix-button {
background-color: $ui-green;
......@@ -267,6 +247,7 @@ $description-input-small: 120px; // normal $description-input - $remix-credit
}
.project-description-edit {
display: flex;
margin-bottom: .75rem;
border: 1px solid $ui-blue-10percent;
border-radius: 8px;
......@@ -293,15 +274,12 @@ $description-input-small: 120px; // normal $description-input - $remix-credit
}
}
.inplace-textarea {
height: $description-input;
& > .grow {
display: flex;
flex: 1;
}
}
.project-description-edit.remixes .inplace-textarea {
height: $description-input-small;
}
.copyleft {
display: inline-block;
transform: scale(-1, 1);
......
const React = require('react');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Avatar = require('../../components/avatar/avatar.jsx');
const projectShape = require('./projectshape.jsx').projectShape;
const RemixCredit = props => {
const projectInfo = props.projectInfo;
if (Object.keys(projectInfo).length === 0) return null;
return (
<FlexRow className="remix-credit">
<Avatar
className="remix"
src={`https://cdn2.scratch.mit.edu/get_image/user/${projectInfo.author.id}_48x48.png`}
/>
<div className="credit-text">
Thanks to <a
href={`/users/${projectInfo.author.username}`}
>
{projectInfo.author.username}
</a> for the original project <a
href={`/preview/${projectInfo.id}`}
>
{projectInfo.title}
</a>.
</div>
</FlexRow>
);
};
RemixCredit.propTypes = {
projectInfo: projectShape
};
module.exports = RemixCredit;
const React = require('react');
const PropTypes = require('prop-types');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const ThumbnailColumn = require('../../components/thumbnailcolumn/thumbnailcolumn.jsx');
const projectShape = require('./projectshape.jsx').projectShape;
const RemixList = props => {
const remixes = props.remixes;
if (remixes.length === 0) return null;
return (
<FlexRow className="remix-list">
<div className="project-title">
Remixes
</div>
{remixes.length === 0 ? (
// TODO: style remix invitation
<span>Invite user to remix</span>
) : (
<ThumbnailColumn
cards
showAvatar
itemType="preview"
items={remixes.slice(0, 5)}
showFavorites={false}
showLoves={false}
showViews={false}
/>
)}
</FlexRow>
);
};
RemixList.propTypes = {
remixes: PropTypes.arrayOf(projectShape)
};
module.exports = RemixList;
const PropTypes = require('prop-types');
const React = require('react');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Button = require('../../components/forms/button.jsx');
require('./share-banner.scss');
const ShareBanner = props => {
if (props.shared) return null;
return (
<div className="shareBanner">
<div className="inner">
<FlexRow className="preview-row">
<span className="share-text">
This project is not shared — so only you can see it. Click share to let everyone see it!
</span>
<Button className="button share-button">
Share
</Button>
</FlexRow>
</div>
</div>
);
};
ShareBanner.propTypes = {
shared: PropTypes.bool.isRequired
};
module.exports = ShareBanner;
@import "../../colors";
$navigation-height: 50px;
.shareBanner {
background-color: $ui-orange-25percent;
width: 100%;
overflow: hidden;
color: $ui-orange;
}
.share-button {
margin-top: 0;
background-color: $ui-orange;
font-size: .875rem;
font-weight: normal;
&:before {
display: inline-block;
margin-right: .5rem;
background-image: url("/svgs/project/share-white.svg");
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
width: 1.25rem;
height: 1.25rem;
vertical-align: middle;
content: "";
}
}
const React = require('react');
const PropTypes = require('prop-types');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const ThumbnailColumn = require('../../components/thumbnailcolumn/thumbnailcolumn.jsx');
const projectShape = require('./projectshape.jsx').projectShape;
const StudioList = props => {
const studios = props.studios;
if (studios.length === 0) return null;
return (
<FlexRow className="remix-list">
<div className="project-title">
Studios
</div>
{studios.length === 0 ? (
// TODO: style remix invitation
<span>Invite user to add to studio</span>
) : (
<ThumbnailColumn
cards
showAvatar
itemType="studio"
items={studios.slice(0, 5)}
showFavorites={false}
showLoves={false}
showViews={false}
/>
)}
</FlexRow>
);
};
StudioList.propTypes = {
studios: PropTypes.arrayOf(projectShape)
};
module.exports = StudioList;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment