mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 01:25:52 -05:00
Merge pull request #3565 from LLK/hotfix/project-creation-replication-lag
[Develop] Work around replication lag problems on project creation
This commit is contained in:
commit
b7bdafd34c
4 changed files with 110 additions and 3 deletions
25
package-lock.json
generated
25
package-lock.json
generated
|
@ -12032,6 +12032,24 @@
|
||||||
"prepend-http": "^1.0.0",
|
"prepend-http": "^1.0.0",
|
||||||
"query-string": "^4.1.0",
|
"query-string": "^4.1.0",
|
||||||
"sort-keys": "^1.0.0"
|
"sort-keys": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"query-string": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||||
|
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"strict-uri-encode": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strict-uri-encode": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm-run-path": {
|
"npm-run-path": {
|
||||||
|
@ -13907,11 +13925,12 @@
|
||||||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
||||||
},
|
},
|
||||||
"query-string": {
|
"query-string": {
|
||||||
"version": "4.3.4",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
||||||
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"decode-uri-component": "^0.2.0",
|
||||||
"object-assign": "^4.1.0",
|
"object-assign": "^4.1.0",
|
||||||
"strict-uri-encode": "^1.0.0"
|
"strict-uri-encode": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
"po2icu": "0.0.2",
|
"po2icu": "0.0.2",
|
||||||
"postcss-loader": "2.0.10",
|
"postcss-loader": "2.0.10",
|
||||||
"prop-types": "15.6.0",
|
"prop-types": "15.6.0",
|
||||||
|
"query-string": "^5.1.1",
|
||||||
"react": "16.2.0",
|
"react": "16.2.0",
|
||||||
"react-dom": "16.2.0",
|
"react-dom": "16.2.0",
|
||||||
"react-intl": "2.8.0",
|
"react-intl": "2.8.0",
|
||||||
|
|
|
@ -111,6 +111,7 @@ const PreviewPresentation = ({
|
||||||
onSocialClosed,
|
onSocialClosed,
|
||||||
onToggleComments,
|
onToggleComments,
|
||||||
onToggleStudio,
|
onToggleStudio,
|
||||||
|
onUpdateProjectData,
|
||||||
onUpdateProjectId,
|
onUpdateProjectId,
|
||||||
onUpdateProjectThumbnail,
|
onUpdateProjectThumbnail,
|
||||||
originalInfo,
|
originalInfo,
|
||||||
|
@ -345,6 +346,7 @@ const PreviewPresentation = ({
|
||||||
onProjectLoaded={onProjectLoaded}
|
onProjectLoaded={onProjectLoaded}
|
||||||
onRemixing={onRemixing}
|
onRemixing={onRemixing}
|
||||||
onSetProjectThumbnailer={onSetProjectThumbnailer}
|
onSetProjectThumbnailer={onSetProjectThumbnailer}
|
||||||
|
onUpdateProjectData={onUpdateProjectData}
|
||||||
onUpdateProjectId={onUpdateProjectId}
|
onUpdateProjectId={onUpdateProjectId}
|
||||||
onUpdateProjectThumbnail={onUpdateProjectThumbnail}
|
onUpdateProjectThumbnail={onUpdateProjectThumbnail}
|
||||||
/>
|
/>
|
||||||
|
@ -725,6 +727,7 @@ PreviewPresentation.propTypes = {
|
||||||
onSocialClosed: PropTypes.func,
|
onSocialClosed: PropTypes.func,
|
||||||
onToggleComments: PropTypes.func,
|
onToggleComments: PropTypes.func,
|
||||||
onToggleStudio: PropTypes.func,
|
onToggleStudio: PropTypes.func,
|
||||||
|
onUpdateProjectData: PropTypes.func,
|
||||||
onUpdateProjectId: PropTypes.func,
|
onUpdateProjectId: PropTypes.func,
|
||||||
onUpdateProjectThumbnail: PropTypes.func,
|
onUpdateProjectThumbnail: PropTypes.func,
|
||||||
originalInfo: projectShape,
|
originalInfo: projectShape,
|
||||||
|
|
|
@ -8,7 +8,9 @@ const PropTypes = require('prop-types');
|
||||||
const connect = require('react-redux').connect;
|
const connect = require('react-redux').connect;
|
||||||
const injectIntl = require('react-intl').injectIntl;
|
const injectIntl = require('react-intl').injectIntl;
|
||||||
const parser = require('scratch-parser');
|
const parser = require('scratch-parser');
|
||||||
|
const queryString = require('query-string');
|
||||||
|
|
||||||
|
const api = require('../../lib/api');
|
||||||
const Page = require('../../components/page/www/page.jsx');
|
const Page = require('../../components/page/www/page.jsx');
|
||||||
const storage = require('../../lib/storage.js').default;
|
const storage = require('../../lib/storage.js').default;
|
||||||
const log = require('../../lib/log');
|
const log = require('../../lib/log');
|
||||||
|
@ -36,6 +38,7 @@ const IntlGUI = injectIntl(GUI.default);
|
||||||
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
|
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
|
||||||
|
|
||||||
const initSentry = require('../../lib/sentry.js');
|
const initSentry = require('../../lib/sentry.js');
|
||||||
|
const xhr = require('xhr');
|
||||||
initSentry();
|
initSentry();
|
||||||
|
|
||||||
class Preview extends React.Component {
|
class Preview extends React.Component {
|
||||||
|
@ -73,6 +76,7 @@ class Preview extends React.Component {
|
||||||
'handleSeeInside',
|
'handleSeeInside',
|
||||||
'handleSetProjectThumbnailer',
|
'handleSetProjectThumbnailer',
|
||||||
'handleShare',
|
'handleShare',
|
||||||
|
'handleUpdateProjectData',
|
||||||
'handleUpdateProjectId',
|
'handleUpdateProjectId',
|
||||||
'handleUpdateProjectTitle',
|
'handleUpdateProjectTitle',
|
||||||
'handleToggleComments',
|
'handleToggleComments',
|
||||||
|
@ -219,6 +223,84 @@ class Preview extends React.Component {
|
||||||
this.props.getRemixes(this.state.projectId);
|
this.props.getRemixes(this.state.projectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is copy of what is in save-project-to-server in GUI that adds
|
||||||
|
// an extra get of the project info from api. We do this to wait for replication
|
||||||
|
// lag to pass. This is intended to be a temporary fix until we use the data
|
||||||
|
// from the create request to fill the projectInfo state.
|
||||||
|
handleUpdateProjectData (projectId, vmState, params) {
|
||||||
|
const opts = {
|
||||||
|
body: vmState,
|
||||||
|
// If we set json:true then the body is double-stringified, so don't
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
withCredentials: true
|
||||||
|
};
|
||||||
|
const creatingProject = projectId === null || typeof projectId === 'undefined';
|
||||||
|
const queryParams = {};
|
||||||
|
if (params.hasOwnProperty('originalId')) queryParams.original_id = params.originalId;
|
||||||
|
if (params.hasOwnProperty('isCopy')) queryParams.is_copy = params.isCopy;
|
||||||
|
if (params.hasOwnProperty('isRemix')) queryParams.is_remix = params.isRemix;
|
||||||
|
if (params.hasOwnProperty('title')) queryParams.title = params.title;
|
||||||
|
let qs = queryString.stringify(queryParams);
|
||||||
|
if (qs) qs = `?${qs}`;
|
||||||
|
if (creatingProject) {
|
||||||
|
Object.assign(opts, {
|
||||||
|
method: 'post',
|
||||||
|
url: `${this.props.projectHost}/${qs}`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Object.assign(opts, {
|
||||||
|
method: 'put',
|
||||||
|
url: `${this.props.projectHost}/${projectId}${qs}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
xhr(opts, (err, response) => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
if (response.statusCode !== 200) return reject(response.statusCode);
|
||||||
|
let body;
|
||||||
|
try {
|
||||||
|
// Since we didn't set json: true, we have to parse manually
|
||||||
|
body = JSON.parse(response.body);
|
||||||
|
} catch (e) {
|
||||||
|
return reject(e);
|
||||||
|
}
|
||||||
|
body.id = projectId;
|
||||||
|
if (creatingProject) {
|
||||||
|
body.id = body['content-name'];
|
||||||
|
}
|
||||||
|
resolve(body);
|
||||||
|
});
|
||||||
|
}).then(body => {
|
||||||
|
const fetchProjectInfo = (count, resolve) => {
|
||||||
|
api({
|
||||||
|
uri: `/projects/${body.id}`,
|
||||||
|
authentication: this.props.user.token
|
||||||
|
}, (err, projectInfo, response) => {
|
||||||
|
if (err) {
|
||||||
|
log.error(`Could not fetch project after creating: ${err}`);
|
||||||
|
return resolve(body);
|
||||||
|
}
|
||||||
|
if (typeof body === 'undefined' || response.statusCode === 404) {
|
||||||
|
// Retry after 500ms, 1.5s, 3.5s, 7.5s and then stop.
|
||||||
|
if (count > 4) {
|
||||||
|
return resolve(body);
|
||||||
|
}
|
||||||
|
return setTimeout(
|
||||||
|
fetchProjectInfo.bind(this, count + 1, resolve),
|
||||||
|
500 * Math.pow(2, count));
|
||||||
|
}
|
||||||
|
return resolve(body);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (creatingProject) {
|
||||||
|
return new Promise((resolve, reject) => fetchProjectInfo(1, resolve, reject));
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
});
|
||||||
|
}
|
||||||
setScreenFromOrientation () {
|
setScreenFromOrientation () {
|
||||||
/*
|
/*
|
||||||
* If the user is on a mobile device, switching to
|
* If the user is on a mobile device, switching to
|
||||||
|
@ -702,6 +784,7 @@ class Preview extends React.Component {
|
||||||
onSocialClosed={this.handleSocialClose}
|
onSocialClosed={this.handleSocialClose}
|
||||||
onToggleComments={this.handleToggleComments}
|
onToggleComments={this.handleToggleComments}
|
||||||
onToggleStudio={this.handleToggleStudio}
|
onToggleStudio={this.handleToggleStudio}
|
||||||
|
onUpdateProjectData={this.handleUpdateProjectData}
|
||||||
onUpdateProjectId={this.handleUpdateProjectId}
|
onUpdateProjectId={this.handleUpdateProjectId}
|
||||||
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
|
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
|
||||||
/>
|
/>
|
||||||
|
@ -739,6 +822,7 @@ class Preview extends React.Component {
|
||||||
onSetLanguage={this.handleSetLanguage}
|
onSetLanguage={this.handleSetLanguage}
|
||||||
onShare={this.handleShare}
|
onShare={this.handleShare}
|
||||||
onToggleLoginOpen={this.props.handleToggleLoginOpen}
|
onToggleLoginOpen={this.props.handleToggleLoginOpen}
|
||||||
|
onUpdateProjectData={this.handleUpdateProjectData}
|
||||||
onUpdateProjectId={this.handleUpdateProjectId}
|
onUpdateProjectId={this.handleUpdateProjectId}
|
||||||
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
|
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
|
||||||
onUpdateProjectTitle={this.handleUpdateProjectTitle}
|
onUpdateProjectTitle={this.handleUpdateProjectTitle}
|
||||||
|
|
Loading…
Reference in a new issue