@finos/legend-studio
Version:
319 lines • 28.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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 { Fragment, useRef, useEffect, useState, forwardRef } from 'react';
import { observer } from 'mobx-react-lite';
import { clsx, Dialog, MenuContent, MenuContentItem, MenuContentItemBlankIcon, MenuContentItemIcon, MenuContentItemLabel, ContextMenu, DropdownMenu, PanelLoadingIndicator, BlankPanelContent, TreeView, ProjectConfigurationIcon, ChevronDownIcon, ChevronRightIcon, CompressIcon, FolderIcon, FolderOpenIcon, PlusIcon, LockIcon, ExclamationTriangleIcon, SearchIcon, FileImportIcon, } from '@finos/legend-art';
import { getElementIcon, getElementTypeIcon, } from '../../shared/ElementIconUtils.js';
import { getElementTypeLabel, CreateNewElementModal, } from './CreateNewElementModal.js';
import { useDrag } from 'react-dnd';
import { ElementDragSource } from '../../../stores/shared/DnDUtil.js';
import { LEGEND_STUDIO_TEST_ID } from '../../LegendStudioTestID.js';
import { ACTIVITY_MODE } from '../../../stores/EditorConfig.js';
import { getTreeChildNodes } from '../../../stores/shared/PackageTreeUtil.js';
import { getFileGenerationChildNodes, } from '../../../stores/shared/FileGenerationTreeUtil.js';
import { FileGenerationTree } from '../../editor/edit-panel/element-generation-editor/FileGenerationEditor.js';
import { generateViewEntityRoute } from '../../../stores/LegendStudioRouter.js';
import { toTitleCase } from '@finos/legend-shared';
import { flowResult } from 'mobx';
import { useEditorStore } from '../EditorStoreProvider.js';
import { ELEMENT_PATH_DELIMITER, ROOT_PACKAGE_NAME, Package, isValidFullPath, isValidPath, getElementRootPackage, } from '@finos/legend-graph';
import { useApplicationStore } from '@finos/legend-application';
import { PACKAGEABLE_ELEMENT_TYPE } from '../../../stores/shared/ModelUtil.js';
import { useLegendStudioApplicationStore } from '../../LegendStudioBaseStoreProvider.js';
const isGeneratedPackageTreeNode = (node) => getElementRootPackage(node.packageableElement).name ===
ROOT_PACKAGE_NAME.MODEL_GENERATION;
const isSystemPackageTreeNode = (node) => getElementRootPackage(node.packageableElement).name ===
ROOT_PACKAGE_NAME.SYSTEM;
const isDependencyTreeNode = (node) => getElementRootPackage(node.packageableElement).name ===
ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT;
const ElementRenamer = observer(() => {
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const explorerTreeState = editorStore.explorerTreeState;
const element = explorerTreeState.elementToRename;
const [path, setPath] = useState(element?.path ?? '');
const pathInputRef = useRef(null);
const changePath = (event) => setPath(event.target.value);
const isElementPathNonEmpty = path !== '';
const isNotTopLevelElement = element instanceof Package || path.includes(ELEMENT_PATH_DELIMITER);
const isValidElementPath = (element instanceof Package && isValidPath(path)) || isValidFullPath(path);
const existingElement = editorStore.graphManagerState.graph.getNullableElement(path, true);
const isElementUnique = !existingElement || existingElement === element;
const elementRenameValidationErrorMessage = !isElementPathNonEmpty
? `Element path cannot be empty`
: !isNotTopLevelElement
? `Creating top level element is not allowed`
: !isValidElementPath
? `Element path is not valid`
: !isElementUnique
? `Element of the same path already existed`
: undefined;
const canRenameElement = isElementPathNonEmpty &&
isNotTopLevelElement &&
isValidElementPath &&
isElementUnique;
const close = (event) => {
event.preventDefault();
if (element && canRenameElement) {
explorerTreeState.setElementToRename(undefined);
flowResult(editorStore.renameElement(element, path)).catch(applicationStore.alertUnhandledError);
}
};
const abort = () => explorerTreeState.setElementToRename(undefined);
const onEnter = () => pathInputRef.current?.focus();
useEffect(() => {
if (element) {
setPath(element.path);
}
}, [element]);
return (_jsx(Dialog, { open: Boolean(element), onClose: abort, TransitionProps: {
onEnter: onEnter,
}, classes: { container: 'search-modal__container' }, PaperProps: { classes: { root: 'search-modal__inner-container' } }, children: _jsxs("form", { className: "modal modal--dark search-modal explorer__element-renamer", children: [_jsxs("div", { className: "input-group", children: [_jsx("input", { className: "input-group__input input--dark explorer__element-renamer__input", ref: pathInputRef, value: path, placeholder: "Enter element path", onChange: changePath }), elementRenameValidationErrorMessage && (_jsx("div", { className: "input-group__error-message", children: elementRenameValidationErrorMessage }))] }), _jsx("button", { type: "submit", className: "explorer__element-renamer__close-btn", onClick: close })] }) }));
});
const ExplorerContextMenu = observer(forwardRef(function ExplorerContextMenu(props, ref) {
const { node, nodeIsImmutable } = props;
const editorStore = useEditorStore();
const applicationStore = useLegendStudioApplicationStore();
const extraExplorerContextMenuItems = editorStore.pluginManager
.getApplicationPlugins()
.flatMap((plugin) => plugin.getExtraExplorerContextMenuItemRendererConfigurations?.() ??
[])
.map((config) => (_jsx(Fragment, { children: config.renderer(editorStore, node?.packageableElement) }, config.key)));
const projectId = editorStore.sdlcState.currentProject?.projectId;
const isReadOnly = editorStore.isInViewerMode || Boolean(nodeIsImmutable);
const _package = node
? node.packageableElement instanceof Package
? node.packageableElement
: undefined
: editorStore.graphManagerState.graph.root;
const removeElement = () => {
if (node) {
flowResult(editorStore.deleteElement(node.packageableElement)).catch(applicationStore.alertUnhandledError);
}
};
const renameElement = () => {
if (node) {
editorStore.explorerTreeState.setElementToRename(node.packageableElement);
}
};
const openElementInViewerMode = () => {
if (node && projectId) {
applicationStore.navigator.openNewWindow(applicationStore.navigator.generateLocation(generateViewEntityRoute(projectId, node.packageableElement.path)));
}
};
const copyLinkToElementInViewerMode = () => {
if (node) {
applicationStore
.copyTextToClipboard(applicationStore.navigator.generateLocation(editorStore.editorMode.generateElementLink(node.packageableElement.path)))
.then(() => applicationStore.notifySuccess('Copied element link to clipboard'))
.catch(applicationStore.alertUnhandledError);
}
};
const createNewElement = (type) => () => editorStore.newElementState.openModal(type, _package);
const elementTypes = [PACKAGEABLE_ELEMENT_TYPE.PACKAGE]
.concat(editorStore.getSupportedElementTypes())
.filter(
// NOTE: we can only create package in root
(type) => _package !== editorStore.graphManagerState.graph.root ||
type === PACKAGEABLE_ELEMENT_TYPE.PACKAGE);
if (_package && !isReadOnly) {
return (_jsxs(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: [elementTypes.map((type) => (_jsxs(MenuContentItem, { onClick: createNewElement(type), children: [_jsx(MenuContentItemIcon, { children: getElementTypeIcon(editorStore, type) }), _jsxs(MenuContentItemLabel, { children: ["New ", toTitleCase(getElementTypeLabel(editorStore, type)), "..."] })] }, type))), _jsxs(MenuContentItem, { onClick: renameElement, children: [_jsx(MenuContentItemBlankIcon, {}), _jsx(MenuContentItemLabel, { children: "Rename" })] }), node && (_jsxs(MenuContentItem, { onClick: removeElement, children: [_jsx(MenuContentItemBlankIcon, {}), _jsx(MenuContentItemLabel, { children: "Remove" })] }))] }));
}
return (_jsxs(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: [extraExplorerContextMenuItems, !isReadOnly && node && (_jsxs(_Fragment, { children: [_jsx(MenuContentItem, { onClick: renameElement, children: "Rename" }), _jsx(MenuContentItem, { onClick: removeElement, children: "Remove" })] })), node && (_jsxs(_Fragment, { children: [!editorStore.isInViewerMode && (_jsx(MenuContentItem, { onClick: openElementInViewerMode, children: "View in Project" })), _jsx(MenuContentItem, { onClick: copyLinkToElementInViewerMode, children: "Copy Link" })] }))] }));
}));
const ProjectConfig = observer(() => {
const editorStore = useEditorStore();
const openConfigurationEditor = () => editorStore.openSingletonEditorState(editorStore.projectConfigurationEditorState);
const isSelected = editorStore.currentEditorState ===
editorStore.projectConfigurationEditorState &&
// if we select non-element like packages, we need to deselect project configuration
// so maybe a good TODO is to move this to explorer tree state
!editorStore.explorerTreeState.selectedNode;
return (_jsxs("div", { className: clsx('tree-view__node__container explorer__package-tree__node__container explorer__floating-item', { 'explorer__package-tree__node__container--selected': isSelected }), onClick: openConfigurationEditor, children: [_jsx("div", { className: "tree-view__node__icon explorer__package-tree__node__icon", children: _jsx("div", { className: "explorer__package-tree__node__icon__type explorer__config__icon", children: _jsx(ProjectConfigurationIcon, {}) }) }), _jsx("button", { className: "tree-view__node__label explorer__package-tree__node__label", tabIndex: -1, title: 'Project configuration', children: "config" })] }));
});
const PackageTreeNodeContainer = observer((props) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const editorStore = useEditorStore();
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false);
const { disableContextMenu, isContextImmutable } = innerProps;
const [, dragRef] = useDrag(() => ({
type: node.dndType,
item: new ElementDragSource(node),
}), [node]);
const isPackage = node.packageableElement instanceof Package;
const expandIcon = !isPackage ? (_jsx("div", {})) : node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}));
const iconPackageColor = isGeneratedPackageTreeNode(node)
? 'color--generated'
: isSystemPackageTreeNode(node)
? 'color--system'
: isDependencyTreeNode(node)
? 'color--dependency'
: '';
const nodeIcon = isPackage ? (node.isOpen ? (_jsx("div", { className: iconPackageColor, children: _jsx(FolderOpenIcon, {}) })) : (_jsx("div", { className: iconPackageColor, children: _jsx(FolderIcon, {}) }))) : (getElementIcon(editorStore, node.packageableElement));
const selectNode = () => onNodeSelect?.(node);
const onContextMenuOpen = () => setIsSelectedFromContextMenu(true);
const onContextMenuClose = () => setIsSelectedFromContextMenu(false);
return (_jsx(ContextMenu, { content: _jsx(ExplorerContextMenu, { node: node, nodeIsImmutable: isContextImmutable }), disabled: disableContextMenu, menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("div", { className: clsx('tree-view__node__container explorer__package-tree__node__container', {
'menu__trigger--on-menu-open': !node.isSelected && isSelectedFromContextMenu,
}, {
'explorer__package-tree__node__container--selected': node.isSelected,
}), ref: dragRef, onClick: selectNode, style: {
paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`,
display: 'flex',
}, children: [_jsxs("div", { className: "tree-view__node__icon explorer__package-tree__node__icon", children: [_jsx("div", { className: "explorer__package-tree__node__icon__expand", children: expandIcon }), _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, title: node.packageableElement.path, children: node.label })] }) }));
});
const ExplorerDropdownMenu = observer(() => {
const editorStore = useEditorStore();
const _package = editorStore.explorerTreeState.getSelectedNodePackage();
const createNewElement = (type) => () => editorStore.newElementState.openModal(type, _package);
const elementTypes = [PACKAGEABLE_ELEMENT_TYPE.PACKAGE]
.concat(editorStore.getSupportedElementTypes())
.filter(
// NOTE: we can only create package in root
(type) => _package !== editorStore.graphManagerState.graph.root ||
type === PACKAGEABLE_ELEMENT_TYPE.PACKAGE);
return (_jsx(MenuContent, { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU, children: elementTypes.map((type) => (_jsxs(MenuContentItem, { onClick: createNewElement(type), children: [_jsx(MenuContentItemIcon, { children: getElementTypeIcon(editorStore, type) }), _jsxs(MenuContentItemLabel, { children: ["New ", toTitleCase(getElementTypeLabel(editorStore, type)), "..."] })] }, type))) }));
});
const ExplorerTrees = observer(() => {
const editorStore = useEditorStore();
const { isInGrammarTextMode, isInViewerMode } = editorStore;
const openModelLoader = () => editorStore.openSingletonEditorState(editorStore.modelLoaderState);
const graph = editorStore.graphManagerState.graph;
// Explorer tree
const treeData = editorStore.explorerTreeState.getTreeData();
const selectedTreeNode = editorStore.explorerTreeState.selectedNode;
const onNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, treeData);
const getChildNodes = (node) => getTreeChildNodes(editorStore, node, treeData);
const deselectTreeNode = () => {
if (selectedTreeNode) {
selectedTreeNode.isSelected = false;
editorStore.explorerTreeState.setTreeData({ ...treeData });
}
editorStore.explorerTreeState.setSelectedNode(undefined);
};
// Generated Tree
const generationTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.MODEL_GENERATION);
const onGenerationTreeNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, generationTreeData, ROOT_PACKAGE_NAME.MODEL_GENERATION);
const getGenerationTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, generationTreeData);
// Generated Files Tree
const generationFileTreeData = editorStore.explorerTreeState.getFileGenerationTreeData();
const onGenerationFileTreeNodeSelect = (node) => editorStore.graphState.graphGenerationState.onTreeNodeSelect(node, generationFileTreeData);
const getGenerationFileTreeChildNodes = (node) => getFileGenerationChildNodes(node, generationFileTreeData);
// System Tree
const systemTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.SYSTEM);
const onSystemTreeNodeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, systemTreeData, ROOT_PACKAGE_NAME.SYSTEM);
const getSystemTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, systemTreeData);
// Dependency Tree
const dependencyTreeData = editorStore.explorerTreeState.getTreeData(ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT);
const onDependencyTreeSelect = (node) => editorStore.explorerTreeState.onTreeNodeSelect(node, dependencyTreeData, ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT);
const getDependencyTreeChildNodes = (node) => getTreeChildNodes(editorStore, node, dependencyTreeData);
const showPackageTrees = treeData.nodes.size || graph.dependencyManager.hasDependencies;
return (_jsxs(ContextMenu, { className: "explorer__content", disabled: isInGrammarTextMode || isInViewerMode, content: _jsx(ExplorerContextMenu, {}), menuProps: { elevation: 7 }, children: [_jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.EXPLORER_TREES, children: [editorStore.explorerTreeState.buildState.hasCompleted &&
showPackageTrees && (_jsxs(_Fragment, { children: [_jsx(TreeView, { components: {
TreeNodeContainer: PackageTreeNodeContainer,
}, treeData: treeData, onNodeSelect: onNodeSelect, getChildNodes: getChildNodes, innerProps: {
disableContextMenu: isInGrammarTextMode,
} }), _jsx(ElementRenamer, {}), editorStore.projectConfigurationEditorState
.projectConfiguration && _jsx(ProjectConfig, {}), Boolean(editorStore.graphManagerState.systemModel.allOwnElements.length) && (_jsx(TreeView, { components: {
TreeNodeContainer: PackageTreeNodeContainer,
}, treeData: systemTreeData, onNodeSelect: onSystemTreeNodeSelect, getChildNodes: getSystemTreeChildNodes, innerProps: {
disableContextMenu: true,
} })), graph.dependencyManager.hasDependencies && (_jsx(TreeView, { components: {
TreeNodeContainer: PackageTreeNodeContainer,
}, treeData: dependencyTreeData, onNodeSelect: onDependencyTreeSelect, getChildNodes: getDependencyTreeChildNodes, innerProps: {
disableContextMenu: isInGrammarTextMode,
isContextImmutable: true,
} })), Boolean(graph.generationModel.allOwnElements.length) && (_jsx(TreeView, { components: {
TreeNodeContainer: PackageTreeNodeContainer,
}, treeData: generationTreeData, onNodeSelect: onGenerationTreeNodeSelect, getChildNodes: getGenerationTreeChildNodes, innerProps: {
disableContextMenu: isInGrammarTextMode,
isContextImmutable: true,
} })), _jsx("div", {}), Boolean(editorStore.graphState.graphGenerationState.rootFileDirectory
.children.length) && (_jsxs(_Fragment, { children: [_jsx("div", { className: "explorer__content__separator" }), _jsx(FileGenerationTree, { selectedNode: editorStore.explorerTreeState.selectedNode, directoryTreeData: generationFileTreeData, onNodeSelect: onGenerationFileTreeNodeSelect, getFileElementTreeChildNodes: getGenerationFileTreeChildNodes })] }))] })), editorStore.explorerTreeState.buildState.hasCompleted &&
!showPackageTrees && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: "Your workspace is empty, you can add elements or load existing model/entites for quick adding" }), _jsx("button", { className: "btn--dark explorer__content--empty__btn", onClick: openModelLoader, children: "Open Model Loader" })] }))] }), _jsx("div", { className: "explorer__deselector", onClick: deselectTreeNode })] }));
});
const ProjectExplorerActionPanel = observer((props) => {
const { disabled } = props;
const editorStore = useEditorStore();
const isInGrammarMode = editorStore.isInGrammarTextMode;
const showSearchModal = () => editorStore.searchElementCommandState.open();
// Explorer tree
const selectedTreeNode = editorStore.explorerTreeState.selectedNode;
const collapseTree = () => {
const treeData = editorStore.explorerTreeState.getTreeData();
treeData.nodes.forEach((node) => {
node.isOpen = false;
});
editorStore.explorerTreeState.setTreeData({ ...treeData });
};
const isImmutablePackageTreeNode = (node) => isGeneratedPackageTreeNode(node) ||
isSystemPackageTreeNode(node) ||
isDependencyTreeNode(node);
const showModelLoader = () => editorStore.openState(editorStore.modelLoaderState);
return (_jsxs("div", { className: "panel__header__actions", children: [!editorStore.isInViewerMode && (_jsx("button", { className: "panel__header__action", disabled: disabled, title: "Open Model Loader (F2)", onClick: showModelLoader, children: _jsx(FileImportIcon, {}) })), _jsx(DropdownMenu, { disabled: disabled ||
isInGrammarMode ||
(selectedTreeNode && isImmutablePackageTreeNode(selectedTreeNode)), content: _jsx(ExplorerDropdownMenu, {}), menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
transformOrigin: { vertical: 'top', horizontal: 'left' },
elevation: 7,
}, children: !editorStore.isInViewerMode && (_jsx("button", { disabled: disabled ||
isInGrammarMode ||
(selectedTreeNode && isImmutablePackageTreeNode(selectedTreeNode)), className: "panel__header__action", tabIndex: -1, title: "New Element... (Ctrl + Shift + N)", children: _jsx(PlusIcon, {}) })) }), _jsx("button", { className: "panel__header__action", disabled: disabled, onClick: collapseTree, tabIndex: -1, title: "Collapse All", children: _jsx(CompressIcon, {}) }), _jsx("button", { className: "panel__header__action", disabled: disabled, tabIndex: -1, onClick: showSearchModal, title: "Open Element... (Ctrl + P)", children: _jsx(SearchIcon, {}) })] }));
});
export const Explorer = observer(() => {
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const sdlcState = editorStore.sdlcState;
const isLoading = ((!editorStore.explorerTreeState.buildState.hasCompleted &&
!editorStore.isInGrammarTextMode) ||
editorStore.graphState.isUpdatingGraph) &&
!editorStore.graphManagerState.graphBuildState.hasFailed;
const showExplorerTrees = editorStore.graphManagerState.graphBuildState.hasSucceeded &&
editorStore.explorerTreeState.buildState.hasCompleted &&
// NOTE: if not in viewer mode, we would only show the explorer tree
// when graph is properly observed to make sure edit after that can trigger
// change detection. Realistically, this doesn't not affect user as they
// don't edit elements that fast in form mode, but this could throw off
// test runner
(editorStore.isInViewerMode ||
editorStore.changeDetectionState.graphObserveState.hasSucceeded);
// conflict resolution
const showConflictResolutionContent = editorStore.isInConflictResolutionMode &&
!editorStore.conflictResolutionState.hasResolvedAllConflicts;
const goToConflictResolutionTab = () => editorStore.setActiveActivity(ACTIVITY_MODE.CONFLICT_RESOLUTION);
const buildGrapnInConflictResolutionMode = () => {
editorStore.conflictResolutionState.confirmHasResolvedAllConflicts();
flowResult(editorStore.conflictResolutionState.buildGraphInConflictResolutionMode()).catch(applicationStore.alertUnhandledError);
};
return (_jsxs("div", { className: "panel explorer", children: [_jsxs("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: "EXPLORER" }) }), editorStore.isInViewerMode && (_jsxs("div", { className: "panel__header__title side-bar__header__title__viewer-mode-badge", children: [_jsx(LockIcon, {}), "READ-ONLY"] }))] }), _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", children: sdlcState.currentProject && (_jsxs(_Fragment, { children: [_jsx("div", { className: "panel__header__title__label", children: sdlcState.currentWorkspace && !editorStore.isInViewerMode
? 'workspace'
: 'project' }), _jsxs("div", { className: "panel__header__title__content", children: [editorStore.isInViewerMode &&
sdlcState.currentProject.name, !editorStore.isInViewerMode &&
(sdlcState.currentWorkspace?.workspaceId ?? '(unknown) ')] })] })) }), _jsx(ProjectExplorerActionPanel, { disabled: !editorStore.explorerTreeState.buildState.hasCompleted })] }), editorStore.explorerTreeState.buildState.hasCompleted && (_jsx(CreateNewElementModal, {})), _jsxs("div", { className: "panel__content explorer__content__container", children: [showConflictResolutionContent && (_jsxs(_Fragment, { children: [!editorStore.conflictResolutionState.conflicts.length && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: "All conflicts have been resolved, you can build the graph now to start testing your changes" }), _jsx("button", { className: "btn--dark btn--conflict btn--important explorer__content--empty__btn", onClick: buildGrapnInConflictResolutionMode, children: "Build Graph" })] })), Boolean(editorStore.conflictResolutionState.conflicts.length) && (_jsxs("div", { className: "explorer__content--empty", children: [_jsx("div", { className: "explorer__content--empty__text", children: "Can't build graph as workspace contains merge conflicts, please resolve them before trying to build the graph again" }), _jsx("button", { className: "btn--dark btn--conflict btn--important explorer__content--empty__btn", onClick: goToConflictResolutionTab, children: "Resolve Merge Conflicts" })] }))] })), !showConflictResolutionContent && (_jsxs(_Fragment, { children: [_jsx(PanelLoadingIndicator, { isLoading: isLoading }), showExplorerTrees && _jsx(ExplorerTrees, {}), !showExplorerTrees &&
!editorStore.graphManagerState.graphBuildState.hasFailed && (_jsx("div", { className: "explorer__content__progress-msg", children: editorStore.initState.message ??
editorStore.graphManagerState.systemBuildState
.message ??
editorStore.graphManagerState.dependenciesBuildState
.message ??
editorStore.graphManagerState.generationsBuildState
.message ??
editorStore.graphManagerState.graphBuildState.message ??
editorStore.changeDetectionState.graphObserveState
.message })), !showExplorerTrees &&
editorStore.graphManagerState.graphBuildState.hasFailed && (_jsx(BlankPanelContent, { children: _jsxs("div", { className: "explorer__content__failure-notice", children: [_jsx("div", { className: "explorer__content__failure-notice__icon", children: _jsx(ExclamationTriangleIcon, {}) }), _jsx("div", { className: "explorer__content__failure-notice__text", children: "Failed to build graph" })] }) }))] }))] })] }) })] }));
});
//# sourceMappingURL=Explorer.js.map