diff --git a/frontend/src/js/components/workspace/Workspaces.tsx b/frontend/src/js/components/workspace/Workspaces.tsx index 6363dd1b..89d21cd4 100644 --- a/frontend/src/js/components/workspace/Workspaces.tsx +++ b/frontend/src/js/components/workspace/Workspaces.tsx @@ -28,7 +28,7 @@ import { listUsers } from '../../actions/users/listUsers'; import DocumentIcon from 'react-icons/lib/ti/document'; import {Icon, Loader, Menu, Popup} from 'semantic-ui-react'; import WorkspaceSummary from './WorkspaceSummary'; -import { ColumnsConfig, isTreeLeaf, isTreeNode, TreeEntry, TreeLeaf } from '../../types/Tree'; +import {ColumnsConfig, isTreeLeaf, isTreeNode, TreeEntry, TreeLeaf} from '../../types/Tree'; import {isWorkspaceLeaf, Workspace, WorkspaceEntry} from '../../types/Workspaces'; import { GiantState } from '../../types/redux/GiantState'; import { GiantDispatch } from '../../types/redux/GiantDispatch'; @@ -73,6 +73,13 @@ type State = { } } +type ContextMenuEntry = { + key: string + content: string; + icon: string; + +} + class WorkspacesUnconnected extends React.Component { stringSort = (a: string, b: string) => { @@ -496,12 +503,46 @@ class WorkspacesUnconnected extends React.Component { }); }; + /** + * Searches through tree beginning at startNode for entryId, if successful returns an array of nodes between startNode and entryId + * @param entryId + * @param startNode + */ + getEntryTreeNodes (entryId: string, startNode: TreeEntry): TreeEntry[] | undefined { + if (startNode.id === entryId) { + return [startNode] + } + if (isTreeNode(startNode)) { + for (const child of startNode.children) { + const result = this.getEntryTreeNodes(entryId, child) + if (result !== undefined) { + return [startNode, ...result] + } + } + } + return undefined + } + + getEntryPath (entryId: string, workspaceRootNode: TreeEntry): string { + const pathArray = this.getEntryTreeNodes(entryId, workspaceRootNode) + if (pathArray) { + const path = pathArray.map(p => p.name).join("/") + console.log(path) + return path + } + return "unknown" + } + - renderContextMenu(entry: TreeEntry, positionX: number, positionY: number, currentUser: PartialUser) { + renderContextMenu(entry: TreeEntry, positionX: number, positionY: number, currentUser: PartialUser, workspace: Workspace) { + const copyFilenameContent = "Copy file name" + const copyFilePathContent = "Copy file path" const items = [ + {key : "copyFilename", content: copyFilenameContent, icon: "copy"}, + {key : "copyFilePath", content: copyFilePathContent, icon: "copy"}, // or 'pencil alternate' { key: "rename", content: "Rename", icon: "pen square" }, - { key: "remove", content: "Remove from workspace", icon: "trash" }, + { key: "remove", content: "Remove from workspace", icon: "trash" } ]; if (entry.data.addedBy.username === currentUser.username && isWorkspaceLeaf(entry.data)) { @@ -519,6 +560,7 @@ class WorkspacesUnconnected extends React.Component { vertical onItemClick={(e, menuItemProps) => { const workspaceId = this.props.match.params.id; + let closeMenuDelay = 0; if (menuItemProps.content === 'Rename') { this.props.setEntryBeingRenamed(entry); } @@ -528,6 +570,16 @@ class WorkspacesUnconnected extends React.Component { this.props.resetFocusedAndSelectedEntries(); } + if (menuItemProps.content === copyFilenameContent || menuItemProps.content === copyFilePathContent) { + const text = menuItemProps.content === copyFilenameContent ? entry.name : this.getEntryPath(entry.id, workspace.rootNode); + navigator.clipboard.writeText(text); + const menuItem = items.find((i: ContextMenuEntry) => i.content === menuItemProps.content) + if (menuItem) { + menuItem.content = 'Copied!' + menuItem.icon = 'check' + closeMenuDelay = 700; + } + } if (menuItemProps.content === "Delete file") { this.setState({ @@ -542,7 +594,7 @@ class WorkspacesUnconnected extends React.Component { if (menuItemProps.content === 'Reprocess source file' && (isWorkspaceLeaf(entry.data))) { this.props.reprocessBlob(workspaceId, entry.data.uri) } - this.closeContextMenu(); + setTimeout(() => this.closeContextMenu(), closeMenuDelay); }} /> ; @@ -640,7 +692,8 @@ class WorkspacesUnconnected extends React.Component { this.state.contextMenu.entry, this.state.contextMenu.positionX, this.state.contextMenu.positionY, - this.props.currentUser + this.props.currentUser, + this.props.currentWorkspace ) : null }