start to add create project
This commit is contained in:
parent
165ad75e8b
commit
e1a79ba7a6
12 changed files with 124 additions and 17 deletions
21
server/controllers/project.controller.js
Normal file
21
server/controllers/project.controller.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import Project from '../models/project'
|
||||||
|
|
||||||
|
export function createProject(req, res) {
|
||||||
|
if (req.user) {
|
||||||
|
Project.create({
|
||||||
|
user: req.user._id,
|
||||||
|
file: {}
|
||||||
|
}, function(err, newProject) {
|
||||||
|
if (err) { return res.json({success: false}) }
|
||||||
|
return res.json({
|
||||||
|
name: newProject.name,
|
||||||
|
file: {
|
||||||
|
name: newProject.file.name,
|
||||||
|
content: newProject.file.content
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.json({success: false});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
import mongoose from 'mongoose';
|
|
||||||
const Schema = mongoose.Schema;
|
|
||||||
|
|
||||||
const fileSchema = new Schema({
|
|
||||||
name: {type: String, default: 'sketch.js'},
|
|
||||||
project: {type: Schema.Types.ObjectId, ref: 'Project'},
|
|
||||||
content: {type: String}
|
|
||||||
}, {timestamps: true});
|
|
||||||
|
|
||||||
export default mongoose.model('File', fileSchema);
|
|
|
@ -1,10 +1,15 @@
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
const Schema = mongoose.Schema;
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
const fileSchema = new Schema({
|
||||||
|
name: {type: String, default: 'sketch.js'},
|
||||||
|
content: {type: String}
|
||||||
|
}, {timestamps: true});
|
||||||
|
|
||||||
const projectSchema = new Schema({
|
const projectSchema = new Schema({
|
||||||
name: {type: String, default: 'Hello p5.js'},
|
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'},
|
||||||
file: {type: Schema.Types.ObjectId, ref: 'File'}
|
file: {type: fileSchema}
|
||||||
}, {timestamps: true});
|
}, {timestamps: true});
|
||||||
|
|
||||||
export default mongoose.model('Project', projectSchema);
|
export default mongoose.model('Project', projectSchema);
|
8
server/routes/project.routes.js
Normal file
8
server/routes/project.routes.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Router } from 'express';
|
||||||
|
import * as ProjectController from '../controllers/project.controller';
|
||||||
|
|
||||||
|
const router = new Router();
|
||||||
|
|
||||||
|
router.route('/projects').post(ProjectController.createProject);
|
||||||
|
|
||||||
|
export default router;
|
|
@ -24,6 +24,7 @@ app.use(webpackHotMiddleware(compiler));
|
||||||
import serverConfig from './config';
|
import serverConfig from './config';
|
||||||
import users from './routes/user.routes';
|
import users from './routes/user.routes';
|
||||||
import sessions from './routes/session.routes';
|
import sessions from './routes/session.routes';
|
||||||
|
import projects from './routes/project.routes';
|
||||||
|
|
||||||
//Body parser, cookie parser, sessions, serve public assets
|
//Body parser, cookie parser, sessions, serve public assets
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ app.use(passport.initialize());
|
||||||
app.use(passport.session());
|
app.use(passport.session());
|
||||||
app.use('/', users);
|
app.use('/', users);
|
||||||
app.use('/', sessions);
|
app.use('/', sessions);
|
||||||
|
app.use('/', projects);
|
||||||
|
|
||||||
const passportConfig = require('./config/passport');
|
const passportConfig = require('./config/passport');
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,22 @@ class Nav extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<nav className="nav">
|
<nav className="nav">
|
||||||
<ul className="nav__items">
|
<ul className="nav__items-left">
|
||||||
<li>
|
<li className="nav__item">
|
||||||
|
<p className="nav__new"
|
||||||
|
onClick={this.props.createProject}>
|
||||||
|
New
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li className="nav__item">
|
||||||
|
<p className="nav__save"
|
||||||
|
onClick={this.props.saveProject}>
|
||||||
|
Save
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul className="nav__items-right">
|
||||||
|
<li className="nav__item">
|
||||||
{this.props.user.authenticated && <p>Hello, {this.props.user.username}!</p>}
|
{this.props.user.authenticated && <p>Hello, {this.props.user.username}!</p>}
|
||||||
{!this.props.user.authenticated && <p><Link to={`/login`}>Login</Link> or <Link to={`/signup`}>Sign Up</Link></p>}
|
{!this.props.user.authenticated && <p><Link to={`/login`}>Login</Link> or <Link to={`/signup`}>Sign Up</Link></p>}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -12,7 +12,9 @@ class IDEView extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="ide">
|
<div className="ide">
|
||||||
<Nav user={this.props.user}/>
|
<Nav user={this.props.user}
|
||||||
|
createProject={this.props.createProject}
|
||||||
|
saveProject={this.props.saveProject}/>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
className="Toolbar"
|
className="Toolbar"
|
||||||
isPlaying={this.props.ide.isPlaying}
|
isPlaying={this.props.ide.isPlaying}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import * as ActionTypes from '../constants/constants';
|
import * as ActionTypes from '../constants/constants';
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000' : '/';
|
||||||
|
|
||||||
export function updateFile(name, content) {
|
export function updateFile(name, content) {
|
||||||
return {
|
return {
|
||||||
|
@ -49,3 +52,37 @@ export function decreaseFont() {
|
||||||
type: ActionTypes.DECREASE_FONTSIZE
|
type: ActionTypes.DECREASE_FONTSIZE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function saveProject() {
|
||||||
|
// return function(dispatch) {
|
||||||
|
// let projectValues = {};
|
||||||
|
// axios.put(`${ROOT_URL}/projects`, projectValues, {withCredentials: true})
|
||||||
|
// .then(response => {
|
||||||
|
// dispatch({
|
||||||
|
// type: ActionTypes.PROJECT_SAVE_SUCCESS
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
// .catch(response => dispatch({
|
||||||
|
// type: ActionTypes.PROJECT_SAVE_FAIL
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
return function(dispatch) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function createProject() {
|
||||||
|
return function(dispatch) {
|
||||||
|
axios.post(`${ROOT_URL}/projects`, {}, {withCredentials: true})
|
||||||
|
.then(response => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.NEW_PROJECT,
|
||||||
|
name: response.data.name
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(response => dispatch({
|
||||||
|
type: ActionTypes.PROJECT_SAVE_FAIL
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,3 +15,8 @@ export const UNAUTH_USER = 'UNAUTH_USER';
|
||||||
export const AUTH_ERROR = 'AUTH_ERROR';
|
export const AUTH_ERROR = 'AUTH_ERROR';
|
||||||
|
|
||||||
export const SET_PROJECT_NAME = 'SET_PROJECT_NAME';
|
export const SET_PROJECT_NAME = 'SET_PROJECT_NAME';
|
||||||
|
|
||||||
|
export const PROJECT_SAVE_SUCCESS = 'PROJECT_SAVE_SUCCESS';
|
||||||
|
export const PROJECT_SAVE_FAIL = 'PROJECT_SAVE_FAIL';
|
||||||
|
export const NEW_PROJECT = 'NEW_PROJECT';
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@ const project = (state = initialState, action) => {
|
||||||
return {
|
return {
|
||||||
name: action.name
|
name: action.name
|
||||||
}
|
}
|
||||||
|
case ActionTypes.NEW_PROJECT:
|
||||||
|
return {
|
||||||
|
name: action.name
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,3 +67,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%fake-link {
|
||||||
|
color: $light-secondary-text-color;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: $light-primary-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
.nav {
|
.nav {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: #{10 / $base-font-size}rem #{40 / $base-font-size}rem;
|
padding: #{10 / $base-font-size}rem #{40 / $base-font-size}rem;
|
||||||
|
padding-left: #{170 / $base-font-size}rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-end;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav__items {
|
.nav__items-left, .nav__items-right {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -14,3 +15,13 @@
|
||||||
padding: #{5 / $base-font-size}rem #{10 / $base-font-size}rem;
|
padding: #{5 / $base-font-size}rem #{10 / $base-font-size}rem;
|
||||||
border-bottom: 2px dashed;
|
border-bottom: 2px dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav__save, .nav__new {
|
||||||
|
@extend %fake-link;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav__item {
|
||||||
|
& + & {
|
||||||
|
margin-left: #{20 / $base-font-size}rem;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue