UNPKG

@finos/legend-application-pure-ide

Version:
166 lines 11.2 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; /** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { forwardRef, useState } from 'react'; import { observer } from 'mobx-react-lite'; import { flowResult } from 'mobx'; import { FileEditorState } from '../../stores/FileEditorState.js'; import { CreateNewFilePrompt } from './CreateNewFilePrompt.js'; import { CreateNewDirectoryPrompt } from './CreateNewDirectoryPrompt.js'; import { useApplicationStore } from '@finos/legend-application'; import { clsx, BlankPanelContent, ContextMenu, PanelLoadingIndicator, TreeView, ChevronDownIcon, ChevronRightIcon, CircleNotchIcon, RefreshIcon, CrosshairsIcon, CompressIcon, FileAltIcon, FolderIcon, FolderOpenIcon, WrenchIcon, MenuContent, MenuContentItem, MenuContentDivider, } from '@finos/legend-art'; import { isNonNullable } from '@finos/legend-shared'; import { DirectoryNode, } from '../../server/models/DirectoryTree.js'; import { usePureIDEStore } from '../PureIDEStoreProvider.js'; import { RenameFilePrompt } from './RenameFilePrompt.js'; const FileExplorerContextMenu = observer(forwardRef(function FileExplorerContextMenu(props, ref) { const { node } = props; const applicationStore = useApplicationStore(); const ideStore = usePureIDEStore(); const isDir = node.data.isFolderNode; const hasChildContent = Boolean(node.data.children); const createNewFile = () => ideStore.directoryTreeState.setNodeForCreateNewFile(node); const createNewDirectory = () => ideStore.directoryTreeState.setNodeForCreateNewDirectory(node); const deleteFileOrDirectory = () => { flowResult(ideStore.deleteDirectoryOrFile(node.data.li_attr.path, isDir, hasChildContent)).catch(applicationStore.alertUnhandledError); }; const renameFile = () => ideStore.directoryTreeState.setNodeForRenameFile(node); const copyPath = () => { applicationStore.clipboardService .copyTextToClipboard(node.data.li_attr.path) .catch(applicationStore.alertUnhandledError); }; return (_jsxs(MenuContent, { ref: ref, children: [_jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }), !node.data.li_attr.RO && (_jsxs(_Fragment, { children: [_jsx(MenuContentDivider, {}), isDir && (_jsx(MenuContentItem, { onClick: createNewFile, children: "New File" })), isDir && (_jsx(MenuContentItem, { onClick: createNewDirectory, children: "New Directory" })), !isDir && (_jsx(MenuContentItem, { onClick: renameFile, children: "Rename" })), _jsx(MenuContentItem, { disabled: Boolean(node.data instanceof DirectoryNode && node.data.children), onClick: deleteFileOrDirectory, children: "Delete" })] }))] })); })); const FileTreeNodeContainer = (props) => { const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props; const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false); const { onNodeOpen, onNodeExpand, onNodeCompress } = innerProps; const isPlatformDirectory = node.data instanceof DirectoryNode && node.data.isRepoNode && node.data.li_attr.path === '/platform'; const isReadOnly = node.data.li_attr.RO; const isDirectory = node.data.isFolderNode; const isChildlessDirectory = node.data instanceof DirectoryNode && !node.data.children; const nodeIcon = isPlatformDirectory || (node.data.isRepoNode && node.data.li_attr.path.startsWith('/platform_')) ? (_jsx(WrenchIcon, { className: "explorer__icon--readonly" })) : isDirectory ? (isChildlessDirectory ? (_jsx(FolderIcon, { className: clsx('explorer__icon--folder', { 'explorer__icon--readonly': isReadOnly, }) })) : node.isOpen ? (_jsx(FolderOpenIcon, { className: clsx('explorer__icon--folder', { 'explorer__icon--readonly': isReadOnly, }) })) : (_jsx(FolderIcon, { className: clsx('explorer__icon--folder', { 'explorer__icon--readonly': isReadOnly, }) }))) : (_jsx(FileAltIcon, { className: clsx('explorer__icon--file', { 'explorer__icon--readonly': isReadOnly, }) })); const selectNode = (event) => { event.stopPropagation(); event.preventDefault(); onNodeSelect?.(node); }; const onContextMenuOpen = () => setIsSelectedFromContextMenu(true); const onContextMenuClose = () => setIsSelectedFromContextMenu(false); const toggleExpansion = () => { if (isChildlessDirectory) { return; } if (node.isLoading) { return; } if (node.isOpen) { onNodeCompress(node); } else { onNodeExpand(node); } }; const onDoubleClick = () => { if (node.isLoading) { return; } if (isDirectory) { toggleExpansion(); } else { onNodeOpen(node); } }; return (_jsx(ContextMenu, { content: _jsx(FileExplorerContextMenu, { node: node }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("div", { id: node.id, className: clsx('tree-view__node__container explorer__package-tree__node__container', { 'explorer__package-tree__node__container--selected-from-context-menu': !node.isSelected && isSelectedFromContextMenu, }, { 'explorer__package-tree__node__container--selected': node.isSelected, }), onClick: selectNode, onDoubleClick: onDoubleClick, style: { paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`, display: 'flex', }, children: [_jsxs("div", { className: "tree-view__node__icon explorer__package-tree__node__icon", children: [node.isLoading && (_jsx("div", { className: "explorer__package-tree__node__icon__expand explorer__package-tree__node__icon__expand--is-loading", children: _jsx(CircleNotchIcon, {}) })), !node.isLoading && (_jsx("div", { className: "explorer__package-tree__node__icon__expand", onClick: toggleExpansion, children: !isDirectory || isChildlessDirectory ? (_jsx("div", {})) : node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {})) })), _jsx("div", { className: "explorer__package-tree__node__icon__type", children: nodeIcon })] }), _jsx("button", { className: "tree-view__node__label explorer__package-tree__node__label", tabIndex: -1, children: isPlatformDirectory ? 'platform' : node.label })] }) })); }; const FileExplorerTree = observer(() => { const ideStore = usePureIDEStore(); const applicationStore = useApplicationStore(); const treeState = ideStore.directoryTreeState; const treeData = ideStore.directoryTreeState.getTreeData(); const onNodeSelect = (node) => treeState.setSelectedNode(node); const onNodeOpen = (node) => { flowResult(treeState.openNode(node)).catch(applicationStore.alertUnhandledError); }; const onNodeExpand = (node) => { flowResult(treeState.expandNode(node)).catch(applicationStore.alertUnhandledError); }; const onNodeCompress = (node) => { node.isOpen = false; treeState.refreshTree(); }; const getChildNodes = (node) => { if (node.isLoading || !node.childrenIds) { return []; } return node.childrenIds .map((childId) => treeData.nodes.get(childId)) .filter(isNonNullable); }; const deselectTreeNode = () => treeState.setSelectedNode(undefined); return (_jsxs("div", { className: "explorer__content", onClick: deselectTreeNode, children: [_jsx(TreeView, { components: { TreeNodeContainer: FileTreeNodeContainer, }, treeData: treeData, onNodeSelect: onNodeSelect, getChildNodes: getChildNodes, innerProps: { onNodeOpen, onNodeExpand, onNodeCompress, } }), treeState.nodeForCreateNewFile && (_jsx(CreateNewFilePrompt, { node: treeState.nodeForCreateNewFile })), treeState.nodeForCreateNewDirectory && (_jsx(CreateNewDirectoryPrompt, { node: treeState.nodeForCreateNewDirectory })), treeState.nodeForRenameFile && (_jsx(RenameFilePrompt, { node: treeState.nodeForRenameFile }))] })); }); export const DirectoryTreeExplorer = observer(() => { const ideStore = usePureIDEStore(); const applicationStore = useApplicationStore(); const treeState = ideStore.directoryTreeState; const refreshTree = () => { flowResult(treeState.refreshTreeData()).catch(applicationStore.alertUnhandledError); }; const focus = () => { const currentTab = ideStore.tabManagerState.currentTab; if (currentTab instanceof FileEditorState) { flowResult(treeState.revealPath(currentTab.filePath)).catch(applicationStore.alertUnhandledError); } }; const collapseTree = () => { const treeData = treeState.getTreeData(); treeData.nodes.forEach((node) => { node.isOpen = false; }); treeState.setSelectedNode(undefined); treeState.refreshTree(); }; return (_jsxs("div", { className: "panel explorer", children: [_jsx("div", { className: "panel__header side-bar__header", children: _jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__content side-bar__header__title__content", children: "FILES" }) }) }), _jsx("div", { className: "panel__content side-bar__content", children: _jsxs("div", { className: "panel explorer", children: [_jsxs("div", { className: "panel__header explorer__header", children: [_jsx("div", { className: "panel__header__title" }), _jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: "panel__header__action explorer__btn__refresh", onClick: refreshTree, title: "Refresh Tree", children: _jsx(RefreshIcon, {}) }), _jsx("button", { className: "panel__header__action", onClick: focus, title: "Focus", children: _jsx(CrosshairsIcon, {}) }), _jsx("button", { className: "panel__header__action", onClick: collapseTree, title: "Collapse All", children: _jsx(CompressIcon, {}) })] })] }), _jsxs("div", { className: "panel__content explorer__content__container", children: [_jsx(PanelLoadingIndicator, { isLoading: treeState.loadInitialDataState.isInProgress }), treeState.loadInitialDataState.hasSucceeded && (_jsx(FileExplorerTree, {})), treeState.loadInitialDataState.hasFailed && (_jsx(BlankPanelContent, { children: "Failed to build directory tree" }))] })] }) })] })); }); //# sourceMappingURL=DirectoryTreeExplorer.js.map