Extract types

pull/1575/head
ioedeveloper 3 years ago
parent 9084e342ed
commit 1a51147266
  1. 18
      apps/remix-ide/src/app/files/workspaceFileProvider.js
  2. 1
      libs/remix-ui/file-explorer/src/index.ts
  3. 7
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  4. 1
      libs/remix-ui/file-explorer/src/lib/types/index.ts
  5. 179
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  6. 51
      libs/remix-ui/workspace/src/lib/types/index.ts

@ -81,16 +81,14 @@ class WorkspaceFileProvider extends FileProvider {
}
async createWorkspace (name) {
if (!name) name = 'default_workspace'
this.setWorkspace(name)
const workspacePath = 'browser/' + this.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + this.workspacesPath
const workspaceRootPathExists = await super.exists(workspaceRootPath)
const workspacePathExists = await super.exists(workspacePath)
if (!workspaceRootPathExists) super.createDir(workspaceRootPath)
if (!workspacePathExists) super.createDir(workspacePath)
this.event.emit('createWorkspace', name)
try {
if (!name) name = 'default_workspace'
this.setWorkspace(name)
await super.createDir(name)
this.event.emit('createWorkspace', name)
} catch (e) {
throw new Error(e)
}
}
}

@ -1 +1,2 @@
export * from './lib/file-explorer'
export * from './lib/types'

@ -18,7 +18,7 @@ import './css/file-explorer.css'
const queryParams = new QueryParams()
export const FileExplorer = (props: FileExplorerProps) => {
const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads, removedContextMenuItems } = props
const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads, removedContextMenuItems, resetFocus } = props
const [state, setState] = useState({
focusElement: [{
key: '',
@ -204,7 +204,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
setState(prevState => {
return { ...prevState, focusElement: [{ key: '', type: 'folder' }] }
})
plugin.resetFocus(false)
resetFocus(false)
}
}, [focusRoot])
@ -230,7 +230,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
useEffect(() => {
if (externalUploads) {
uploadFile(externalUploads)
plugin.resetUploadFile()
}
}, [externalUploads])
@ -988,7 +987,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
setState(prevState => {
return { ...prevState, expandPath }
})
plugin.resetFocus(true)
resetFocus(true)
}}>
<FileExplorerMenu
title={''}

