Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE hover icons #4446

Merged
merged 15 commits into from
Feb 14, 2024
178 changes: 89 additions & 89 deletions apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,101 +3,101 @@ import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'

const checkBrowserIsChrome = function (browser: NightwatchBrowser) {
return browser.browserName.indexOf('chrome') > -1
return browser.browserName.indexOf('chrome') > -1
}


module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'drag and drop file from root to contracts #group1 ': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser
.clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.findElement('*[data-id="treeViewLitreeViewItemcontracts"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemREADME.txt"]', 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/README.txt"]')
})
}
},
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'drag and drop file from root to contracts #group1 ': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser
.clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.findElement('*[data-id="treeViewLitreeViewItemcontracts"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemREADME.txt"]', 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/README.txt"]')
})
}
},

'drag and drop file from contracts to root #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.findElement('*[data-id="treeViewUltreeViewMenu"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]')
.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() })
})
browser.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItem1_Storage.sol"]')
}
},
'drag and drop scripts from root to contracts #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.findElement('*[data-id="treeViewLitreeViewItemcontracts"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemscripts"]', 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/scripts"]')
})
}
},
'drag scripts from contracts to root #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.findElement('*[data-id="treeViewUltreeViewMenu"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/scripts"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/scripts"]', id)
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
})
browser.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
}
},
'drag into nested folder': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemnewFolder')
.click('[data-id="contextMenuItemnewFolder')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'nested')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.findElement('*[data-id="treeViewLitreeViewItemscripts/nested"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 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="treeViewLitreeViewItemscripts/nested/README.txt"]')
})
}
'drag and drop file from contracts to root #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.findElement('*[data-id="treeViewUltreeViewMenu"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]')
.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() })
})
browser.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItem1_Storage.sol"]')
}
},
'drag and drop scripts from root to contracts #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.findElement('*[data-id="treeViewLitreeViewItemcontracts"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('div[data-id="treeViewDivDraggableItemscripts"]')
.dragAndDrop('div[data-id="treeViewDivDraggableItemscripts"]', 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/scripts"]')
})
}
},
'drag scripts from contracts to root #group1': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.findElement('*[data-id="treeViewUltreeViewMenu"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/scripts"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/scripts"]', id)
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
})
browser.pause(1000)
.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
}
},
'drag into nested folder': function (browser: NightwatchBrowser) {
if (checkBrowserIsChrome(browser)) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemscripts"]')
.rightClick('li[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementPresent('[data-id="contextMenuItemnewFolder')
.click('[data-id="contextMenuItemnewFolder')
.waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'nested')
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
.findElement('*[data-id="treeViewLitreeViewItemscripts/nested"]', (el) => {
console.log((el as any).value.getId())
const id = (el as any).value.getId()
browser
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]')
.dragAndDrop('li[data-id="treeViewLitreeViewItemcontracts/README.txt"]', 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="treeViewLitreeViewItemscripts/nested/README.txt"]')
})
}
}



}
}
2 changes: 1 addition & 1 deletion apps/remix-ide/src/app/tabs/locales/en/filePanel.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,4 @@
"filePanel.movingFolderFailedMsg": "Unexpected error while moving folder: {src}",
"filePanel.workspaceActions": "Workspace actions",
"filePanel.saveCodeSample": "This code-sample workspace will not be persisted. Click here to save it."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useState } from 'react'
import { CustomTooltip } from '@remix-ui/helper'
import { FormattedMessage } from 'react-intl'

export type FileHoverIconsProps = {
file: any
handleNewFolderOp?: any
handleNewFileOp?: any
renamePathOp?: (path: string, type: string, isNew?: boolean) => void
deletePathOp?: (path: string | string[]) => void | Promise<void>
}

