hoist function to fileTree component

pull/5370/head
Joseph Izang 10 months ago
parent ecba8151c4
commit b519f8dfc8
  1. 43
      libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
  2. 72
      libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx
  3. 21
      libs/remix-ui/workspace/src/lib/components/flat-tree.tsx

@ -300,16 +300,16 @@ export const FileExplorer = (props: FileExplorerProps) => {
* @param src path of the source * @param src path of the source
* @returns {void} * @returns {void}
*/ */
const moveFileSilently = async (dest: string, sourcesrc: string[]) => { const moveFileSilently = async (dest: string, src: string) => {
if (dest.length === 0 || sourcesrc.length === 0) return if (dest.length === 0 || src.length === 0) return
if (await moveFilesIsAllowed(sourcesrc, dest) === false) return if (await moveFileIsAllowed(src, dest) === false) return
try { try {
props.dispatchMoveFiles(sourcesrc, dest) props.dispatchMoveFile(src, dest)
} catch (error) { } catch (error) {
props.modal( props.modal(
intl.formatMessage({ id: 'filePanel.movingFileFailed' }), intl.formatMessage({ id: 'filePanel.movingFileFailed' }),
intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src: sourcesrc.join(' ') }), intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src }),
intl.formatMessage({ id: 'filePanel.close' }), intl.formatMessage({ id: 'filePanel.close' }),
async () => { } async () => { }
) )
@ -323,35 +323,34 @@ export const FileExplorer = (props: FileExplorerProps) => {
* @param src path of the source * @param src path of the source
* @returns {void} * @returns {void}
*/ */
const moveFolderSilently = async (dest: string, sourcesrc: string[]) => { const moveFolderSilently = async (dest: string, src: string) => {
if (dest.length === 0 || sourcesrc.length === 0) return if (dest.length === 0 || src.length === 0) return
if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return if (await moveFolderIsAllowed(src, dest) === false) return
// console.log('moveFolderSilently', { src, dest, sourcesrc })
try { try {
props.dispatchMoveFolders(sourcesrc, dest) props.dispatchMoveFolder(src, dest)
} catch (error) { } catch (error) {
props.modal( props.modal(
intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), intl.formatMessage({ id: 'filePanel.movingFolderFailed' }),
intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src: sourcesrc.join(' ') }), intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src }),
intl.formatMessage({ id: 'filePanel.close' }), intl.formatMessage({ id: 'filePanel.close' }),
async () => { } async () => { }
) )
} }
} }
const handleFileMove = async (dest: string, sourcesrc: string[]) => { const handleFileMove = async (dest: string, copySrc: string) => {
if (await moveFilesIsAllowed(sourcesrc, dest) === false) return if (await moveFileIsAllowed(copySrc, dest) === false) return
console.log('What files have been selected?', filesSelected)
const files = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') const src = filesSelected && filesSelected.length > 0 ? filesSelected.join(' ') : ''
const src = files.length > 0 ? files : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ')
console.log('handleFileMove sourcesrc', {files, sourcesrc, dest, src }) console.log('handleFileMove sourcesrc', {src, copySrc, dest })
try { try {
props.modal( props.modal(
intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFile' }),
intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }),
intl.formatMessage({ id: 'filePanel.yes' }), intl.formatMessage({ id: 'filePanel.yes' }),
() => props.dispatchMoveFiles(sourcesrc, dest), () => props.dispatchMoveFile(copySrc, dest),
intl.formatMessage({ id: 'filePanel.cancel' }), intl.formatMessage({ id: 'filePanel.cancel' }),
() => { } () => { }
) )
@ -365,17 +364,17 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
} }
const handleFolderMove = async (dest: string, sourcesrc: string[]) => { const handleFolderMove = async (dest: string, src: string) => {
if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return if (await moveFolderIsAllowed(src, dest) === false) return
const folders = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') const folders = filesSelected && filesSelected.length > 0 && filesSelected.join(' ')
console.log(folders) console.log(folders)
const src = folders.length > 0 ? folders : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ')
try { try {
props.modal( props.modal(
intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFile' }),
intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }),
intl.formatMessage({ id: 'filePanel.yes' }), intl.formatMessage({ id: 'filePanel.yes' }),
() => props.dispatchMoveFolders(sourcesrc, dest), () => props.dispatchMoveFolder(src, dest),
intl.formatMessage({ id: 'filePanel.cancel' }), intl.formatMessage({ id: 'filePanel.cancel' }),
() => { } () => { }
) )

@ -1,6 +1,6 @@
import React, { SyntheticEvent, useContext, useEffect, useRef, useState } from 'react' import React, { SyntheticEvent, useContext, useEffect, useRef, useState } from 'react'
import { DragStructure, FileType, FlatTreeDropProps } from '../types' import { DragStructure, FileType, FlatTreeDropProps } from '../types'
import { getEventTarget } from '../utils/getEventTarget' import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEventTarget'
import { extractParentFromKey } from '@remix-ui/helper' import { extractParentFromKey } from '@remix-ui/helper'
import { FileSystemContext } from '../contexts' import { FileSystemContext } from '../contexts'
@ -14,20 +14,14 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
// folder to open // folder to open
const [folderToOpen, setFolderToOpen] = useState<string>() const [folderToOpen, setFolderToOpen] = useState<string>()
const globalFEContext = useContext(FileSystemContext) const globalFEContext = useContext(FileSystemContext)
const [selectedItems, setSelectedItems] = useState<DragStructure[]>([])
<<<<<<< HEAD
=======
useEffect(() => {
}, [globalFEContext.fs.focusElement.length]) const [selectedItems, setSelectedItems] = useState<DragStructure[]>([])
>>>>>>> consume function to move files silently
const onDragOver = async (e: SyntheticEvent) => { const onDragOver = async (e: SyntheticEvent) => {
e.preventDefault() e.preventDefault()
const target = await getEventTarget(e) const target = await getEventTarget(e)
buildMultiSelectedItemProfiles(target)
if (!target || !target.path) { if (!target || !target.path) {
clearTimeout(timer) clearTimeout(timer)
setFolderToOpen(null) setFolderToOpen(null)
@ -56,7 +50,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
event.preventDefault() event.preventDefault()
const target = await getEventTarget(event) const target = await getEventTarget(event)
const items = buildMultiSelectedItemProfiles(target) // const items = buildMultiSelectedItemProfiles(target)
const filePaths = [] const filePaths = []
let dragDestination: any let dragDestination: any
@ -69,62 +63,32 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
dragDestination = getFlatTreeItem(target.path) dragDestination = getFlatTreeItem(target.path)
} }
items.forEach((item) => filePaths.push(item.path)) props.selectedItems.forEach((item) => filePaths.push(item.path))
props.setFilesSelected(filePaths) props.setFilesSelected(filePaths)
if (dragDestination.isDirectory) { if (dragDestination.isDirectory) {
if (dragSource.isDirectory) { if (dragSource.isDirectory) {
moveFolder(dragDestination.path, [dragSource.path]) moveFolder(dragDestination.path, dragSource.path)
await moveFoldersSilently(items, dragDestination.path) await moveFoldersSilently(props.selectedItems, dragDestination.path)
} else { } else {
moveFile(dragDestination.path, [dragSource.path]) moveFile(dragDestination.path, dragSource.path)
await moveFilesSilently(items, dragDestination.path) await moveFilesSilently(props.selectedItems, dragDestination.path)
} }
} else { } else {
const path = extractParentFromKey(dragDestination.path) || '/' const path = extractParentFromKey(dragDestination.path) || '/'
if (dragSource.isDirectory) { if (dragSource.isDirectory) {
moveFolder(path, [dragSource.path]) moveFolder(path, dragSource.path)
await moveFoldersSilently(items, dragDestination.path) await moveFoldersSilently(props.selectedItems, dragDestination.path)
} else { } else {
moveFile(path, [dragSource.path]) moveFile(path, dragSource.path)
await moveFilesSilently(items, dragDestination.path) await moveFilesSilently(props.selectedItems, dragDestination.path)
} }
} }
document.querySelectorAll('li.remix_selected').forEach(item => { document.querySelectorAll('li.remixui_selected').forEach(item => {
item.classList.remove('remix_selected') item.classList.remove('remixui_selected')
}) item.classList.remove('bg-secondary')
}
/**
* When multiple files are selected in FileExplorer,
* and these files are dragged to a target folder,
* this function will build the profile of each selected item
* in FileExplorer so they can be moved when dropped
* @param target - Initial target item in FileExplorer
* @returns - {DragStructure} Array of selected items
*/
const buildMultiSelectedItemProfiles = (target: {
path: string
type: string
content: string
position: {
top: number
left: number
}
}) => {
const selectItems = []
document.querySelectorAll('li.remix_selected').forEach(item => {
const dragTarget = {
position: { top: target?.position.top || 0, left: target?.position.left || 0 },
path: item.getAttribute('data-path') || item.getAttribute('data-label-path') || '',
type: item.getAttribute('data-type') || item.getAttribute('data-label-type') || '',
content: item.textContent || ''
}
selectItems.push(dragTarget)
}) })
return selectItems
} }
/** /**
@ -138,7 +102,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
const promises = items.filter(item => item.path !== targetPath) const promises = items.filter(item => item.path !== targetPath)
.map(async (item) => { .map(async (item) => {
if (item.type === 'file') { if (item.type === 'file') {
await props.moveFileSilently(targetPath, [item.path]) await props.moveFileSilently(targetPath, item.path)
} }
}) })
await Promise.all(promises) await Promise.all(promises)
@ -155,7 +119,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
const promises = items.filter(item => item.path !== targetPath) const promises = items.filter(item => item.path !== targetPath)
.map(async (item) => { .map(async (item) => {
if (item.type === 'folder') { if (item.type === 'folder') {
await props.moveFolderSilently(targetPath, [item.path]) await props.moveFolderSilently(targetPath, item.path)
} }
}) })
await Promise.all(promises) await Promise.all(promises)

@ -1,11 +1,11 @@
import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext, Dispatch } from 'react' import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext, Dispatch } from 'react'
import { Popover } from 'react-bootstrap' import { Popover } from 'react-bootstrap'
import { FileType, WorkspaceElement } from '../types' import { DragStructure, FileType, WorkspaceElement } from '../types'
import { getPathIcon } from '@remix-ui/helper'; import { getPathIcon } from '@remix-ui/helper';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso' import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'
import { FlatTreeItemInput } from './flat-tree-item-input'; import { FlatTreeItemInput } from './flat-tree-item-input';
import { FlatTreeDrop } from './flat-tree-drop'; import { FlatTreeDrop } from './flat-tree-drop';
import { getEventTarget } from '../utils/getEventTarget'; import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEventTarget';
import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators'; import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators';
import { FileHoverIcons } from './file-explorer-hovericons'; import { FileHoverIcons } from './file-explorer-hovericons';
import { deletePath } from '../actions'; import { deletePath } from '../actions';
@ -36,10 +36,10 @@ interface FlatTreeProps {
handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void
handleTreeClick: (e: SyntheticEvent) => void handleTreeClick: (e: SyntheticEvent) => void
handleClickFolder: (path: string, type: string) => void handleClickFolder: (path: string, type: string) => void
moveFile: (dest: string, src: string[]) => void moveFile: (dest: string, src: string) => void
moveFolder: (dest: string, src: string[]) => void moveFolder: (dest: string, src: string) => void
moveFolderSilently: (dest: string, src: string[]) => Promise<void> moveFolderSilently: (dest: string, src: string) => Promise<void>
moveFileSilently: (dest: string, src: string[]) => Promise<void> moveFileSilently: (dest: string, src: string) => Promise<void>
setFilesSelected: Dispatch<React.SetStateAction<string[]>> setFilesSelected: Dispatch<React.SetStateAction<string[]>>
fileState: fileDecoration[] fileState: fileDecoration[]
createNewFile?: any createNewFile?: any
@ -71,12 +71,14 @@ export const FlatTree = (props: FlatTreeProps) => {
const ref = useRef(null) const ref = useRef(null)
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const virtuoso = useRef<VirtuosoHandle>(null) const virtuoso = useRef<VirtuosoHandle>(null)
const [selectedItems, setSelectedItems] = useState<DragStructure[]>([])
const labelClass = (file: FileType) => const labelClass = (file: FileType) =>
props.focusEdit.element === file.path props.focusEdit.element === file.path
? 'bg-light' ? 'bg-light'
: props.focusElement.findIndex((item) => item.key === file.path) !== -1 : props.focusElement.findIndex((item) => item.key === file.path) !== -1
? 'bg-secondary remix_selected' ? 'bg-secondary remixui_selected'
: hover == file.path : hover == file.path
? 'bg-light border-no-shift' ? 'bg-light border-no-shift'
: props.focusContext.element === file.path && props.focusEdit.element !== file.path : props.focusContext.element === file.path && props.focusEdit.element !== file.path
@ -107,6 +109,9 @@ export const FlatTree = (props: FlatTreeProps) => {
const target = await getEventTarget(event) const target = await getEventTarget(event)
setDragSource(flatTree.find((item) => item.path === target.path)) setDragSource(flatTree.find((item) => item.path === target.path))
setIsDragging(true) setIsDragging(true)
const items = buildMultiSelectedItemProfiles(target)
setSelectedItems(items)
setFilesSelected(items.map((item) => item.path))
} }
useEffect(() => { useEffect(() => {
@ -258,6 +263,8 @@ export const FlatTree = (props: FlatTreeProps) => {
setFilesSelected={setFilesSelected} setFilesSelected={setFilesSelected}
handleClickFolder={handleClickFolder} handleClickFolder={handleClickFolder}
expandPath={expandPath} expandPath={expandPath}
selectedItems={selectedItems}
setSelectedItems={setSelectedItems}
> >
<div data-id="treeViewUltreeViewMenu" <div data-id="treeViewUltreeViewMenu"
className='d-flex h-100 w-100 pb-2' className='d-flex h-100 w-100 pb-2'

Loading…
Cancel
Save