From d293af79d9f84e661e5c9c66921b05fbcff289aa Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 08:54:50 +0100 Subject: [PATCH 01/44] add types --- .../remix-ui/workspace/src/lib/types/index.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 1d8b515759..f70b7611e3 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -342,3 +342,25 @@ export interface Action { export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionPayloadTypes] export type WorkspaceElement = 'folder' | 'file' | 'workspace' + +export interface FlatTreeDropProps { + moveFile: (dest: string, src: string) => void + moveFolder: (dest: string, src: string) => void + moveFolderSilently: (dest: string, src: string) => Promise + moveFileSilently: (dest: string, src: string) => Promise + getFlatTreeItem: (path: string) => FileType + handleClickFolder: (path: string, type: string) => void + dragSource: FileType + children: React.ReactNode + expandPath: string[] +} + +export type DragStructure = { + position: { + top: number + left: number + } + path: string + type: string + content: string +} From cc46dfab89641289ba6a3620dac1b50e3bbf9b62 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 08:55:52 +0100 Subject: [PATCH 02/44] pass props --- .../workspace/src/lib/components/flat-tree.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index db5a960cbe..da9eb1aca5 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -1,4 +1,4 @@ -import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo } from 'react' +import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext } from 'react' import { Popover } from 'react-bootstrap' import { FileType, WorkspaceElement } from '../types' import { getPathIcon } from '@remix-ui/helper'; @@ -9,6 +9,7 @@ import { getEventTarget } from '../utils/getEventTarget'; import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators'; import { FileHoverIcons } from './file-explorer-hovericons'; import { deletePath } from '../actions'; +import { FileSystemContext } from '../contexts'; export default function useOnScreen(ref: RefObject) { @@ -37,6 +38,8 @@ interface FlatTreeProps { handleClickFolder: (path: string, type: string) => void moveFile: (dest: string, src: string) => void moveFolder: (dest: string, src: string) => void + moveFolderSilently: (dest: string, src: string) => Promise + moveFileSilently: (dest: string, src: string) => Promise fileState: fileDecoration[] createNewFile?: any createNewFolder?: any @@ -50,7 +53,7 @@ let mouseTimer: any = { } export const FlatTree = (props: FlatTreeProps) => { - const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, editPath } = props + const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently } = props const [hover, setHover] = useState('') const [mouseOverTarget, setMouseOverTarget] = useState<{ path: string, @@ -249,6 +252,8 @@ export const FlatTree = (props: FlatTreeProps) => { getFlatTreeItem={getFlatTreeItem} moveFile={moveFile} moveFolder={moveFolder} + moveFolderSilently={moveFolderSilently} + moveFileSilently={moveFileSilently} handleClickFolder={handleClickFolder} expandPath={expandPath} > @@ -257,7 +262,8 @@ export const FlatTree = (props: FlatTreeProps) => { onClick={handleTreeClick} onMouseLeave={onMouseLeave} onMouseMove={onMouseMove} - onContextMenu={handleContextMenu}> + onContextMenu={handleContextMenu} + > { showMouseOverTarget && mouseOverTarget && !isDragging && Date: Thu, 25 Apr 2024 08:56:41 +0100 Subject: [PATCH 03/44] add functions for silent moving of files --- .../src/lib/components/file-explorer.tsx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index e3b301901c..211994d118 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -292,6 +292,50 @@ export const FileExplorer = (props: FileExplorerProps) => { props.dispatchHandleExpandPath(expandPath) } + /** + * This offers the ability to move a file to a new location + * without showing a modal dialong to the user. + * @param dest path of the destination + * @param src path of the source + * @returns {void} + */ + const moveFileSilently = async (dest: string, src: string) => { + if (dest.length === 0 || src.length === 0) return + if (await moveFileIsAllowed(src, dest) === false) return + try { + props.dispatchMoveFile(src, dest) + } catch (error) { + props.modal( + intl.formatMessage({ id: 'filePanel.movingFileFailed' }), + intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src }), + intl.formatMessage({ id: 'filePanel.close' }), + async () => { } + ) + } + } + + /** + * This offers the ability to move a folder to a new location + * without showing a modal dialong to the user. + * @param dest path of the destination + * @param src path of the source + * @returns {void} + */ + const moveFolderSilently = async (dest: string, src: string) => { + if (dest.length === 0 || src.length === 0) return + if (await moveFolderIsAllowed(src, dest) === false) return + try { + props.dispatchMoveFolder(src, dest) + } catch (error) { + props.modal( + intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), + intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src }), + intl.formatMessage({ id: 'filePanel.close' }), + async () => { } + ) + } + } + const handleFileMove = async (dest: string, src: string) => { if (await moveFileIsAllowed(src, dest) === false) return try { @@ -403,6 +447,8 @@ export const FileExplorer = (props: FileExplorerProps) => { handleContextMenu={handleContextMenu} moveFile={handleFileMove} moveFolder={handleFolderMove} + moveFolderSilently={moveFolderSilently} + moveFileSilently={moveFileSilently} handleClickFolder={handleClickFolder} createNewFile={props.createNewFile} createNewFolder={props.createNewFolder} From f75a36bffbc9dd7c1b2e77219d1fb22486f07e29 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 08:57:41 +0100 Subject: [PATCH 04/44] consume function to move files silently --- .../src/lib/components/flat-tree-drop.tsx | 101 ++++++++++++++++-- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 92de1ff8f1..d7aaee0fe9 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -1,16 +1,11 @@ -import React, { SyntheticEvent, useEffect, useRef, useState } from 'react' -import { FileType } from '../types' +import React, { SyntheticEvent, useContext, useEffect, useRef, useState } from 'react' +import { DragStructure, FileType, FlatTreeDropProps } from '../types' import { getEventTarget } from '../utils/getEventTarget' import { extractParentFromKey } from '@remix-ui/helper' -interface FlatTreeDropProps { - moveFile: (dest: string, src: string) => void - moveFolder: (dest: string, src: string) => void - getFlatTreeItem: (path: string) => FileType - handleClickFolder: (path: string, type: string) => void - dragSource: FileType - children: React.ReactNode - expandPath: string[] -} +import { FileSystemContext } from '../contexts' + + + export const FlatTreeDrop = (props: FlatTreeDropProps) => { const { getFlatTreeItem, dragSource, moveFile, moveFolder, handleClickFolder, expandPath } = props @@ -18,10 +13,21 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const [timer, setTimer] = useState() // folder to open const [folderToOpen, setFolderToOpen] = useState() + const globalFEContext = useContext(FileSystemContext) + const [selectedItems, setSelectedItems] = useState([]) + +<<<<<<< HEAD +======= + useEffect(() => { + }, [globalFEContext.fs.focusElement.length]) + +>>>>>>> consume function to move files silently const onDragOver = async (e: SyntheticEvent) => { e.preventDefault() + const target = await getEventTarget(e) + buildMultiSelectedItemProfiles(target) if (!target || !target.path) { clearTimeout(timer) setFolderToOpen(null) @@ -50,6 +56,8 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { event.preventDefault() const target = await getEventTarget(event) + const items = buildMultiSelectedItemProfiles(target) + console.log('onDrop', { items, target }) let dragDestination: any if (!target || !target.path) { dragDestination = { @@ -62,20 +70,91 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { if (dragDestination.isDirectory) { if (dragSource.isDirectory) { moveFolder(dragDestination.path, dragSource.path) + await moveFoldersSilently(items, dragDestination.path) } else { moveFile(dragDestination.path, dragSource.path) + await moveFilesSilently(items, dragDestination.path) } } else { const path = extractParentFromKey(dragDestination.path) || '/' if (dragSource.isDirectory) { moveFolder(path, dragSource.path) + await moveFoldersSilently(items, dragDestination.path) } else { moveFile(path, dragSource.path) + await moveFilesSilently(items, dragDestination.path) } } } + /** + * 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.bg-secondary.li_tv').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) + }) + // console.log('selectItem', { selectItems, target }) + return selectItems + } + + /** + * Moves items silently without showing a confirmation dialog. + * @param items MultiSelected items built into a DragStructure profile + * @param dragSource source FileExplorer item being dragged. + * @returns Promise + */ + const moveFilesSilently = async (items: DragStructure[], targetPath: string) => { + console.log('moveItemsSilently', { items, targetPath }) + const promises = items.filter(item => item.path !== targetPath) + .map(async (item) => { + if (item.type === 'file') { + await props.moveFileSilently(item.path, targetPath) + } + }) + await Promise.all(promises) + } + + /** + * Moves items silently without showing a confirmation dialog. + * @param items MultiSelected items built into a DragStructure profile + * @param dragSource source FileExplorer item being dragged. + * @returns Promise + */ + const moveFoldersSilently = async (items: DragStructure[], targetPath: string) => { + console.log('moveItemsSilently', { items, targetPath }) + const promises = items.filter(item => item.path !== targetPath) + .map(async (item) => { + if (item.type === 'folder') { + await props.moveFolderSilently(item.path, targetPath) + } + }) + await Promise.all(promises) + } + + return (
Date: Thu, 25 Apr 2024 09:23:21 +0100 Subject: [PATCH 05/44] remove console log --- libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index d7aaee0fe9..5c5bec50b4 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -116,7 +116,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } selectItems.push(dragTarget) }) - // console.log('selectItem', { selectItems, target }) return selectItems } From ae9af3bb951706560f705ed12bd51310ec1d23b8 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 10:23:25 +0100 Subject: [PATCH 06/44] fix parameter order --- .../workspace/src/lib/components/flat-tree-drop.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 5c5bec50b4..0fc8f38637 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -107,7 +107,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { }) => { const selectItems = [] document.querySelectorAll('li.bg-secondary.li_tv').forEach(item => { - + item.classList.add('dragging') const dragTarget = { position: { top: target?.position.top || 0, left: target?.position.left || 0 }, path: item.getAttribute('data-path') || item.getAttribute('data-label-path') || '', @@ -130,7 +130,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'file') { - await props.moveFileSilently(item.path, targetPath) + await props.moveFileSilently(targetPath, item.path) } }) await Promise.all(promises) @@ -147,7 +147,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'folder') { - await props.moveFolderSilently(item.path, targetPath) + await props.moveFolderSilently(targetPath, item.path) } }) await Promise.all(promises) From c12ea724a6afa48aabe3beed53c1e76396dc67cf Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 10:51:08 +0100 Subject: [PATCH 07/44] add jsdoc comments --- apps/remix-ide/src/app/files/fileManager.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index bf0564d814..be40d899ab 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -927,6 +927,12 @@ class FileManager extends Plugin { return exists } + /** + * Check if a file can be moved + * @param src source file + * @param dest destination file + * @returns {boolean} true if the file is allowed to be moved + */ async moveFileIsAllowed (src: string, dest: string) { try { src = this.normalize(src) @@ -949,6 +955,12 @@ class FileManager extends Plugin { } } + /** + * Check if a folder can be moved + * @param src source folder + * @param dest destination folder + * @returns {boolean} true if the folder is allowed to be moved + */ async moveDirIsAllowed (src: string, dest: string) { try { src = this.normalize(src) From 6db2efec50a43ef712841b1f969759da79196390 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 10:51:36 +0100 Subject: [PATCH 08/44] add functions to handle array of source paths --- .../workspace/src/lib/actions/index.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index b4480e2019..772bdff1a6 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -656,3 +656,21 @@ export const moveFolderIsAllowed = async (src: string, dest: string) => { return isAllowed } +export const moveFilesIsAllowed = async (src: string[], dest: string) => { + const fileManager = plugin.fileManager + const boolArray: boolean[] = [] + for (const srcFile of src) { + boolArray.push(await fileManager.moveFileIsAllowed(srcFile, dest)) + } + return boolArray.every(p => p === true) || false +} + +export const moveFoldersIsAllowed = async (src: string[], dest: string) => { + const fileManager = plugin.fileManager + const boolArray: boolean[] = [] + for (const srcFile of src) { + boolArray.push(await fileManager.moveDirIsAllowed(srcFile, dest)) + } + return boolArray.every(p => p === true) || false +} + From 45ece83528f7bffb8f17027874de373ddcff58ab Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 10:51:55 +0100 Subject: [PATCH 09/44] add dispatch functions to handle multiple files --- .../src/lib/providers/FileSystemProvider.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 481991dd12..1b2057be99 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -201,10 +201,22 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await moveFile(src, dest) } + const dispatchMoveFiles = async (src: string[], dest: string) => { + for (const path of src) { + await moveFile(path, dest) + } + } + const dispatchMoveFolder = async (src: string, dest: string) => { await moveFolder(src, dest) } + const dispatchMoveFolders = async (src: string[], dest: string) => { + for (const path of src) { + await moveFolder(path, dest) + } + } + const dispatchShowAllBranches = async () => { await showAllBranches() } @@ -367,7 +379,9 @@ export const FileSystemProvider = (props: WorkspaceProps) => { dispatchHandleRestoreBackup, dispatchCloneRepository, dispatchMoveFile, + dispatchMoveFiles, dispatchMoveFolder, + dispatchMoveFolders, dispatchShowAllBranches, dispatchSwitchToBranch, dispatchCreateNewBranch, From 1f59ab14dd1f22554fd2010e5c186c4df96c6cf6 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 11:28:53 +0100 Subject: [PATCH 10/44] refactor to handle string array --- .../src/lib/components/file-explorer.tsx | 36 +++++++++++-------- .../src/lib/components/flat-tree-drop.tsx | 12 +++---- .../src/lib/components/flat-tree.tsx | 8 ++--- .../workspace/src/lib/contexts/index.ts | 2 ++ .../workspace/src/lib/remix-ui-workspace.tsx | 4 +++ .../remix-ui/workspace/src/lib/types/index.ts | 10 +++--- 6 files changed, 43 insertions(+), 29 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 211994d118..c423ab4987 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -9,7 +9,7 @@ import '../css/file-explorer.css' import { checkSpecialChars, extractNameFromKey, extractParentFromKey, getPathIcon, joinPath } from '@remix-ui/helper' // eslint-disable-next-line @typescript-eslint/no-unused-vars import { ROOT_PATH } from '../utils/constants' -import { moveFileIsAllowed, moveFolderIsAllowed } from '../actions' +import { moveFileIsAllowed, moveFilesIsAllowed, moveFolderIsAllowed, moveFoldersIsAllowed } from '../actions' import { FlatTree } from './flat-tree' export const FileExplorer = (props: FileExplorerProps) => { @@ -299,11 +299,13 @@ export const FileExplorer = (props: FileExplorerProps) => { * @param src path of the source * @returns {void} */ - const moveFileSilently = async (dest: string, src: string) => { - if (dest.length === 0 || src.length === 0) return - if (await moveFileIsAllowed(src, dest) === false) return + const moveFileSilently = async (dest: string, sourcesrc: string[]) => { + if (dest.length === 0 || sourcesrc.length === 0) return + if (await moveFilesIsAllowed(sourcesrc, dest) === false) return + + const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { - props.dispatchMoveFile(src, dest) + props.dispatchMoveFiles(sourcesrc, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFileFailed' }), @@ -321,11 +323,13 @@ export const FileExplorer = (props: FileExplorerProps) => { * @param src path of the source * @returns {void} */ - const moveFolderSilently = async (dest: string, src: string) => { - if (dest.length === 0 || src.length === 0) return - if (await moveFolderIsAllowed(src, dest) === false) return + const moveFolderSilently = async (dest: string, sourcesrc: string[]) => { + if (dest.length === 0 || sourcesrc.length === 0) return + if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return + + const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { - props.dispatchMoveFolder(src, dest) + props.dispatchMoveFolders(sourcesrc, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), @@ -336,14 +340,15 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const handleFileMove = async (dest: string, src: string) => { - if (await moveFileIsAllowed(src, dest) === false) return + const handleFileMove = async (dest: string, sourcesrc: string[]) => { + if (await moveFilesIsAllowed(sourcesrc, dest) === false) return + const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFile(src, dest), + () => props.dispatchMoveFiles(sourcesrc, dest), intl.formatMessage({ id: 'filePanel.cancel' }), () => { } ) @@ -357,14 +362,15 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const handleFolderMove = async (dest: string, src: string) => { - if (await moveFolderIsAllowed(src, dest) === false) return + const handleFolderMove = async (dest: string, sourcesrc: string[]) => { + if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return + const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFolder(src, dest), + () => props.dispatchMoveFolders(sourcesrc, dest), intl.formatMessage({ id: 'filePanel.cancel' }), () => { } ) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 0fc8f38637..e4d3d558d2 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -69,20 +69,20 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } if (dragDestination.isDirectory) { if (dragSource.isDirectory) { - moveFolder(dragDestination.path, dragSource.path) + moveFolder(dragDestination.path, [dragSource.path]) await moveFoldersSilently(items, dragDestination.path) } else { - moveFile(dragDestination.path, dragSource.path) + moveFile(dragDestination.path, [dragSource.path]) await moveFilesSilently(items, dragDestination.path) } } else { const path = extractParentFromKey(dragDestination.path) || '/' if (dragSource.isDirectory) { - moveFolder(path, dragSource.path) + moveFolder(path, [dragSource.path]) await moveFoldersSilently(items, dragDestination.path) } else { - moveFile(path, dragSource.path) + moveFile(path, [dragSource.path]) await moveFilesSilently(items, dragDestination.path) } } @@ -130,7 +130,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'file') { - await props.moveFileSilently(targetPath, item.path) + await props.moveFileSilently(targetPath, [item.path]) } }) await Promise.all(promises) @@ -147,7 +147,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'folder') { - await props.moveFolderSilently(targetPath, item.path) + await props.moveFolderSilently(targetPath, [item.path]) } }) await Promise.all(promises) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index da9eb1aca5..af7048c932 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -36,10 +36,10 @@ interface FlatTreeProps { handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void handleTreeClick: (e: SyntheticEvent) => void handleClickFolder: (path: string, type: string) => void - moveFile: (dest: string, src: string) => void - moveFolder: (dest: string, src: string) => void - moveFolderSilently: (dest: string, src: string) => Promise - moveFileSilently: (dest: string, src: string) => Promise + moveFile: (dest: string, src: string[]) => void + moveFolder: (dest: string, src: string[]) => void + moveFolderSilently: (dest: string, src: string[]) => Promise + moveFileSilently: (dest: string, src: string[]) => Promise fileState: fileDecoration[] createNewFile?: any createNewFolder?: any diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 7e297ffb0d..5b58bfba61 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -39,6 +39,8 @@ export const FileSystemContext = createContext<{ dispatchCloneRepository: (url: string) => Promise, dispatchMoveFile: (src: string, dest: string) => Promise, dispatchMoveFolder: (src: string, dest: string) => Promise, + dispatchMoveFiles: (src: string[], dest: string) => Promise, + dispatchMoveFolders: (src: string[], dest: string) => Promise, dispatchShowAllBranches: () => Promise, dispatchSwitchToBranch: (branch: string) => Promise, dispatchCreateNewBranch: (branch: string) => Promise, diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 3da9063576..29a52a8654 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -1251,7 +1251,9 @@ export function Workspace() { dispatchAddInputField={global.dispatchAddInputField} dispatchHandleExpandPath={global.dispatchHandleExpandPath} dispatchMoveFile={global.dispatchMoveFile} + dispatchMoveFiles={global.dispatchMoveFiles} dispatchMoveFolder={global.dispatchMoveFolder} + dispatchMoveFolders={global.dispatchMoveFolders} handleCopyClick={handleCopyClick} handlePasteClick={handlePasteClick} addMenuItems={addMenuItems} @@ -1317,7 +1319,9 @@ export function Workspace() { dispatchAddInputField={global.dispatchAddInputField} dispatchHandleExpandPath={global.dispatchHandleExpandPath} dispatchMoveFile={global.dispatchMoveFile} + dispatchMoveFiles={global.dispatchMoveFiles} dispatchMoveFolder={global.dispatchMoveFolder} + dispatchMoveFolders={global.dispatchMoveFolders} handleCopyClick={handleCopyClick} handlePasteClick={handlePasteClick} addMenuItems={addMenuItems} diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index f70b7611e3..95f3380b99 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -135,6 +135,8 @@ export interface FileExplorerProps { dispatchAddInputField:(path: string, type: 'file' | 'folder') => Promise, dispatchHandleExpandPath: (paths: string[]) => Promise, dispatchMoveFile: (src: string, dest: string) => Promise, + dispatchMoveFiles: (src: string[], dest: string) => Promise, + dispatchMoveFolders: (src: string[], dest: string) => Promise, dispatchMoveFolder: (src: string, dest: string) => Promise, handlePasteClick: (dest: string, destType: string) => void handleCopyClick: (path: string, type: WorkspaceElement) => void @@ -344,10 +346,10 @@ export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionP export type WorkspaceElement = 'folder' | 'file' | 'workspace' export interface FlatTreeDropProps { - moveFile: (dest: string, src: string) => void - moveFolder: (dest: string, src: string) => void - moveFolderSilently: (dest: string, src: string) => Promise - moveFileSilently: (dest: string, src: string) => Promise + moveFile: (dest: string, src: string[]) => void + moveFolder: (dest: string, src: string[]) => void + moveFolderSilently: (dest: string, src: string[]) => Promise + moveFileSilently: (dest: string, src: string[]) => Promise getFlatTreeItem: (path: string) => FileType handleClickFolder: (path: string, type: string) => void dragSource: FileType From 12619db60d82fe389ebc6a2cfbe065072e94e90d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 25 Apr 2024 12:16:34 +0100 Subject: [PATCH 11/44] add state to track file names being moved. --- .../workspace/src/lib/components/file-explorer.tsx | 10 ++++++++-- .../workspace/src/lib/components/flat-tree-drop.tsx | 6 +++++- .../workspace/src/lib/components/flat-tree.tsx | 6 ++++-- libs/remix-ui/workspace/src/lib/types/index.ts | 3 ++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index c423ab4987..b3eaeddab1 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -35,6 +35,7 @@ export const FileExplorer = (props: FileExplorerProps) => { const [state, setState] = useState(workspaceState) // const [isPending, startTransition] = useTransition(); const treeRef = useRef(null) + const [filesSelected, setFilesSelected] = useState([]) useEffect(() => { if (contextMenuItems) { @@ -342,7 +343,9 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleFileMove = async (dest: string, sourcesrc: string[]) => { if (await moveFilesIsAllowed(sourcesrc, dest) === false) return - const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') + const files = filesSelected && filesSelected.length > 0 && filesSelected.join('\n') + console.log(files) + const src = files.length > 0 ? files : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), @@ -364,7 +367,9 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleFolderMove = async (dest: string, sourcesrc: string[]) => { if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return - const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') + const folders = filesSelected && filesSelected.length > 0 && filesSelected.join('\n') + console.log(folders) + const src = folders.length > 0 ? folders : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), @@ -455,6 +460,7 @@ export const FileExplorer = (props: FileExplorerProps) => { moveFolder={handleFolderMove} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} + setFilesSelected={setFilesSelected} handleClickFolder={handleClickFolder} createNewFile={props.createNewFile} createNewFolder={props.createNewFolder} diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index e4d3d558d2..26ace2dce1 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -57,7 +57,11 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const target = await getEventTarget(event) const items = buildMultiSelectedItemProfiles(target) - console.log('onDrop', { items, target }) + const filePaths = [] + filePaths.push(target && target.path ? target.path : '/') + items.forEach((item) => filePaths.push(item.path)) + props.setFilesSelected(filePaths) + console.log('onDrop', { items, target, filePaths }) let dragDestination: any if (!target || !target.path) { dragDestination = { diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index af7048c932..1d22b912f6 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -1,4 +1,4 @@ -import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext } from 'react' +import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext, Dispatch } from 'react' import { Popover } from 'react-bootstrap' import { FileType, WorkspaceElement } from '../types' import { getPathIcon } from '@remix-ui/helper'; @@ -40,6 +40,7 @@ interface FlatTreeProps { moveFolder: (dest: string, src: string[]) => void moveFolderSilently: (dest: string, src: string[]) => Promise moveFileSilently: (dest: string, src: string[]) => Promise + setFilesSelected: Dispatch> fileState: fileDecoration[] createNewFile?: any createNewFolder?: any @@ -53,7 +54,7 @@ let mouseTimer: any = { } export const FlatTree = (props: FlatTreeProps) => { - const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently } = props + const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently, setFilesSelected } = props const [hover, setHover] = useState('') const [mouseOverTarget, setMouseOverTarget] = useState<{ path: string, @@ -254,6 +255,7 @@ export const FlatTree = (props: FlatTreeProps) => { moveFolder={moveFolder} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} + setFilesSelected={setFilesSelected} handleClickFolder={handleClickFolder} expandPath={expandPath} > diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 95f3380b99..4fa993bc70 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -1,5 +1,5 @@ /* eslint-disable @nrwl/nx/enforce-module-boundaries */ -import React from 'react' +import React, { Dispatch } from 'react' import { customAction } from '@remixproject/plugin-api' import { fileDecoration } from '@remix-ui/file-decorators' import { RemixAppManager } from 'libs/remix-ui/plugin-manager/src/types' @@ -350,6 +350,7 @@ export interface FlatTreeDropProps { moveFolder: (dest: string, src: string[]) => void moveFolderSilently: (dest: string, src: string[]) => Promise moveFileSilently: (dest: string, src: string[]) => Promise + setFilesSelected: Dispatch> getFlatTreeItem: (path: string) => FileType handleClickFolder: (path: string, type: string) => void dragSource: FileType From f233290bcd6b0751ba2f90ce58ebb69cb5bca0a5 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Fri, 26 Apr 2024 13:15:36 +0100 Subject: [PATCH 12/44] fix exception when files have been dropped on destination --- .../workspace/src/lib/components/flat-tree-drop.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 26ace2dce1..652b1e43f8 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -58,10 +58,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const target = await getEventTarget(event) const items = buildMultiSelectedItemProfiles(target) const filePaths = [] - filePaths.push(target && target.path ? target.path : '/') - items.forEach((item) => filePaths.push(item.path)) - props.setFilesSelected(filePaths) - console.log('onDrop', { items, target, filePaths }) + // console.log('onDrop', { items, target, filePaths }) let dragDestination: any if (!target || !target.path) { dragDestination = { @@ -71,6 +68,11 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } else { dragDestination = getFlatTreeItem(target.path) } + + filePaths.push(dragDestination.path) + items.forEach((item) => filePaths.push(item.path)) + props.setFilesSelected(filePaths) + if (dragDestination.isDirectory) { if (dragSource.isDirectory) { moveFolder(dragDestination.path, [dragSource.path]) From 28072ed6e157553b10417333ce88edbd6d1fe591 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 09:35:17 +0100 Subject: [PATCH 13/44] changes after review --- .../src/lib/components/file-explorer.tsx | 19 ++++++++++--------- .../src/lib/components/flat-tree-drop.tsx | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index b3eaeddab1..f4aaa85e8e 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -304,13 +304,13 @@ export const FileExplorer = (props: FileExplorerProps) => { if (dest.length === 0 || sourcesrc.length === 0) return if (await moveFilesIsAllowed(sourcesrc, dest) === false) return - const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') try { props.dispatchMoveFiles(sourcesrc, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFileFailed' }), - intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src }), + intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src: sourcesrc.join(' ') }), + intl.formatMessage({ id: 'filePanel.close' }), async () => { } ) @@ -328,13 +328,13 @@ export const FileExplorer = (props: FileExplorerProps) => { if (dest.length === 0 || sourcesrc.length === 0) return if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return - const src = sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') + // console.log('moveFolderSilently', { src, dest, sourcesrc }) try { props.dispatchMoveFolders(sourcesrc, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), - intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src }), + intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src: sourcesrc.join(' ') }), intl.formatMessage({ id: 'filePanel.close' }), async () => { } ) @@ -343,9 +343,10 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleFileMove = async (dest: string, sourcesrc: string[]) => { if (await moveFilesIsAllowed(sourcesrc, dest) === false) return - const files = filesSelected && filesSelected.length > 0 && filesSelected.join('\n') - console.log(files) - const src = files.length > 0 ? files : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') + console.log('What files have been selected?', filesSelected) + const files = 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 }) try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), @@ -367,9 +368,9 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleFolderMove = async (dest: string, sourcesrc: string[]) => { if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return - const folders = filesSelected && filesSelected.length > 0 && filesSelected.join('\n') + const folders = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') console.log(folders) - const src = folders.length > 0 ? folders : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join('\n') + const src = folders.length > 0 ? folders : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 652b1e43f8..2a5c29575b 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -53,12 +53,13 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } const onDrop = async (event: SyntheticEvent) => { + event.stopPropagation() event.preventDefault() const target = await getEventTarget(event) const items = buildMultiSelectedItemProfiles(target) const filePaths = [] - // console.log('onDrop', { items, target, filePaths }) + let dragDestination: any if (!target || !target.path) { dragDestination = { @@ -68,8 +69,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } else { dragDestination = getFlatTreeItem(target.path) } - - filePaths.push(dragDestination.path) + items.forEach((item) => filePaths.push(item.path)) props.setFilesSelected(filePaths) From 639a2080ab4cc47adbe12c3c990862c6ecb65088 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 09:57:37 +0100 Subject: [PATCH 14/44] change css class selector --- .../workspace/src/lib/components/file-explorer.tsx | 1 - .../workspace/src/lib/components/flat-tree-drop.tsx | 8 +++++--- libs/remix-ui/workspace/src/lib/components/flat-tree.tsx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index f4aaa85e8e..8d092c33f3 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -310,7 +310,6 @@ export const FileExplorer = (props: FileExplorerProps) => { props.modal( intl.formatMessage({ id: 'filePanel.movingFileFailed' }), intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src: sourcesrc.join(' ') }), - intl.formatMessage({ id: 'filePanel.close' }), async () => { } ) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 2a5c29575b..aea7d1fbac 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -53,7 +53,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } const onDrop = async (event: SyntheticEvent) => { - event.stopPropagation() event.preventDefault() const target = await getEventTarget(event) @@ -92,6 +91,9 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { await moveFilesSilently(items, dragDestination.path) } } + document.querySelectorAll('li.remix_selected').forEach(item => { + item.classList.remove('remix_selected') + }) } /** @@ -112,8 +114,8 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } }) => { const selectItems = [] - document.querySelectorAll('li.bg-secondary.li_tv').forEach(item => { - item.classList.add('dragging') + 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') || '', diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index 1d22b912f6..61050ae965 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -76,7 +76,7 @@ export const FlatTree = (props: FlatTreeProps) => { props.focusEdit.element === file.path ? 'bg-light' : props.focusElement.findIndex((item) => item.key === file.path) !== -1 - ? 'bg-secondary' + ? 'bg-secondary remix_selected' : hover == file.path ? 'bg-light border-no-shift' : props.focusContext.element === file.path && props.focusEdit.element !== file.path From cd273264594df5978ef6edf48f9c45ec5d88b30a Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:11:01 +0100 Subject: [PATCH 15/44] move function outside of drop component --- .../workspace/src/lib/utils/getEventTarget.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts index e61cc7a226..e7cd32bc4a 100644 --- a/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts +++ b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts @@ -22,4 +22,35 @@ export const getEventTarget = async (e: any, useLabel: boolean = false) => { position: endPosition } } -} \ No newline at end of file +} + +/** + * 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 + */ +export const buildMultiSelectedItemProfiles = (target: { + path: string + type: string + content: string + position: { + top: number + left: number + } + }) => { + const selectItems = [] + document.querySelectorAll('li.remixui_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 +} From ef35ea21b48c7c40a01d2b86d64eed56bcd95e8b Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:11:26 +0100 Subject: [PATCH 16/44] clean up types removing string array parameter --- libs/remix-ui/workspace/src/lib/types/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 4fa993bc70..56bf8b839e 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -346,16 +346,18 @@ export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionP export type WorkspaceElement = 'folder' | 'file' | 'workspace' export interface FlatTreeDropProps { - moveFile: (dest: string, src: string[]) => void - moveFolder: (dest: string, src: string[]) => void - moveFolderSilently: (dest: string, src: string[]) => Promise - moveFileSilently: (dest: string, src: string[]) => Promise + moveFile: (dest: string, src: string) => void + moveFolder: (dest: string, src: string) => void + moveFolderSilently: (dest: string, src: string) => Promise + moveFileSilently: (dest: string, src: string) => Promise setFilesSelected: Dispatch> getFlatTreeItem: (path: string) => FileType handleClickFolder: (path: string, type: string) => void dragSource: FileType children: React.ReactNode expandPath: string[] + selectedItems: DragStructure[] + setSelectedItems: Dispatch> } export type DragStructure = { From ecba8151c459a3eca229b61d2469f39448296058 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:11:48 +0100 Subject: [PATCH 17/44] add placeholder css class for selected files --- libs/remix-ui/workspace/src/lib/css/file-explorer.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/css/file-explorer.css b/libs/remix-ui/workspace/src/lib/css/file-explorer.css index 16f0ffca51..4ccf2096c7 100644 --- a/libs/remix-ui/workspace/src/lib/css/file-explorer.css +++ b/libs/remix-ui/workspace/src/lib/css/file-explorer.css @@ -69,3 +69,7 @@ ul { .remixui_icons:hover { color: var(--text); } + +.remixui_selected { + +} From b519f8dfc82895e3b41fc9a27497bc7b9fa72294 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:12:06 +0100 Subject: [PATCH 18/44] hoist function to fileTree component --- .../src/lib/components/file-explorer.tsx | 43 ++++++----- .../src/lib/components/flat-tree-drop.tsx | 72 +++++-------------- .../src/lib/components/flat-tree.tsx | 21 ++++-- 3 files changed, 53 insertions(+), 83 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 8d092c33f3..7530cbf2c0 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -300,16 +300,16 @@ export const FileExplorer = (props: FileExplorerProps) => { * @param src path of the source * @returns {void} */ - const moveFileSilently = async (dest: string, sourcesrc: string[]) => { - if (dest.length === 0 || sourcesrc.length === 0) return - if (await moveFilesIsAllowed(sourcesrc, dest) === false) return + const moveFileSilently = async (dest: string, src: string) => { + if (dest.length === 0 || src.length === 0) return + if (await moveFileIsAllowed(src, dest) === false) return try { - props.dispatchMoveFiles(sourcesrc, dest) + props.dispatchMoveFile(src, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFileFailed' }), - intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src: sourcesrc.join(' ') }), + intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src }), intl.formatMessage({ id: 'filePanel.close' }), async () => { } ) @@ -323,35 +323,34 @@ export const FileExplorer = (props: FileExplorerProps) => { * @param src path of the source * @returns {void} */ - const moveFolderSilently = async (dest: string, sourcesrc: string[]) => { - if (dest.length === 0 || sourcesrc.length === 0) return - if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return + const moveFolderSilently = async (dest: string, src: string) => { + if (dest.length === 0 || src.length === 0) return + if (await moveFolderIsAllowed(src, dest) === false) return - // console.log('moveFolderSilently', { src, dest, sourcesrc }) try { - props.dispatchMoveFolders(sourcesrc, dest) + props.dispatchMoveFolder(src, dest) } catch (error) { props.modal( intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), - intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src: sourcesrc.join(' ') }), + intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src }), intl.formatMessage({ id: 'filePanel.close' }), async () => { } ) } } - const handleFileMove = async (dest: string, sourcesrc: string[]) => { - if (await moveFilesIsAllowed(sourcesrc, dest) === false) return - console.log('What files have been selected?', filesSelected) - const files = 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 }) + const handleFileMove = async (dest: string, copySrc: string) => { + if (await moveFileIsAllowed(copySrc, dest) === false) return + + const src = filesSelected && filesSelected.length > 0 ? filesSelected.join(' ') : '' + + console.log('handleFileMove sourcesrc', {src, copySrc, dest }) try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFiles(sourcesrc, dest), + () => props.dispatchMoveFile(copySrc, dest), intl.formatMessage({ id: 'filePanel.cancel' }), () => { } ) @@ -365,17 +364,17 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const handleFolderMove = async (dest: string, sourcesrc: string[]) => { - if (await moveFoldersIsAllowed(sourcesrc, dest) === false) return + const handleFolderMove = async (dest: string, src: string) => { + if (await moveFolderIsAllowed(src, dest) === false) return const folders = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') console.log(folders) - const src = folders.length > 0 ? folders : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ') + try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFolders(sourcesrc, dest), + () => props.dispatchMoveFolder(src, dest), intl.formatMessage({ id: 'filePanel.cancel' }), () => { } ) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index aea7d1fbac..11300819ad 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -1,6 +1,6 @@ import React, { SyntheticEvent, useContext, useEffect, useRef, useState } from 'react' import { DragStructure, FileType, FlatTreeDropProps } from '../types' -import { getEventTarget } from '../utils/getEventTarget' +import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEventTarget' import { extractParentFromKey } from '@remix-ui/helper' import { FileSystemContext } from '../contexts' @@ -14,20 +14,14 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { // folder to open const [folderToOpen, setFolderToOpen] = useState() const globalFEContext = useContext(FileSystemContext) - const [selectedItems, setSelectedItems] = useState([]) - -<<<<<<< HEAD -======= - useEffect(() => { - }, [globalFEContext.fs.focusElement.length]) + const [selectedItems, setSelectedItems] = useState([]) ->>>>>>> consume function to move files silently const onDragOver = async (e: SyntheticEvent) => { e.preventDefault() const target = await getEventTarget(e) - buildMultiSelectedItemProfiles(target) + if (!target || !target.path) { clearTimeout(timer) setFolderToOpen(null) @@ -56,7 +50,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { event.preventDefault() const target = await getEventTarget(event) - const items = buildMultiSelectedItemProfiles(target) + // const items = buildMultiSelectedItemProfiles(target) const filePaths = [] let dragDestination: any @@ -69,62 +63,32 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { dragDestination = getFlatTreeItem(target.path) } - items.forEach((item) => filePaths.push(item.path)) + props.selectedItems.forEach((item) => filePaths.push(item.path)) props.setFilesSelected(filePaths) if (dragDestination.isDirectory) { if (dragSource.isDirectory) { - moveFolder(dragDestination.path, [dragSource.path]) - await moveFoldersSilently(items, dragDestination.path) + moveFolder(dragDestination.path, dragSource.path) + await moveFoldersSilently(props.selectedItems, dragDestination.path) } else { - moveFile(dragDestination.path, [dragSource.path]) - await moveFilesSilently(items, dragDestination.path) + moveFile(dragDestination.path, dragSource.path) + await moveFilesSilently(props.selectedItems, dragDestination.path) } } else { const path = extractParentFromKey(dragDestination.path) || '/' if (dragSource.isDirectory) { - moveFolder(path, [dragSource.path]) - await moveFoldersSilently(items, dragDestination.path) + moveFolder(path, dragSource.path) + await moveFoldersSilently(props.selectedItems, dragDestination.path) } else { - moveFile(path, [dragSource.path]) - await moveFilesSilently(items, dragDestination.path) + moveFile(path, dragSource.path) + await moveFilesSilently(props.selectedItems, dragDestination.path) } } - document.querySelectorAll('li.remix_selected').forEach(item => { - item.classList.remove('remix_selected') - }) - } - - /** - * 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) + document.querySelectorAll('li.remixui_selected').forEach(item => { + item.classList.remove('remixui_selected') + item.classList.remove('bg-secondary') }) - return selectItems } /** @@ -138,7 +102,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'file') { - await props.moveFileSilently(targetPath, [item.path]) + await props.moveFileSilently(targetPath, item.path) } }) await Promise.all(promises) @@ -155,7 +119,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'folder') { - await props.moveFolderSilently(targetPath, [item.path]) + await props.moveFolderSilently(targetPath, item.path) } }) await Promise.all(promises) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index 61050ae965..6a56153cf8 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -1,11 +1,11 @@ import React, { SyntheticEvent, useEffect, useRef, useState, RefObject, useMemo, useContext, Dispatch } from 'react' import { Popover } from 'react-bootstrap' -import { FileType, WorkspaceElement } from '../types' +import { DragStructure, FileType, WorkspaceElement } from '../types' import { getPathIcon } from '@remix-ui/helper'; import { Virtuoso, VirtuosoHandle } from 'react-virtuoso' import { FlatTreeItemInput } from './flat-tree-item-input'; 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 { FileHoverIcons } from './file-explorer-hovericons'; import { deletePath } from '../actions'; @@ -36,10 +36,10 @@ interface FlatTreeProps { handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void handleTreeClick: (e: SyntheticEvent) => void handleClickFolder: (path: string, type: string) => void - moveFile: (dest: string, src: string[]) => void - moveFolder: (dest: string, src: string[]) => void - moveFolderSilently: (dest: string, src: string[]) => Promise - moveFileSilently: (dest: string, src: string[]) => Promise + moveFile: (dest: string, src: string) => void + moveFolder: (dest: string, src: string) => void + moveFolderSilently: (dest: string, src: string) => Promise + moveFileSilently: (dest: string, src: string) => Promise setFilesSelected: Dispatch> fileState: fileDecoration[] createNewFile?: any @@ -71,12 +71,14 @@ export const FlatTree = (props: FlatTreeProps) => { const ref = useRef(null) const containerRef = useRef(null) const virtuoso = useRef(null) + const [selectedItems, setSelectedItems] = useState([]) + const labelClass = (file: FileType) => props.focusEdit.element === file.path ? 'bg-light' : props.focusElement.findIndex((item) => item.key === file.path) !== -1 - ? 'bg-secondary remix_selected' + ? 'bg-secondary remixui_selected' : hover == file.path ? 'bg-light border-no-shift' : props.focusContext.element === file.path && props.focusEdit.element !== file.path @@ -107,6 +109,9 @@ export const FlatTree = (props: FlatTreeProps) => { const target = await getEventTarget(event) setDragSource(flatTree.find((item) => item.path === target.path)) setIsDragging(true) + const items = buildMultiSelectedItemProfiles(target) + setSelectedItems(items) + setFilesSelected(items.map((item) => item.path)) } useEffect(() => { @@ -258,6 +263,8 @@ export const FlatTree = (props: FlatTreeProps) => { setFilesSelected={setFilesSelected} handleClickFolder={handleClickFolder} expandPath={expandPath} + selectedItems={selectedItems} + setSelectedItems={setSelectedItems} >
Date: Mon, 29 Apr 2024 12:24:44 +0100 Subject: [PATCH 19/44] rename parameter for moveSilently. cleanup comment --- .../workspace/src/lib/components/file-explorer.tsx | 9 ++++----- .../workspace/src/lib/components/flat-tree-drop.tsx | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 7530cbf2c0..d9618e8453 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -364,17 +364,16 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const handleFolderMove = async (dest: string, src: string) => { - if (await moveFolderIsAllowed(src, dest) === false) return - const folders = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') - console.log(folders) + const handleFolderMove = async (dest: string, copySrc: string) => { + if (await moveFolderIsAllowed(copySrc, dest) === false) return + const src = filesSelected && filesSelected.length > 0 ? filesSelected.join(' ') : '' try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFolder(src, dest), + () => props.dispatchMoveFolder(copySrc, dest), intl.formatMessage({ id: 'filePanel.cancel' }), () => { } ) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 11300819ad..acbc74a075 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -50,7 +50,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { event.preventDefault() const target = await getEventTarget(event) - // const items = buildMultiSelectedItemProfiles(target) const filePaths = [] let dragDestination: any From 8e369e39d572aef71a97cba6621ab4da5ae5a30e Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:31:12 +0100 Subject: [PATCH 20/44] update JSDoc --- libs/remix-ui/workspace/src/lib/components/file-explorer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index d9618e8453..ff2daf211e 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -298,7 +298,7 @@ export const FileExplorer = (props: FileExplorerProps) => { * without showing a modal dialong to the user. * @param dest path of the destination * @param src path of the source - * @returns {void} + * @returns {Promise} */ const moveFileSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return @@ -321,7 +321,7 @@ export const FileExplorer = (props: FileExplorerProps) => { * without showing a modal dialong to the user. * @param dest path of the destination * @param src path of the source - * @returns {void} + * @returns {Promise} */ const moveFolderSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return From f383677905087c75acf419fbbde915301bab6efc Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 12:59:31 +0100 Subject: [PATCH 21/44] add console log --- libs/remix-ui/workspace/src/lib/components/file-explorer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index ff2daf211e..7768366f4b 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -303,7 +303,7 @@ export const FileExplorer = (props: FileExplorerProps) => { const moveFileSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return if (await moveFileIsAllowed(src, dest) === false) return - + console.log({ src, dest }) try { props.dispatchMoveFile(src, dest) } catch (error) { @@ -326,7 +326,7 @@ export const FileExplorer = (props: FileExplorerProps) => { const moveFolderSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return if (await moveFolderIsAllowed(src, dest) === false) return - + console.log({ src, dest }) try { props.dispatchMoveFolder(src, dest) } catch (error) { From 29d6ddada4c7dfac16c4d4580650cce22cb37ca2 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 14:12:46 +0100 Subject: [PATCH 22/44] clean onDrop function in flat-tree --- libs/remix-ui/workspace/src/lib/components/flat-tree.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index 6a56153cf8..42ced37826 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -125,6 +125,12 @@ export const FlatTree = (props: FlatTreeProps) => { const onDragEnd = (event: SyntheticEvent) => { setIsDragging(false) + document.querySelectorAll('li.remixui_selected').forEach(item => { + item.classList.remove('remixui_selected') + item.classList.remove('bg-secondary') + }) + props.setFilesSelected([]) + setSelectedItems([]) } const getFlatTreeItem = (path: string) => { From e10ea923457335883104402d144c520d6d520759 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 14:13:05 +0100 Subject: [PATCH 23/44] refactor --- apps/remix-ide/src/app/files/fileManager.ts | 1 + libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index be40d899ab..401cce42ee 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -83,6 +83,7 @@ class FileManager extends Plugin { * @param {string} message message to display if path doesn't exist. */ async _handleExists(path: string, message?: string) { + console.log('_handleExists is called ', { path, message }) const exists = await this.exists(path) if (!exists) { diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index acbc74a075..121e790b38 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -84,10 +84,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { await moveFilesSilently(props.selectedItems, dragDestination.path) } } - document.querySelectorAll('li.remixui_selected').forEach(item => { - item.classList.remove('remixui_selected') - item.classList.remove('bg-secondary') - }) } /** From 6a50dbca2643a1b78e89f3f9876d0f0d51644422 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 29 Apr 2024 14:38:44 +0100 Subject: [PATCH 24/44] using path --- libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 121e790b38..fb2c08ff21 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -78,10 +78,10 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { if (dragSource.isDirectory) { moveFolder(path, dragSource.path) - await moveFoldersSilently(props.selectedItems, dragDestination.path) + await moveFoldersSilently(props.selectedItems, path) } else { moveFile(path, dragSource.path) - await moveFilesSilently(props.selectedItems, dragDestination.path) + await moveFilesSilently(props.selectedItems, path) } } } From 9c48c6e563ae12cca276c34114dc9b7fa704de07 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 Apr 2024 19:20:29 +0200 Subject: [PATCH 25/44] add warn message --- .../src/lib/components/file-explorer.tsx | 22 ++++++++++++++----- .../src/lib/components/flat-tree-drop.tsx | 20 ++++++++--------- .../src/lib/components/flat-tree.tsx | 4 +++- .../remix-ui/workspace/src/lib/types/index.ts | 1 + 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 7768366f4b..8169053528 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -339,12 +339,23 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const handleFileMove = async (dest: string, copySrc: string) => { - if (await moveFileIsAllowed(copySrc, dest) === false) return - - const src = filesSelected && filesSelected.length > 0 ? filesSelected.join(' ') : '' + const warnMovingItems = async (src: string[], dest: string): Promise => { + return new Promise((resolve, reject) => { + props.modal( + intl.formatMessage({ id: 'filePanel.moveFile' }), + intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src: src.join(', '), dest }), + intl.formatMessage({ id: 'filePanel.yes' }), + () => resolve(null), + intl.formatMessage({ id: 'filePanel.cancel' }), + () => reject() + ) + }) + } - console.log('handleFileMove sourcesrc', {src, copySrc, dest }) + const handleFileMove = async (dest: string, sourcesrc: string[]) => { + if (await moveFilesIsAllowed(sourcesrc, dest) === false) return + const files = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') + const src = files.length > 0 ? files : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ') try { props.modal( intl.formatMessage({ id: 'filePanel.moveFile' }), @@ -454,6 +465,7 @@ export const FileExplorer = (props: FileExplorerProps) => { fileState={fileState} expandPath={props.expandPath} handleContextMenu={handleContextMenu} + warnMovingItems={warnMovingItems} moveFile={handleFileMove} moveFolder={handleFolderMove} moveFolderSilently={moveFolderSilently} diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index fb2c08ff21..8d48aaccd9 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -8,7 +8,7 @@ import { FileSystemContext } from '../contexts' export const FlatTreeDrop = (props: FlatTreeDropProps) => { - const { getFlatTreeItem, dragSource, moveFile, moveFolder, handleClickFolder, expandPath } = props + const { getFlatTreeItem, dragSource, handleClickFolder, expandPath } = props // delay timer const [timer, setTimer] = useState() // folder to open @@ -67,21 +67,21 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { if (dragDestination.isDirectory) { if (dragSource.isDirectory) { - moveFolder(dragDestination.path, dragSource.path) - await moveFoldersSilently(props.selectedItems, dragDestination.path) + await props.warnMovingItems(filePaths, dragDestination.path) + await moveFoldersSilently(filePaths, dragDestination.path) } else { - moveFile(dragDestination.path, dragSource.path) - await moveFilesSilently(props.selectedItems, dragDestination.path) + await props.warnMovingItems(filePaths, dragDestination.path) + await moveFilesSilently(filePaths, dragDestination.path) } } else { const path = extractParentFromKey(dragDestination.path) || '/' if (dragSource.isDirectory) { - moveFolder(path, dragSource.path) - await moveFoldersSilently(props.selectedItems, path) + await props.warnMovingItems(filePaths, path) + await moveFoldersSilently(filePaths, path) } else { - moveFile(path, dragSource.path) - await moveFilesSilently(props.selectedItems, path) + await props.warnMovingItems(filePaths, path) + await moveFilesSilently(filePaths, path) } } } @@ -93,7 +93,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { * @returns Promise */ const moveFilesSilently = async (items: DragStructure[], targetPath: string) => { - console.log('moveItemsSilently', { items, targetPath }) const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'file') { @@ -110,7 +109,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { * @returns Promise */ const moveFoldersSilently = async (items: DragStructure[], targetPath: string) => { - console.log('moveItemsSilently', { items, targetPath }) const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'folder') { diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index 42ced37826..4f8e8f7aa0 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -46,6 +46,7 @@ interface FlatTreeProps { createNewFolder?: any deletePath?: (path: string | string[]) => void | Promise editPath?: (path: string, type: string, isNew?: boolean) => void + warnMovingItems: (srcs: string[], dests: string) => Promise } let mouseTimer: any = { @@ -54,7 +55,7 @@ let mouseTimer: any = { } export const FlatTree = (props: FlatTreeProps) => { - const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently, setFilesSelected } = props + const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, warnMovingItems, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently, setFilesSelected } = props const [hover, setHover] = useState('') const [mouseOverTarget, setMouseOverTarget] = useState<{ path: string, @@ -264,6 +265,7 @@ export const FlatTree = (props: FlatTreeProps) => { getFlatTreeItem={getFlatTreeItem} moveFile={moveFile} moveFolder={moveFolder} + warnMovingItems={warnMovingItems} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} setFilesSelected={setFilesSelected} diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 56bf8b839e..9ba1843b4c 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -358,6 +358,7 @@ export interface FlatTreeDropProps { expandPath: string[] selectedItems: DragStructure[] setSelectedItems: Dispatch> + warnMovingItems: (srcs: string[], dest: string) => Promise } export type DragStructure = { From b31285cf3979f133f2b92d9cb310035f55b94dc6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 29 Apr 2024 19:46:06 +0200 Subject: [PATCH 26/44] refactor and fix --- apps/remix-ide/src/app/files/fileManager.ts | 1 - .../src/lib/components/file-explorer.tsx | 50 ------------------- .../src/lib/components/flat-tree-drop.tsx | 8 +-- .../src/lib/components/flat-tree.tsx | 6 +-- .../remix-ui/workspace/src/lib/types/index.ts | 2 - 5 files changed, 5 insertions(+), 62 deletions(-) diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index 401cce42ee..be40d899ab 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -83,7 +83,6 @@ class FileManager extends Plugin { * @param {string} message message to display if path doesn't exist. */ async _handleExists(path: string, message?: string) { - console.log('_handleExists is called ', { path, message }) const exists = await this.exists(path) if (!exists) { diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 8169053528..47599beca3 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -303,7 +303,6 @@ export const FileExplorer = (props: FileExplorerProps) => { const moveFileSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return if (await moveFileIsAllowed(src, dest) === false) return - console.log({ src, dest }) try { props.dispatchMoveFile(src, dest) } catch (error) { @@ -326,7 +325,6 @@ export const FileExplorer = (props: FileExplorerProps) => { const moveFolderSilently = async (dest: string, src: string) => { if (dest.length === 0 || src.length === 0) return if (await moveFolderIsAllowed(src, dest) === false) return - console.log({ src, dest }) try { props.dispatchMoveFolder(src, dest) } catch (error) { @@ -352,52 +350,6 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const handleFileMove = async (dest: string, sourcesrc: string[]) => { - if (await moveFilesIsAllowed(sourcesrc, dest) === false) return - const files = filesSelected && filesSelected.length > 0 && filesSelected.join(' ') - const src = files.length > 0 ? files : sourcesrc.length === 1 ? sourcesrc[0] : sourcesrc.join(' ') - try { - props.modal( - intl.formatMessage({ id: 'filePanel.moveFile' }), - intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), - intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFile(copySrc, dest), - intl.formatMessage({ id: 'filePanel.cancel' }), - () => { } - ) - } catch (error) { - props.modal( - intl.formatMessage({ id: 'filePanel.movingFileFailed' }), - intl.formatMessage({ id: 'filePanel.movingFileFailedMsg' }, { src }), - intl.formatMessage({ id: 'filePanel.close' }), - async () => { } - ) - } - } - - const handleFolderMove = async (dest: string, copySrc: string) => { - if (await moveFolderIsAllowed(copySrc, dest) === false) return - const src = filesSelected && filesSelected.length > 0 ? filesSelected.join(' ') : '' - - try { - props.modal( - intl.formatMessage({ id: 'filePanel.moveFile' }), - intl.formatMessage({ id: 'filePanel.moveFileMsg1' }, { src, dest }), - intl.formatMessage({ id: 'filePanel.yes' }), - () => props.dispatchMoveFolder(copySrc, dest), - intl.formatMessage({ id: 'filePanel.cancel' }), - () => { } - ) - } catch (error) { - props.modal( - intl.formatMessage({ id: 'filePanel.movingFolderFailed' }), - intl.formatMessage({ id: 'filePanel.movingFolderFailedMsg' }, { src }), - intl.formatMessage({ id: 'filePanel.close' }), - async () => { } - ) - } - } - const handleTreeClick = (event: SyntheticEvent) => { let target = event.target as HTMLElement while (target && target.getAttribute && !target.getAttribute('data-path')) { @@ -466,8 +418,6 @@ export const FileExplorer = (props: FileExplorerProps) => { expandPath={props.expandPath} handleContextMenu={handleContextMenu} warnMovingItems={warnMovingItems} - moveFile={handleFileMove} - moveFolder={handleFolderMove} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} setFilesSelected={setFilesSelected} diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 8d48aaccd9..d825bb99ad 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -68,20 +68,20 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { if (dragDestination.isDirectory) { if (dragSource.isDirectory) { await props.warnMovingItems(filePaths, dragDestination.path) - await moveFoldersSilently(filePaths, dragDestination.path) + await moveFoldersSilently(props.selectedItems, dragDestination.path) } else { await props.warnMovingItems(filePaths, dragDestination.path) - await moveFilesSilently(filePaths, dragDestination.path) + await moveFilesSilently(props.selectedItems, dragDestination.path) } } else { const path = extractParentFromKey(dragDestination.path) || '/' if (dragSource.isDirectory) { await props.warnMovingItems(filePaths, path) - await moveFoldersSilently(filePaths, path) + await moveFoldersSilently(props.selectedItems, path) } else { await props.warnMovingItems(filePaths, path) - await moveFilesSilently(filePaths, path) + await moveFilesSilently(props.selectedItems, path) } } } diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx index 4f8e8f7aa0..deacbfbac0 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx @@ -36,8 +36,6 @@ interface FlatTreeProps { handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void handleTreeClick: (e: SyntheticEvent) => void handleClickFolder: (path: string, type: string) => void - moveFile: (dest: string, src: string) => void - moveFolder: (dest: string, src: string) => void moveFolderSilently: (dest: string, src: string) => Promise moveFileSilently: (dest: string, src: string) => Promise setFilesSelected: Dispatch> @@ -55,7 +53,7 @@ let mouseTimer: any = { } export const FlatTree = (props: FlatTreeProps) => { - const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, warnMovingItems, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently, setFilesSelected } = props + const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, warnMovingItems, fileState, focusElement, handleClickFolder, deletePath, moveFileSilently, moveFolderSilently, setFilesSelected } = props const [hover, setHover] = useState('') const [mouseOverTarget, setMouseOverTarget] = useState<{ path: string, @@ -263,8 +261,6 @@ export const FlatTree = (props: FlatTreeProps) => { }[keyof ActionP export type WorkspaceElement = 'folder' | 'file' | 'workspace' export interface FlatTreeDropProps { - moveFile: (dest: string, src: string) => void - moveFolder: (dest: string, src: string) => void moveFolderSilently: (dest: string, src: string) => Promise moveFileSilently: (dest: string, src: string) => Promise setFilesSelected: Dispatch> From 803ffb612ea56f16f5390e4919cfde1a4c36599c Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Tue, 30 Apr 2024 09:55:07 +0100 Subject: [PATCH 27/44] add e2e tests --- .../tests/file_explorer_multiselect.test.ts | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 1d31d6a9b5..65ff7c553e 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -22,6 +22,49 @@ module.exports = { .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemtests"]') - .end() + }, + 'Should select multiple items in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { + const selectedElements = [] + browser + .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) + .findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { + selectedElements.push(el) + }) + browser.selectFiles(selectedElements) + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/1_Storage.sol"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') + }) + }, + 'should select multiple files and folders in file explorer to contracts folder #group1': function (browser: NightwatchBrowser) { + const selectedElements = [] + browser + .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) + .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, (el) => { + selectedElements.push(el) + }) + browser.selectFiles(selectedElements) + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') + }) } } From 215d356972bf3d94ebdb224a47ac1e7b28d18ca3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 30 Apr 2024 11:00:50 +0200 Subject: [PATCH 28/44] fix tests --- .../tests/file_explorer_multiselect.test.ts | 4 +- .../src/lib/components/file-explorer.tsx | 2 +- .../src/lib/components/flat-tree-drop.tsx | 43 +++---------------- .../src/lib/components/flat-tree.tsx | 1 - 4 files changed, 9 insertions(+), 41 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 65ff7c553e..8d1ce137d1 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -23,7 +23,7 @@ module.exports = { .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemtests"]') }, - 'Should select multiple items in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { + 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] browser .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) @@ -45,7 +45,7 @@ module.exports = { .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') }) }, - 'should select multiple files and folders in file explorer to contracts folder #group1': function (browser: NightwatchBrowser) { + 'should drag and drop multiple files and folders in file explorer to contracts folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] browser .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 47599beca3..3d421830a1 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -347,7 +347,7 @@ export const FileExplorer = (props: FileExplorerProps) => { intl.formatMessage({ id: 'filePanel.cancel' }), () => reject() ) - }) + }) } const handleTreeClick = (event: SyntheticEvent) => { diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index d825bb99ad..75697137b2 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -4,8 +4,6 @@ import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEven import { extractParentFromKey } from '@remix-ui/helper' import { FileSystemContext } from '../contexts' - - export const FlatTreeDrop = (props: FlatTreeDropProps) => { const { getFlatTreeItem, dragSource, handleClickFolder, expandPath } = props @@ -13,9 +11,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { const [timer, setTimer] = useState() // folder to open const [folderToOpen, setFolderToOpen] = useState() - const globalFEContext = useContext(FileSystemContext) - - const [selectedItems, setSelectedItems] = useState([]) const onDragOver = async (e: SyntheticEvent) => { e.preventDefault() @@ -66,23 +61,12 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { props.setFilesSelected(filePaths) if (dragDestination.isDirectory) { - if (dragSource.isDirectory) { - await props.warnMovingItems(filePaths, dragDestination.path) - await moveFoldersSilently(props.selectedItems, dragDestination.path) - } else { - await props.warnMovingItems(filePaths, dragDestination.path) - await moveFilesSilently(props.selectedItems, dragDestination.path) - } + await props.warnMovingItems(filePaths, dragDestination.path) + await moveItemsSilently(props.selectedItems, dragDestination.path) } else { const path = extractParentFromKey(dragDestination.path) || '/' - - if (dragSource.isDirectory) { - await props.warnMovingItems(filePaths, path) - await moveFoldersSilently(props.selectedItems, path) - } else { - await props.warnMovingItems(filePaths, path) - await moveFilesSilently(props.selectedItems, path) - } + await props.warnMovingItems(filePaths, path) + await moveItemsSilently(props.selectedItems, path) } } @@ -92,33 +76,18 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { * @param dragSource source FileExplorer item being dragged. * @returns Promise */ - const moveFilesSilently = async (items: DragStructure[], targetPath: string) => { + const moveItemsSilently = async (items: DragStructure[], targetPath: string) => { const promises = items.filter(item => item.path !== targetPath) .map(async (item) => { if (item.type === 'file') { await props.moveFileSilently(targetPath, item.path) - } - }) - await Promise.all(promises) - } - - /** - * Moves items silently without showing a confirmation dialog. - * @param items MultiSelected items built into a DragStructure profile - * @param dragSource source FileExplorer item being dragged. - * @returns Promise - */ - const moveFoldersSilently = async (items: DragStructure[], targetPath: string) => { - const promises = items.filter(item => item.path !== targetPath) - .map(async (item) => { - if (item.type === 'folder') { + } else if (item.type === 'folder') { await props.moveFolderSilently(targetPath, item.path) } }) await Promise.all(promises) } - return (
{ const virtuoso = useRef(null) const [selectedItems, setSelectedItems] = useState([]) - const labelClass = (file: FileType) => props.focusEdit.element === file.path ? 'bg-light' From 8bef427b64634795bcd7fc61b97d3d1a446c509f Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 30 Apr 2024 16:19:00 +0200 Subject: [PATCH 29/44] fix dragging --- libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts index e7cd32bc4a..ea663acf11 100644 --- a/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts +++ b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts @@ -42,15 +42,15 @@ export const buildMultiSelectedItemProfiles = (target: { } }) => { const selectItems = [] + selectItems.push(target) document.querySelectorAll('li.remixui_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) + if (dragTarget.path !== target.path) selectItems.push(dragTarget) }) return selectItems } From 0a34381fd39561a72043ad4ae2d5c7a732bf2f3d Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 30 Apr 2024 16:47:16 +0200 Subject: [PATCH 30/44] fix test --- apps/remix-ide-e2e/src/commands/selectFiles.ts | 2 +- .../src/tests/file_explorer_multiselect.test.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/remix-ide-e2e/src/commands/selectFiles.ts b/apps/remix-ide-e2e/src/commands/selectFiles.ts index d24ec1e42b..86a2777440 100644 --- a/apps/remix-ide-e2e/src/commands/selectFiles.ts +++ b/apps/remix-ide-e2e/src/commands/selectFiles.ts @@ -11,7 +11,7 @@ class SelectFiles extends EventEmitter { for(let i = 0; i < selectedElements.length; i++) { actions.click(selectedElements[i].value) } - return actions.contextClick(selectedElements[0].value) + // return actions.contextClick(selectedElements[0].value) }) this.emit('complete') return this diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 8d1ce137d1..b137f42af5 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -2,6 +2,7 @@ import { NightwatchBrowser } from 'nightwatch' import init from '../helpers/init' module.exports = { + "@disabled": true, before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done) }, @@ -31,7 +32,8 @@ module.exports = { selectedElements.push(el) }) browser.selectFiles(selectedElements) - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, (el: any) => { const id = (el as any).value.getId() browser @@ -43,17 +45,21 @@ module.exports = { .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') + .perform(() => done()) }) + }) }, - 'should drag and drop multiple files and folders in file explorer to contracts folder #group1': function (browser: NightwatchBrowser) { + 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { const selectedElements = [] browser + .clickLaunchIcon('filePanel') .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, (el) => { selectedElements.push(el) }) browser.selectFiles(selectedElements) - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, (el: any) => { const id = (el as any).value.getId() browser @@ -65,6 +71,8 @@ module.exports = { .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') + .perform(() => done()) }) + }) } } From ff07fa0ef7161dc7c8f2db181a089421ccbfc960 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 30 May 2024 13:56:52 +0200 Subject: [PATCH 31/44] fix test --- .../remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index b137f42af5..87caa9a626 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -67,8 +67,8 @@ module.exports = { .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]') - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') .perform(() => done()) From ff556aeb4fc6165a5f532fa92293dba369350030 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 30 May 2024 15:01:27 +0200 Subject: [PATCH 32/44] add resetMultiselect --- .../workspace/src/lib/components/file-explorer.tsx | 7 +++++++ .../workspace/src/lib/components/flat-tree-drop.tsx | 1 + libs/remix-ui/workspace/src/lib/components/flat-tree.tsx | 2 ++ libs/remix-ui/workspace/src/lib/types/index.ts | 1 + 4 files changed, 11 insertions(+) diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 3d421830a1..10dea83d97 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -315,6 +315,12 @@ export const FileExplorer = (props: FileExplorerProps) => { } } + const resetMultiselect = () => { + setState((prevState) => { + return { ...prevState, ctrlKey: false } + }) + } + /** * This offers the ability to move a folder to a new location * without showing a modal dialong to the user. @@ -420,6 +426,7 @@ export const FileExplorer = (props: FileExplorerProps) => { warnMovingItems={warnMovingItems} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} + resetMultiselect={resetMultiselect} setFilesSelected={setFilesSelected} handleClickFolder={handleClickFolder} createNewFile={props.createNewFile} diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx index 75697137b2..d049a2bb6c 100644 --- a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx +++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx @@ -86,6 +86,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => { } }) await Promise.all(promises) + props.resetMultiselect() } return (
void moveFolderSilently: (dest: string, src: string) => Promise moveFileSilently: (dest: string, src: string) => Promise + resetMultiselect: () => void setFilesSelected: Dispatch> fileState: fileDecoration[] createNewFile?: any @@ -263,6 +264,7 @@ export const FlatTree = (props: FlatTreeProps) => { warnMovingItems={warnMovingItems} moveFolderSilently={moveFolderSilently} moveFileSilently={moveFileSilently} + resetMultiselect={props.resetMultiselect} setFilesSelected={setFilesSelected} handleClickFolder={handleClickFolder} expandPath={expandPath} diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index af6f5d95ac..684bf80046 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -346,6 +346,7 @@ export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionP export type WorkspaceElement = 'folder' | 'file' | 'workspace' export interface FlatTreeDropProps { + resetMultiselect: () => void moveFolderSilently: (dest: string, src: string) => Promise moveFileSilently: (dest: string, src: string) => Promise setFilesSelected: Dispatch> From 47ecf5ff24bc3f1034ea1dea8553eac6c4df9718 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Tue, 25 Jun 2024 13:26:58 +0100 Subject: [PATCH 33/44] changes to e2e --- .../src/tests/file_explorer_multiselect.test.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 87caa9a626..e494e5bac2 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -11,11 +11,13 @@ module.exports = { const selectedElements = [] browser .openFile('contracts') - .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) - .findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { + .pause() + // .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) + .click({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) + .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { selectedElements.push(el) }) - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, + browser.findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemtests"]', locateStrategy: 'xpath' }, (el: any) => { selectedElements.push(el) }) @@ -47,7 +49,7 @@ module.exports = { .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .perform(() => done()) }) - }) + }) }, 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { const selectedElements = [] @@ -73,6 +75,6 @@ module.exports = { .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') .perform(() => done()) }) - }) + }) } } From 7bb1cea9f2cd339f04de8c166bf94bb27ccf9098 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Wed, 26 Jun 2024 09:48:08 +0100 Subject: [PATCH 34/44] fix e2e --- .../remix-ide-e2e/src/commands/selectFiles.ts | 5 +- .../tests/file_explorer_multiselect.test.ts | 63 ++++++++++--------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/apps/remix-ide-e2e/src/commands/selectFiles.ts b/apps/remix-ide-e2e/src/commands/selectFiles.ts index 86a2777440..544f36ba3d 100644 --- a/apps/remix-ide-e2e/src/commands/selectFiles.ts +++ b/apps/remix-ide-e2e/src/commands/selectFiles.ts @@ -8,15 +8,14 @@ class SelectFiles extends EventEmitter { browser.perform(function () { const actions = this.actions({ async: true }) actions.keyDown(this.Keys.SHIFT) - for(let i = 0; i < selectedElements.length; i++) { + for (let i = 0; i < selectedElements.length; i++) { actions.click(selectedElements[i].value) } - // return actions.contextClick(selectedElements[0].value) + return actions//.contextClick(selectedElements[0].value) }) this.emit('complete') return this } } - module.exports = SelectFiles diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index e494e5bac2..fdfa4c3e42 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -11,7 +11,6 @@ module.exports = { const selectedElements = [] browser .openFile('contracts') - .pause() // .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { @@ -29,27 +28,29 @@ module.exports = { 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] browser + .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) .findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { selectedElements.push(el) }) browser.selectFiles(selectedElements) - .perform((done) => { - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, - (el: any) => { - const id = (el as any).value.getId() - browser - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') - .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) - .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') - .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/1_Storage.sol"]') - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') - .perform(() => done()) + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .pause() + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/1_Storage.sol"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') + .perform(() => done()) + }) }) - }) }, 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { const selectedElements = [] @@ -60,21 +61,21 @@ module.exports = { selectedElements.push(el) }) browser.selectFiles(selectedElements) - .perform((done) => { - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, - (el: any) => { - const id = (el as any).value.getId() - browser - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]') - .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) - .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') - .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') - .perform(() => done()) + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') + .perform(() => done()) + }) }) - }) } } From b40d6dd9945fb8985f8ed1c23423e9aa8a515c8d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Wed, 26 Jun 2024 11:06:29 +0100 Subject: [PATCH 35/44] fixed more e2e --- .../src/tests/file_explorer_multiselect.test.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index fdfa4c3e42..6707b1ca7f 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -11,7 +11,6 @@ module.exports = { const selectedElements = [] browser .openFile('contracts') - // .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { selectedElements.push(el) @@ -39,7 +38,6 @@ module.exports = { (el: any) => { const id = (el as any).value.getId() browser - .pause() .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') @@ -57,7 +55,11 @@ module.exports = { browser .clickLaunchIcon('filePanel') .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) - .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, (el) => { + .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemscripts"]', locateStrategy: 'xpath' }, (el) => { + selectedElements.push(el) + }) + browser.findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, + (el: any) => { selectedElements.push(el) }) browser.selectFiles(selectedElements) @@ -72,6 +74,7 @@ module.exports = { .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/scripts"]', 5000) .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') .perform(() => done()) From ae23e6698abca77370d239f6fe6ff39eca4a5693 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 27 Jun 2024 22:51:35 +0100 Subject: [PATCH 36/44] address firefox failure --- apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 6707b1ca7f..434e2d1111 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -26,6 +26,7 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] + if (browser.browserName.indexOf('firefox') > -1) return browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) From 0face74a39b8471bb19c67c9deb6ec4c733a1907 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 27 Jun 2024 23:23:52 +0100 Subject: [PATCH 37/44] end session correctly for firefox --- .../src/tests/file_explorer_multiselect.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 434e2d1111..77224ad604 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -26,7 +26,11 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] - if (browser.browserName.indexOf('firefox') > -1) return + if (browser.options.desiredCapabilities.browserName === 'firefox') { + console.log('Skipping test for Firefox') + browser.end() + return + } browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) From a384fd88d32f21ab11f77ace4bd7b0fbd38ac837 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 27 Jun 2024 23:43:43 +0100 Subject: [PATCH 38/44] fix e2e --- .../src/tests/file_explorer_multiselect.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 77224ad604..1e1df4309b 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -26,11 +26,7 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] - if (browser.options.desiredCapabilities.browserName === 'firefox') { - console.log('Skipping test for Firefox') - browser.end() - return - } + browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) From d803514fda14ad2cf6603b23b306268739f82f16 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 8 Jul 2024 14:59:05 +0100 Subject: [PATCH 39/44] disabled test for firefox --- .../src/tests/file_explorer_multiselect.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 1e1df4309b..701afb9b27 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -26,6 +26,11 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] + if (browser.options.desiredCapabilities?.browserName === 'firefox') { + console.log('Skipping test for firefox') + browser.end() + return; + } browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) From 92d9257f4186c1928cef6515921f79a82217270c Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 8 Jul 2024 17:02:09 +0100 Subject: [PATCH 40/44] disable flaky test --- apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 701afb9b27..e9852fd6b6 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -24,7 +24,7 @@ module.exports = { .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemtests"]') }, - 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { + 'Should drag and drop multiple files in file explorer to tests folder #group1': ''+function (browser: NightwatchBrowser) { const selectedElements = [] if (browser.options.desiredCapabilities?.browserName === 'firefox') { console.log('Skipping test for firefox') From c21f26b41a5c1789f0507b311e05c5d091285009 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Mon, 8 Jul 2024 23:18:44 +0100 Subject: [PATCH 41/44] deal with flaky test --- .../tests/file_explorer_multiselect.test.ts | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index e9852fd6b6..c38a0673ed 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -24,37 +24,37 @@ module.exports = { .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') .assert.visible('.bg-secondary[data-id="treeViewLitreeViewItemtests"]') }, - 'Should drag and drop multiple files in file explorer to tests folder #group1': ''+function (browser: NightwatchBrowser) { + 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] if (browser.options.desiredCapabilities?.browserName === 'firefox') { console.log('Skipping test for firefox') browser.end() return; + } else { + browser + .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) + .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) + .findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { + selectedElements.push(el) + }) + browser.selectFiles(selectedElements) + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/1_Storage.sol"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') + .perform(() => done()) + }) + }) } - - browser - .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) - .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) - .findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]', locateStrategy: 'xpath' }, (el) => { - selectedElements.push(el) - }) - browser.selectFiles(selectedElements) - .perform((done) => { - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }, - (el: any) => { - const id = (el as any).value.getId() - browser - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests"]') - .dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', id) - .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') - .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/1_Storage.sol"]') - .waitForElementVisible('li[data-id="treeViewLitreeViewItemtests/2_Owner.sol"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]') - .perform(() => done()) - }) - }) }, 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { const selectedElements = [] From 50e860415a213853b2be5275e5f9bf2dd69c095d Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 11 Jul 2024 10:48:22 +0100 Subject: [PATCH 42/44] disable test in firefox --- .../src/tests/file_explorer_multiselect.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index c38a0673ed..d7c04376c7 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -8,6 +8,7 @@ module.exports = { }, 'Should select multiple items in file explorer #group1': function (browser: NightwatchBrowser) { + console.log(browser) const selectedElements = [] browser .openFile('contracts') @@ -26,11 +27,7 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] - if (browser.options.desiredCapabilities?.browserName === 'firefox') { - console.log('Skipping test for firefox') - browser.end() - return; - } else { + if (browser.options.desiredCapabilities?.browserName === 'chrome') { browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) @@ -54,6 +51,8 @@ module.exports = { .perform(() => done()) }) }) + } else { + browser.end() } }, 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { From fd0ffc1c796a22caa81a68a268047d9c90892b8f Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 11 Jul 2024 11:16:03 +0100 Subject: [PATCH 43/44] disable duplicate test --- .../src/tests/file_explorer_multiselect.test.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index d7c04376c7..18a52f587f 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -8,7 +8,6 @@ module.exports = { }, 'Should select multiple items in file explorer #group1': function (browser: NightwatchBrowser) { - console.log(browser) const selectedElements = [] browser .openFile('contracts') @@ -27,7 +26,11 @@ module.exports = { }, 'Should drag and drop multiple files in file explorer to tests folder #group1': function (browser: NightwatchBrowser) { const selectedElements = [] - if (browser.options.desiredCapabilities?.browserName === 'chrome') { + if (browser.options.desiredCapabilities?.browserName === 'firefox') { + console.log('Skipping test for firefox') + browser.end() + return; + } else { browser .click({ selector: '//*[@data-id="treeViewUltreeViewMenu"]', locateStrategy: 'xpath' }) .click({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', locateStrategy: 'xpath' }) @@ -51,11 +54,9 @@ module.exports = { .perform(() => done()) }) }) - } else { - browser.end() } }, - 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { + 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': ''+function (browser: NightwatchBrowser) { const selectedElements = [] browser .clickLaunchIcon('filePanel') From ba251d7efc6ff338b44f72d1e568ee558ed4b07c Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 11 Jul 2024 11:25:11 +0100 Subject: [PATCH 44/44] skip firefox for test --- .../tests/file_explorer_multiselect.test.ts | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts index 18a52f587f..214217af38 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_multiselect.test.ts @@ -56,35 +56,41 @@ module.exports = { }) } }, - 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': ''+function (browser: NightwatchBrowser) { + 'should drag and drop multiple files and folders in file explorer to contracts folder #group3': function (browser: NightwatchBrowser) { const selectedElements = [] - browser - .clickLaunchIcon('filePanel') - .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) - .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemscripts"]', locateStrategy: 'xpath' }, (el) => { - selectedElements.push(el) - }) - browser.findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, - (el: any) => { - selectedElements.push(el) - }) - browser.selectFiles(selectedElements) - .perform((done) => { - browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, - (el: any) => { - const id = (el as any).value.getId() - browser - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]') - .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) - .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') - .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) - .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/scripts"]', 5000) - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') - .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') - .perform(() => done()) - }) - }) + if (browser.options.desiredCapabilities?.browserName === 'firefox') { + console.log('Skipping test for firefox') + browser.end() + return; + } else { + browser + .clickLaunchIcon('filePanel') + .click({ selector: '//*[@data-id="treeViewLitreeViewItemtests"]', locateStrategy: 'xpath' }) + .findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemscripts"]', locateStrategy: 'xpath' }, (el) => { + selectedElements.push(el) + }) + browser.findElement({ selector: '//*[@data-id="treeViewDivtreeViewItemREADME.txt"]', locateStrategy: 'xpath' }, + (el: any) => { + selectedElements.push(el) + }) + browser.selectFiles(selectedElements) + .perform((done) => { + browser.findElement({ selector: '//*[@data-id="treeViewLitreeViewItemcontracts"]', locateStrategy: 'xpath' }, + (el: any) => { + const id = (el as any).value.getId() + browser + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]') + .dragAndDrop('li[data-id="treeViewLitreeViewItemtests"]', id) + .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') + .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/tests"]', 5000) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 5000) + .waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/scripts"]', 5000) + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemtests"]') + .waitForElementNotPresent('li[data-id="treeViewLitreeViewItemREADME.txt"]') + .perform(() => done()) + }) + }) + } } }