UNPKG

@finos/legend-application-studio

Version:
194 lines 20.3 kB
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 { useApplicationStore } from '@finos/legend-application'; import { observer } from 'mobx-react-lite'; import { BlankPanelContent, Panel, PanelLoadingIndicator, TreeView, ChevronDownIcon, ChevronRightIcon, GenericTextFileIcon, FolderIcon, FolderOpenIcon, HomeIcon, SearchIcon, TimesIcon, CodeIcon, clsx, CopyIcon, compareLabelFn, } from '@finos/legend-art'; import { SHOWCASE_MANAGER_SEARCH_CATEGORY, SHOWCASE_MANAGER_VIEW, ShowcaseManagerState, } from '../stores/ShowcaseManagerState.js'; import { debounce, isNonNullable } from '@finos/legend-shared'; import { flowResult } from 'mobx'; import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor'; import { CodeEditor } from '@finos/legend-lego/code-editor'; import React, { useEffect, useMemo, useRef } from 'react'; import { generateShowcasePath } from '../__lib__/LegendStudioNavigation.js'; const ShowcasesExplorerTreeNodeContainer = observer((props) => { const { node, level, innerProps } = props; const { toggleExpandNode, showcaseManagerState } = innerProps; const applicationStore = useApplicationStore(); const expandIcon = !node.metadata ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : (_jsx("div", {})); const nodeIcon = !node.metadata ? (node.isOpen ? (_jsx(FolderOpenIcon, {})) : (_jsx(FolderIcon, {}))) : (_jsx(GenericTextFileIcon, {})); const onNodeClick = () => { if (!node.metadata) { toggleExpandNode(node); } else { flowResult(showcaseManagerState.openShowcase(node.metadata)).catch(applicationStore.alertUnhandledError); } }; return (_jsxs("div", { className: "tree-view__node__container showcase-manager__explorer__node__container", style: { paddingLeft: `${(level - 1) * 1.4}rem`, display: 'flex', }, onClick: onNodeClick, children: [_jsx("div", { className: "showcase-manager__explorer__node__expand-icon", children: expandIcon }), _jsx("div", { className: "showcase-manager__explorer__node__type-icon", children: nodeIcon }), _jsx("div", { className: "tree-view__node__label showcase-manager__explorer__node__label", title: node.metadata ? `${node.metadata.description ? `${node.metadata.description}\n\n` : ''}Click to open showcase` : undefined, children: node.label })] })); }); const ShowcaseManagerExplorer = observer((props) => { const { showcaseManagerState } = props; const treeData = showcaseManagerState.explorerTreeData; const getChildNodes = (node) => { if (treeData) { return node.childrenIds .map((id) => treeData.nodes.get(id)) .filter(isNonNullable) .sort(compareLabelFn); } return []; }; const toggleExpandNode = (node) => { if (treeData) { node.isOpen = !node.isOpen; showcaseManagerState.setExplorerTreeData({ ...treeData }); } }; return (_jsxs("div", { className: "showcase-manager__view", children: [_jsxs("div", { className: "showcase-manager__view__header", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumbs", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumb", children: [_jsx("div", { className: "showcase-manager__view__breadcrumb__icon", children: _jsx(HomeIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: "Showcases" })] }), _jsx("div", { className: "showcase-manager__view__breadcrumb__arrow", children: _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb", children: _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: "Explorer" }) })] }), _jsx("button", { className: "showcase-manager__view__search-action", tabIndex: -1, title: "Search", onClick: () => { showcaseManagerState.closeShowcase(); showcaseManagerState.setCurrentView(SHOWCASE_MANAGER_VIEW.SEARCH); }, children: _jsx(SearchIcon, {}) })] }), _jsx("div", { className: "showcase-manager__view__content", children: _jsx("div", { className: "showcase-manager__explorer", children: showcaseManagerState.explorerTreeData && (_jsx(TreeView, { components: { TreeNodeContainer: ShowcasesExplorerTreeNodeContainer, }, treeData: showcaseManagerState.explorerTreeData, getChildNodes: getChildNodes, innerProps: { toggleExpandNode, showcaseManagerState, } })) }) })] })); }); const renderPreviewLine = (line, text, result) => { const lineMatches = result.match.matches .filter((match) => match.line === line) .sort((a, b) => a.startColumn - b.startColumn); const chunks = []; let currentIdx = 0; lineMatches.forEach((match, idx) => { if (currentIdx < match.startColumn - 1) { chunks.push(text.substring(currentIdx, match.startColumn - 1)); } chunks.push(_jsx("span", { className: "showcase-manager__search__code-result__content__line__text--highlighted", children: text.substring(match.startColumn - 1, match.endColumn - 1) })); currentIdx = match.endColumn - 1; }); if (currentIdx < text.length) { chunks.push(text.substring(currentIdx, text.length)); } return (_jsx(_Fragment, { children: chunks.map((chunk, idx) => ( // eslint-disable-next-line react/no-array-index-key _jsx(React.Fragment, { children: chunk }, idx))) })); }; const ShowcaseManagerCodeSearchResult = observer((props) => { const { showcaseManagerState, result } = props; const applicationStore = useApplicationStore(); return (_jsxs("div", { className: "showcase-manager__search__code-result", children: [_jsxs("div", { className: "showcase-manager__search__code-result__header", title: `Showcase: ${result.showcase.title}\n\n${result.showcase.description ?? '(no description)'}\n\nClick to open showcase`, onClick: () => { flowResult(showcaseManagerState.openShowcase(result.showcase)).catch(applicationStore.alertUnhandledError); }, children: [_jsx("div", { className: "showcase-manager__search__code-result__header__icon", children: _jsx(GenericTextFileIcon, {}) }), _jsx("div", { className: "showcase-manager__search__code-result__header__title", children: result.showcase.path })] }), _jsx("div", { className: "showcase-manager__search__code-result__content", children: result.match.preview.map((entry) => (_jsxs("div", { className: "showcase-manager__search__code-result__content__line", onClick: () => { flowResult(showcaseManagerState.openShowcase(result.showcase, entry.line)).catch(applicationStore.alertUnhandledError); }, children: [_jsx("div", { className: clsx('showcase-manager__search__code-result__content__line__gutter', { 'showcase-manager__search__code-result__content__line__gutter--highlighted': Boolean(result.match.matches.find((match) => match.line === entry.line)), }), children: entry.line }), _jsx("div", { className: "showcase-manager__search__code-result__content__line__text", children: renderPreviewLine(entry.line, entry.text, result) })] }, entry.line))) })] })); }); const ShowcaseManagerSearchPanel = observer((props) => { const { showcaseManagerState } = props; const applicationStore = useApplicationStore(); const searchTextInpurRef = useRef(null); const debouncedSearch = useMemo(() => debounce(() => flowResult(showcaseManagerState.search()).catch(applicationStore.alertUnhandledError), 300), [applicationStore, showcaseManagerState]); const clearSearchText = () => { debouncedSearch.cancel(); showcaseManagerState.resetSearch(); }; const onSearchTextChange = (event) => { const value = event.target.value; showcaseManagerState.setSearchText(value); debouncedSearch.cancel(); if (!value) { showcaseManagerState.resetSearch(); } else { debouncedSearch()?.catch(applicationStore.alertUnhandledError); } }; const onSearchKeyDown = (event) => { if (event.code === 'Enter') { debouncedSearch.cancel(); if (showcaseManagerState.searchText) { debouncedSearch()?.catch(applicationStore.alertUnhandledError); } } else if (event.code === 'Escape') { searchTextInpurRef.current?.select(); } }; useEffect(() => { searchTextInpurRef.current?.select(); searchTextInpurRef.current?.focus(); }, []); return (_jsxs("div", { className: "showcase-manager__view", children: [_jsxs("div", { className: "showcase-manager__view__header", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumbs", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumb", onClick: () => { showcaseManagerState.closeShowcase(); showcaseManagerState.setCurrentView(SHOWCASE_MANAGER_VIEW.EXPLORER); }, children: [_jsx("div", { className: "showcase-manager__view__breadcrumb__icon", children: _jsx(HomeIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: "Showcases" })] }), _jsx("div", { className: "showcase-manager__view__breadcrumb__arrow", children: _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb", children: _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: "Search" }) })] }), _jsx("button", { className: "showcase-manager__view__search-action", tabIndex: -1, title: "Search", onClick: () => { // since we're already on the search tab, clicking this will just focus the search input searchTextInpurRef.current?.select(); }, children: _jsx(SearchIcon, {}) })] }), _jsxs("div", { className: "showcase-manager__view__content", children: [_jsxs("div", { className: "showcase-manager__search__header", children: [_jsx("input", { ref: searchTextInpurRef, className: "showcase-manager__search__input input--dark", spellCheck: false, placeholder: "Search for showcase, code, etc.", value: showcaseManagerState.searchText, onChange: onSearchTextChange, onKeyDown: onSearchKeyDown }), !showcaseManagerState.searchText ? (_jsx("div", { className: "showcase-manager__search__input__search__icon", children: _jsx(SearchIcon, {}) })) : (_jsx("button", { className: "showcase-manager__search__input__clear-btn", tabIndex: -1, onClick: clearSearchText, title: "Clear", children: _jsx(TimesIcon, {}) }))] }), _jsxs("div", { className: "showcase-manager__search__results", children: [_jsxs("div", { className: "showcase-manager__search__results__categories", children: [_jsxs("div", { className: clsx('showcase-manager__search__results__category', { 'showcase-manager__search__results__category--active': showcaseManagerState.currentSearchCaterogy === SHOWCASE_MANAGER_SEARCH_CATEGORY.SHOWCASE, }), onClick: () => showcaseManagerState.setCurrentSearchCategory(SHOWCASE_MANAGER_SEARCH_CATEGORY.SHOWCASE), title: "Click to select category", children: [_jsxs("div", { className: "showcase-manager__search__results__category__content", children: [_jsx("div", { className: "showcase-manager__search__results__category__icon", children: _jsx(GenericTextFileIcon, {}) }), _jsx("div", { className: "showcase-manager__search__results__category__label", children: "Showcases" })] }), _jsx("div", { className: "showcase-manager__search__results__category__counter", children: showcaseManagerState.showcaseSearchResults?.length ?? 0 })] }), _jsxs("div", { className: clsx('showcase-manager__search__results__category', { 'showcase-manager__search__results__category--active': showcaseManagerState.currentSearchCaterogy === SHOWCASE_MANAGER_SEARCH_CATEGORY.CODE, }), onClick: () => showcaseManagerState.setCurrentSearchCategory(SHOWCASE_MANAGER_SEARCH_CATEGORY.CODE), title: "Click to select category", children: [_jsxs("div", { className: "showcase-manager__search__results__category__content", children: [_jsx("div", { className: "showcase-manager__search__results__category__icon", children: _jsx(CodeIcon, {}) }), _jsx("div", { className: "showcase-manager__search__results__category__label", children: "Code" })] }), _jsx("div", { className: "showcase-manager__search__results__category__counter", children: showcaseManagerState.textSearchResults?.length ?? 0 })] })] }), _jsxs("div", { className: "showcase-manager__search__results__list", children: [showcaseManagerState.currentSearchCaterogy === SHOWCASE_MANAGER_SEARCH_CATEGORY.SHOWCASE && (_jsxs(_Fragment, { children: [!showcaseManagerState.showcaseSearchResults?.length && (_jsx(BlankPanelContent, { children: "No results" })), showcaseManagerState.showcaseSearchResults?.map((showcase) => (_jsxs("div", { className: "showcase-manager__search__showcase-result", title: `Showcase: ${showcase.title}\n\n${showcase.description ?? '(no description)'}\n\nClick to open showcase`, onClick: () => { flowResult(showcaseManagerState.openShowcase(showcase)).catch(applicationStore.alertUnhandledError); }, children: [_jsx("div", { className: "showcase-manager__search__showcase-result__title", children: showcase.title }), _jsx("div", { className: "showcase-manager__search__showcase-result__description", children: showcase.description ?? '(no description)' })] }, showcase.uuid)))] })), showcaseManagerState.currentSearchCaterogy === SHOWCASE_MANAGER_SEARCH_CATEGORY.CODE && (_jsxs(_Fragment, { children: [!showcaseManagerState.textSearchResults?.length && (_jsx(BlankPanelContent, { children: "No results" })), showcaseManagerState.textSearchResults?.map((result) => (_jsx(ShowcaseManagerCodeSearchResult, { showcaseManagerState: showcaseManagerState, result: result }, result.showcase.uuid)))] }))] })] })] })] })); }); const ShowcaseViewer = observer((props) => { const { showcaseManagerState, showcase } = props; const prettyPath = showcase.path.replaceAll(/\s*\/\s*/g, ' / '); const launchShowcase = () => { const applicationStore = showcaseManagerState.applicationStore; applicationStore.navigationService.navigator.visitAddress(applicationStore.navigationService.navigator.generateAddress(generateShowcasePath(showcase.path))); }; const handleCopy = showcaseManagerState.applicationStore.guardUnhandledError(() => showcaseManagerState.applicationStore.clipboardService.copyTextToClipboard(showcase.code, { notifySuccessMessage: 'Showcase grammar copied to clipboard', })); return (_jsxs("div", { className: "showcase-manager__view", children: [_jsxs("div", { className: "showcase-manager__view__header", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumbs", children: [_jsxs("div", { className: "showcase-manager__view__breadcrumb", onClick: () => { showcaseManagerState.closeShowcase(); showcaseManagerState.setCurrentView(SHOWCASE_MANAGER_VIEW.EXPLORER); }, children: [_jsx("div", { className: "showcase-manager__view__breadcrumb__icon", children: _jsx(HomeIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: "Showcases" })] }), _jsx("div", { className: "showcase-manager__view__breadcrumb__arrow", children: _jsx(ChevronRightIcon, {}) }), _jsxs("div", { className: "showcase-manager__view__breadcrumb", children: [_jsx("div", { className: "showcase-manager__view__breadcrumb__icon", children: _jsx(GenericTextFileIcon, {}) }), _jsx("div", { className: "showcase-manager__view__breadcrumb__text", children: showcase.title })] })] }), _jsx("button", { className: "showcase-manager__view__search-action", tabIndex: -1, title: "Search", onClick: () => { showcaseManagerState.closeShowcase(); showcaseManagerState.setCurrentView(SHOWCASE_MANAGER_VIEW.SEARCH); }, children: _jsx(SearchIcon, {}) })] }), _jsxs("div", { className: "showcase-manager__view__content showcase-manager__viewer__content", children: [_jsxs("div", { className: "showcase-manager__viewer__title", children: [_jsx("div", { className: "showcase-manager__viewer__title__label", children: showcase.title }), _jsx("div", { className: "showcase-manager__viewer__title__action", children: _jsx("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary showcase-manager__viewer__title__action-btn", children: _jsx("button", { className: "btn__dropdown-combo__label", onClick: launchShowcase, title: "Open Showcase Project", tabIndex: -1, children: _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Launch" }) }) }) }), _jsx("div", { className: "showcase-manager__viewer__title__action", children: _jsx("div", { onClick: handleCopy, className: "showcase-manager__viewer__title__action-icon", children: _jsx(CopyIcon, {}) }) })] }), _jsx("div", { className: "showcase-manager__viewer__path", children: prettyPath }), _jsx("div", { className: "showcase-manager__viewer__code", children: _jsx(CodeEditor, { language: CODE_EDITOR_LANGUAGE.PURE, inputValue: showcase.code, isReadOnly: true, lineToScroll: showcaseManagerState.showcaseLineToScroll }) })] })] })); }); const ShowcaseManagerContent = observer((props) => { const { showcaseManagerState } = props; const currentShowcase = showcaseManagerState.currentShowcase; const currentView = showcaseManagerState.currentView; return (_jsxs("div", { className: "showcase-manager", children: [currentShowcase && (_jsx(ShowcaseViewer, { showcaseManagerState: showcaseManagerState, showcase: currentShowcase })), !currentShowcase && (_jsxs(_Fragment, { children: [currentView === SHOWCASE_MANAGER_VIEW.EXPLORER && (_jsx(ShowcaseManagerExplorer, { showcaseManagerState: showcaseManagerState })), currentView === SHOWCASE_MANAGER_VIEW.SEARCH && (_jsx(ShowcaseManagerSearchPanel, { showcaseManagerState: showcaseManagerState }))] }))] })); }); export const ShowcaseManager = observer(() => { const applicationStore = useApplicationStore(); const showcaseManagerState = ShowcaseManagerState.retrieveNullableState(applicationStore); if (!showcaseManagerState) { return null; } return (_jsxs(Panel, { children: [_jsx(PanelLoadingIndicator, { isLoading: showcaseManagerState.initState.isInProgress }), showcaseManagerState.initState.isInProgress && (_jsx(BlankPanelContent, { children: "Initializing..." })), showcaseManagerState.initState.hasFailed && (_jsx(BlankPanelContent, { children: "Failed to initialize" })), showcaseManagerState.initState.hasSucceeded && (_jsx(ShowcaseManagerContent, { showcaseManagerState: showcaseManagerState }))] })); }); //# sourceMappingURL=ShowcaseManager.js.map