diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js index 0d1b0f4c..d277ea18 100644 --- a/client/modules/IDE/actions/ide.js +++ b/client/modules/IDE/actions/ide.js @@ -201,19 +201,6 @@ export function resetJustOpenedProject() { }; } -export function setProjectSavedTime(value) { - return { - type: ActionTypes.SET_PROJECT_SAVED_TIME, - value - }; -} - -export function resetProjectSavedTime() { - return { - type: ActionTypes.RESET_PROJECT_SAVED_TIME, - }; -} - export function setPreviousPath(path) { return { type: ActionTypes.SET_PREVIOUS_PATH, diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js index b1a85e74..3aff9e00 100644 --- a/client/modules/IDE/actions/project.js +++ b/client/modules/IDE/actions/project.js @@ -1,39 +1,21 @@ import { browserHistory } from 'react-router'; import axios from 'axios'; import objectID from 'bson-objectid'; -import moment from 'moment'; import * as ActionTypes from '../../../constants'; import { showToast, setToastText } from './toast'; import { setUnsavedChanges, justOpenedProject, resetJustOpenedProject, - setProjectSavedTime, - resetProjectSavedTime, showErrorModal } from './ide'; const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api'; -export function getProject(id) { - return (dispatch, getState) => { - const state = getState(); - dispatch(justOpenedProject()); - if (state.ide.justOpenedProject) { - dispatch(resetProjectSavedTime()); - } - axios.get(`${ROOT_URL}/projects/${id}`, { withCredentials: true }) - .then((response) => { - dispatch({ - type: ActionTypes.SET_PROJECT, - project: response.data, - files: response.data.files, - owner: response.data.user - }); - dispatch(setUnsavedChanges(false)); - }) - .catch(response => dispatch({ - type: ActionTypes.ERROR, - error: response.data - })); +export function setProject(project) { + return { + type: ActionTypes.SET_PROJECT, + project, + files: project.files, + owner: project.user }; } @@ -44,6 +26,21 @@ export function setProjectName(name) { }; } +export function getProject(id) { + return (dispatch, getState) => { + dispatch(justOpenedProject()); + axios.get(`${ROOT_URL}/projects/${id}`, { withCredentials: true }) + .then((response) => { + dispatch(setProject(response.data)); + dispatch(setUnsavedChanges(false)); + }) + .catch(response => dispatch({ + type: ActionTypes.ERROR, + error: response.data + })); + }; +} + export function saveProject(autosave = false) { return (dispatch, getState) => { const state = getState(); @@ -54,9 +51,9 @@ export function saveProject(autosave = false) { formParams.files = [...state.files]; if (state.project.id) { axios.put(`${ROOT_URL}/projects/${state.project.id}`, formParams, { withCredentials: true }) - .then(() => { + .then((response) => { dispatch(setUnsavedChanges(false)); - dispatch(setProjectSavedTime(moment().format())); + dispatch(setProject(response.data)); dispatch({ type: ActionTypes.PROJECT_SAVE_SUCCESS }); @@ -88,7 +85,7 @@ export function saveProject(autosave = false) { axios.post(`${ROOT_URL}/projects`, formParams, { withCredentials: true }) .then((response) => { dispatch(setUnsavedChanges(false)); - dispatch(setProjectSavedTime(moment().format())); + dispatch(setProject(response.data)); browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`); dispatch({ type: ActionTypes.NEW_PROJECT, diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 6411ca55..9d8724a0 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -114,6 +114,7 @@ class Editor extends React.Component { if (this.props.files.length !== nextProps.files.length) { this.initializeDocuments(nextProps.files); } + console.log(nextProps.projectSavedTime); } componentDidUpdate(prevProps) { diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index af689876..a095f51d 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -304,7 +304,7 @@ class IDEView extends React.Component { stopSketch={this.props.stopSketch} autorefresh={this.props.preferences.autorefresh} unsavedChanges={this.props.ide.unsavedChanges} - projectSavedTime={this.props.ide.projectSavedTime} + projectSavedTime={this.props.project.updatedAt} isExpanded={this.props.ide.sidebarIsExpanded} expandSidebar={this.props.expandSidebar} collapseSidebar={this.props.collapseSidebar} @@ -486,7 +486,8 @@ IDEView.propTypes = { owner: PropTypes.shape({ username: PropTypes.string, id: PropTypes.string - }) + }), + updatedAt: PropTypes.string }).isRequired, setProjectName: PropTypes.func.isRequired, openPreferences: PropTypes.func.isRequired, diff --git a/client/modules/IDE/reducers/ide.js b/client/modules/IDE/reducers/ide.js index f4908f2a..40f4e0e2 100644 --- a/client/modules/IDE/reducers/ide.js +++ b/client/modules/IDE/reducers/ide.js @@ -17,7 +17,6 @@ const initialState = { previewIsRefreshing: false, infiniteLoopMessage: '', justOpenedProject: false, - projectSavedTime: '', previousPath: '/', errorType: undefined }; @@ -86,10 +85,6 @@ const ide = (state = initialState, action) => { return Object.assign({}, state, { justOpenedProject: true }); case ActionTypes.RESET_JUST_OPENED_PROJECT: return Object.assign({}, state, { justOpenedProject: false }); - case ActionTypes.SET_PROJECT_SAVED_TIME: - return Object.assign({}, state, { projectSavedTime: action.value }); - case ActionTypes.RESET_PROJECT_SAVED_TIME: - return Object.assign({}, state, { projectSavedTime: '' }); case ActionTypes.SET_PREVIOUS_PATH: return Object.assign({}, state, { previousPath: action.path }); case ActionTypes.SHOW_ERROR_MODAL: diff --git a/client/modules/IDE/reducers/project.js b/client/modules/IDE/reducers/project.js index e09e72ce..d4ae3383 100644 --- a/client/modules/IDE/reducers/project.js +++ b/client/modules/IDE/reducers/project.js @@ -36,6 +36,8 @@ const project = (state, action) => { return Object.assign({}, state, { isEditingName: true }); case ActionTypes.HIDE_EDIT_PROJECT_NAME: return Object.assign({}, state, { isEditingName: false }); + case ActionTypes.SET_PROJECT_SAVED_TIME: + return Object.assign({}, state, { updatedAt: action.value }); default: return state; } diff --git a/server/controllers/project.controller.js b/server/controllers/project.controller.js index 00ce586d..0ff5ebc8 100644 --- a/server/controllers/project.controller.js +++ b/server/controllers/project.controller.js @@ -1,5 +1,6 @@ import archiver from 'archiver'; import request from 'request'; +import moment from 'moment'; import Project from '../models/project'; import User from '../models/user'; @@ -39,12 +40,15 @@ export function updateProject(req, res) { res.status(403).send({ success: false, message: 'Session does not match owner of project.' }); return; } - // if (req.body.updatedAt && moment(req.body.updatedAt) < moment(project.updatedAt)) { - // return res.status(409).send({ success: false, message: 'Attempted to save stale version of project.' }); - // } + if (req.body.updatedAt && moment(req.body.updatedAt) < moment(project.updatedAt)) { + return res.status(409).send({ success: false, message: 'Attempted to save stale version of project.' }); + } Project.findByIdAndUpdate(req.params.project_id, { $set: req.body + }, + { + new: true }) .populate('user', 'username') .exec((updateProjectErr, updatedProject) => { @@ -60,13 +64,13 @@ export function updateProject(req, res) { staleIds.forEach((staleId) => { updatedProject.files.id(staleId).remove(); }); - updatedProject.save((innerErr) => { + updatedProject.save((innerErr, savedProject) => { if (innerErr) { console.log(innerErr); res.json({ success: false }); return; } - res.json(updatedProject); + res.json(savedProject); }); } res.json(updatedProject);