Change files structure.

pull/1140/head
ioedeveloper 4 years ago
parent 48f6b50e36
commit ee357b65da
  1. 81
      libs/remix-ui/file-explorer/src/lib/actions/fileSystem.ts
  2. 180
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  3. 76
      libs/remix-ui/file-explorer/src/lib/reducers/fileSystem.ts

@ -1,14 +1,6 @@
import React from 'react'
import { File } from '../types'
import { extractNameFromKey, extractParentFromKey } from '../utils'
const globalRegistry = require('../../../../../../apps/remix-ide/src/global/registry')
const initializeProvider = () => {
const fileProviders = globalRegistry.get('fileproviders').api
const browser = fileProviders.browser // eslint-disable-line
const workspace = fileProviders.workspace
const localhost = fileProviders.localhost // eslint-disable-line
}
import { extractNameFromKey } from '../utils'
export const fetchDirectoryError = (error: any) => {
return {
@ -37,9 +29,9 @@ export const fileSystemReset = () => {
}
}
const normalize = (filesList): File[] => {
const folders = []
const files = []
const normalize = (filesList): any => {
const folders = {}
const files = {}
Object.keys(filesList || {}).forEach(key => {
key = key.replace(/^\/|\/$/g, '') // remove first and last slash
@ -47,36 +39,35 @@ const normalize = (filesList): File[] => {
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
if (filesList[key].isDirectory) {
folders.push({
folders[key] = {
path,
name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory
})
}
} else {
files.push({
files[key] = {
path,
name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory
})
}
}
})
return [...folders, ...files]
return Object.assign({}, folders, files)
}
const fetchDirectoryContent = async (provider, folderPath: string): Promise<File[]> => {
const fetchDirectoryContent = async (provider, folderPath: string): Promise<any> => {
return new Promise((resolve) => {
provider.resolveDirectory(folderPath, (error, fileTree) => {
if (error) console.error(error)
const files = normalize(fileTree)
resolve(files)
resolve({ [extractNameFromKey(folderPath)]: files })
})
})
}
export const fetchDirectory = (provider, path: string) => (dispatch: React.Dispatch<any>) => {
initializeProvider()
const promise = fetchDirectoryContent(provider, path)
dispatch(fetchDirectoryRequest(promise))
@ -88,6 +79,39 @@ export const fetchDirectory = (provider, path: string) => (dispatch: React.Dispa
return promise
}
export const resolveDirectoryError = (error: any) => {
return {
type: 'RESOLVE_DIRECTORY_ERROR',
payload: error
}
}
export const resolveDirectoryRequest = (promise: Promise<any>) => {
return {
type: 'RESOLVE_DIRECTORY_REQUEST',
payload: promise
}
}
export const resolveDirectorySuccess = (path: string, files: File[]) => {
return {
type: 'RESOLVE_DIRECTORY_SUCCESS',
payload: { path, files }
}
}
export const resolveDirectory = (provider, path: string) => (dispatch: React.Dispatch<any>) => {
const promise = fetchDirectoryContent(provider, path)
dispatch(resolveDirectoryRequest(promise))
promise.then((files) => {
dispatch(resolveDirectorySuccess(path, files))
}).catch((error) => {
dispatch(resolveDirectoryError({ error }))
})
return promise
}
export const fetchProviderError = (error: any) => {
return {
type: 'FETCH_PROVIDER_ERROR',
@ -109,15 +133,10 @@ export const fetchProviderSuccess = (provider: any) => {
}
}
export const setProvider = () => (dispatch: React.Dispatch<any>) => {
initializeProvider()
const promise = fetchDirectoryContent(provider, path)
dispatch(fetchDirectoryRequest(promise))
promise.then((files) => {
dispatch(fetchDirectorySuccess(path, files))
}).catch((error) => {
dispatch(fetchDirectoryError({ error }))
})
return promise
export const setProvider = (provider) => (dispatch: React.Dispatch<any>) => {
if (provider) {
dispatch(fetchProviderSuccess(provider))
} else {
dispatch(fetchProviderError('No provider available'))
}
}

@ -8,7 +8,7 @@ import { FileExplorerMenu } from './file-explorer-menu' // eslint-disable-line
import { FileExplorerContextMenu } from './file-explorer-context-menu' // eslint-disable-line
import { FileExplorerProps, File } from './types'
import { fileSystemReducer, fileSystemInitialState } from './reducers/fileSystem'
import { fetchDirectory } from './actions/fileSystem'
import { fetchDirectory, setProvider, resolveDirectory } from './actions/fileSystem'
import * as helper from '../../../../../apps/remix-ide/src/lib/helper'
import QueryParams from '../../../../../apps/remix-ide/src/lib/query-params'
@ -17,7 +17,7 @@ import './css/file-explorer.css'
const queryParams = new QueryParams()
export const FileExplorer = (props: FileExplorerProps) => {
const { filesProvider, name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props
const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props
const [state, setState] = useState({
focusElement: [{
key: '',
@ -26,10 +26,51 @@ export const FileExplorer = (props: FileExplorerProps) => {
focusPath: null,
files: [],
fileManager: null,
filesProvider,
ctrlKey: false,
newFileName: '',
actions: [],
actions: [{
id: 'newFile',
name: 'New File',
type: ['folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'newFolder',
name: 'New Folder',
type: ['folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'rename',
name: 'Rename',
type: ['file', 'folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'delete',
name: 'Delete',
type: ['file', 'folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'pushChangesToGist',
name: 'Push changes to gist',
type: [],
path: [],
extension: [],
pattern: ['^browser/gists/([0-9]|[a-z])*$']
}, {
id: 'run',
name: 'Run',
type: [],
path: [],
extension: ['.js'],
pattern: []
}],
focusContext: {
element: null,
x: null,
@ -65,6 +106,20 @@ export const FileExplorer = (props: FileExplorerProps) => {
const [fileSystem, dispatch] = useReducer(fileSystemReducer, fileSystemInitialState)
const editRef = useRef(null)
useEffect(() => {
if (props.filesProvider) {
setProvider(props.filesProvider)(dispatch)
}
}, [props.filesProvider])
useEffect(() => {
const provider = fileSystem.provider.provider
if (provider) {
fetchDirectory(provider, props.name)(dispatch)
}
}, [fileSystem.provider.provider])
useEffect(() => {
if (state.focusEdit.element) {
setTimeout(() => {
@ -77,83 +132,21 @@ export const FileExplorer = (props: FileExplorerProps) => {
useEffect(() => {
(async () => {
await fetchDirectory(filesProvider, name)(dispatch)
const fileManager = registry.get('filemanager').api
const actions = [{
id: 'newFile',
name: 'New File',
type: ['folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'newFolder',
name: 'New Folder',
type: ['folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'rename',
name: 'Rename',
type: ['file', 'folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'delete',
name: 'Delete',
type: ['file', 'folder'],
path: [],
extension: [],
pattern: []
}, {
id: 'pushChangesToGist',
name: 'Push changes to gist',
type: [],
path: [],
extension: [],
pattern: ['^browser/gists/([0-9]|[a-z])*$']
}, {
id: 'run',
name: 'Run',
type: [],
path: [],
extension: ['.js'],
pattern: []
}]
setState(prevState => {
return { ...prevState, fileManager, actions, expandPath: [name] }
return { ...prevState, fileManager, expandPath: [name] }
})
})()
}, [name])
useEffect(() => {
if (state.fileManager) {
filesProvider.event.register('fileExternallyChanged', fileExternallyChanged)
filesProvider.event.register('fileRenamedError', fileRenamedError)
filesProvider.event.register('rootFolderChanged', rootFolderChanged)
}
}, [state.fileManager])
// useEffect(() => {
// const { expandPath } = state
// const expandFn = async () => {
// let files = state.files
// for (let i = 0; i < expandPath.length; i++) {
// files = await resolveDirectory(expandPath[i], files)
// await setState(prevState => {
// return { ...prevState, files }
// })
// }
// if (state.fileManager) {
// filesProvider.event.register('fileExternallyChanged', fileExternallyChanged)
// filesProvider.event.register('fileRenamedError', fileRenamedError)
// filesProvider.event.register('rootFolderChanged', rootFolderChanged)
// }
// if (expandPath && expandPath.length > 0) {
// expandFn()
// }
// }, [state.expandPath])
// }, [state.fileManager])
// useEffect(() => {
// // unregister event to update state in callback
@ -262,44 +255,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
// return dir
// }
const fetchDirectoryContent = async (folderPath: string): Promise<File[]> => {
console.log('folderPath: ', folderPath)
return new Promise((resolve) => {
filesProvider.resolveDirectory(folderPath, (_error, fileTree) => {
const files = normalize(fileTree)
console.log('files: ', files)
resolve(files)
})
})
}
const normalize = (filesList): File[] => {
const folders = []
const files = []
Object.keys(filesList || {}).forEach(key => {
key = key.replace(/^\/|\/$/g, '') // remove first and last slash
let path = key
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
if (filesList[key].isDirectory) {
folders.push({
path,
name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory
})
} else {
files.push({
path,
name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory
})
}
})
return [...folders, ...files]
}
const extractNameFromKey = (key: string):string => {
const keyPath = key.split('/')
@ -771,6 +726,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
setState(prevState => {
return { ...prevState, focusElement: [{ key: path, type: 'folder' }], expandPath }
})
resolveDirectory(path)(dispatch)
}
}
@ -1033,8 +989,8 @@ export const FileExplorer = (props: FileExplorerProps) => {
<div className='pb-2'>
<TreeView id='treeViewMenu'>
{
fileSystem.files.files.map((file, index) => {
return renderFiles(file, index)
fileSystem.files.files[props.name] && Object.keys(fileSystem.files.files[props.name]).map((key, index) => {
return renderFiles(fileSystem.files.files[props.name][key], index)
})
}
</TreeView>

@ -1,4 +1,4 @@
import { extractNameFromKey, extractParentFromKey } from '../utils'
import { File } from '../types'
interface Action {
type: string;
payload: Record<string, any>;
@ -7,6 +7,7 @@ interface Action {
export const fileSystemInitialState = {
files: {
files: [],
activeDirectory: {},
expandPath: [],
isRequesting: false,
isSuccessful: false,
@ -57,6 +58,41 @@ export const fileSystemReducer = (state = fileSystemInitialState, action: Action
}
}
}
case 'RESOLVE_DIRECTORY_REQUEST': {
return {
...state,
files: {
...state.files,
isRequesting: true,
isSuccessful: false,
error: null
}
}
}
case 'RESOLVE_DIRECTORY_SUCCESS': {
return {
...state,
files: {
...state.files,
files: action.payload.files,
expandPath: [...state.files.expandPath, action.payload.path],
isRequesting: false,
isSuccessful: true,
error: null
}
}
}
case 'RESOLVE_DIRECTORY_ERROR': {
return {
...state,
files: {
...state.files,
isRequesting: false,
isSuccessful: false,
error: action.payload
}
}
}
case 'FETCH_PROVIDER_REQUEST': {
return {
...state,
@ -91,7 +127,45 @@ export const fileSystemReducer = (state = fileSystemInitialState, action: Action
}
}
}
case 'ADD_EMPTY_FILE': {
return {
...state,
files: {
...state.files,
files: []
}
}
}
default:
throw new Error()
}
}
const addEmptyFile = (path: string, files: File[]): File[] => {
if (path === name) {
files.push({
path: 'browser/blank',
name: '',
isDirectory: false
})
return files
}
return files.map(file => {
if (file.child) {
if (file.path === path) {
file.child = [...file.child, {
path: file.path + '/blank',
name: '',
isDirectory: false
}]
return file
} else {
file.child = addEmptyFile(path, file.child)
return file
}
} else {
return file
}
})
}

Loading…
Cancel
Save