From da98dcd47ec304d26c0702843cc2e063b4f79176 Mon Sep 17 00:00:00 2001 From: catarak Date: Wed, 3 Aug 2016 15:11:59 -0400 Subject: [PATCH] add file deletion --- client/constants.js | 6 + client/modules/IDE/actions/files.js | 29 +++++ client/modules/IDE/components/Sidebar.js | 125 ++++++++++--------- client/modules/IDE/components/SidebarItem.js | 73 +++++++++++ client/modules/IDE/pages/IDEView.js | 11 +- client/modules/IDE/reducers/files.js | 34 +++++ client/styles/components/_sidebar.scss | 26 ++++ 7 files changed, 245 insertions(+), 59 deletions(-) create mode 100644 client/modules/IDE/components/SidebarItem.js diff --git a/client/constants.js b/client/constants.js index 50ca8f8e..8e41ad91 100644 --- a/client/constants.js +++ b/client/constants.js @@ -42,5 +42,11 @@ export const CONSOLE_EVENT = 'CONSOLE_EVENT'; export const EXPAND_CONSOLE = 'EXPAND_CONSOLE'; export const COLLAPSE_CONSOLE = 'COLLAPSE_CONSOLE'; +export const SHOW_FILE_OPTIONS = 'SHOW_FILE_OPTIONS'; +export const HIDE_FILE_OPTIONS = 'HIDE_FILE_OPTIONS'; + +export const UPDATE_FILE_NAME = 'UPDATE_FILE_NAME'; +export const DELETE_FILE = 'DELETE_FILE'; + // eventually, handle errors more specifically and better export const ERROR = 'ERROR'; diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js index a4db7961..e7bed3a2 100644 --- a/client/modules/IDE/actions/files.js +++ b/client/modules/IDE/actions/files.js @@ -112,3 +112,32 @@ export function createFile(formProps) { } }; } + +export function showFileOptions(fileId) { + return { + type: ActionTypes.SHOW_FILE_OPTIONS, + id: fileId + }; +} + +export function hideFileOptions(fileId) { + return { + type: ActionTypes.HIDE_FILE_OPTIONS, + id: fileId + }; +} + +export function updateFileName(id, name) { + return { + type: ActionTypes.UPDATE_FILE_NAME, + id, + name + }; +} + +export function deleteFile(id) { + return { + type: ActionTypes.DELETE_FILE, + id + }; +} diff --git a/client/modules/IDE/components/Sidebar.js b/client/modules/IDE/components/Sidebar.js index b680364a..54bcd246 100644 --- a/client/modules/IDE/components/Sidebar.js +++ b/client/modules/IDE/components/Sidebar.js @@ -1,71 +1,84 @@ import React, { PropTypes } from 'react'; import classNames from 'classnames'; import InlineSVG from 'react-inlinesvg'; +import SidebarItem from './SidebarItem'; const rightArrowUrl = require('../../../images/right-arrow.svg'); const leftArrowUrl = require('../../../images/left-arrow.svg'); -function Sidebar(props) { - const sidebarClass = classNames({ - sidebar: true, - 'sidebar--contracted': !props.isExpanded - }); +class Sidebar extends React.Component { + constructor(props) { + super(props); + this.resetSelectedFile = this.resetSelectedFile.bind(this); + } - return ( - - ); + + + + + + + + + + ); + } } Sidebar.propTypes = { files: PropTypes.array.isRequired, - selectedFile: PropTypes.shape({ - id: PropTypes.string.isRequired - }), - setSelectedFile: PropTypes.func.isRequired + setSelectedFile: PropTypes.func.isRequired, + isExpanded: PropTypes.bool.isRequired, + newFile: PropTypes.func.isRequired, + collapseSidebar: PropTypes.func.isRequired, + expandSidebar: PropTypes.func.isRequired, + showFileOptions: PropTypes.func.isRequired, + hideFileOptions: PropTypes.func.isRequired, + deleteFile: PropTypes.func.isRequired }; export default Sidebar; diff --git a/client/modules/IDE/components/SidebarItem.js b/client/modules/IDE/components/SidebarItem.js new file mode 100644 index 00000000..6b749307 --- /dev/null +++ b/client/modules/IDE/components/SidebarItem.js @@ -0,0 +1,73 @@ +import React, { PropTypes } from 'react'; +import InlineSVG from 'react-inlinesvg'; +import classNames from 'classnames'; +const downArrowUrl = require('../../../images/down-arrow.svg'); + +class SidebarItem extends React.Component { + onFocus() { + + } + + render() { + let itemClass = classNames({ + 'sidebar__file-item': true, + 'sidebar__file-item--selected': this.props.file.isSelected, + 'sidebar__file-item--open': this.props.file.isOptionsOpen + }); + return ( +
  • this.props.hideFileOptions(this.props.file.id)} + tabIndex={this.props.fileIndex} + > + this.props.setSelectedFile(this.props.file.id)} + >{this.props.file.name} + this.props.showFileOptions(this.props.file.id)} + > + + +
    + +
    +
  • + ); + } +} + +SidebarItem.propTypes = { + file: PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + isSelected: PropTypes.bool, + isOptionsOpen: PropTypes.bool + }).isRequired, + setSelectedFile: PropTypes.func.isRequired, + fileIndex: PropTypes.number.isRequired, + showFileOptions: PropTypes.func.isRequired, + hideFileOptions: PropTypes.func.isRequired, + deleteFile: PropTypes.func.isRequired, + resetSelectedFile: PropTypes.func.isRequired +}; + +export default SidebarItem; diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js index c5dfd30f..db31bedb 100644 --- a/client/modules/IDE/pages/IDEView.js +++ b/client/modules/IDE/pages/IDEView.js @@ -12,7 +12,7 @@ import { connect } from 'react-redux'; import * as FileActions from '../actions/files'; import * as IDEActions from '../actions/ide'; import * as ProjectActions from '../actions/project'; -import { getFile, getHTMLFile, getJSFiles, getCSSFiles } from '../reducers/files'; +import { getFile, getHTMLFile, getJSFiles, getCSSFiles, setSelectedFile } from '../reducers/files'; class IDEView extends React.Component { componentDidMount() { @@ -50,12 +50,14 @@ class IDEView extends React.Component {
    { return [...action.files]; case ActionTypes.CREATE_FILE: return [...state, { name: action.name, id: action.id, content: '', url: action.url }]; + case ActionTypes.SHOW_FILE_OPTIONS: + return state.map(file => { + if (file.id !== action.id) { + return file; + } + + return Object.assign({}, file, { isOptionsOpen: true }); + }); + case ActionTypes.HIDE_FILE_OPTIONS: + return state.map(file => { + if (file.id !== action.id) { + return file; + } + + return Object.assign({}, file, { isOptionsOpen: false }); + }); + case ActionTypes.UPDATE_FILE_NAME: + return state.map(file => { + if (file.id !== action.id) { + return file; + } + + return Object.assign({}, file, { name: action.name }); + }); + case ActionTypes.DELETE_FILE: + return state.filter(file => file.id !== action.id); default: return state; } }; +export const setSelectedFile = (state, id) => + state.map(file => { + if (file.id === id) { + return Object.assign({}, file, { isSelected: true }); + } + return file; + }); + export const getFile = (state, id) => state.filter(file => file.id === id)[0]; export const getHTMLFile = (state) => state.filter(file => file.name.match(/.*\.html$/))[0]; export const getJSFiles = (state) => state.filter(file => file.name.match(/.*\.js$/)); diff --git a/client/styles/components/_sidebar.scss b/client/styles/components/_sidebar.scss index 5dcd5725..b42dd303 100644 --- a/client/styles/components/_sidebar.scss +++ b/client/styles/components/_sidebar.scss @@ -38,11 +38,37 @@ padding: #{8 / $base-font-size}rem #{20 / $base-font-size}rem; color: $light-inactive-text-color; cursor: pointer; + display: flex; + justify-content: space-between; + position: relative; &--selected { background-color: $ide-border-color; } } +.sidebar__file-item-show-options { + @extend %icon; + display: none; + .sidebar__file-item--selected & { + display: inline-block; + } +} + +.sidebar__file-item-options { + @extend %modal; + position: absolute; + top: 95%; + left: 77%; + display: none; + z-index: 100; + padding: #{8 / $base-font-size}rem #{16 / $base-font-size}rem; + background-color: $light-modal-background-color; + z-index: 100; + .sidebar__file-item--open & { + display: block; + } +} + .sidebar__contract { @extend %icon; height: #{14 / $base-font-size}rem;