start to add selected file stuff

This commit is contained in:
catarak 2016-07-08 14:57:22 -04:00
parent e06c821923
commit 7a84137e9b
9 changed files with 70 additions and 19 deletions

View file

@ -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';

View file

@ -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
});
})

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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",

View file

@ -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);

View file

@ -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);