diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js index 01937f1f..88946782 100644 --- a/client/modules/IDE/actions/project.js +++ b/client/modules/IDE/actions/project.js @@ -69,11 +69,14 @@ export function saveProject() { })); } else { // this might be unnecessary, but to prevent collisions in mongodb - formParams.files.map(file => { - const newFile = Object.assign({}, file); - delete newFile.id; - return newFile; - }); + // formParams.files.map(file => { + // if (file.name !== 'root') { + // const newFile = Object.assign({}, file); + // delete newFile.id; + // return newFile; + // } + // return file; + // }); axios.post(`${ROOT_URL}/projects`, formParams, { withCredentials: true }) .then(response => { browserHistory.push(`/projects/${response.data.id}`); diff --git a/client/modules/IDE/components/FileNode.js b/client/modules/IDE/components/FileNode.js index bfe3c8f6..5ffbc8a0 100644 --- a/client/modules/IDE/components/FileNode.js +++ b/client/modules/IDE/components/FileNode.js @@ -152,7 +152,7 @@ FileNode.propTypes = { }; function mapStateToProps(state, ownProps) { - return setSelectedFile(state.files, state.ide.selectedFile).find((file) => file.id === ownProps.id); + return setSelectedFile(state.files, state.ide.selectedFile || state.files[1].id).find((file) => file.id === ownProps.id); } function mapDispatchToProps(dispatch) { diff --git a/client/modules/IDE/components/PreviewFrame.js b/client/modules/IDE/components/PreviewFrame.js index 5b0aa80c..f02901ae 100644 --- a/client/modules/IDE/components/PreviewFrame.js +++ b/client/modules/IDE/components/PreviewFrame.js @@ -125,7 +125,7 @@ class PreviewFrame extends React.Component { this.renderSketch(); } - // I apologize for this, it is a hack. + // I apologize for this, it is a hack. A simple way to check if the files have changed. if (this.props.isPlaying && this.props.files[0].id !== prevProps.files[0].id) { this.renderSketch(); } @@ -242,8 +242,6 @@ class PreviewFrame extends React.Component { PreviewFrame.propTypes = { isPlaying: PropTypes.bool.isRequired, - isTextOutputPlaying: PropTypes.bool.isRequired, - textOutput: PropTypes.bool.isRequired, head: PropTypes.object.isRequired, content: PropTypes.string, htmlFile: PropTypes.shape({ diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js index 14a19320..33dbd56b 100644 --- a/client/modules/IDE/pages/IDEView.js +++ b/client/modules/IDE/pages/IDEView.js @@ -21,6 +21,7 @@ import SplitPane from 'react-split-pane'; import Overlay from '../../App/components/Overlay'; import SketchList from '../components/SketchList'; import About from '../components/About'; +import { setDefaultSelectedFile } from '../reducers/ide'; class IDEView extends React.Component { constructor(props) { @@ -376,11 +377,11 @@ IDEView.propTypes = { function mapStateToProps(state) { return { files: setSelectedFile(state.files, state.ide.selectedFile), - selectedFile: getFile(state.files, state.ide.selectedFile), + selectedFile: getFile(state.files, state.ide.selectedFile || state.files[1].id), htmlFile: getHTMLFile(state.files), jsFiles: getJSFiles(state.files), cssFiles: getCSSFiles(state.files), - ide: state.ide, + ide: setDefaultSelectedFile(state.ide, state.files), preferences: state.preferences, editorAccessibility: state.editorAccessibility, user: state.user, diff --git a/client/modules/IDE/reducers/files.js b/client/modules/IDE/reducers/files.js index d3f6040b..e6dd9b51 100644 --- a/client/modules/IDE/reducers/files.js +++ b/client/modules/IDE/reducers/files.js @@ -1,4 +1,5 @@ import * as ActionTypes from '../../../constants'; +import objectID from 'bson-objectid'; const defaultSketch = `function setup() { createCanvas(400, 400); @@ -31,31 +32,37 @@ const defaultCSS = } `; -// if the project has never been saved, -const initialState = [ - { - name: 'root', - id: '0', - children: ['1', '2', '3'] - }, - { - name: 'sketch.js', - content: defaultSketch, - id: '1' - }, - { - name: 'index.html', - content: defaultHTML, - id: '2' - }, - { - name: 'style.css', - content: defaultCSS, - id: '3' - }]; +function initialState() { + const a = objectID().toHexString(); + const b = objectID().toHexString(); + const c = objectID().toHexString(); + return [ + { + name: 'root', + id: '0', + children: [a, b, c] + }, + { + name: 'sketch.js', + content: defaultSketch, + id: a + }, + { + name: 'index.html', + content: defaultHTML, + id: b + }, + { + name: 'style.css', + content: defaultCSS, + id: c + }]; +} - -const files = (state = initialState, action) => { +const files = (state, action) => { + if (state === undefined) { + state = initialState(); // eslint-disable-line + } switch (action.type) { case ActionTypes.UPDATE_FILE_CONTENT: return state.map(file => { diff --git a/client/modules/IDE/reducers/ide.js b/client/modules/IDE/reducers/ide.js index a73fddc0..175b8078 100644 --- a/client/modules/IDE/reducers/ide.js +++ b/client/modules/IDE/reducers/ide.js @@ -3,7 +3,6 @@ import * as ActionTypes from '../../../constants'; const initialState = { isPlaying: false, isTextOutputPlaying: false, - selectedFile: '1', consoleEvent: { method: undefined, arguments: [] @@ -55,4 +54,15 @@ const ide = (state = initialState, action) => { } }; +export const setDefaultSelectedFile = (state, files) => { + if (!state.selectedFile) { + files.forEach((file) => { + if (file.name !== 'root') { + state.selectedFile = file.id; // eslint-disable-line + } + }); + } + return state; +}; + export default ide; diff --git a/server/controllers/project.controller.js b/server/controllers/project.controller.js index ee749da4..6698f8a7 100644 --- a/server/controllers/project.controller.js +++ b/server/controllers/project.controller.js @@ -38,7 +38,6 @@ export function getProject(req, res) { if (err) { return res.status(404).send({ message: 'Project with that id does not exist' }); } - return res.json(project); }); } diff --git a/server/models/project.js b/server/models/project.js index 7ee038c3..faa85e48 100644 --- a/server/models/project.js +++ b/server/models/project.js @@ -37,7 +37,7 @@ const fileSchema = new Schema({ name: { type: String, default: 'sketch.js' }, content: { type: String }, url: { type: String }, - children: { type: [Schema.Types.ObjectId], default: [] }, + children: { type: [ String ], default: [] }, fileType: { type: String } }, { timestamps: true, _id: true }); @@ -52,10 +52,7 @@ fileSchema.set('toJSON', { const projectSchema = new Schema({ name: { type: String, default: "Hello p5.js, it's the server" }, user: { type: Schema.Types.ObjectId, ref: 'User' }, - files: { type: [ fileSchema ], default: [{ name: 'sketch.js', content: defaultSketch, _id: new ObjectId() }, - { name: 'index.html', content: defaultHTML, _id: new ObjectId() }, - { name: 'style.css', content: defaultCSS, _id: new ObjectId() }, - { name: 'root', _id: '0'}]}, + files: { type: [ fileSchema ] }, _id: { type: String, default: shortid.generate }, selectedFile: Schema.Types.ObjectId }, { timestamps: true }); @@ -74,6 +71,15 @@ projectSchema.pre('save', function createSelectedFile(next) { project.selectedFile = project.files[0]._id; // eslint-disable-line no-underscore-dangle return next(); } + if (project.isNew && project.files.length === 0) { + let a = new ObjectId(); + let b = new ObjectId(); + let c = new ObjectId(); + project.files = [{ name: 'sketch.js', content: defaultSketch, _id: a }, + { name: 'index.html', content: defaultHTML, _id: b }, + { name: 'style.css', content: defaultCSS, _id: c }, + { name: 'root', _id: '0', children: [a, b, c] }]; + } }); export default mongoose.model('Project', projectSchema);