Display modal on delete

pull/5370/head
ioedeveloper 4 years ago
parent 660aa44ee0
commit ae560ac72e
  1. 132
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  2. 77
      libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.tsx
  3. 14
      libs/remix-ui/modal-dialog/src/lib/types/index.ts

@ -3,6 +3,7 @@ import { TreeView, TreeViewItem } from '@remix-ui/tree-view' // eslint-disable-l
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd' // eslint-disable-line import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd' // eslint-disable-line
import { FileExplorerMenu } from './file-explorer-menu' // eslint-disable-line import { FileExplorerMenu } from './file-explorer-menu' // eslint-disable-line
import { FileExplorerContextMenu } from './file-explorer-context-menu' // eslint-disable-line import { FileExplorerContextMenu } from './file-explorer-context-menu' // eslint-disable-line
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { FileExplorerProps, File } from './types' import { FileExplorerProps, File } from './types'
import * as helper from '../../../../../apps/remix-ide/src/lib/helper' import * as helper from '../../../../../apps/remix-ide/src/lib/helper'
@ -34,7 +35,21 @@ export const FileExplorer = (props: FileExplorerProps) => {
isNew: false isNew: false
}, },
fileExternallyChanged: false, fileExternallyChanged: false,
expandPath: [] expandPath: [],
modalOptions: {
hide: true,
title: '',
message: '',
ok: {
label: 'Ok',
fn: null
},
cancel: {
label: 'Cancel',
fn: null
},
handleHide: null
}
}) })
useEffect(() => { useEffect(() => {
@ -147,7 +162,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
const createNewFile = (parentFolder: string, newFilePath: string) => { const createNewFile = (parentFolder: string, newFilePath: string) => {
// if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name
const fileManager = state.fileManager const fileManager = state.fileManager
helper.createNonClashingName(newFilePath, filesProvider, async (error, newName) => { helper.createNonClashingName(newFilePath, filesProvider, async (error, newName) => {
@ -166,8 +180,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
const createNewFolder = async (parentFolder: string, newFolderPath: string) => { const createNewFolder = async (parentFolder: string, newFolderPath: string) => {
// if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name
// else if (parentFolder.indexOf('.sol') !== -1) parentFolder = extractParentFromKey(parentFolder)
// const self = this // const self = this
// modalDialogCustom.prompt('Create new folder', '', 'New folder', (input) => { // modalDialogCustom.prompt('Create new folder', '', 'New folder', (input) => {
// if (!input) { // if (!input) {
@ -192,27 +204,31 @@ export const FileExplorer = (props: FileExplorerProps) => {
const deletePath = async (path: string) => { const deletePath = async (path: string) => {
// if (self.files.isReadOnly(key)) { return tooltip('cannot delete file. ' + self.files.type + ' is a read only explorer') } // if (self.files.isReadOnly(key)) { return tooltip('cannot delete file. ' + self.files.type + ' is a read only explorer') }
if (filesProvider.isReadOnly(path)) return if (filesProvider.isReadOnly(path)) return
// const currentFilename = extractNameFromKey(path)
// modalDialogCustom.confirm( // modalDialogCustom.confirm(
// 'Delete file', `Are you sure you want to delete ${currentFilename} file?`, // 'Delete file', `Are you sure you want to delete ${currentFilename} file?`,
// async () => { // async () => {
try { const isDir = state.fileManager.isDirectory(path)
const fileManager = state.fileManager
await fileManager.remove(path) showModal('Delete file', `Are you sure you want to delete ${path} ${isDir ? 'folder' : 'file'}?`, {
const files = removePath(path, state.files) label: 'Ok',
const updatedFiles = files.filter(file => file) fn: async () => {
try {
const fileManager = state.fileManager
await fileManager.remove(path)
const files = removePath(path, state.files)
const updatedFiles = files.filter(file => file)
setState(prevState => { setState(prevState => {
return { ...prevState, files: updatedFiles } return { ...prevState, files: updatedFiles }
}) })
} catch (e) { } catch (e) {
// tooltip(`Failed to remove file ${key}.`) // tooltip(`Failed to remove file ${key}.`)
} }
// }, }
// () => {} }, {
// ) label: 'Cancel',
fn: () => {}
})
} }
const renamePath = async (oldPath: string, newPath: string) => { const renamePath = async (oldPath: string, newPath: string) => {
@ -482,6 +498,29 @@ export const FileExplorer = (props: FileExplorerProps) => {
// } // }
// }) // })
const handleHideModal = () => {
setState(prevState => {
return { ...prevState, modalOptions: { ...state.modalOptions, hide: true } }
})
}
const showModal = (title: string, message: string, ok: { label: string, fn: () => void }, cancel: { label: string, fn: () => void }) => {
setState(prevState => {
return {
...prevState,
modalOptions: {
...prevState.modalOptions,
hide: false,
message,
title,
ok,
cancel,
handleHide: handleHideModal
}
}
})
}
const handleClickFile = (path: string) => { const handleClickFile = (path: string) => {
state.fileManager.open(path) state.fileManager.open(path)
setState(prevState => { setState(prevState => {
@ -564,28 +603,33 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
} }
return
}
if (state.focusEdit.isNew) {
state.focusEdit.type === 'file' ? createNewFile(parentFolder, parentFolder + '/' + content) : createNewFolder(parentFolder, parentFolder + '/' + content)
const files = removePath(state.focusEdit.element, state.files)
const updatedFiles = files.filter(file => file)
setState(prevState => {
return { ...prevState, files: updatedFiles }
})
} else { } else {
if (helper.checkSpecialChars(content)) return if (helper.checkSpecialChars(content)) {
// modalDialogCustom.alert('Special characters are not allowed') showModal('Validation Error', 'Special characters are not allowed', {
const oldPath: string = state.focusEdit.element label: 'Ok',
const oldName = extractNameFromKey(oldPath) fn: () => {}
const newPath = oldPath.replace(oldName, content) }, null)
} else {
if (state.focusEdit.isNew) {
state.focusEdit.type === 'file' ? createNewFile(parentFolder, parentFolder + '/' + content) : createNewFolder(parentFolder, parentFolder + '/' + content)
const files = removePath(state.focusEdit.element, state.files)
const updatedFiles = files.filter(file => file)
renamePath(oldPath, newPath) setState(prevState => {
return { ...prevState, files: updatedFiles }
})
} else {
const oldPath: string = state.focusEdit.element
const oldName = extractNameFromKey(oldPath)
const newPath = oldPath.replace(oldName, content)
renamePath(oldPath, newPath)
}
setState(prevState => {
return { ...prevState, focusEdit: { element: null, isNew: false, type: '' } }
})
}
} }
setState(prevState => {
return { ...prevState, focusEdit: { element: null, isNew: false, type: '' } }
})
} }
const handleNewFileInput = async (parentFolder?: string) => { const handleNewFileInput = async (parentFolder?: string) => {
@ -602,7 +646,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
const handleNewFolderInput = async (parentFolder?: string) => { const handleNewFolderInput = async (parentFolder?: string) => {
if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name
else if (parentFolder.indexOf('.sol') !== -1) parentFolder = extractParentFromKey(parentFolder) else if ((parentFolder.indexOf('.sol') !== -1) || (parentFolder.indexOf('.js') !== -1)) parentFolder = extractParentFromKey(parentFolder)
let files = await resolveDirectory(parentFolder, state.files) let files = await resolveDirectory(parentFolder, state.files)
const expandPath = [...state.expandPath, parentFolder] const expandPath = [...state.expandPath, parentFolder]
@ -765,6 +809,14 @@ export const FileExplorer = (props: FileExplorerProps) => {
</div> </div>
</TreeViewItem> </TreeViewItem>
</TreeView> </TreeView>
<ModalDialog
title={ state.modalOptions.title }
message={ state.modalOptions.message }
hide={ state.modalOptions.hide }
ok={ state.modalOptions.ok }
cancel={ state.modalOptions.cancel }
handleHide={ handleHideModal }
/>
</div> </div>
) )
} }

@ -9,14 +9,12 @@ export const ModalDialog = (props: ModalDialogProps) => {
}) })
const modal = useRef(null) const modal = useRef(null)
const handleHide = () => { const handleHide = () => {
props.hide() props.handleHide()
} }
useEffect( useEffect(() => {
() => { modal.current.focus()
modal.current.focus() }, [props.hide])
}, []
)
const modalKeyEvent = (keyCode) => { const modalKeyEvent = (keyCode) => {
if (keyCode === 27) { // Esc if (keyCode === 27) { // Esc
@ -41,74 +39,73 @@ export const ModalDialog = (props: ModalDialogProps) => {
} }
handleHide() handleHide()
} }
return (<>
return (
<div <div
id="modal-dialog" id="modal-dialog"
data-id="modalDialogContainer" data-id="modalDialogContainer"
data-backdrop="static" data-backdrop="static"
data-keyboard="false" data-keyboard="false"
tabIndex={-1} className='modal'
className="modal d-block" style={{ display: props.hide ? 'none' : 'block' }}
role="dialog" role="dialog"
> >
<div id="modal-background" className="modal-dialog" role="document"> <div id="modal-background" className="modal-dialog" role="document">
<div <div
tabIndex={1}
onBlur={(e) => { onBlur={(e) => {
e.stopPropagation() e.stopPropagation()
handleHide() handleHide()
}} }}
ref={modal} ref={modal}
className={'modal-content remixModalContent ' + (props.opts ? props.opts.class ? props.opts.class : '' : '')} tabIndex={-1}
className={'modal-content remixModalContent ' + (props.modalClass ? props.modalClass : '')}
onKeyDown={({ keyCode }) => { modalKeyEvent(keyCode) }} onKeyDown={({ keyCode }) => { modalKeyEvent(keyCode) }}
> >
<div className="modal-header"> <div className="modal-header">
<h6 className="modal-title" data-id="modalDialogModalTitle"> <h6 className="modal-title" data-id="modalDialogModalTitle">
{props.title && props.title} {props.title && props.title}
</h6> </h6>
{!props.opts.hideClose && {!props.showCancelIcon &&
<span className="modal-close" onClick={() => handleHide()}> <span className="modal-close" onClick={() => handleHide()}>
<i id="modal-close" title="Close" className="fas fa-times" aria-hidden="true"></i> <i id="modal-close" title="Close" className="fas fa-times" aria-hidden="true"></i>
</span> </span>
} }
</div> </div>
<div className="modal-body text-break remixModalBody" data-id="modalDialogModalBody"> <div className="modal-body text-break remixModalBody" data-id="modalDialogModalBody">
{props.content && { props.children ? props.children : props.message }
props.content
}
</div> </div>
<div className="modal-footer" data-id="modalDialogModalFooter"> <div className="modal-footer" data-id="modalDialogModalFooter">
{/* todo add autofocus ^^ */} {/* todo add autofocus ^^ */}
{props.ok && { props.ok &&
<span <span
id="modal-footer-ok" id="modal-footer-ok"
className={'modal-ok btn btn-sm ' + (state.toggleBtn ? 'btn-dark' : 'btn-light')} className={'modal-ok btn btn-sm ' + (state.toggleBtn ? 'btn-dark' : 'btn-light')}
onClick={() => { onClick={() => {
if (props.ok && props.ok.fn) props.ok.fn() if (props.ok.fn) props.ok.fn()
handleHide() handleHide()
}} }}
tabIndex={1} >
> { props.ok.label ? props.ok.label : 'OK' }
{props.ok && props.ok.label ? props.ok.label : 'OK'} </span>
</span> }
{ props.cancel &&
<span
id="modal-footer-cancel"
className={'modal-cancel btn btn-sm ' + (state.toggleBtn ? 'btn-light' : 'btn-dark')}
data-dismiss="modal"
onClick={() => {
if (props.cancel.fn) props.cancel.fn()
handleHide()
}}
>
{ props.cancel.label ? props.cancel.label : 'Cancel' }
</span>
} }
<span
id="modal-footer-cancel"
className={'modal-cancel btn btn-sm ' + (state.toggleBtn ? 'btn-light' : 'btn-dark')}
data-dismiss="modal"
onClick={() => {
if (props.cancel && props.cancel.fn) props.cancel.fn()
handleHide()
}}
tabIndex={2}
>
{props.cancel && props.cancel.label ? props.cancel.label : 'Cancel'}
</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</>) )
} }
export default ModalDialog export default ModalDialog

@ -1,9 +1,11 @@
export interface ModalDialogProps { export interface ModalDialogProps {
title?: string, title?: string,
content?: JSX.Element, message?: string,
ok?: {label:string, fn: () => void}, ok?: { label: string, fn: () => void },
cancel?: {label:string, fn: () => void}, cancel: { label: string, fn: () => void },
focusSelector?: string, modalClass?: string,
opts?: {class: string, hideClose?: boolean}, showCancelIcon?: boolean,
hide: () => void hide: boolean,
handleHide: (hideState?: boolean) => void,
children?: React.ReactNode
} }

Loading…
Cancel
Save