@ -13,6 +13,7 @@ export interface FileExplorerProps {
removedContextMenuItems: MenuItems,
displayInput?: boolean,
externalUploads?: EventTarget & HTMLInputElement,
resetFocus?: (value: boolean) => void
}
export interface File {

@ -1,57 +1,37 @@
import React, { useState, useEffect, useRef, useReducer } from 'react' // eslint-disable-line
import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line
import { FileExplorer, MenuItems } from '@remix-ui/file-explorer' // eslint-disable-line
import './remix-ui-workspace.css'
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { Toaster } from '@remix-ui/toaster'// eslint-disable-line
import { MenuItems } from 'libs/remix-ui/file-explorer/src/lib/types'
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
import { WorkspaceProps, WorkspaceState, Modal } from './types'
import { initWorkspace } from './actions/workspace'
import { browserReducer, browserInitialState } from './reducers/workspace'
/* eslint-disable-next-line */
export interface WorkspaceProps {
setWorkspace: ({ name: string, isLocalhost: boolean }, setEvent: boolean) => void,
createWorkspace: (name: string) => void,
renameWorkspace: (oldName: string, newName: string) => void
workspaceRenamed: ({ name: string }) => void,
workspaceCreated: ({ name: string }) => void,
workspaceDeleted: ({ name: string }) => void,
workspace: any // workspace provider,
browser: any // browser provider
localhost: any // localhost provider
fileManager : any
registry: any // registry
plugin: any // plugin call and resetFocus
request: any // api request,
workspaces: any,
registeredMenuItems: MenuItems // menu items
removedMenuItems: MenuItems
initialWorkspace: string
}
const canUpload = window.File || window.FileReader || window.FileList || window.Blob
var canUpload = window.File || window.FileReader || window.FileList || window.Blob
export const Workspace = (props: WorkspaceProps) => {
export function Workspace (props: WorkspaceProps) {
const LOCALHOST = ' - connect to localhost - '
const NO_WORKSPACE = ' - none - '
const [state, setState] = useState({
const [state, setState] = useState<WorkspaceState>({
workspaces: [],
reset: false,
hideRemixdExplorer: true,
displayNewFile: false,
externalUploads: null,
uploadFileEvent: null,
modal: {
hide: true,
title: '',
message: null,
okLabel: '',
okFn: () => {},
cancelLabel: '',
cancelFn: () => {},
handleHide: null
},
loadingLocalhost: false,
toasterMsg: ''
})
const [modal, setModal] = useState<Modal>({
hide: true,
title: '',
message: null,
okLabel: '',
okFn: () => {},
cancelLabel: '',
cancelFn: () => {},
handleHide: null
})
const [currentWorkspace, setCurrentWorkspace] = useState<string>(NO_WORKSPACE)
const [fs, dispatch] = useReducer(browserReducer, browserInitialState)
@ -63,36 +43,27 @@ export const Workspace = (props: WorkspaceProps) => {
if (fs.browser.currentWorkspace) setCurrentWorkspace(fs.browser.currentWorkspace)
}, [fs.browser.currentWorkspace])
/* extends the parent 'plugin' with some function needed by the file explorer */
props.plugin.resetFocus = (reset) => {
setState(prevState => {
return { ...prevState, reset }
})
}
props.plugin.resetNewFile = () => {
setState(prevState => {
return { ...prevState, displayNewFile: !state.displayNewFile }
})
}
props.plugin.resetUploadFile = () => {}
/* implement an external API, consumed by the parent */
props.request.createWorkspace = () => {
props.plugin.request.createWorkspace = () => {
return createWorkspace()
}
props.request.setWorkspace = (workspaceName) => {
props.plugin.request.setWorkspace = (workspaceName) => {
return setWorkspace(workspaceName)
}
props.request.createNewFile = async () => {
props.plugin.request.createNewFile = async () => {
if (!state.workspaces.length) await createNewWorkspace('default_workspace')
props.plugin.resetNewFile()
}
props.request.uploadFile = async (target) => {
props.plugin.request.uploadFile = async (target: EventTarget & HTMLInputElement) => {
if (!state.workspaces.length) await createNewWorkspace('default_workspace')
setState(prevState => {
@ -100,23 +71,23 @@ export const Workspace = (props: WorkspaceProps) => {
})
}
props.request.getCurrentWorkspace = () => {
return { name: currentWorkspace, isLocalhost: currentWorkspace === LOCALHOST, absolutePath: `${props.workspace.workspacesPath}/${currentWorkspace}` }
props.plugin.request.getCurrentWorkspace = () => {
return { name: currentWorkspace, isLocalhost: currentWorkspace === LOCALHOST, absolutePath: `${props.plugin.workspace.workspacesPath}/${currentWorkspace}` }
}
const localhostDisconnect = () => {
if (currentWorkspace === LOCALHOST) setWorkspace(props.workspaces.length > 0 ? props.workspaces[0] : NO_WORKSPACE)
if (currentWorkspace === LOCALHOST) setWorkspace(props.plugin.workspaces.length > 0 ? props.plugin.workspaces[0] : NO_WORKSPACE)
// This should be removed some time after refactoring: https://github.com/ethereum/remix-project/issues/1197
else {
setWorkspace(currentWorkspace) // Useful to switch to last selcted workspace when remixd is disconnected
props.fileManager.setMode('browser')
props.plugin.fileManager.setMode('browser')
}
}
const createNewWorkspace = async (workspaceName) => {
try {
await props.fileManager.closeAllFiles()
await props.createWorkspace(workspaceName)
await props.plugin.fileManager.closeAllFiles()
await props.plugin.createWorkspace(workspaceName)
await setWorkspace(workspaceName)
toast('New default workspace has been created.')
} catch (e) {
@ -134,20 +105,20 @@ export const Workspace = (props: WorkspaceProps) => {
/* workspace creation, renaming and deletion */
const renameCurrentWorkspace = () => {
modal('Rename Current Workspace', renameModalMessage(), 'OK', onFinishRenameWorkspace, '', () => {})
modalDialog('Rename Current Workspace', renameModalMessage(), 'OK', onFinishRenameWorkspace, '', () => {})
}
const createWorkspace = () => {
modal('Create Workspace', createModalMessage(), 'OK', onFinishCreateWorkspace, '', () => {})
modalDialog('Create Workspace', createModalMessage(), 'OK', onFinishCreateWorkspace, '', () => {})
}
const deleteCurrentWorkspace = () => {
modal('Delete Current Workspace', 'Are you sure to delete the current workspace?', 'OK', onFinishDeleteWorkspace, '', () => {})
modalDialog('Delete Current Workspace', 'Are you sure to delete the current workspace?', 'OK', onFinishDeleteWorkspace, '', () => {})
}
const modalMessage = (title: string, body: string) => {
setTimeout(() => { // wait for any previous modal a chance to close
modal(title, body, 'OK', () => {}, '', null)
modalDialog(title, body, 'OK', () => {}, '', null)
}, 200)
}
@ -160,9 +131,9 @@ export const Workspace = (props: WorkspaceProps) => {
const workspaceName = workspaceRenameInput.current.value
try {
await props.renameWorkspace(currentWorkspace, workspaceName)
await props.plugin.renameWorkspace(currentWorkspace, workspaceName)
setWorkspace(workspaceName)
props.workspaceRenamed({ name: workspaceName })
props.plugin.workspaceRenamed({ name: workspaceName })
} catch (e) {
modalMessage('Rename Workspace', e.message)
console.error(e)
@ -175,8 +146,8 @@ export const Workspace = (props: WorkspaceProps) => {
const workspaceName = workspaceCreateInput.current.value
try {
await props.fileManager.closeAllFiles()
await props.createWorkspace(workspaceName)
await props.plugin.fileManager.closeAllFiles()
await props.plugin.createWorkspace(workspaceName)
await setWorkspace(workspaceName)
} catch (e) {
modalMessage('Create Workspace', e.message)
@ -185,12 +156,12 @@ export const Workspace = (props: WorkspaceProps) => {
}
const onFinishDeleteWorkspace = async () => {
await props.fileManager.closeAllFiles()
const workspacesPath = props.workspace.workspacesPath
props.browser.remove(workspacesPath + '/' + currentWorkspace)
await props.plugin.fileManager.closeAllFiles()
const workspacesPath = props.plugin.workspace.workspacesPath
props.plugin.browser.remove(workspacesPath + '/' + currentWorkspace)
const name = currentWorkspace
setWorkspace(NO_WORKSPACE)
props.workspaceDeleted({ name })
props.plugin.workspaceDeleted({ name })
}
/** ** ****/
@ -201,15 +172,15 @@ export const Workspace = (props: WorkspaceProps) => {
}
const setWorkspace = async (name) => {
await props.fileManager.closeAllFiles()
await props.plugin.fileManager.closeAllFiles()
if (name === LOCALHOST) {
props.workspace.clearWorkspace()
props.plugin.workspace.clearWorkspace()
} else if (name === NO_WORKSPACE) {
props.workspace.clearWorkspace()
props.plugin.workspace.clearWorkspace()
} else {
await props.workspace.setWorkspace(name)
await props.plugin.workspace.setWorkspace(name)
}
await props.setWorkspace({ name, isLocalhost: name === LOCALHOST }, !(name === LOCALHOST || name === NO_WORKSPACE))
await props.plugin.setWorkspace({ name, isLocalhost: name === LOCALHOST }, !(name === LOCALHOST || name === NO_WORKSPACE))
props.plugin.getWorkspaces()
setState(prevState => {
return { ...prevState, currentWorkspace: name }
@ -221,7 +192,7 @@ export const Workspace = (props: WorkspaceProps) => {
// If 'connect to localhost' is clicked from home tab, mode is not 'localhost'
// if (props.fileManager.mode === 'localhost') {
await setWorkspace(NO_WORKSPACE)
props.fileManager.setMode('browser')
props.plugin.fileManager.setMode('browser')
setState(prevState => {
return { ...prevState, hideRemixdExplorer: true, loadingLocalhost: false }
})
@ -233,7 +204,7 @@ export const Workspace = (props: WorkspaceProps) => {
// }
},
show: () => {
props.fileManager.setMode('localhost')
props.plugin.fileManager.setMode('localhost')
setState(prevState => {
return { ...prevState, hideRemixdExplorer: false, loadingLocalhost: false }
})
@ -246,34 +217,21 @@ export const Workspace = (props: WorkspaceProps) => {
}
const handleHideModal = () => {
setState(prevState => {
return { ...prevState, modal: { ...state.modal, hide: true, message: null } }
setModal(prevModal => {
return { ...prevModal, hide: true, message: null }
})
}
// eslint-disable-next-line no-undef
const modal = async (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel: string, cancelFn: () => void) => {
await setState(prevState => {
return {
...prevState,
modal: {
...prevState.modal,
hide: false,
message,
title,
okLabel,
okFn,
cancelLabel,
cancelFn,
handleHide: handleHideModal
}
}
const modalDialog = async (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel: string, cancelFn: () => void) => {
await setModal(prevModal => {
return { ...prevModal, hide: false, message, title, okLabel, okFn, cancelLabel, cancelFn, handleHide: handleHideModal }
})
}
const createModalMessage = () => {
return (
<>
<span>{ state.modal.message }</span>
<span>{ modal.message }</span>
<input type="text" data-id="modalDialogCustomPromptTextCreate" defaultValue={`workspace_${Date.now()}`} ref={workspaceCreateInput} className="form-control" />
</>
)
@ -282,7 +240,7 @@ export const Workspace = (props: WorkspaceProps) => {
const renameModalMessage = () => {
return (
<>
<span>{ state.modal.message }</span>
<span>{ modal.message }</span>
<input type="text" data-id="modalDialogCustomPromptTextRename" defaultValue={ currentWorkspace } ref={workspaceRenameInput} className="form-control" />
</>
)
@ -290,17 +248,8 @@ export const Workspace = (props: WorkspaceProps) => {
return (
<div className='remixui_container'>
{ state.modal.message && <ModalDialog
id='workspacesModalDialog'
title={ state.modal.title }
message={ state.modal.message }
hide={ state.modal.hide }
okLabel={ state.modal.okLabel }
okFn={ state.modal.okFn }
cancelLabel={ state.modal.cancelLabel }
cancelFn={ state.modal.cancelFn }
handleHide={ handleHideModal }>
{ (typeof state.modal.message !== 'string') && state.modal.message }
<ModalDialog id='workspacesModalDialog' {...modal}>
{ (typeof modal.message !== 'string') && modal.message }
</ModalDialog>
}
<Toaster message={state.toasterMsg} />
@ -364,15 +313,16 @@ export const Workspace = (props: WorkspaceProps) => {
{ state.hideRemixdExplorer && currentWorkspace && currentWorkspace !== NO_WORKSPACE && currentWorkspace !== LOCALHOST &&
<FileExplorer
name={currentWorkspace}
registry={props.registry}
filesProvider={props.workspace}
registry={props.plugin.registry}
filesProvider={props.plugin.workspace}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={props.plugin}
focusRoot={state.reset}
contextMenuItems={props.registeredMenuItems}
removedContextMenuItems={props.removedMenuItems}
contextMenuItems={props.plugin.registeredMenuItems}
removedContextMenuItems={props.plugin.removedMenuItems}
displayInput={state.displayNewFile}
externalUploads={state.uploadFileEvent}
resetFocus={resetFocus}
/>
}
</div>
@ -382,13 +332,14 @@ export const Workspace = (props: WorkspaceProps) => {
{ !state.hideRemixdExplorer &&
<FileExplorer
name='localhost'
registry={props.registry}
filesProvider={props.localhost}
registry={props.plugin.registry}
filesProvider={props.plugin.localhost}
menuItems={['createNewFile', 'createNewFolder']}
plugin={props.plugin}
focusRoot={state.reset}
contextMenuItems={props.registeredMenuItems}
removedContextMenuItems={props.removedMenuItems}
contextMenuItems={props.plugin.registeredMenuItems}
removedContextMenuItems={props.plugin.removedMenuItems}
resetFocus={resetFocus}
/>
}
</div>

@ -0,0 +1,51 @@
import { MenuItems } from '@remix-ui/file-explorer'
export interface WorkspaceProps {
plugin: {
setWorkspace: ({ name: string, isLocalhost: boolean }, setEvent: boolean) => void,
createWorkspace: (name: string) => void,
renameWorkspace: (oldName: string, newName: string) => void
workspaceRenamed: ({ name: string }) => void,
workspaceCreated: ({ name: string }) => void,
workspaceDeleted: ({ name: string }) => void,
workspace: any // workspace provider,
browser: any // browser provider
localhost: any // localhost provider
fileManager : any
registry: any // registry
request: {
createWorkspace: () => void,
setWorkspace: (workspaceName: string) => void,
createNewFile: () => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void,
getCurrentWorkspace: () => void
} // api request,
workspaces: any,
registeredMenuItems: MenuItems // menu items
removedMenuItems: MenuItems
initialWorkspace: string,
resetNewFile: () => void,
getWorkspaces: () => string[]
}
}
export interface WorkspaceState {
workspaces: string[]
reset: boolean
hideRemixdExplorer: boolean
displayNewFile: boolean
externalUploads: EventTarget & HTMLInputElement
uploadFileEvent: EventTarget & HTMLInputElement
loadingLocalhost: boolean
toasterMsg: string
}
export interface Modal {
hide: boolean
title: string
message: string | JSX.Element
okLabel: string
okFn: () => void
cancelLabel: string
cancelFn: () => void
handleHide: () => void
}
Loading…
Cancel
Save