Move project saving to server to helper, allow external save action

This commit is contained in:
Paul Kaplan committed 2019-03-18 12:00:01 -04:00
1 parent b26ac6d62b
commit 7709580710
2 files changed
+78 -45

No files matched your search

+16 -45
View File
@@ -1,15 +1,14 @@
import bindAll from 'lodash.bindall';
import React from 'react';
import PropTypes from 'prop-types';
import queryString from 'query-string';
import {connect} from 'react-redux';
import VM from 'scratch-vm';
import xhr from 'xhr';
import collectMetadata from '../lib/collect-metadata';
import log from '../lib/log';
import storage from '../lib/storage';
import dataURItoBlob from '../lib/data-uri-to-blob';
import saveProjectToServer from '../lib/save-project-to-server';
import {
showAlertWithTimeout,
@@ -176,8 +175,8 @@ const ProjectSaverHOC = function (WrappedComponent) {
createCopyToStorage () {
this.props.onShowCreatingCopyAlert();
return this.storeProject(null, {
original_id: this.props.reduxProjectId,
is_copy: 1,
originalId: this.props.reduxProjectId,
isCopy: 1,
title: this.props.reduxProjectTitle
})
.then(response => {
@@ -192,8 +191,8 @@ const ProjectSaverHOC = function (WrappedComponent) {
createRemixToStorage () {
this.props.onShowCreatingRemixAlert();
return this.storeProject(null, {
original_id: this.props.reduxProjectId,
is_remix: 1,
originalId: this.props.reduxProjectId,
isRemix: 1,
title: this.props.reduxProjectTitle
})
.then(response => {
@@ -234,45 +233,14 @@ const ProjectSaverHOC = function (WrappedComponent) {
)
)
).then(() => {
const opts = {
body: savedVMState,
// 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';
let qs = queryString.stringify(requestParams);
if (qs) qs = `?${qs}`;
if (creatingProject) {
Object.assign(opts, {
method: 'post',
url: `${storage.projectHost}/${qs}`
});
} else {
Object.assign(opts, {
method: 'put',
url: `${storage.projectHost}/${projectId}${qs}`
});
const {onUpdateProjectData} = this.props;
const saveReturnValue = onUpdateProjectData(projectId,
savedVMState, requestParams);
// Allow onUpdateProjectData to either return immediately or a promise.
if (!(saveReturnValue.then && saveReturnValue.catch)) {
return Promise.resolve(saveReturnValue);
}
return new Promise((resolve, reject) => {
xhr(opts, (err, response) => {
if (err) return reject(err);
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);
});
});
return saveReturnValue;
})
.then(response => {
this.props.onSetProjectUnchanged();
@@ -358,6 +326,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
onShowSaveSuccessAlert,
onShowSavingAlert,
onUpdatedProject,
onUpdateProjectData,
onUpdateProjectThumbnail,
reduxProjectId,
reduxProjectTitle,
@@ -403,6 +372,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
onShowRemixSuccessAlert: PropTypes.func,
onShowSaveSuccessAlert: PropTypes.func,
onShowSavingAlert: PropTypes.func,
onUpdateProjectData: PropTypes.func.isRequired,
onUpdateProjectThumbnail: PropTypes.func,
onUpdatedProject: PropTypes.func,
projectChanged: PropTypes.bool,
@@ -413,7 +383,8 @@ const ProjectSaverHOC = function (WrappedComponent) {
ProjectSaverComponent.defaultProps = {
autoSaveIntervalSecs: 120,
onRemixing: () => {},
onSetProjectThumbnailer: () => {}
onSetProjectThumbnailer: () => {},
onUpdateProjectData: saveProjectToServer
};
const mapStateToProps = (state, ownProps) => {
const loadingState = state.scratchGui.projectState.loadingState;
+62
View File
@@ -0,0 +1,62 @@
import queryString from 'query-string';
import xhr from 'xhr';
import storage from '../lib/storage';
/**
* Save a project JSON to the project server.
* This should eventually live in scratch-www.
* @param {number} projectId the ID of the project, null if a new project.
* @param {object} vmState the JSON project representation.
* @param {object} params the request params.
* @property {?number} params.originalId the original project ID if a copy/remix.
* @property {?boolean} params.isCopy a flag indicating if this save is creating a copy.
* @property {?boolean} params.isRemix a flag indicating if this save is creating a remix.
* @property {?string} params.title the title of the project.
* @return {Promise} A promise that resolves when the network request resolves.
*/
export default function (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: `${storage.projectHost}/${qs}`
});
} else {
Object.assign(opts, {
method: 'put',
url: `${storage.projectHost}/${projectId}${qs}`
});
}
return new Promise((resolve, reject) => {
xhr(opts, (err, response) => {
if (err) return reject(err);
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);
});
});
}