Upload file

pull/5370/head
ioedeveloper 3 years ago
parent bc48ce3f82
commit 52967bebc0
  1. 63
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  2. 3
      libs/remix-ui/file-explorer/src/lib/types/index.ts
  3. 49
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  4. 5
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  5. 11
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx

@ -13,13 +13,12 @@ import { contextMenuActions } from './utils'
import './css/file-explorer.css'
export const FileExplorer = (props: FileExplorerProps) => {
const { name, plugin, focusRoot, contextMenuItems, displayInput, externalUploads, removedContextMenuItems, resetFocus, files } = props
const { name, focusRoot, contextMenuItems, displayInput, externalUploads, removedContextMenuItems, resetFocus, files } = props
const [state, setState] = useState<FileExplorerState>({
focusElement: [{
key: '',
type: 'folder'
}],
fileManager: null,
ctrlKey: false,
newFileName: '',
actions: contextMenuActions,
@ -36,7 +35,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
lastEdit: ''
},
expandPath: [name],
toasterMsg: '',
mouseOverElement: null,
showContextMenu: false,
reservedKeywords: [name, 'gist-'],
@ -205,7 +203,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
const createFile = await fileManager.writeFile(newName, '')
if (!createFile) {
return toast('Failed to create file ' + newName)
return global.toast('Failed to create file ' + newName)
} else {
const path = newName.indexOf(props.name + '/') === 0 ? newName.replace(props.name + '/', '') : newName
@ -239,7 +237,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
const deletePath = async (path: string | string[]) => {
if (global.fs.readonly) return toast('cannot delete file. ' + name + ' is a read only explorer')
if (global.fs.readonly) return global.toast('cannot delete file. ' + name + ' is a read only explorer')
if (!Array.isArray(path)) path = [path]
global.modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, deleteMessage(path), 'OK', async () => {
@ -251,7 +249,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
} catch (e) {
const isDir = await state.fileManager.isDirectory(p)
toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`)
global.toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`)
}
}
}, 'Cancel', () => {})
@ -273,55 +271,13 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
const uploadFile = (target) => {
const filesProvider = fileSystem.provider.provider
// TODO The file explorer is merely a view on the current state of
// the files module. Please ask the user here if they want to overwrite
// a file and then just use `files.add`. The file explorer will
// pick that up via the 'fileAdded' event from the files module.
const parentFolder = getFocusedFolder()
const expandPath = [...new Set([...state.expandPath, parentFolder])]
setState(prevState => {
return { ...prevState, expandPath }
});
[...target.files].forEach((file) => {
const loadFile = (name: string): void => {
const fileReader = new FileReader()
fileReader.onload = async function (event) {
if (helper.checkSpecialChars(file.name)) {
global.modal('File Upload Failed', 'Special characters are not allowed', 'Close', async () => {})
return
}
const success = await filesProvider.set(name, event.target.result)
if (!success) {
return global.modal('File Upload Failed', 'Failed to create file ' + name, 'Close', async () => {})
}
const config = registry.get('config').api
const editor = registry.get('editor').api
if ((config.get('currentFile') === name) && (editor.currentContent() !== event.target.result)) {
editor.setText(event.target.result)
}
}
fileReader.readAsText(file)
}
const name = `${parentFolder}/${file.name}`
filesProvider.exists(name).then(exist => {
if (!exist) {
loadFile(name)
} else {
global.modal('Confirm overwrite', `The file ${name} already exists! Would you like to overwrite it?`, 'OK', () => {
loadFile(name)
}, 'Cancel', () => {})
}
}).catch(error => {
if (error) console.log(error)
})
})
global.dispatchUploadFile(target, parentFolder)
}
const copyFile = (src: string, dest: string) => {
@ -377,12 +333,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
plugin.call(cmd.id, cmd.name, cmd)
}
const toast = (message: string) => {
setState(prevState => {
return { ...prevState, toasterMsg: message }
})
}
const handleClickFile = (path: string, type: 'folder' | 'file' | 'gist') => {
path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path
if (!state.ctrlKey) {
@ -564,7 +514,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
return { ...prevState, copyElement: [{ key: path, type }] }
})
setCanPaste(true)
toast(`Copied to clipboard ${path}`)
global.toast(`Copied to clipboard ${path}`)
}
const handlePasteClick = (dest: string, destType: string) => {
@ -735,7 +685,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
</div>
</TreeViewItem>
</TreeView>
<Toaster message={state.toasterMsg} />
{ state.showContextMenu &&
<FileExplorerContextMenu
actions={state.focusElement.length > 1 ? state.actions.filter(item => item.multiselect) : state.actions.filter(item => !item.multiselect)}

@ -5,7 +5,6 @@ export type MenuItems = action[] // eslint-disable-line no-use-before-define
export interface FileExplorerProps {
name: string,
menuItems?: string[],
plugin: any,
focusRoot: boolean,
contextMenuItems: MenuItems,
removedContextMenuItems: MenuItems,
@ -63,7 +62,6 @@ export interface FileExplorerState {
key: string
type: 'folder' | 'file' | 'gist'
}[]
fileManager: any
ctrlKey: boolean
newFileName: string
actions: {
@ -89,7 +87,6 @@ export interface FileExplorerState {
lastEdit: string
}
expandPath: string[]
toasterMsg: string
mouseOverElement: string
showContextMenu: boolean
reservedKeywords: string[]

@ -254,7 +254,7 @@ const createWorkspaceTemplate = async (workspaceName: string, setDefaults = true
provider.lastLoadedGistId = gistId
} else {
displayNotification('', errorLoadingFile.message || errorLoadingFile, 'OK', null, () => {}, null)
dispatch(displayNotification('', errorLoadingFile.message || errorLoadingFile, 'OK', null, () => {}, null))
}
})
} catch (e) {
@ -697,7 +697,7 @@ export const publishToGist = (path?: string, type?: string) => async (dispatch:
}
} catch (error) {
console.log(error)
displayNotification('Publish to gist Failed', 'Failed to create gist: ' + error.message, 'Close', null, async () => {})
dispatch(displayNotification('Publish to gist Failed', 'Failed to create gist: ' + error.message, 'Close', null, async () => {}))
}
}
@ -705,6 +705,51 @@ export const clearPopUp = () => async (dispatch: React.Dispatch<any>) => {
dispatch(hidePopUp())
}
export const uploadFile = (target, targetFolder: string) => async (dispatch: React.Dispatch<any>) => {
// TODO The file explorer is merely a view on the current state of
// the files module. Please ask the user here if they want to overwrite
// a file and then just use `files.add`. The file explorer will
// pick that up via the 'fileAdded' event from the files module.
[...target.files].forEach((file) => {
const workspaceProvider = plugin.fileProviders.workspace
const loadFile = (name: string): void => {
const fileReader = new FileReader()
fileReader.onload = async function (event) {
if (checkSpecialChars(file.name)) {
dispatch(displayNotification('File Upload Failed', 'Special characters are not allowed', 'Close', null, async () => {}))
return
}
const success = await workspaceProvider.set(name, event.target.result)
if (!success) {
return dispatch(displayNotification('File Upload Failed', 'Failed to create file ' + name, 'Close', null, async () => {}))
}
const config = plugin.registry.get('config').api
const editor = plugin.registry.get('editor').api
if ((config.get('currentFile') === name) && (editor.currentContent() !== event.target.result)) {
editor.setText(event.target.result)
}
}
fileReader.readAsText(file)
}
const name = `${targetFolder}/${file.name}`
workspaceProvider.exists(name).then(exist => {
if (!exist) {
loadFile(name)
} else {
dispatch(displayNotification('Confirm overwrite', `The file ${name} already exists! Would you like to overwrite it?`, 'OK', null, () => {
loadFile(name)
}, () => {}))
}
}).catch(error => {
if (error) console.log(error)
})
})
}
const fileAdded = async (filePath: string) => {
await dispatch(fileAddedSuccess(filePath))
if (filePath.includes('_test.sol')) {

@ -1,4 +1,4 @@
import { createContext } from 'react'
import { createContext, SyntheticEvent } from 'react'
import { BrowserState } from '../reducers/workspace'
export const FileSystemContext = createContext<{
@ -14,5 +14,6 @@ export const FileSystemContext = createContext<{
dispatchSwitchToWorkspace: (name: string) => Promise<void>,
dispatchRenameWorkspace: (oldName: string, workspaceName: string) => Promise<void>,
dispatchDeleteWorkspace: (workspaceName: string) => Promise<void>,
dispatchPublishToGist: (path?: string, type?: string) => Promise<void>
dispatchPublishToGist: (path?: string, type?: string) => Promise<void>,
dispatchUploadFile: (target?: SyntheticEvent, targetFolder?: string) => Promise<void>
}>(null)

@ -1,11 +1,11 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React, { useReducer, useState, useEffect } from 'react'
import React, { useReducer, useState, useEffect, SyntheticEvent } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { FileSystemContext } from '../contexts'
import { browserReducer, browserInitialState } from '../reducers/workspace'
import { initWorkspace, fetchDirectory, addInputField, removeInputField, createWorkspace, fetchWorkspaceDirectory, switchToWorkspace, renameWorkspace, deleteWorkspace, clearPopUp, publishToGist } from '../actions/workspace'
import { initWorkspace, fetchDirectory, addInputField, removeInputField, createWorkspace, fetchWorkspaceDirectory, switchToWorkspace, renameWorkspace, deleteWorkspace, clearPopUp, publishToGist, uploadFile } from '../actions/workspace'
import { Modal, WorkspaceProps } from '../types'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Workspace } from '../remix-ui-workspace'
@ -66,6 +66,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await publishToGist(path, type)(fsDispatch)
}
const dispatchUploadFile = async (target?: SyntheticEvent, targetFolder?: string) => {
await uploadFile(target, targetFolder)(fsDispatch)
}
useEffect(() => {
if (modals.length > 0) {
setFocusModal(() => {
@ -149,7 +153,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchSwitchToWorkspace,
dispatchRenameWorkspace,
dispatchDeleteWorkspace,
dispatchPublishToGist
dispatchPublishToGist,
dispatchUploadFile
}
return (
<FileSystemContext.Provider value={value}>

Loading…
Cancel
Save