diff --git a/client/modules/IDE/components/FileNode.jsx b/client/modules/IDE/components/FileNode.jsx index 882b2070..aecefccf 100644 --- a/client/modules/IDE/components/FileNode.jsx +++ b/client/modules/IDE/components/FileNode.jsx @@ -6,40 +6,29 @@ import InlineSVG from 'react-inlinesvg'; import classNames from 'classnames'; import * as IDEActions from '../actions/ide'; import * as FileActions from '../actions/files'; - -const downArrowUrl = require('../../../images/down-filled-triangle.svg'); -const folderRightUrl = require('../../../images/triangle-arrow-right.svg'); -const folderDownUrl = require('../../../images/triangle-arrow-down.svg'); -const fileUrl = require('../../../images/file.svg'); +import downArrowUrl from '../../../images/down-filled-triangle.svg'; +import folderRightUrl from '../../../images/triangle-arrow-right.svg'; +import folderDownUrl from '../../../images/triangle-arrow-down.svg'; +import fileUrl from '../../../images/file.svg'; export class FileNode extends React.Component { constructor(props) { super(props); - this.renderChild = this.renderChild.bind(this); - this.handleKeyPress = this.handleKeyPress.bind(this); - this.handleFileNameChange = this.handleFileNameChange.bind(this); - this.validateFileName = this.validateFileName.bind(this); - this.handleFileClick = this.handleFileClick.bind(this); - this.toggleFileOptions = this.toggleFileOptions.bind(this); - this.hideFileOptions = this.hideFileOptions.bind(this); - this.showEditFileName = this.showEditFileName.bind(this); - this.hideEditFileName = this.hideEditFileName.bind(this); - this.onBlurComponent = this.onBlurComponent.bind(this); - this.onFocusComponent = this.onFocusComponent.bind(this); this.state = { isOptionsOpen: false, isEditingName: false, isFocused: false, + isDeleting: false, updatedName: this.props.name }; } - onFocusComponent() { + onFocusComponent = () => { this.setState({ isFocused: true }); } - onBlurComponent() { + onBlurComponent = () => { this.setState({ isFocused: false }); setTimeout(() => { if (!this.state.isFocused) { @@ -48,11 +37,12 @@ export class FileNode extends React.Component { }, 200); } - get updatedName() { - return this.state.updatedName; + + setUpdatedName = (updatedName) => { + this.setState({ updatedName }); } - commitFileNameChange() { + saveUpdatedFileName = () => { const { updatedName } = this.state; const { name, updateFileName, id } = this.props; @@ -61,42 +51,77 @@ export class FileNode extends React.Component { } } - handleFileClick(e) { - e.stopPropagation(); - if (this.updatedName !== 'root' && !this.isDeleting) { - this.props.setSelectedFile(this.props.id); + handleFileClick = (event) => { + event.stopPropagation(); + const { isDeleting } = this.state; + const { id, setSelectedFile, name } = this.props; + if (name !== 'root' && !isDeleting) { + setSelectedFile(id); } } - handleFileNameChange(event) { - const newname = event.target.value; - this.setState({ updatedName: newname }); + handleFileNameChange = (event) => { + const newName = event.target.value; + this.setUpdatedName(newName); } - handleKeyPress(event) { + handleFileNameBlur = () => { + this.validateFileName(); + this.hideEditFileName(); + } + + handleClickRename = () => { + this.setUpdatedName(this.props.name); + this.showEditFileName(); + setTimeout(() => this.fileNameInput.focus(), 0); + setTimeout(() => this.hideFileOptions(), 0); + } + + handleClickAddFile = () => { + this.props.newFile(this.props.id); + setTimeout(() => this.hideFileOptions(), 0); + } + + handleClickAddFolder = () => { + this.props.newFolder(this.props.id); + setTimeout(() => this.hideFileOptions(), 0); + } + + handleClickDelete = () => { + if (window.confirm(`Are you sure you want to delete ${this.props.name}?`)) { + this.setState({ isDeleting: true }); + this.props.resetSelectedFile(this.props.id); + setTimeout(() => this.props.deleteFile(this.props.id, this.props.parentId), 100); + } + } + + handleKeyPress = (event) => { if (event.key === 'Enter') { this.hideEditFileName(); } } - validateFileName() { - const oldFileExtension = this.originalFileName.match(/\.[0-9a-z]+$/i); - const newFileExtension = this.updatedName.match(/\.[0-9a-z]+$/i); - const hasPeriod = this.updatedName.match(/\.+/); - const newFileName = this.updatedName; + validateFileName = () => { + const currentName = this.props.name; + const { updatedName } = this.state; + const oldFileExtension = currentName.match(/\.[0-9a-z]+$/i); + const newFileExtension = updatedName.match(/\.[0-9a-z]+$/i); + const hasPeriod = updatedName.match(/\.+/); const hasNoExtension = oldFileExtension && !newFileExtension; const hasExtensionIfFolder = this.props.fileType === 'folder' && hasPeriod; const notSameExtension = oldFileExtension && newFileExtension && oldFileExtension[0].toLowerCase() !== newFileExtension[0].toLowerCase(); - const hasEmptyFilename = newFileName === ''; - const hasOnlyExtension = newFileExtension && newFileName === newFileExtension[0]; + const hasEmptyFilename = updatedName === ''; + const hasOnlyExtension = newFileExtension && updatedName === newFileExtension[0]; if (hasEmptyFilename || hasNoExtension || notSameExtension || hasOnlyExtension || hasExtensionIfFolder) { - this.setState({ updatedName: this.originalFileName }); - } else this.commitFileNameChange(); + this.setUpdatedName(currentName); + } else { + this.saveUpdatedFileName(); + } } - toggleFileOptions(e) { - e.preventDefault(); + toggleFileOptions = (event) => { + event.preventDefault(); if (!this.props.canEdit) { return; } @@ -108,181 +133,156 @@ export class FileNode extends React.Component { } } - hideFileOptions() { + hideFileOptions = () => { this.setState({ isOptionsOpen: false }); } - showEditFileName() { + showEditFileName = () => { this.setState({ isEditingName: true }); } - hideEditFileName() { + hideEditFileName = () => { this.setState({ isEditingName: false }); } - renderChild(childId) { - return ( -
  • - -
  • - ); + showFolderChildren = () => { + this.props.showFolderChildren(this.props.id); } + hideFolderChildren = () => { + this.props.hideFolderChildren(this.props.id); + } + + renderChild = childId => ( +
  • + +
  • + ) + render() { const itemClass = classNames({ - 'sidebar__root-item': this.updatedName === 'root', - 'sidebar__file-item': this.updatedName !== 'root', + 'sidebar__root-item': this.props.name === 'root', + 'sidebar__file-item': this.props.name !== 'root', 'sidebar__file-item--selected': this.props.isSelectedFile, 'sidebar__file-item--open': this.state.isOptionsOpen, 'sidebar__file-item--editing': this.state.isEditingName, 'sidebar__file-item--closed': this.props.isFolderClosed }); + const isFile = this.props.fileType === 'file'; + const isFolder = this.props.fileType === 'folder'; + const isRoot = this.props.name === 'root'; + return (
    - {(() => { // eslint-disable-line - if (this.updatedName !== 'root') { - return ( -
    - - {(() => { // eslint-disable-line - if (this.props.fileType === 'file') { - return ( - - - - ); - } - return ( -
    - - -
    - ); - })()} - - { this.fileNameInput = element; }} - onBlur={() => { - this.validateFileName(); - this.hideEditFileName(); - }} - onKeyPress={this.handleKeyPress} - /> + { !isRoot && +
    + + { isFile && + + + + } + { isFolder && +
    + -
    -
      - {(() => { // eslint-disable-line - if (this.props.fileType === 'folder') { - return ( -
    • - -
    • - ); - } - })()} - {(() => { // eslint-disable-line - if (this.props.fileType === 'folder') { - return ( -
    • - -
    • - ); - } - })()} -
    • - -
    • -
    • - -
    • -
    -
    - ); - } - })()} - {(() => { // eslint-disable-line - if (this.props.children) { - return ( -
      - {this.props.children.map(this.renderChild)} + } + + { this.fileNameInput = element; }} + onBlur={this.handleFileNameBlur} + onKeyPress={this.handleKeyPress} + /> + +
      +
        + { isFolder && + +
      • + +
      • +
      • + +
      • +
        + } +
      • + +
      • +
      • + +
      - ); - } - })()} +
      +
    + } + { this.props.children && + + }
    ); }