diff --git a/README.md b/README.md index efefa058..5639195f 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,6 @@ This project is currently in the early stages of development! It will definitely GITHUB_ID= GITHUB_SECRET= ``` - For production, you will need to have real Github and Amazon credentions. Refer to [this gist](https://gist.github.com/catarak/70c9301f0fd1ac2d6b58de03f61997e3) for creating an S3 bucket for testing. 5. `$ npm run build` 6. `$ npm run start:prod` diff --git a/client/constants.js b/client/constants.js index ef4f9041..da70c015 100644 --- a/client/constants.js +++ b/client/constants.js @@ -35,6 +35,8 @@ export const HIDE_EDIT_PROJECT_NAME = 'HIDE_EDIT_PROJECT_NAME'; export const SET_PROJECT = 'SET_PROJECT'; export const SET_PROJECTS = 'SET_PROJECTS'; +export const DELETE_PROJECT = 'DELETE_PROJECT'; + export const SET_SELECTED_FILE = 'SET_SELECTED_FILE'; export const SHOW_MODAL = 'SHOW_MODAL'; export const HIDE_MODAL = 'HIDE_MODAL'; diff --git a/client/images/trash-can.svg b/client/images/trash-can.svg new file mode 100755 index 00000000..8b0caffd --- /dev/null +++ b/client/images/trash-can.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/client/modules/IDE/actions/projects.js b/client/modules/IDE/actions/projects.js index 71bd5db0..4595d759 100644 --- a/client/modules/IDE/actions/projects.js +++ b/client/modules/IDE/actions/projects.js @@ -29,3 +29,15 @@ export function getProjects(username) { export function closeSketchList() { browserHistory.goBack(); } + +export function deleteProject(id) { + return (dispatch) => { + axios.delete(`${ROOT_URL}/projects/${id}`, { withCredentials: true }) + .then(() => { + dispatch({ + type: ActionTypes.DELETE_PROJECT, + id + }); + }); + }; +} diff --git a/client/modules/IDE/components/SketchList.js b/client/modules/IDE/components/SketchList.js index 524a7df2..f7919b9d 100644 --- a/client/modules/IDE/components/SketchList.js +++ b/client/modules/IDE/components/SketchList.js @@ -7,6 +7,7 @@ import * as SketchActions from '../actions/projects'; import * as ProjectActions from '../actions/project'; import InlineSVG from 'react-inlinesvg'; const exitUrl = require('../../../images/exit.svg'); +const trashCan = require('../../../images/trash-can.svg'); class SketchList extends React.Component { componentDidMount() { @@ -27,6 +28,7 @@ class SketchList extends React.Component { + @@ -34,7 +36,19 @@ class SketchList extends React.Component { {this.props.sketches.map(sketch => - + + @@ -53,7 +67,8 @@ SketchList.propTypes = { getProjects: PropTypes.func.isRequired, sketches: PropTypes.array.isRequired, closeSketchList: PropTypes.func.isRequired, - username: PropTypes.string + username: PropTypes.string, + deleteProject: PropTypes.func.isRequired }; function mapStateToProps(state) { diff --git a/client/modules/IDE/reducers/projects.js b/client/modules/IDE/reducers/projects.js index b973bccc..f167c8a3 100644 --- a/client/modules/IDE/reducers/projects.js +++ b/client/modules/IDE/reducers/projects.js @@ -4,6 +4,10 @@ const sketches = (state = [], action) => { switch (action.type) { case ActionTypes.SET_PROJECTS: return action.projects; + case ActionTypes.DELETE_PROJECT: + return state.filter((sketch) => + sketch.id !== action.id + ); default: return state; } diff --git a/client/modules/Sketch/actions.js b/client/modules/Sketch/actions.js deleted file mode 100644 index ed980d4e..00000000 --- a/client/modules/Sketch/actions.js +++ /dev/null @@ -1,20 +0,0 @@ -import * as ActionTypes from '../../constants'; -import axios from 'axios'; - -const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api'; - -export function getProjects() { - return (dispatch) => { - axios.get(`${ROOT_URL}/projects`, { withCredentials: true }) - .then(response => { - dispatch({ - type: ActionTypes.SET_PROJECTS, - projects: response.data - }); - }) - .catch(response => dispatch({ - type: ActionTypes.ERROR, - error: response.data - })); - }; -} diff --git a/client/modules/Sketch/pages/SketchListView.js b/client/modules/Sketch/pages/SketchListView.js deleted file mode 100644 index 1f775429..00000000 --- a/client/modules/Sketch/pages/SketchListView.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { PropTypes } from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import moment from 'moment'; -import { Link } from 'react-router'; -import Nav from '../../../components/Nav'; -import * as SketchActions from '../actions'; -import * as ProjectActions from '../../IDE/actions/project'; - -class SketchListView extends React.Component { - componentDidMount() { - this.props.getProjects(); - } - - render() { - return ( -
-
Name Created Last Updated
+ + {sketch.name} {moment(sketch.createdAt).format('MMM D, YYYY h:mm:ss A')} {moment(sketch.updatedAt).format('MMM D, YYYY h:mm:ss A')}
- - - - - - - - - {this.props.sketches.map(sketch => - - - - - - )} - -
NameCreatedLast Updated
{sketch.name}{moment(sketch.createdAt).format('MMM D, YYYY')}{moment(sketch.updatedAt).format('MMM D, YYYY')}
- - - ); - } -} - -SketchListView.propTypes = { - user: PropTypes.object.isRequired, - newProject: PropTypes.func.isRequired, - saveProject: PropTypes.func.isRequired, - getProjects: PropTypes.func.isRequired, - sketches: PropTypes.array.isRequired, - exportProjectAsZip: PropTypes.func.isRequired, - cloneProject: PropTypes.func.isRequired -}; - -function mapStateToProps(state) { - return { - user: state.user, - sketches: state.sketches - }; -} - -function mapDispatchToProps(dispatch) { - return bindActionCreators(Object.assign({}, SketchActions, ProjectActions), dispatch); -} - -export default connect(mapStateToProps, mapDispatchToProps)(SketchListView); diff --git a/client/modules/Sketch/reducers.js b/client/modules/Sketch/reducers.js deleted file mode 100644 index 6f0d2e14..00000000 --- a/client/modules/Sketch/reducers.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as ActionTypes from '../../constants'; - -const sketches = (state = [], action) => { - switch (action.type) { - case ActionTypes.SET_PROJECTS: - return action.projects; - default: - return state; - } -}; - -export default sketches; diff --git a/client/reducers.js b/client/reducers.js index 8581c55b..f3a433d3 100644 --- a/client/reducers.js +++ b/client/reducers.js @@ -5,7 +5,7 @@ import preferences from './modules/IDE/reducers/preferences'; import project from './modules/IDE/reducers/project'; import editorAccessibility from './modules/IDE/reducers/editorAccessibility'; import user from './modules/User/reducers'; -import sketches from './modules/Sketch/reducers'; +import sketches from './modules/IDE/reducers/projects'; import toast from './modules/IDE/reducers/toast'; import { reducer as form } from 'redux-form'; diff --git a/client/styles/components/_sketch-list.scss b/client/styles/components/_sketch-list.scss index a630b148..188713b2 100644 --- a/client/styles/components/_sketch-list.scss +++ b/client/styles/components/_sketch-list.scss @@ -23,14 +23,41 @@ padding: #{10 / $base-font-size}rem 0; padding-left: #{20 / $base-font-size}rem; max-height: 100%; + + & .sketch-list__trash-column { + width: #{22 / $base-font-size}rem; + } } .sketches-table__row { margin: #{10 / $base-font-size}rem; + height: #{25 / $base-font-size}rem; } .sketch-list__exit-button { @include themify() { @extend %icon; } -} \ No newline at end of file +} + +.visibility-toggle .sketch-list__trash-button { + @extend %hidden-element; +} + +.visibility-toggle:hover .sketch-list__trash-button { + @include themify() { + background-color: transparent; + border: none; + cursor: pointer; + padding: 0; + position: initial; + left: 0; + top: 0; + width:#{20 / $base-font-size}rem; + height:#{20 / $base-font-size}rem; + & g { + opacity: 1; + fill: getThemifyVariable('icon-hover-color'); + } + } +} diff --git a/server/controllers/project.controller.js b/server/controllers/project.controller.js index bdcd728d..ec46869f 100644 --- a/server/controllers/project.controller.js +++ b/server/controllers/project.controller.js @@ -60,6 +60,15 @@ export function getProject(req, res) { }); } +export function deleteProject(req, res) { + Project.remove({_id: req.params.project_id}, (err) => { + if (err) { + return res.status(404).send({ message: 'Project with that id does not exist' }); + } + return res.json({ success: true }); + }); +} + export function getProjects(req, res) { if (req.user) { Project.find({user: req.user._id}) // eslint-disable-line no-underscore-dangle diff --git a/server/routes/project.routes.js b/server/routes/project.routes.js index 36bef1b6..1cff8e54 100644 --- a/server/routes/project.routes.js +++ b/server/routes/project.routes.js @@ -9,6 +9,8 @@ router.route('/projects/:project_id').put(ProjectController.updateProject); router.route('/projects/:project_id').get(ProjectController.getProject); +router.route('/projects/:project_id').delete(ProjectController.deleteProject); + router.route('/projects').get(ProjectController.getProjects); router.route('/:username/projects').get(ProjectController.getProjectsForUser);