diff --git a/client/constants.js b/client/constants.js index 9c5f9ae353..73b58b820d 100644 --- a/client/constants.js +++ b/client/constants.js @@ -63,6 +63,7 @@ export const CLEAR_LINT_MESSAGE = 'CLEAR_LINT_MESSAGE'; export const TOGGLE_FORCE_DESKTOP = 'TOGGLE_FORCE_DESKTOP'; export const UPDATE_FILE_NAME = 'UPDATE_FILE_NAME'; +export const CHANGE_PARENT = 'CHANGE_PARENT'; export const DELETE_FILE = 'DELETE_FILE'; export const SET_AUTOSAVE = 'SET_AUTOSAVE'; diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js index f87f5d1c6d..69318d5107 100644 --- a/client/modules/IDE/actions/files.js +++ b/client/modules/IDE/actions/files.js @@ -53,6 +53,16 @@ export function createFile(file, parentId) { }; } +export function changeParent(id, oldParentId, newParentId) { + return (dispatch) => + dispatch({ + type: ActionTypes.CHANGE_PARENT, + id, + oldParentId, + newParentId + }); +} + export function submitFile(formProps, files, parentId, projectId) { if (projectId) { const postParams = { diff --git a/client/modules/IDE/components/FileNode.jsx b/client/modules/IDE/components/FileNode.jsx index 0b6424a783..42c7c52830 100644 --- a/client/modules/IDE/components/FileNode.jsx +++ b/client/modules/IDE/components/FileNode.jsx @@ -230,6 +230,45 @@ class FileNode extends React.Component { this.props.hideFolderChildren(this.props.id); }; + handleDrag = (e) => { + e.dataTransfer.setData('text', `${this.props.id} ${this.props.parentId}`); + }; + + handleDragOver = (e) => { + e.preventDefault(); + if (this.props.fileType === 'folder') { + e.target.parentNode.parentNode.style.border = '1px solid #ed225d'; + } else if (this.props.fileType === 'file') { + e.target.parentNode.parentNode.parentNode.parentNode.parentNode.style.border = + '1px solid #ed225d'; + } + }; + + handleDragLeave = (e) => { + e.preventDefault(); + if (this.props.fileType === 'folder') { + e.target.parentNode.parentNode.style.border = null; + } else if (this.props.fileType === 'file') { + e.target.parentNode.parentNode.parentNode.parentNode.parentNode.style.border = null; + } + }; + + handleDrop = (e) => { + e.preventDefault(); + const dragPayload = e.dataTransfer.getData('text'); + const [id, oldParentId] = dragPayload.split(' '); + let newParentId = null; + if (this.props.fileType === 'folder') { + newParentId = this.props.id; + this.props.showFolderChildren(this.props.id); + e.target.parentNode.parentNode.style.border = null; + } else if (this.props.fileType === 'file') { + e.target.parentNode.parentNode.parentNode.parentNode.parentNode.style.border = null; + newParentId = this.props.parentId; + } + this.props.changeParent(id, oldParentId, newParentId); + }; + renderChild = (childId) => (
  • +
    this.getRootID()}> {!isRoot && (
    this.handleDrag(e)} + onDrop={(e) => this.handleDrop(e)} + onDragOver={(e) => this.handleDragOver(e)} + onDragLeave={(e) => this.handleDragLeave(e)} onContextMenu={this.toggleFileOptions} > @@ -418,6 +462,7 @@ FileNode.propTypes = { deleteFile: PropTypes.func.isRequired, updateFileName: PropTypes.func.isRequired, resetSelectedFile: PropTypes.func.isRequired, + changeParent: PropTypes.func.isRequired, newFile: PropTypes.func.isRequired, newFolder: PropTypes.func.isRequired, showFolderChildren: PropTypes.func.isRequired, diff --git a/client/modules/IDE/reducers/files.js b/client/modules/IDE/reducers/files.js index de1b9b1aa7..65a4dfe8fd 100644 --- a/client/modules/IDE/reducers/files.js +++ b/client/modules/IDE/reducers/files.js @@ -108,6 +108,20 @@ function updateParent(state, action) { }); } +function changeParent(state, action) { + return state.map((file) => { + // Add to children list of new parent + if (file.id === action.newParentId) { + file.children = [...file.children, action.id]; + } + // Remove from children list of old parent + else if (file.id === action.oldParentId) { + file.children = file.children.filter((childId) => childId !== action.id); + } + return file; + }); +} + function renameFile(state, action) { return state.map((file) => { if (file.id !== action.id) { @@ -230,6 +244,9 @@ const files = (state, action) => { return file; }); } + case ActionTypes.CHANGE_PARENT: { + return changeParent(state, action); + } case ActionTypes.DELETE_FILE: { const newState = deleteMany(state, [ action.id,