From 4d6e4857ba427d3256b55f22c1a652147c6989f5 Mon Sep 17 00:00:00 2001 From: catarak Date: Wed, 13 Jul 2016 18:53:56 -0400 Subject: [PATCH] add files, server side, only css and js files --- client/modules/IDE/actions/files.js | 41 +++++++++++++++++-- client/modules/IDE/components/NewFileModal.js | 6 +-- client/modules/IDE/reducers/files.js | 4 +- client/styles/components/_modal.scss | 2 +- server/controllers/file.controller.js | 19 +++++++++ server/routes/file.routes.js | 8 ++++ server/server.js | 2 + 7 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 server/controllers/file.controller.js create mode 100644 server/routes/file.routes.js diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js index 8bc0c6c3..1eead2ae 100644 --- a/client/modules/IDE/actions/files.js +++ b/client/modules/IDE/actions/files.js @@ -1,4 +1,7 @@ import * as ActionTypes from '../../../constants'; +import axios from 'axios'; + +const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api'; export function updateFileContent(name, content) { return { @@ -9,9 +12,39 @@ export function updateFileContent(name, content) { } // TODO make req to server -export function createFile(name) { - return { - type: ActionTypes.CREATE_FILE, - name +export function createFile(formProps) { + return (dispatch, getState) => { + const state = getState(); + if (state.project.id) { + const postParams = { + name: formProps.name + }; + axios.post(`${ROOT_URL}/projects/${state.project.id}/files`, postParams, { withCredentials: true }) + .then(response => { + dispatch({ + type: ActionTypes.CREATE_FILE, + ...response.data + }); + }) + .catch(response => dispatch({ + type: ActionTypes.ERROR, + error: response.data + })); + } else { + let maxFileId = 0; + state.files.forEach(file => { + if (parseInt(file.id, 10) > maxFileId) { + maxFileId = parseInt(file.id, 10); + } + }); + dispatch({ + type: ActionTypes.CREATE_FILE, + name: formProps.name, + id: `${maxFileId + 1}` + }); + dispatch({ + type: ActionTypes.HIDE_MODAL + }); + } }; } diff --git a/client/modules/IDE/components/NewFileModal.js b/client/modules/IDE/components/NewFileModal.js index 1072348b..f24ae645 100644 --- a/client/modules/IDE/components/NewFileModal.js +++ b/client/modules/IDE/components/NewFileModal.js @@ -51,12 +51,10 @@ function validate(formProps) { if (!formProps.name) { errors.name = 'Please enter a name'; + } else if (!formProps.name.match(/(.+\.js$|.+\.css$)/)) { + errors.name = 'File must be of type JavaScript or CSS.'; } - // if (formProps.name.match(/(.+\.js$|.+\.css$)/)) { - // errors.name = 'File must be of type JavaScript or CSS.'; - // } - return errors; } diff --git a/client/modules/IDE/reducers/files.js b/client/modules/IDE/reducers/files.js index 6bc35e1b..2b32bc04 100644 --- a/client/modules/IDE/reducers/files.js +++ b/client/modules/IDE/reducers/files.js @@ -64,8 +64,8 @@ const files = (state = initialState, action) => { return [...action.files]; case ActionTypes.SET_PROJECT: return [...action.files]; - case ActionTypes.NEW_FILE: - return [{ name: action.name, content: '' }, ...state.files]; + case ActionTypes.CREATE_FILE: + return [...state, { name: action.name, id: action.id, content: '' }]; default: return state; } diff --git a/client/styles/components/_modal.scss b/client/styles/components/_modal.scss index 22745606..11f79db3 100644 --- a/client/styles/components/_modal.scss +++ b/client/styles/components/_modal.scss @@ -1,7 +1,7 @@ .modal { position: absolute; top: #{66 / $base-font-size}rem; - right: #{400 / $base-font-size}rem;; + right: #{400 / $base-font-size}rem; z-index: 100; } diff --git a/server/controllers/file.controller.js b/server/controllers/file.controller.js new file mode 100644 index 00000000..73058b07 --- /dev/null +++ b/server/controllers/file.controller.js @@ -0,0 +1,19 @@ +import Project from '../models/Project' + +// Bug -> timestamps don't get created, but it seems like this will +// be fixed in mongoose soon +// https://github.com/Automattic/mongoose/issues/4049 +export function createFile(req, res) { + Project.findByIdAndUpdate(req.params.project_id, + { + $push: { + 'files': req.body + } + }, + { + new: true + }, (err, updatedProject) => { + if (err) { return res.json({ success: false }); } + return res.json(updatedProject.files[updatedProject.files.length - 1]); + }); +} \ No newline at end of file diff --git a/server/routes/file.routes.js b/server/routes/file.routes.js new file mode 100644 index 00000000..c7035ac6 --- /dev/null +++ b/server/routes/file.routes.js @@ -0,0 +1,8 @@ +import { Router } from 'express'; +import * as FileController from '../controllers/file.controller'; + +const router = new Router(); + +router.route('/projects/:project_id/files').post(FileController.createFile); + +export default router; \ No newline at end of file diff --git a/server/server.js b/server/server.js index 99879244..3d59d285 100644 --- a/server/server.js +++ b/server/server.js @@ -27,6 +27,7 @@ import serverConfig from './config'; import users from './routes/user.routes'; import sessions from './routes/session.routes'; import projects from './routes/project.routes'; +import files from './routes/file.routes'; import serverRoutes from './routes/server.routes'; // Body parser, cookie parser, sessions, serve public assets @@ -55,6 +56,7 @@ app.use(passport.session()); app.use('/api', users); app.use('/api', sessions); app.use('/api', projects); +app.use('/api', files); // this is supposed to be TEMPORARY -- until i figure out // isomorphic rendering app.use('/', serverRoutes);