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