Merge pull request #4446 from ethereum/fe-hoverIcons

FE hover icons
pull/4531/head
yann300 9 months ago committed by GitHub
commit 46459f208f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 178
      apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts
  2. 2
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  3. 100
      libs/remix-ui/workspace/src/lib/components/file-explorer-hovericons.tsx
  4. 10
      libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
  5. 8
      libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx
  6. 90
      libs/remix-ui/workspace/src/lib/components/flat-tree.tsx
  7. 10
      libs/remix-ui/workspace/src/lib/css/file-explorer.css
  8. 22
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  9. 4
      libs/remix-ui/workspace/src/lib/types/index.ts

@ -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"]')
})
}
}
}
}

@ -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."
}
}

@ -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>
}
</>
)
}

@ -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
@ -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(() => {
@ -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(
@ -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>

@ -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'
@ -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)
@ -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(
@ -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)
@ -84,4 +82,4 @@ export const FlatTreeDrop = (props: FlatTreeDropProps) => {
onDrop={onDrop} onDragOver={onDragOver}
className="d-flex h-100"
>{props.children}</div>)
}
}

@ -7,6 +7,8 @@ import { FlatTreeItemInput } from './flat-tree-item-input';
import { FlatTreeDrop } from './flat-tree-drop';
import { getEventTarget } from '../utils/getEventTarget';
import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators';
import { FileHoverIcons } from './file-explorer-hovericons';
import { deletePath } from '../actions';
export default function useOnScreen(ref: RefObject<HTMLElement>) {
@ -36,6 +38,10 @@ interface FlatTreeProps {
moveFile: (dest: string, src: string) => void
moveFolder: (dest: string, src: string) => void
fileState: fileDecoration[]
createNewFile?: any
createNewFolder?: any
deletePath?: (path: string | string[]) => void | Promise<void>
editPath?: (path: string, type: string, isNew?: boolean) => void
}
let mouseTimer: any = {
@ -44,7 +50,7 @@ let mouseTimer: any = {
}
export const FlatTree = (props: FlatTreeProps) => {
const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder } = props
const { files, flatTree, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder, fileState, focusElement, handleClickFolder, deletePath, editPath } = props
const [hover, setHover] = useState<string>('')
const [mouseOverTarget, setMouseOverTarget] = useState<{
path: string,
@ -178,42 +184,62 @@ export const FlatTree = (props: FlatTreeProps) => {
}
}, [focusEdit])
const showIcons = (file: FileType) =>
file.path === hover && !isDragging ? (
<div>
<FileHoverIcons
file={file}
renamePathOp={props.editPath}
deletePathOp={deletePath}
handleNewFileOp={props.createNewFile}
handleNewFolderOp={props.createNewFolder}
/>
</div>
) : null
const Row = (index: number) => {
const node = Object.keys(flatTree)[index]
const file = flatTree[node]
return (<li
className={`${labelClass(file)} li_tv`}
onMouseOver={() => setHover(file.path)}
onMouseOut={() => setHover(file.path)}
data-type={file.isDirectory ? 'folder' : 'file'}
data-path={`${file.path}`}
data-id={`treeViewLitreeViewItem${file.path}`}
>
<div data-id={`treeViewDivtreeViewItem${file.path}`} className={`d-flex flex-row align-items-center`}>
{getIndentLevelDiv(file.path)}
<div className={`pl-2 ${file.isDirectory ? expandPath && expandPath.includes(file.path) ? 'fa fa-folder-open' : 'fa fa-folder' : `${getPathIcon(file.path)} pr-2 caret caret_tv`} `}></div>
{focusEdit && file.path && focusEdit.element === file.path ?
<FlatTreeItemInput
editModeOff={editModeOff}
file={file} /> :
<><div
draggable={true}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
className={`ml-1 pl-2 text-nowrap remixui_leaf ${getFileStateClasses(file)}`}
data-label-type={file.isDirectory ? 'folder' : 'file'}
data-label-path={`${file.path}`}
key={index}>
{file.name}
return (
<li
className={`${labelClass(file)} li_tv`}
onMouseOver={(e) => {
setHover(file.path)
}}
onMouseOut={() => {
setHover('')
}}
data-type={file.isDirectory ? 'folder' : 'file'}
data-path={`${file.path}`}
data-id={`treeViewLitreeViewItem${file.path}`}
>
<div data-id={`treeViewDivtreeViewItem${file.path}`} className={`d-flex flex-row align-items-center`}>
{getIndentLevelDiv(file.path)}
</div>
{getFileStateIcons(file)}
</>
}
</div>
</li>)
<div className={`pl-2 ${file.isDirectory ? expandPath && expandPath.includes(file.path) ? 'fa fa-folder-open' : 'fa fa-folder' : `${getPathIcon(file.path)} pr-2 caret caret_tv`} `}></div>
{focusEdit && file.path && focusEdit.element === file.path ?
<FlatTreeItemInput
editModeOff={editModeOff}
file={file} /> :
<><div
data-id={`treeViewDivDraggableItem${file.path}`}
draggable={true}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
className={`ml-1 pl-2 text-nowrap remixui_leaf ${getFileStateClasses(file)}`}
data-label-type={file.isDirectory ? 'folder' : 'file'}
data-label-path={`${file.path}`}
key={index}>
{file.name}
</div>
<div className="d-flex flex-row align-items-center">
{showIcons(file)}
{getFileStateIcons(file)}
</div>
</>
}
</div>
</li>)
}
return (<>

@ -60,4 +60,12 @@ ul {
[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
}
.remixui_icons {
}
.remixui_icons:hover {
color: var(--text);
}

@ -796,7 +796,7 @@ export function Workspace() {
</option>
<option style={{fontSize: 'small'}} value="breakthroughLabsUniswapv4Hooks">
{intl.formatMessage({id: 'filePanel.breakthroughLabsUniswapv4Hooks'})}
</option>
</option>
<option style={{fontSize: 'small'}} value="uniswapV4HookBookMultiSigSwapHook">
{intl.formatMessage({id: 'filePanel.uniswapV4HookBookMultiSigSwapHook'})}
@ -988,7 +988,7 @@ export function Workspace() {
>
<i onClick={() => saveSampleCodeWorkspace()} className="far fa-exclamation-triangle text-warning ml-2 align-self-center" aria-hidden="true"></i>
</CustomTooltip>}
</span>
</span>
</div>
<div className='mx-2'>
{(platform !== appPlatformTypes.desktop) ? (
@ -1063,7 +1063,7 @@ export function Workspace() {
</div>
</header>
</div>
<ElectronMenu></ElectronMenu>
<ElectronMenu></ElectronMenu>
<div
className="h-100 remixui_fileExplorerTree"
onFocus={() => {
@ -1077,7 +1077,7 @@ export function Workspace() {
</div>
)}
{!(global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) && global.fs.mode === 'browser' && currentWorkspace !== NO_WORKSPACE && (
<FileExplorer
fileState={global.fs.browser.fileState}
name={currentWorkspace}
@ -1129,8 +1129,12 @@ export function Workspace() {
handleNewFileInput={handleNewFileInput}
handleNewFolderInput={handleNewFolderInput}
dragStatus={dragStatus}
createNewFile={handleNewFileInput}
createNewFolder={handleNewFolderInput}
deletePath={deletePath}
renamePath={editModeOn}
/>
)}
{global.fs.localhost.isRequestingLocalhost && (
<div className="text-center py-5">
@ -1188,6 +1192,10 @@ export function Workspace() {
editModeOn={editModeOn}
handleNewFileInput={handleNewFileInput}
handleNewFolderInput={handleNewFolderInput}
createNewFile={handleNewFileInput}
createNewFolder={handleNewFolderInput}
deletePath={deletePath}
renamePath={editModeOn}
dragStatus={dragStatus}
/>
)}
@ -1199,11 +1207,11 @@ export function Workspace() {
<div className={`bg-light border-top ${selectedWorkspace.isGitRepo && currentBranch ? 'd-block' : 'd-none'}`} data-id="workspaceGitPanel">
<div className="d-flex justify-space-between p-1">
<div className="mr-auto text-uppercase text-dark pt-2 pl-2">GIT</div>
{selectedWorkspace.hasGitSubmodules?
{selectedWorkspace.hasGitSubmodules?
<div className="pt-1 mr-1">
{global.fs.browser.isRequestingCloning ? <div style={{ height: 30 }} className='btn btn-sm border text-muted small'><i className="fad fa-spinner fa-spin"></i> updating submodules</div> :
<div style={{ height: 30 }} onClick={updateSubModules} data-id='updatesubmodules' className='btn btn-sm border text-muted small'>update submodules</div>}
</div>
</div>
: null}
<div className="pt-1 mr-1" data-id="workspaceGitBranchesDropdown">
<Dropdown style={{height: 30, minWidth: 80}} onToggle={toggleBranches} show={showBranches} drop={'up'}>

@ -130,6 +130,10 @@ export interface FileExplorerProps {
toGist: (path?: string, type?: string) => void
handleNewFileInput: (parentFolder?: string) => Promise<void>
handleNewFolderInput: (parentFolder?: string) => Promise<void>
deletePath?: (path: string[]) => Promise<void>
createNewFile:(parentFolder?: string) => Promise<void>
createNewFolder:(parentFolder?: string) => Promise<void>
renamePath:(path: string, type: string, isNew?: boolean) => void
dragStatus: (status: boolean) => void
}

Loading…
Cancel
Save