start to add selected file stuff
This commit is contained in:
parent
e06c821923
commit
7a84137e9b
9 changed files with 70 additions and 19 deletions
|
@ -23,5 +23,7 @@ export const NEW_PROJECT = 'NEW_PROJECT';
|
|||
export const SET_PROJECT = 'SET_PROJECT';
|
||||
export const SET_PROJECTS = 'SET_PROJECTS';
|
||||
|
||||
export const SET_SELECTED_FILE = 'SET_SELECTED_FILE';
|
||||
|
||||
// eventually, handle errors more specifically and better
|
||||
export const ERROR = 'ERROR';
|
||||
|
|
|
@ -12,7 +12,8 @@ export function getProject(id) {
|
|||
dispatch({
|
||||
type: ActionTypes.SET_PROJECT,
|
||||
project: response.data,
|
||||
files: response.data.files
|
||||
files: response.data.files,
|
||||
selectedFile: response.data.selectedFile
|
||||
});
|
||||
})
|
||||
.catch(response => dispatch({
|
||||
|
@ -34,7 +35,7 @@ export function saveProject() {
|
|||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const formParams = Object.assign({}, state.project);
|
||||
formParams.files = state.files;
|
||||
formParams.files = [...state.files];
|
||||
if (state.project.id) {
|
||||
axios.put(`${ROOT_URL}/projects/${state.project.id}`, formParams, { withCredentials: true })
|
||||
.then(() => {
|
||||
|
@ -47,6 +48,12 @@ export function saveProject() {
|
|||
error: response.data
|
||||
}));
|
||||
} 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;
|
||||
});
|
||||
axios.post(`${ROOT_URL}/projects`, formParams, { withCredentials: true })
|
||||
.then(response => {
|
||||
browserHistory.push(`/projects/${response.data.id}`);
|
||||
|
@ -54,6 +61,7 @@ export function saveProject() {
|
|||
type: ActionTypes.NEW_PROJECT,
|
||||
name: response.data.name,
|
||||
id: response.data.id,
|
||||
selectedFile: response.data.selectedFile,
|
||||
files: response.data.files
|
||||
});
|
||||
})
|
||||
|
@ -75,6 +83,7 @@ export function createProject() {
|
|||
type: ActionTypes.NEW_PROJECT,
|
||||
name: response.data.name,
|
||||
id: response.data.id,
|
||||
selectedFile: response.data.selectedFile,
|
||||
files: response.data.files
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,22 +1,32 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
function Sidebar(props) {
|
||||
return (
|
||||
<section className="sidebar">
|
||||
<ul className="sidebar__file-list">
|
||||
{props.files.map(file =>
|
||||
{props.files.map(file => {
|
||||
let itemClass = classNames({
|
||||
'sidebar__file-item': true,
|
||||
'sidebar__file-item--selected': file.id === props.selectedFile.id
|
||||
});
|
||||
return (
|
||||
<li
|
||||
className="sidebar__file-item"
|
||||
className={itemClass}
|
||||
key={file.id}
|
||||
>{file.name}</li>
|
||||
)}
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Sidebar.propTypes = {
|
||||
files: PropTypes.array.isRequired
|
||||
files: PropTypes.array.isRequired,
|
||||
selectedFile: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired
|
||||
})
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
|
|
|
@ -11,6 +11,7 @@ import * as FileActions from '../actions/files';
|
|||
import * as IDEActions from '../actions/ide';
|
||||
import * as PreferencesActions from '../actions/preferences';
|
||||
import * as ProjectActions from '../actions/project';
|
||||
import { getFile } from '../reducers/files';
|
||||
|
||||
class IDEView extends React.Component {
|
||||
componentDidMount() {
|
||||
|
@ -45,14 +46,18 @@ class IDEView extends React.Component {
|
|||
decreaseFont={this.props.decreaseFont}
|
||||
fontSize={this.props.preferences.fontSize}
|
||||
/>
|
||||
<Sidebar files={this.props.files} />
|
||||
<Sidebar
|
||||
files={this.props.files}
|
||||
selectedFile={this.props.selectedFile}
|
||||
/>
|
||||
<Editor
|
||||
content={this.props.files[0].content}
|
||||
content={this.props.selectedFile.content}
|
||||
updateFileContent={this.props.updateFileContent}
|
||||
fontSize={this.props.preferences.fontSize}
|
||||
files={this.props.files}
|
||||
/>
|
||||
<PreviewFrame
|
||||
content={this.props.files[0].content}
|
||||
content={this.props.selectedFile.content}
|
||||
head={
|
||||
<link type="text/css" rel="stylesheet" href="/preview-styles.css" />
|
||||
}
|
||||
|
@ -89,12 +94,17 @@ IDEView.propTypes = {
|
|||
increaseFont: PropTypes.func.isRequired,
|
||||
decreaseFont: PropTypes.func.isRequired,
|
||||
files: PropTypes.array.isRequired,
|
||||
updateFileContent: PropTypes.func.isRequired
|
||||
updateFileContent: PropTypes.func.isRequired,
|
||||
selectedFile: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
content: PropTypes.string.isRequired
|
||||
})
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
files: state.files,
|
||||
selectedFile: getFile(state.files, state.ide.selectedFile),
|
||||
ide: state.ide,
|
||||
preferences: state.preferences,
|
||||
user: state.user,
|
||||
|
|
|
@ -20,14 +20,18 @@ const defaultHTML =
|
|||
</html>
|
||||
`;
|
||||
|
||||
|
||||
// if the project has never been saved,
|
||||
const initialState = [
|
||||
{
|
||||
name: 'sketch.js',
|
||||
content: defaultSketch
|
||||
content: defaultSketch,
|
||||
id: '1'
|
||||
},
|
||||
{
|
||||
name: 'index.html',
|
||||
content: defaultHTML
|
||||
content: defaultHTML,
|
||||
id: '2'
|
||||
}];
|
||||
|
||||
|
||||
|
@ -50,4 +54,6 @@ const files = (state = initialState, action) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getFile = (state, id) => state.filter(file => file.id === id)[0];
|
||||
|
||||
export default files;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import * as ActionTypes from '../../../constants';
|
||||
|
||||
const initialState = {
|
||||
isPlaying: false
|
||||
isPlaying: false,
|
||||
selectedFile: '1'
|
||||
};
|
||||
|
||||
const ide = (state = initialState, action) => {
|
||||
|
@ -18,6 +19,10 @@ const ide = (state = initialState, action) => {
|
|||
return {
|
||||
isPlaying: false
|
||||
};
|
||||
case ActionTypes.SET_SELECTED_FILE:
|
||||
case ActionTypes.SET_PROJECT:
|
||||
case ActionTypes.NEW_PROJECT:
|
||||
return Object.assign({}, state, { selectedFile: action.selectedFile });
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
"babel-core": "^6.8.0",
|
||||
"bcrypt-nodejs": "0.0.3",
|
||||
"body-parser": "^1.15.1",
|
||||
"bson-objectid": "^1.1.4",
|
||||
"classnames": "^2.2.5",
|
||||
"codemirror": "^5.14.2",
|
||||
"connect-mongo": "^1.2.0",
|
||||
|
|
|
@ -2,8 +2,7 @@ import Project from '../models/project';
|
|||
|
||||
export function createProject(req, res) {
|
||||
const projectValues = {
|
||||
user: req.user ? req.user._id : undefined, // eslint-disable-line no-underscore-dangle
|
||||
file: {}
|
||||
user: req.user ? req.user._id : undefined // eslint-disable-line no-underscore-dangle
|
||||
};
|
||||
|
||||
Object.assign(projectValues, req.body);
|
||||
|
|
|
@ -40,7 +40,8 @@ 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() }]},
|
||||
_id: { type: String, default: shortid.generate }
|
||||
_id: { type: String, default: shortid.generate },
|
||||
selectedFile: Schema.Types.ObjectId
|
||||
}, { timestamps: true });
|
||||
|
||||
projectSchema.virtual('id').get(function(){
|
||||
|
@ -51,4 +52,12 @@ projectSchema.set('toJSON', {
|
|||
virtuals: true
|
||||
});
|
||||
|
||||
projectSchema.pre('save', function createSelectedFile(next) {
|
||||
const project = this;
|
||||
if (!project.selectedFile) {
|
||||
project.selectedFile = project.files[0]._id; // eslint-disable-line no-underscore-dangle
|
||||
return next();
|
||||
}
|
||||
});
|
||||
|
||||
export default mongoose.model('Project', projectSchema);
|
||||
|
|
Loading…
Reference in a new issue