export function FileHoverIcons(props: FileHoverIconsProps) {
const [mouseOver, setMouseOver] = useState(false)
return (
<>
{<div className="d-flex flex-row align-items-center">
{
props.file.isDirectory ? (
<>
<CustomTooltip
placement="bottom"
delay={{show: 1000, hide: 0}}
tooltipText={<FormattedMessage id="filePanel.createNewFolder" />}
tooltipId={`filePanel.createNewFolder.${props.file.path}`}
tooltipClasses="text-nowrap"
>
<span
className="far fa-folder fa-1x mr-2 remixui_icons"
onClick={async (e) => {
e.stopPropagation()
await props.handleNewFolderOp(props.file.path)
}}
style={{ cursor: mouseOver ? 'pointer' : 'default' }}
onMouseEnter={(e) => setMouseOver(true)}
onMouseLeave={(e) => setMouseOver(false)}
></span>
</CustomTooltip>
<CustomTooltip
placement="bottom"
delay={{show: 1000, hide: 0}}
tooltipText={<FormattedMessage id="filePanel.createNewFile" />}
tooltipId={`fileExplorer.createNewFile.${props.file.path}`}
tooltipClasses="text-nowrap"
>
<span
className="far fa-file fa-1x remixui_icons mr-2"
onClick={async (e) => {
e.stopPropagation()
await props.handleNewFileOp(props.file.path)
}}
style={{ cursor: mouseOver ? 'pointer' : 'default' }}
onMouseEnter={(e) => setMouseOver(true)}
onMouseLeave={(e) => setMouseOver(false)}
></span>
</CustomTooltip>
</>
) : null
}
<CustomTooltip
placement="bottom"
delay={{show: 1000, hide: 0}}
tooltipText={<FormattedMessage id="filePanel.rename" />}
tooltipId={`filePanel.rename.${props.file.path}`}
tooltipClasses="text-nowrap"
>
<span
className="far fa-pen fa-1x remixui_icons mr-2"
onClick={(e) => {
e.stopPropagation()
props.renamePathOp(props.file.path, props.file.type)
}}
style={{ cursor: mouseOver ? 'pointer' : 'default' }}
onMouseEnter={(e) => setMouseOver(true)}
onMouseLeave={(e) => setMouseOver(false)}
></span>
</CustomTooltip>
<CustomTooltip
placement="bottom"
delay={{show: 1000, hide: 0}}
tooltipText={<FormattedMessage id="filePanel.deleteItem" />}
tooltipId={`filePanel.deleteItem.${props.file.path}`}
tooltipClasses="text-nowrap"
>
<span
className="far fa-trash fa-1x remixui_icons mr-2"
onClick={async (e) => {
e.stopPropagation()
await props.deletePathOp(props.file.path)
}}
style={{ cursor: mouseOver ? 'pointer' : 'default' }}
onMouseEnter={(e) => setMouseOver(true)}
onMouseLeave={(e) => setMouseOver(false)}
></span>
</CustomTooltip>
</div>
}
</>
)
}
10 changes: 8 additions & 2 deletions libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState, useRef, SyntheticEvent, useTransition } from 'react' // eslint-disable-line
import React, { useEffect, useState, useRef, SyntheticEvent } from 'react' // eslint-disable-line
import { useIntl } from 'react-intl'
import { TreeView } from '@remix-ui/tree-view' // eslint-disable-line
import { FileExplorerMenu } from './file-explorer-menu' // eslint-disable-line
Expand Down Expand Up @@ -27,12 +27,13 @@ export const FileExplorer = (props: FileExplorerProps) => {
handleContextMenu,
handleNewFileInput,
handleNewFolderInput,
deletePath,
uploadFile,
uploadFolder,
fileState
} = props
const [state, setState] = useState<WorkSpaceState>(workspaceState)
const [isPending, startTransition] = useTransition();
// const [isPending, startTransition] = useTransition();
const treeRef = useRef<HTMLDivElement>(null)

useEffect(() => {
Expand Down Expand Up @@ -130,6 +131,7 @@ export const FileExplorer = (props: FileExplorerProps) => {

const renamePath = async (oldPath: string, newPath: string) => {
try {
if (oldPath === newPath) return
props.dispatchRenamePath(oldPath, newPath)
} catch (error) {
props.modal(
Expand Down Expand Up @@ -404,6 +406,10 @@ export const FileExplorer = (props: FileExplorerProps) => {
moveFile={handleFileMove}
moveFolder={handleFolderMove}
handleClickFolder={handleClickFolder}
createNewFile={props.createNewFile}
createNewFolder={props.createNewFolder}
deletePath={deletePath}
editPath={props.editModeOn}
/>
</div>
</div>
Expand Down
8 changes: 3 additions & 5 deletions libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { SyntheticEvent, startTransition, useEffect, useRef, useState } from 'react'
import React, { SyntheticEvent, useEffect, useRef, useState } from 'react'
import { FileType } from '../types'
import { getEventTarget } from '../utils/getEventTarget'
import { extractParentFromKey } from '@remix-ui/helper'
Expand All @@ -23,7 +23,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
const onDragOver = async (e: SyntheticEvent) => {
e.preventDefault()
const target = await getEventTarget(e)

if (!target || !target.path) {
clearTimeout(timer)
setFolderToOpen(null)
Expand All @@ -36,7 +35,7 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
setFolderToOpen(null)
}
if (dragDestination && dragDestination.isDirectory && !expandPath.includes(dragDestination.path) && folderToOpen !== dragDestination.path && props.handleClickFolder) {

setFolderToOpen(dragDestination.path)
timer && clearTimeout(timer)
setTimer(
Expand All @@ -61,7 +60,6 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
} else {
dragDestination = getFlatTreeItem(target.path)
}

if (dragDestination.isDirectory) {
if (dragSource.isDirectory) {
moveFolder(dragDestination.path, dragSource.path)
Expand All @@ -84,4 +82,4 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
onDrop={onDrop} onDragOver={onDragOver}
className="d-flex h-100"
>{props.children}</div>)
}
}
Loading
Loading