mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-29 18:46:20 -05:00
Initial GUI embed (#1869)
- `/preview/editor` will load GUI with an empty project - `/preview/:id/editor` will load GUI with a project from the projects server (not local data) - passes intl object to GUI - `/preview/:id` with show the project page with an embedded player - `/preview/:id/fullscreen` will load the project page with the player in fullscreen mode. * Note that we needed to Increase memory for the build to avoid running out of heap space, and build time increases by about 2 minutes
This commit is contained in:
parent
04e27ec02a
commit
d1420862ea
7 changed files with 129 additions and 64 deletions
6
Makefile
6
Makefile
|
@ -1,10 +1,10 @@
|
||||||
ESLINT=./node_modules/.bin/eslint
|
ESLINT=./node_modules/.bin/eslint
|
||||||
NODE=node
|
NODE= NODE_OPTIONS=--max_old_space_size=8000 node
|
||||||
SASSLINT=./node_modules/.bin/sass-lint -v
|
SASSLINT=./node_modules/.bin/sass-lint -v
|
||||||
S3CMD=s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600
|
S3CMD=s3cmd sync -P --delete-removed --add-header=Cache-Control:no-cache,public,max-age=3600
|
||||||
TAP=./node_modules/.bin/tap
|
TAP=./node_modules/.bin/tap
|
||||||
WATCH=./node_modules/.bin/watch
|
WATCH= NODE_OPTIONS=--max_old_space_size=8000 ./node_modules/.bin/watch
|
||||||
WEBPACK=./node_modules/.bin/webpack
|
WEBPACK= NODE_OPTIONS=--max_old_space_size=8000 ./node_modules/.bin/webpack
|
||||||
|
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@
|
||||||
"redux-thunk": "2.0.1",
|
"redux-thunk": "2.0.1",
|
||||||
"sass-lint": "1.5.1",
|
"sass-lint": "1.5.1",
|
||||||
"sass-loader": "6.0.6",
|
"sass-loader": "6.0.6",
|
||||||
|
"scratch-gui": "0.1.0-prerelease.20180427201459",
|
||||||
"scratchr2_translations": "git://github.com/LLK/scratchr2_translations.git#master",
|
"scratchr2_translations": "git://github.com/LLK/scratchr2_translations.git#master",
|
||||||
"slick-carousel": "1.6.0",
|
"slick-carousel": "1.6.0",
|
||||||
"source-map-support": "0.3.2",
|
"source-map-support": "0.3.2",
|
||||||
|
|
|
@ -193,7 +193,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "preview",
|
"name": "preview",
|
||||||
"pattern": "^/preview/?(\\d+)?/?$",
|
"pattern": "^/preview/(*)/?$",
|
||||||
"routeAlias": "/preview/?$",
|
"routeAlias": "/preview/?$",
|
||||||
"view": "preview/preview",
|
"view": "preview/preview",
|
||||||
"title": "Scratch 3.0 Preview"
|
"title": "Scratch 3.0 Preview"
|
||||||
|
|
|
@ -6,12 +6,14 @@ const React = require('react');
|
||||||
const Formsy = require('formsy-react').default;
|
const Formsy = require('formsy-react').default;
|
||||||
const classNames = require('classnames');
|
const classNames = require('classnames');
|
||||||
|
|
||||||
|
const GUI = require('scratch-gui').default;
|
||||||
|
const IntlGUI = injectIntl(GUI);
|
||||||
|
|
||||||
const sessionActions = require('../../redux/session.js');
|
const sessionActions = require('../../redux/session.js');
|
||||||
const decorateText = require('../../lib/decorate-text.jsx');
|
const decorateText = require('../../lib/decorate-text.jsx');
|
||||||
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
||||||
const Avatar = require('../../components/avatar/avatar.jsx');
|
const Avatar = require('../../components/avatar/avatar.jsx');
|
||||||
const CappedNumber = require('../../components/cappednumber/cappednumber.jsx');
|
const CappedNumber = require('../../components/cappednumber/cappednumber.jsx');
|
||||||
const placeholder = require('./gui-placeholder.png');
|
|
||||||
const ShareBanner = require('../../components/share-banner/share-banner.jsx');
|
const ShareBanner = require('../../components/share-banner/share-banner.jsx');
|
||||||
const ThumbnailColumn = require('../../components/thumbnailcolumn/thumbnailcolumn.jsx');
|
const ThumbnailColumn = require('../../components/thumbnailcolumn/thumbnailcolumn.jsx');
|
||||||
const InplaceInput = require('../../components/forms/inplace-input.jsx');
|
const InplaceInput = require('../../components/forms/inplace-input.jsx');
|
||||||
|
@ -25,8 +27,10 @@ const PreviewPresentation = props => {
|
||||||
faved,
|
faved,
|
||||||
favoriteCount,
|
favoriteCount,
|
||||||
intl,
|
intl,
|
||||||
|
isFullScreen,
|
||||||
loved,
|
loved,
|
||||||
loveCount,
|
loveCount,
|
||||||
|
projectId,
|
||||||
projectInfo,
|
projectInfo,
|
||||||
remixes,
|
remixes,
|
||||||
sessionStatus,
|
sessionStatus,
|
||||||
|
@ -34,6 +38,7 @@ const PreviewPresentation = props => {
|
||||||
user,
|
user,
|
||||||
onFavoriteClicked,
|
onFavoriteClicked,
|
||||||
onLoveClicked,
|
onLoveClicked,
|
||||||
|
onSeeInside,
|
||||||
onUpdate
|
onUpdate
|
||||||
// ...otherProps TBD
|
// ...otherProps TBD
|
||||||
} = props;
|
} = props;
|
||||||
|
@ -93,15 +98,23 @@ const PreviewPresentation = props => {
|
||||||
Remix
|
Remix
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
<button className="button see-inside-button">
|
<button
|
||||||
|
className="button see-inside-button"
|
||||||
|
onClick={onSeeInside}
|
||||||
|
>
|
||||||
See Inside
|
See Inside
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
<FlexRow className="preview-row">
|
<FlexRow className="preview-row">
|
||||||
<div className="placeholder">
|
<IntlGUI
|
||||||
<img src={placeholder} />
|
isPlayerOnly
|
||||||
</div>
|
basePath="/"
|
||||||
|
className="guiPlayer"
|
||||||
|
isFullScreen={isFullScreen}
|
||||||
|
previewInfoVisible="false"
|
||||||
|
projectId={projectId}
|
||||||
|
/>
|
||||||
<FlexRow className="project-notes">
|
<FlexRow className="project-notes">
|
||||||
{shareDate && (
|
{shareDate && (
|
||||||
<div className="share-date">
|
<div className="share-date">
|
||||||
|
@ -286,11 +299,14 @@ PreviewPresentation.propTypes = {
|
||||||
faved: PropTypes.bool,
|
faved: PropTypes.bool,
|
||||||
favoriteCount: PropTypes.number,
|
favoriteCount: PropTypes.number,
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
|
isFullScreen: PropTypes.bool,
|
||||||
loveCount: PropTypes.number,
|
loveCount: PropTypes.number,
|
||||||
loved: PropTypes.bool,
|
loved: PropTypes.bool,
|
||||||
onFavoriteClicked: PropTypes.func,
|
onFavoriteClicked: PropTypes.func,
|
||||||
onLoveClicked: PropTypes.func,
|
onLoveClicked: PropTypes.func,
|
||||||
|
onSeeInside: PropTypes.func,
|
||||||
onUpdate: PropTypes.func,
|
onUpdate: PropTypes.func,
|
||||||
|
projectId: PropTypes.number,
|
||||||
projectInfo: PropTypes.shape({
|
projectInfo: PropTypes.shape({
|
||||||
id: PropTypes.number,
|
id: PropTypes.number,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
|
|
@ -2,6 +2,7 @@ const bindAll = require('lodash.bindall');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const PropTypes = require('prop-types');
|
const PropTypes = require('prop-types');
|
||||||
const connect = require('react-redux').connect;
|
const connect = require('react-redux').connect;
|
||||||
|
const injectIntl = require('react-intl').injectIntl;
|
||||||
const Page = require('../../components/page/www/page.jsx');
|
const Page = require('../../components/page/www/page.jsx');
|
||||||
const render = require('../../lib/render.jsx');
|
const render = require('../../lib/render.jsx');
|
||||||
|
|
||||||
|
@ -9,6 +10,8 @@ const PreviewPresentation = require('./presentation.jsx');
|
||||||
|
|
||||||
const sessionActions = require('../../redux/session.js');
|
const sessionActions = require('../../redux/session.js');
|
||||||
const previewActions = require('../../redux/preview.js');
|
const previewActions = require('../../redux/preview.js');
|
||||||
|
const GUI = require('scratch-gui').default;
|
||||||
|
const IntlGUI = injectIntl(GUI);
|
||||||
|
|
||||||
class Preview extends React.Component {
|
class Preview extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -17,36 +20,28 @@ class Preview extends React.Component {
|
||||||
'handleFavoriteToggle',
|
'handleFavoriteToggle',
|
||||||
'handleLoveToggle',
|
'handleLoveToggle',
|
||||||
'handlePermissions',
|
'handlePermissions',
|
||||||
|
'handleSeeInside',
|
||||||
'handleUpdate',
|
'handleUpdate',
|
||||||
'initCounts'
|
'initCounts'
|
||||||
]);
|
]);
|
||||||
this.state = {
|
this.state = this.initState();
|
||||||
editable: false,
|
|
||||||
favoriteCount: 0,
|
|
||||||
loveCount: 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
let pathname = window.location.pathname.toLowerCase();
|
|
||||||
if (pathname[pathname.length - 1] === '/') {
|
|
||||||
pathname = pathname.substring(0, pathname.length - 1);
|
|
||||||
}
|
|
||||||
const path = pathname.split('/');
|
|
||||||
const projectId = path[path.length - 1];
|
|
||||||
if (this.props.sessionStatus !== prevProps.sessionStatus &&
|
if (this.props.sessionStatus !== prevProps.sessionStatus &&
|
||||||
this.props.sessionStatus === sessionActions.Status.FETCHED) {
|
this.props.sessionStatus === sessionActions.Status.FETCHED &&
|
||||||
|
this.state.projectId) {
|
||||||
if (this.props.user) {
|
if (this.props.user) {
|
||||||
const username = this.props.user.username;
|
const username = this.props.user.username;
|
||||||
const token = this.props.user.token;
|
const token = this.props.user.token;
|
||||||
this.props.getProjectInfo(projectId, token);
|
this.props.getProjectInfo(this.state.projectId, token);
|
||||||
this.props.getRemixes(projectId, token);
|
this.props.getRemixes(this.state.projectId, token);
|
||||||
this.props.getStudios(projectId, token);
|
this.props.getStudios(this.state.projectId, token);
|
||||||
this.props.getFavedStatus(projectId, username, token);
|
this.props.getFavedStatus(this.state.projectId, username, token);
|
||||||
this.props.getLovedStatus(projectId, username, token);
|
this.props.getLovedStatus(this.state.projectId, username, token);
|
||||||
} else {
|
} else {
|
||||||
this.props.getProjectInfo(projectId);
|
this.props.getProjectInfo(this.state.projectId);
|
||||||
this.props.getRemixes(projectId);
|
this.props.getRemixes(this.state.projectId);
|
||||||
this.props.getStudios(projectId);
|
this.props.getStudios(this.state.projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,6 +53,33 @@ class Preview extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initState () {
|
||||||
|
let pathname = window.location.pathname.toLowerCase();
|
||||||
|
const params = {
|
||||||
|
editable: false,
|
||||||
|
favoriteCount: 0,
|
||||||
|
inEditor: false,
|
||||||
|
isFullScreen: false,
|
||||||
|
loveCount: 0,
|
||||||
|
projectId: null
|
||||||
|
};
|
||||||
|
if (pathname[pathname.length - 1] === '/') {
|
||||||
|
pathname = pathname.substring(0, pathname.length - 1);
|
||||||
|
}
|
||||||
|
const path = pathname.split('/');
|
||||||
|
if (path[path.length - 1] === 'editor' || path[path.length - 1] === 'preview') {
|
||||||
|
params.inEditor = true;
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
if (path[path.length - 1] === 'fullscreen') {
|
||||||
|
params.isFullScreen = true;
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
if (/^\d+$/.test(path[path.length - 1])) {
|
||||||
|
params.projectId = path.pop();
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
handleFavoriteToggle () {
|
handleFavoriteToggle () {
|
||||||
this.props.setFavedStatus(
|
this.props.setFavedStatus(
|
||||||
!this.props.faved,
|
!this.props.faved,
|
||||||
|
@ -98,6 +120,10 @@ class Preview extends React.Component {
|
||||||
this.setState({editable: true});
|
this.setState({editable: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleSeeInside () {
|
||||||
|
this.setState({inEditor: true});
|
||||||
|
history.pushState({}, document.title, `/preview/${this.state.projectId}/editor`);
|
||||||
|
}
|
||||||
handleUpdate (jsonData) {
|
handleUpdate (jsonData) {
|
||||||
this.props.updateProject(
|
this.props.updateProject(
|
||||||
this.props.projectInfo.id,
|
this.props.projectInfo.id,
|
||||||
|
@ -114,14 +140,24 @@ class Preview extends React.Component {
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
|
this.state.inEditor ?
|
||||||
|
<IntlGUI
|
||||||
|
basePath="/"
|
||||||
|
className="gui"
|
||||||
|
isPlayerOnly={false}
|
||||||
|
projectId={this.state.projectId}
|
||||||
|
/> :
|
||||||
|
<Page>
|
||||||
<PreviewPresentation
|
<PreviewPresentation
|
||||||
comments={this.props.comments}
|
comments={this.props.comments}
|
||||||
creditInfo={this.props.credit}
|
creditInfo={this.props.credit}
|
||||||
editable={this.state.editable}
|
editable={this.state.editable}
|
||||||
faved={this.props.faved}
|
faved={this.props.faved}
|
||||||
favoriteCount={this.state.favoriteCount}
|
favoriteCount={this.state.favoriteCount}
|
||||||
|
isFullScreen={this.state.isFullScreen}
|
||||||
loveCount={this.state.loveCount}
|
loveCount={this.state.loveCount}
|
||||||
loved={this.props.loved}
|
loved={this.props.loved}
|
||||||
|
projectId={this.state.projectId}
|
||||||
projectInfo={this.props.projectInfo}
|
projectInfo={this.props.projectInfo}
|
||||||
remixes={this.props.remixes}
|
remixes={this.props.remixes}
|
||||||
sessionStatus={this.props.sessionStatus}
|
sessionStatus={this.props.sessionStatus}
|
||||||
|
@ -129,8 +165,10 @@ class Preview extends React.Component {
|
||||||
user={this.props.user}
|
user={this.props.user}
|
||||||
onFavoriteClicked={this.handleFavoriteToggle}
|
onFavoriteClicked={this.handleFavoriteToggle}
|
||||||
onLoveClicked={this.handleLoveToggle}
|
onLoveClicked={this.handleLoveToggle}
|
||||||
|
onSeeInside={this.handleSeeInside}
|
||||||
onUpdate={this.handleUpdate}
|
onUpdate={this.handleUpdate}
|
||||||
/>
|
/>
|
||||||
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +306,7 @@ const ConnectedPreview = connect(
|
||||||
)(Preview);
|
)(Preview);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Page><ConnectedPreview /></Page>,
|
<ConnectedPreview />,
|
||||||
document.getElementById('app'),
|
document.getElementById('app'),
|
||||||
{preview: previewActions.previewReducer}
|
{preview: previewActions.previewReducer}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
@import "../../colors";
|
@import "../../colors";
|
||||||
@import "../../frameless";
|
@import "../../frameless";
|
||||||
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
#app,
|
|
||||||
.gui {
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* override view padding for share banner */
|
/* override view padding for share banner */
|
||||||
#view {
|
#view {
|
||||||
padding: 0 0 20px 0;
|
padding: 0 0 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gui * { box-sizing: border-box; }
|
.gui {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index: 11;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .gui * { box-sizing: border-box; }
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
|
|
||||||
|
@ -162,15 +162,11 @@ body,
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.guiPlayer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 480px;
|
width: 480px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-notes {
|
.project-notes {
|
||||||
width: 45%;
|
width: 45%;
|
||||||
height: 404px;
|
height: 404px;
|
||||||
|
|
|
@ -142,7 +142,21 @@ module.exports = {
|
||||||
new CopyWebpackPlugin([
|
new CopyWebpackPlugin([
|
||||||
{from: 'static'},
|
{from: 'static'},
|
||||||
{from: 'intl', to: 'js'}
|
{from: 'intl', to: 'js'}
|
||||||
])
|
]),
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: 'node_modules/scratch-gui/dist/static/blocks-media',
|
||||||
|
to: 'static/blocks-media'
|
||||||
|
}]),
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: 'node_modules/scratch-gui/dist/extension-worker.js'
|
||||||
|
}]),
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: 'node_modules/scratch-gui/dist/extension-worker.js.map'
|
||||||
|
}]),
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: 'node_modules/scratch-gui/dist/static/assets',
|
||||||
|
to: 'static/assets'
|
||||||
|
}])
|
||||||
])
|
])
|
||||||
.concat(process.env.NODE_ENV === 'production' ? [
|
.concat(process.env.NODE_ENV === 'production' ? [
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
|
Loading…
Reference in a new issue