rearangement

pull/5370/head
yann300 4 years ago
parent 6771fd7b55
commit c8a621b522
  1. 37
      apps/remix-ide/src/app/panels/file-panel.js
  2. 199
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -58,14 +58,23 @@ module.exports = class Filepanel extends ViewPlugin {
this.remixdHandle = new RemixdHandle(this.remixdExplorer, this._deps.fileProviders.localhost, appManager) this.remixdHandle = new RemixdHandle(this.remixdExplorer, this._deps.fileProviders.localhost, appManager)
this.gitHandle = new GitHandle() this.gitHandle = new GitHandle()
this.registeredMenuItems = []
this.request = {} this.request = {}
this.renderComponent()
}
render () {
return this.el
}
renderComponent() {
ReactDOM.render( ReactDOM.render(
<Workspace <Workspace
setWorkspace={this.setWorkspace.bind(this)} setWorkspace={this.setWorkspace.bind(this)}
renameWorkspace={this.renameWorkspace.bind(this)} workspaceRenamed={this.workspaceRenamed.bind(this)}
deleteWorkspace={this.deleteWorkspace.bind(this)} workspaceDeleted={this.workspaceDeleted.bind(this)}
createWorkspace={this.createWorkspace.bind(this)} workspaceCreated={this.workspaceCreated.bind(this)}
workspace={this._deps.fileProviders.workspace} workspace={this._deps.fileProviders.workspace}
browser={this._deps.fileProviders.browser} browser={this._deps.fileProviders.browser}
localhost={this._deps.fileProviders.localhost} localhost={this._deps.fileProviders.localhost}
@ -76,12 +85,22 @@ module.exports = class Filepanel extends ViewPlugin {
registry={this._components.registry} registry={this._components.registry}
plugin={this} plugin={this}
request={this.request} request={this.request}
registeredMenuItems={this.registeredMenuItems}
/> />
, this.el) , this.el)
} }
render () { /**
return this.el * @param item { id: string, name: string, type?: string[], path?: string[], extension?: string[], pattern?: string[] }
* @param callback (...args) => void
*/
registerContextMenuItem (item) {
if (!item) throw new Error('Invalid register context menu argument')
if (!item.name || !item.id) throw new Error('Item name and id is mandatory')
if (!item.type && !item.path && !item.extension && !item.pattern) throw new Error('Invalid file matching criteria provided')
this.registeredMenuItems = [...this.registeredMenuItems, item]
this.renderComponent()
} }
async getCurrentWorkspace () { async getCurrentWorkspace () {
@ -115,15 +134,15 @@ module.exports = class Filepanel extends ViewPlugin {
this.emit('setWorkspace', workspace) this.emit('setWorkspace', workspace)
} }
renameWorkspace (workspace) { workspaceRenamed (workspace) {
this.emit('renameWorkspace', workspace) this.emit('renameWorkspace', workspace)
} }
deleteWorkspace (workspace) { workspaceDeleted (workspace) {
this.emit('deleteWorkspace', workspace) this.emit('deleteWorkspace', workspace)
} }
createWorkspace (workspace) { workspaceCreated (workspace) {
this.emit('createWorkspace', workspace) this.emit('createWorkspace', workspace)
} }
/** end section */ /** end section */

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import ethutil from 'ethereumjs-util' import ethutil from 'ethereumjs-util'
import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line
import './remix-ui-workspace.css'; import './remix-ui-workspace.css';
@ -10,9 +10,9 @@ type CodeExamples = {
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface WorkspaceProps { export interface WorkspaceProps {
setWorkspace: ({ name: string, isLocalhost: boolean }) => void, setWorkspace: ({ name: string, isLocalhost: boolean }) => void,
renameWorkspace: ({ name: string }) => void, workspaceRenamed: ({ name: string }) => void,
createWorkspace: ({ name: string }) => void, workspaceCreated: ({ name: string }) => void,
deleteWorkspace: ({ name: string }) => void, workspaceDeleted: ({ name: string }) => void,
workspace: any // workspace provider, workspace: any // workspace provider,
browser: any // browser provider browser: any // browser provider
localhost: any // localhost provider localhost: any // localhost provider
@ -22,7 +22,8 @@ export interface WorkspaceProps {
gistHandler: any // handle load gist gistHandler: any // handle load gist
registry: any // registry registry: any // registry
plugin: any // plugin call and resetFocus plugin: any // plugin call and resetFocus
request: any // api request request: any // api request,
registeredMenuItems: [] // menu items
} }
var canUpload = window.File || window.FileReader || window.FileList || window.Blob var canUpload = window.File || window.FileReader || window.FileList || window.Blob
@ -30,8 +31,23 @@ export const Workspace = (props: WorkspaceProps) => {
const LOCALHOST = ' - connect to localhost - ' const LOCALHOST = ' - connect to localhost - '
const NO_WORKSPACE = ' - none - ' const NO_WORKSPACE = ' - none - '
/* extends the parent 'plugin' with some function needed by the file explorer */
props.plugin.resetFocus = () => {
setState(prevState => {
return { ...prevState, reset: true }
})
}
props.plugin.resetNewFile = () => {
setState(prevState => {
return { ...prevState, displayNewFile: !state.displayNewFile }
})
}
/**** ****/
/* implement an external API, consumed by the parent */
props.request.createWorkspace = () => { props.request.createWorkspace = () => {
createWorkspace() return createWorkspace()
} }
props.request.getWorkspaces = () => { props.request.getWorkspaces = () => {
@ -39,9 +55,7 @@ export const Workspace = (props: WorkspaceProps) => {
} }
props.request.createNewFile = () => { props.request.createNewFile = () => {
setState(prevState => { props.plugin.resetNewFile()
return { ...prevState, displayNewFile: true }
})
} }
props.request.uploadFile = (target) => { props.request.uploadFile = (target) => {
@ -53,59 +67,15 @@ export const Workspace = (props: WorkspaceProps) => {
props.request.getCurrentWorkspace = () => { props.request.getCurrentWorkspace = () => {
return state.currentWorkspace return state.currentWorkspace
} }
/**** ****/
useEffect(() => { useEffect(() => { initWorkspace() }, [])
initWorkspace()
}, [])
const handleHideCreateModal = () => {
setState(prevState => {
state.createModal.hide = true
return { ...prevState, ...state.createModal }
})
}
const handleHideDeleteModal = () => {
setState(prevState => {
state.deleteModal.hide = true
return { ...prevState, ...state.deleteModal }
})
}
const handleHideRenameModal = () => {
setState(prevState => {
state.renameModal.hide = true
return { ...prevState, ...state.renameModal }
})
}
const createWorkspace = () => {
setState(prevState => {
state.createModal.hide = false
return { ...prevState, ...state.createModal }
})
}
const renameCurrentWorkspace = () => {
setState(prevState => {
state.renameModal.hide = false
return { ...prevState, ...state.renameModal }
})
}
const deleteCurrentWorkspace = () => {
setState(prevState => {
state.deleteModal.hide = false
return { ...prevState, ...state.deleteModal }
})
}
const [state, setState] = useState({ const [state, setState] = useState({
workspaces: [], workspaces: [],
reset: false, reset: false,
currentWorkspace: NO_WORKSPACE, currentWorkspace: NO_WORKSPACE,
hideRemixdExplorer: true, hideRemixdExplorer: true,
registeredMenuItems: [],
displayNewFile: false, displayNewFile: false,
externalUploads: null, externalUploads: null,
uploadFileEvent: null, uploadFileEvent: null,
@ -122,7 +92,12 @@ export const Workspace = (props: WorkspaceProps) => {
label: '', label: '',
fn: () => {} fn: () => {}
}, },
handleHide: handleHideRenameModal handleHide: () => {
setState(prevState => {
state.renameModal.hide = true
return { ...prevState, ...state.renameModal }
})
}
}, },
deleteModal: { deleteModal: {
id: 'deleteWorkspace', id: 'deleteWorkspace',
@ -137,7 +112,12 @@ export const Workspace = (props: WorkspaceProps) => {
label: '', label: '',
fn: () => {} fn: () => {}
}, },
handleHide: handleHideDeleteModal handleHide: () => {
setState(prevState => {
state.deleteModal.hide = true
return { ...prevState, ...state.deleteModal }
})
}
}, },
createModal: { createModal: {
id: 'createWorkspace', id: 'createWorkspace',
@ -152,29 +132,79 @@ export const Workspace = (props: WorkspaceProps) => {
label: '', label: '',
fn: () => {} fn: () => {}
}, },
handleHide: handleHideCreateModal handleHide: () => {
setState(prevState => {
state.createModal.hide = true
return { ...prevState, ...state.createModal }
})
}
} }
}) })
let worspaceNewName // used for renaming and creation /* workspace creation, renaming and deletion */
const modal = (title: string, message: string, ok: { label: string, fn: () => void }, cancel: { label: string, fn: () => void }) => {
setState(prevState => {
return {
...prevState,
modals: [...prevState.modals,
{
message,
title,
ok,
cancel,
handleHide: handleHideModal
}]
}
})
}
const workspaceRenameInput = useRef()
const workspaceCreateInput = useRef()
const createWorkspace = () => {
modal()
setState(prevState => {
state.createModal.hide = false
return { ...prevState, ...state.createModal }
})
}
const renameCurrentWorkspace = () => {
setState(prevState => {
state.renameModal.hide = false
return { ...prevState, ...state.renameModal }
})
}
const deleteCurrentWorkspace = () => {
setState(prevState => {
state.deleteModal.hide = false
return { ...prevState, ...state.deleteModal }
})
}
const onFinishRenameWorkspace = async () => { const onFinishRenameWorkspace = async () => {
if (workspaceRenameInput.current === undefined) return
// @ts-ignore: Object is possibly 'null'.
const workspaceName = workspaceRenameInput.current.value
const workspacesPath = props.workspace.workspacesPath const workspacesPath = props.workspace.workspacesPath
await props.fileManager.rename('browser/' + workspacesPath + '/' + state.currentWorkspace, 'browser/' + workspacesPath + '/' + worspaceNewName) await props.fileManager.rename('browser/' + workspacesPath + '/' + state.currentWorkspace, 'browser/' + workspacesPath + '/' + workspaceName)
setWorkspace(worspaceNewName) setWorkspace(workspaceName)
worspaceNewName = '' props.workspaceRenamed({ name: state.currentWorkspace })
props.renameWorkspace({ name: state.currentWorkspace })
} }
const onFinishCreateWorkspace = async () => { const onFinishCreateWorkspace = async () => {
if (workspaceCreateInput.current === undefined) return
// @ts-ignore: Object is possibly 'null'.
const workspaceName = workspaceCreateInput.current.value
const workspacesPath = props.workspace.workspacesPath const workspacesPath = props.workspace.workspacesPath
props.browser.createDir(workspacesPath + '/' + worspaceNewName, async () => { props.browser.createDir(workspacesPath + '/' + workspaceName, async () => {
setWorkspace(worspaceNewName) setWorkspace(workspaceName)
for (const file in props.examples) { for (const file in props.examples) {
await props.fileManager.writeFile(`${props.examples[file].name}`, props.examples[file].content) await props.fileManager.writeFile(`${props.examples[file].name}`, props.examples[file].content)
} }
worspaceNewName = '' props.workspaceCreated({ name: state.currentWorkspace })
props.createWorkspace({ name: state.currentWorkspace })
}) })
} }
@ -183,13 +213,14 @@ export const Workspace = (props: WorkspaceProps) => {
props.browser.remove(workspacesPath + '/' + state.currentWorkspace) props.browser.remove(workspacesPath + '/' + state.currentWorkspace)
const name = state.currentWorkspace const name = state.currentWorkspace
setWorkspace(NO_WORKSPACE) setWorkspace(NO_WORKSPACE)
props.deleteWorkspace({ name }) props.workspaceDeleted({ name })
} }
/**** ****/
const resetFocus = (reset) => { const resetFocus = (reset) => {
/*setState(prevState => { setState(prevState => {
return { ...prevState, reset } return { ...prevState, reset }
})*/ })
} }
const setWorkspace = async (name) => { const setWorkspace = async (name) => {
@ -233,7 +264,7 @@ export const Workspace = (props: WorkspaceProps) => {
if (Object.keys(filesList).length === 0) { if (Object.keys(filesList).length === 0) {
for (const file in props.examples) { for (const file in props.examples) {
try { try {
await props.fileManager.writeFile('browser/' + workspacesPath + '/default_workspace/' + props.examples[file].name, props.examples[file].content) await props.fileManager.writeFile('browser/' + workspacesPath + '/default_workspace/' + props.examples[file].name, props.examples[file].content)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }
@ -290,34 +321,28 @@ export const Workspace = (props: WorkspaceProps) => {
props.localhost.event.register('closed', (event) => { props.localhost.event.register('closed', (event) => {
remixdExplorer.hide() remixdExplorer.hide()
}) })
props.plugin.resetFocus = () => {
setState(prevState => {
return { ...prevState, reset: true }
})
}
return ( return (
<div className='remixui_container'> <div className='remixui_container'>
<ModalDialog <ModalDialog
id={ state.renameModal.id } id={ state.renameModal.id }
title={ state.renameModal.title } title={ state.renameModal.title }
message={ state.renameModal.message }
hide={ state.renameModal.hide } hide={ state.renameModal.hide }
ok={ state.renameModal.ok } ok={ state.renameModal.ok }
cancel={ state.renameModal.cancel } cancel={ state.renameModal.cancel }
handleHide={ handleHideRenameModal }> handleHide={ state.renameModal.handleHide }>
<input placeholder={ state.currentWorkspace } onChange={(e) => { worspaceNewName = e.target.value } }/> <span>{ state.renameModal.message }</span>
<input placeholder={ state.currentWorkspace } ref={workspaceRenameInput} className="form-control" />
</ModalDialog> </ModalDialog>
<ModalDialog <ModalDialog
id={ state.createModal.id } id={ state.createModal.id }
title={ state.createModal.title } title={ state.createModal.title }
message={ state.createModal.message }
hide={ state.createModal.hide } hide={ state.createModal.hide }
ok={ state.createModal.ok } ok={ state.createModal.ok }
cancel={ state.createModal.cancel } cancel={ state.createModal.cancel }
handleHide={ handleHideCreateModal }> handleHide={ state.createModal.handleHide }>
<input placeholder={ `workspace_${Date.now()}` } onChange={(e) => { worspaceNewName = e.target.value } }/> <span>{ state.createModal.message }</span>
<input placeholder={ `workspace_${Date.now()}` } ref={workspaceCreateInput} className="form-control" />
</ModalDialog> </ModalDialog>
<ModalDialog <ModalDialog
id={ state.deleteModal.id } id={ state.deleteModal.id }
@ -326,7 +351,7 @@ export const Workspace = (props: WorkspaceProps) => {
hide={ state.deleteModal.hide } hide={ state.deleteModal.hide }
ok={ state.deleteModal.ok } ok={ state.deleteModal.ok }
cancel={ state.deleteModal.cancel } cancel={ state.deleteModal.cancel }
handleHide={ handleHideDeleteModal }> handleHide={ state.deleteModal.handleHide }>
</ModalDialog> </ModalDialog>
<div className='remixui_fileexplorer' onClick={() => resetFocus(true)}> <div className='remixui_fileexplorer' onClick={() => resetFocus(true)}>
<div> <div>
@ -393,7 +418,7 @@ export const Workspace = (props: WorkspaceProps) => {
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']} menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={props.plugin} plugin={props.plugin}
focusRoot={state.reset} focusRoot={state.reset}
contextMenuItems={state.registeredMenuItems} contextMenuItems={props.registeredMenuItems}
displayInput={state.displayNewFile} displayInput={state.displayNewFile}
externalUploads={state.uploadFileEvent} externalUploads={state.uploadFileEvent}
/> />
@ -408,7 +433,7 @@ export const Workspace = (props: WorkspaceProps) => {
menuItems={['createNewFile', 'createNewFolder']} menuItems={['createNewFile', 'createNewFolder']}
plugin={props.plugin} plugin={props.plugin}
focusRoot={state.reset} focusRoot={state.reset}
contextMenuItems={state.registeredMenuItems} contextMenuItems={props.registeredMenuItems}
/> />
} }
</div> </div>
@ -420,7 +445,7 @@ export const Workspace = (props: WorkspaceProps) => {
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']} menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={props.plugin} plugin={props.plugin}
focusRoot={state.reset} focusRoot={state.reset}
contextMenuItems={state.registeredMenuItems} contextMenuItems={props.registeredMenuItems}
displayInput={state.displayNewFile} displayInput={state.displayNewFile}
externalUploads={state.uploadFileEvent} externalUploads={state.uploadFileEvent}
/> />

Loading…
Cancel
Save