@finos/legend-lego
Version:
Legend code editor support
378 lines • 34.2 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
* Copyright (c) 2025-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 { AnchorLinkIcon, BasePopover, ChevronDownIcon, ChevronRightIcon, ClockIcon, CogIcon, ControlledDropdownMenu, FilterIcon, InfoCircleIcon, MenuContent, MenuContentItem, MoreVerticalIcon, PlayIcon, SearchIcon, TimesIcon, Tooltip, clsx, TreeView, PackageIcon, CheckSquareIcon, MinusSquareIcon, EmptySquareIcon, CaretRightIcon, CaretLeftIcon, } from '@finos/legend-art';
import { CORE_PURE_PATH, ELEMENT_PATH_DELIMITER, getMultiplicityDescription, MILESTONING_STEREOTYPE, PROPERTY_ACCESSOR, } from '@finos/legend-graph';
import { AssociationDocumentationEntry, BasicDocumentationEntry, ClassDocumentationEntry, EnumerationDocumentationEntry, ModelDocumentationEntry, PropertyDocumentationEntry, } from './ModelDocumentationAnalysis.js';
import { debounce, isNonNullable, prettyCONSTName } from '@finos/legend-shared';
import { DataGrid, } from '../data-grid/DataGrid.js';
import { useApplicationStore, useCommands, } from '@finos/legend-application';
import { observer } from 'mobx-react-lite';
import { checkFilterTreeNode, ModelsDocumentationFilterTreeElementNodeData, ModelsDocumentationFilterTreeNodeCheckType, ModelsDocumentationFilterTreePackageNodeData, ModelsDocumentationFilterTreeRootNodeData, ModelsDocumentationFilterTreeTypeNodeData, uncheckAllFilterTree, uncheckFilterTreeNode, } from './ModelDocumentationState.js';
import { FuzzySearchAdvancedConfigMenu } from '../application/FuzzySearchAdvancedConfigMenu.js';
import { useEffect, useMemo, useRef } from 'react';
export const getMilestoningLabel = (val) => {
switch (val) {
case MILESTONING_STEREOTYPE.BITEMPORAL:
return 'Bi-temporal';
case MILESTONING_STEREOTYPE.BUSINESS_TEMPORAL:
return 'Business Temporal';
case MILESTONING_STEREOTYPE.PROCESSING_TEMPORAL:
return 'Processing Temporal';
default:
return undefined;
}
};
const ElementInfoTooltip = (props) => {
const { entry, children } = props;
return (_jsx(Tooltip, { arrow: false, placement: "bottom-end", disableInteractive: true, classes: {
tooltip: 'models-documentation__tooltip',
tooltipPlacementRight: 'models-documentation__tooltip--right',
}, slotProps: {
transition: {
// disable transition
// NOTE: somehow, this is the only workaround we have, if for example
// we set `appear = true`, the tooltip will jump out of position
timeout: 0,
},
}, title: _jsxs("div", { className: "models-documentation__tooltip__content", children: [_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Name" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.name })] }), _jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Path" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.path })] }), entry instanceof ClassDocumentationEntry &&
entry.milestoning !== undefined && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Milestoning" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMilestoningLabel(entry.milestoning) })] }))] }), children: children }));
};
const PropertyInfoTooltip = (props) => {
const { entry, elementEntry, children } = props;
return (_jsx(Tooltip, { arrow: false, placement: "bottom-end", disableInteractive: true, classes: {
tooltip: 'models-documentation__tooltip',
tooltipPlacementRight: 'models-documentation__tooltip--right',
}, slotProps: {
transition: {
// disable transition
// NOTE: somehow, this is the only workaround we have, if for example
// we set `appear = true`, the tooltip will jump out of position
timeout: 0,
},
}, title: _jsxs("div", { className: "models-documentation__tooltip__content", children: [_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Name" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.name })] }), _jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Owner" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: elementEntry.path })] }), entry.type && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Type" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: entry.type })] })), entry.multiplicity && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Multiplicity" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMultiplicityDescription(entry.multiplicity) })] })), entry.milestoning && (_jsxs("div", { className: "models-documentation__tooltip__item", children: [_jsx("div", { className: "models-documentation__tooltip__item__label", children: "Milestoning" }), _jsx("div", { className: "models-documentation__tooltip__item__value", children: getMilestoningLabel(entry.milestoning) })] }))] }), children: children }));
};
export const ElementContentCellRenderer = observer((params) => {
const { data, modelsDocumentationState } = params;
const applicationStore = useApplicationStore();
const showHumanizedForm = modelsDocumentationState.showHumanizedForm;
if (!data) {
return null;
}
const copyPath = () => {
applicationStore.clipboardService
.copyTextToClipboard(data.elementEntry.path)
.catch(applicationStore.alertUnhandledError);
};
const label = showHumanizedForm
? prettyCONSTName(data.elementEntry.name)
: data.elementEntry.name;
if (data.elementEntry instanceof ClassDocumentationEntry) {
return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Class: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--class", children: "C" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label }), data.elementEntry.milestoning && (_jsx("div", { className: "models-documentation__grid__cell__label__milestoning-badge", title: `Milestoning: ${getMilestoningLabel(data.elementEntry.milestoning)}`, children: _jsx(ClockIcon, {}) }))] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }), _jsx(MenuContentItem, { disabled: true, children: "Preview Data" })] }), children: _jsx(MoreVerticalIcon, {}) })] })] }));
}
else if (data.elementEntry instanceof EnumerationDocumentationEntry) {
return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Enumeration: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--enumeration", children: "E" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] }));
}
else if (data.elementEntry instanceof AssociationDocumentationEntry) {
return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Association: ${data.elementEntry.path}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--association", children: "A" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(ElementInfoTooltip, { entry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyPath, children: "Copy Path" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] }));
}
return null;
});
export const SubElementDocContentCellRenderer = observer((params) => {
const { data, modelsDocumentationState } = params;
const applicationStore = useApplicationStore();
const showHumanizedForm = modelsDocumentationState.showHumanizedForm;
if (!data) {
return null;
}
let label = showHumanizedForm ? prettyCONSTName(data.text) : data.text;
const isDerivedProperty = label.endsWith('()');
label = isDerivedProperty ? label.slice(0, -2) : label;
if (data.entry instanceof ModelDocumentationEntry) {
return null;
}
else if (data.entry instanceof PropertyDocumentationEntry) {
return (_jsxs("div", { className: "models-documentation__grid__cell", title: `${isDerivedProperty ? 'Derived property' : 'Property'}: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--property", children: "P" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label }), isDerivedProperty && (_jsx("div", { className: "models-documentation__grid__cell__label__derived-property-badge", children: "()" })), data.entry.milestoning && (_jsx("div", { className: "models-documentation__grid__cell__label__milestoning-badge", title: `Milestoning: ${getMilestoningLabel(data.entry.milestoning)}`, children: _jsx(ClockIcon, {}) }))] }), _jsxs("div", { className: "models-documentation__grid__cell__actions", children: [_jsx(PropertyInfoTooltip, { entry: data.entry, elementEntry: data.elementEntry, children: _jsx("div", { className: "models-documentation__grid__cell__action", children: _jsx(InfoCircleIcon, { className: "models-documentation__grid__cell__action__info" }) }) }), _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { disabled: true, children: "Preview Data" }) }), children: _jsx(MoreVerticalIcon, {}) })] })] }));
}
else if (data.entry instanceof BasicDocumentationEntry) {
const copyValue = () => {
applicationStore.clipboardService
.copyTextToClipboard(data.elementEntry.path + PROPERTY_ACCESSOR + data.entry.name)
.catch(applicationStore.alertUnhandledError);
};
return (_jsxs("div", { className: "models-documentation__grid__cell", title: `Enum: ${data.elementEntry.path}${PROPERTY_ACCESSOR}${data.entry.name}`, children: [_jsxs("div", { className: "models-documentation__grid__cell__label", children: [_jsx("div", { className: "models-documentation__grid__cell__label__icon models-documentation__grid__cell__label__icon--enum", children: "e" }), _jsx("div", { className: "models-documentation__grid__cell__label__text", children: label })] }), _jsx("div", { className: "models-documentation__grid__cell__actions", children: _jsx(ControlledDropdownMenu, { className: "models-documentation__grid__cell__action", menuProps: {
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
transformOrigin: { vertical: 'top', horizontal: 'right' },
elevation: 7,
}, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: copyValue, children: "Copy Value" }) }), children: _jsx(MoreVerticalIcon, {}) }) })] }));
}
return null;
});
export const ElementDocumentationCellRenderer = (params) => {
const data = params.data;
if (!data) {
return null;
}
return data.documentation.trim() ? (data.documentation) : (_jsx("div", { className: "models-documentation__grid__empty-cell", children: "No documentation provided" }));
};
export const ModelsDocumentationGridPanel = observer((props) => {
const { modelsDocumentationState, applicationStore } = props;
const documentationState = modelsDocumentationState;
const darkMode = !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled;
return (_jsx("div", { className: clsx('models-documentation__viewer__grid', {
'models-documentation__grid': documentationState.showFilterPanel,
'ag-theme-balham': !darkMode,
'ag-theme-balham-dark': darkMode,
}), children: _jsx(DataGrid, { rowData: documentationState.filteredSearchResults, overlayNoRowsTemplate: `<div class="models-documentation__grid--empty">No documentation found</div>`,
// highlight element row
getRowClass: (params) => params.data?.entry instanceof ModelDocumentationEntry
? 'models-documentation__grid__element-row'
: undefined, alwaysShowVerticalScroll: true, gridOptions: {
suppressScrollOnNewData: true,
getRowId: (rowData) => rowData.data.uuid,
}, suppressFieldDotNotation: true, columnDefs: [
{
minWidth: 50,
sortable: true,
resizable: true,
cellRendererParams: {
modelsDocumentationState,
applicationStore,
},
cellRenderer: ElementContentCellRenderer,
headerName: 'Model',
flex: 1,
},
{
minWidth: 50,
sortable: false,
resizable: true,
cellRendererParams: {
modelsDocumentationState,
applicationStore,
},
cellRenderer: SubElementDocContentCellRenderer,
headerName: '',
flex: 1,
},
{
minWidth: 50,
sortable: false,
resizable: false,
headerClass: 'models-documentation__grid__last-column-header',
cellRenderer: ElementDocumentationCellRenderer,
headerName: 'Documentation',
flex: 1,
wrapText: true,
autoHeight: true,
},
] }) }));
});
export const getFilterTreeNodeIcon = (node) => {
if (node instanceof ModelsDocumentationFilterTreeElementNodeData) {
if (node.typePath === CORE_PURE_PATH.CLASS) {
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--class", children: "C" }));
}
else if (node.typePath === CORE_PURE_PATH.ENUMERATION) {
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--enumeration", children: "E" }));
}
else if (node.typePath === CORE_PURE_PATH.ASSOCIATION) {
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--association", children: "A" }));
}
}
else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) {
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--package", children: _jsx(PackageIcon, {}) }));
}
else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) {
switch (node.typePath) {
case CORE_PURE_PATH.CLASS:
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--class", children: "C" }));
case CORE_PURE_PATH.ENUMERATION:
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--enumeration", children: "E" }));
case CORE_PURE_PATH.ASSOCIATION:
return (_jsx("div", { className: "models-documentation__filter__tree__node__type-icon models-documentation__filter__tree__node__type-icon--association", children: "A" }));
default:
return undefined;
}
}
return undefined;
};
const getFilterNodeCount = (node, documentationState) => {
if (node instanceof ModelsDocumentationFilterTreeElementNodeData) {
return documentationState.searchResults.filter((result) => node.elementPath === result.elementEntry.path).length;
}
else if (node instanceof ModelsDocumentationFilterTreePackageNodeData) {
return documentationState.searchResults.filter((result) => node.packagePath === result.elementEntry.path ||
result.elementEntry.path.startsWith(`${node.packagePath}${ELEMENT_PATH_DELIMITER}`)).length;
}
else if (node instanceof ModelsDocumentationFilterTreeTypeNodeData) {
return node.typePath === CORE_PURE_PATH.CLASS
? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof ClassDocumentationEntry).length
: node.typePath === CORE_PURE_PATH.ENUMERATION
? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof EnumerationDocumentationEntry).length
: node.typePath === CORE_PURE_PATH.ASSOCIATION
? documentationState.searchResults.filter((entry) => entry.elementEntry instanceof AssociationDocumentationEntry).length
: undefined;
}
else if (node instanceof ModelsDocumentationFilterTreeRootNodeData) {
return documentationState.searchResults.length;
}
return undefined;
};
const ModelsDocumentationFilterTreeNodeContainer = observer((props) => {
const { node, level, innerProps } = props;
const { documentationState, refreshTreeData, uncheckTree, updateFilter } = innerProps;
const isExpandable = Boolean(node.childrenIds.length);
const expandIcon = isExpandable ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : (_jsx("div", {}));
const checkerIcon = node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED ? (_jsx(CheckSquareIcon, {})) : node.checkType ===
ModelsDocumentationFilterTreeNodeCheckType.PARTIALLY_CHECKED ? (_jsx(MinusSquareIcon, {})) : (_jsx(EmptySquareIcon, {}));
const nodeCount = getFilterNodeCount(node, documentationState);
const toggleChecker = (event) => {
event.stopPropagation();
if (node.checkType === ModelsDocumentationFilterTreeNodeCheckType.CHECKED) {
uncheckFilterTreeNode(node);
}
else {
checkFilterTreeNode(node);
}
refreshTreeData();
updateFilter();
};
const toggleExpandNode = (event) => {
event.stopPropagation();
if (isExpandable) {
node.setIsOpen(!node.isOpen);
refreshTreeData();
}
};
const onNodeClick = () => {
uncheckTree();
checkFilterTreeNode(node);
if (isExpandable && !node.isOpen) {
node.setIsOpen(true);
}
refreshTreeData();
updateFilter();
};
return (_jsxs("div", { className: "tree-view__node__container models-documentation__filter__tree__node__container", style: {
paddingLeft: `${(level - 1) * 1.4}rem`,
display: 'flex',
}, onClick: onNodeClick, children: [_jsx("div", { className: "models-documentation__filter__tree__node__expand-icon", onClick: toggleExpandNode, children: expandIcon }), _jsx("div", { className: "models-documentation__filter__tree__node__checker", onClick: toggleChecker, children: checkerIcon }), getFilterTreeNodeIcon(node), _jsx("div", { className: "tree-view__node__label models-documentation__filter__tree__node__label", children: node.label }), nodeCount !== undefined && (_jsx("div", { className: "tree-view__node__label models-documentation__filter__tree__node__count", children: nodeCount }))] }));
});
const ModelsDocumentationFilterPanel = observer((props) => {
const { modelsDocumentationState } = props;
const documentationState = modelsDocumentationState;
const resetAll = () => documentationState.resetAllFilters();
const resetTypeFilter = () => documentationState.resetTypeFilter();
const resetPackageFilter = () => documentationState.resetPackageFilter();
return (_jsxs("div", { className: "models-documentation__filter__panel", children: [_jsx("div", { className: "models-documentation__filter__group", children: _jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isFilterCustomized, onClick: resetAll, children: "Reset All" }) })] }) }), _jsxs("div", { className: "models-documentation__filter__group models-documentation__filter__group--by-type", children: [_jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter by Type" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isTypeFilterCustomized, onClick: resetTypeFilter, children: "Reset" }) })] }), _jsx("div", { className: "models-documentation__filter__group__content", children: _jsx(TreeView, { components: {
TreeNodeContainer: ModelsDocumentationFilterTreeNodeContainer,
}, treeData: documentationState.typeFilterTreeData, getChildNodes: (node) => node.childrenIds
.map((id) => documentationState.typeFilterTreeData.nodes.get(id))
.filter(isNonNullable)
.sort((a, b) => a.label.localeCompare(b.label)), innerProps: {
documentationState,
refreshTreeData: () => documentationState.resetTypeFilterTreeData(),
uncheckTree: () => uncheckAllFilterTree(documentationState.typeFilterTreeData),
updateFilter: () => documentationState.updateTypeFilter(),
} }) })] }), _jsxs("div", { className: "models-documentation__filter__group models-documentation__filter__group--by-package", children: [_jsxs("div", { className: "models-documentation__filter__group__header", children: [_jsx("div", { className: "models-documentation__filter__group__header__label", children: "Filter by Package" }), _jsx("div", { className: "models-documentation__filter__group__header__actions", children: _jsx("button", { className: "models-documentation__filter__group__header__reset", tabIndex: -1, disabled: !documentationState.isPackageFilterCustomized, onClick: resetPackageFilter, children: "Reset" }) })] }), _jsx("div", { className: "models-documentation__filter__group__content", children: _jsx(TreeView, { components: {
TreeNodeContainer: ModelsDocumentationFilterTreeNodeContainer,
}, treeData: documentationState.packageFilterTreeData, getChildNodes: (node) => node.childrenIds
.map((id) => documentationState.packageFilterTreeData.nodes.get(id))
.filter(isNonNullable)
.sort((a, b) => a.label.localeCompare(b.label)), innerProps: {
documentationState,
refreshTreeData: () => documentationState.resetPackageFilterTreeData(),
uncheckTree: () => uncheckAllFilterTree(documentationState.packageFilterTreeData),
updateFilter: () => documentationState.updatePackageFilter(),
} }) })] })] }));
});
const ModelsDocumentationSearchBar = observer((props) => {
const { modelsDocumentationState } = props;
const searchInputRef = useRef(null);
const searchConfigTriggerRef = useRef(null);
const documentationState = modelsDocumentationState;
const searchText = documentationState.searchText;
const debouncedSearch = useMemo(() => debounce(() => documentationState.search(), 100), [documentationState]);
const onSearchTextChange = (event) => {
documentationState.setSearchText(event.target.value);
debouncedSearch.cancel();
debouncedSearch();
};
// actions
const clearSearchText = () => {
documentationState.resetSearch();
documentationState.focusSearchInput();
};
const toggleSearchConfigMenu = () => documentationState.setShowSearchConfigurationMenu(!documentationState.showSearchConfigurationMenu);
const onKeyDown = (event) => {
if (event.code === 'Escape') {
documentationState.selectSearchInput();
}
};
// search config menu
const closeSearchConfigMenu = () => documentationState.setShowSearchConfigurationMenu(false);
const onSearchConfigMenuOpen = () => documentationState.focusSearchInput();
useEffect(() => {
if (searchInputRef.current) {
documentationState.setSearchInput(searchInputRef.current);
}
return () => documentationState.setSearchInput(undefined);
}, [documentationState]);
return (_jsxs("div", { className: "models-documentation__search", children: [_jsx("input", { ref: searchInputRef, onKeyDown: onKeyDown, className: "models-documentation__search__input input", spellCheck: false, onChange: onSearchTextChange, value: searchText, placeholder: "Search (Ctrl + Shift + F)" }), _jsx("button", { ref: searchConfigTriggerRef, className: clsx('models-documentation__search__input__config__trigger', {
'models-documentation__search__input__config__trigger--toggled': documentationState.showSearchConfigurationMenu,
'models-documentation__search__input__config__trigger--active': documentationState.searchConfigurationState
.isAdvancedSearchActive,
}), tabIndex: -1, onClick: toggleSearchConfigMenu, title: `${documentationState.searchConfigurationState.isAdvancedSearchActive
? 'Advanced search is currently active\n'
: ''}Click to toggle search config menu`, children: _jsx(CogIcon, {}) }), _jsx(BasePopover, { open: Boolean(documentationState.showSearchConfigurationMenu), slotProps: {
transition: {
onEnter: onSearchConfigMenuOpen,
},
}, anchorEl: searchConfigTriggerRef.current, onClose: closeSearchConfigMenu, anchorOrigin: {
vertical: 'bottom',
horizontal: 'center',
}, transformOrigin: {
vertical: 'top',
horizontal: 'center',
}, children: _jsx(FuzzySearchAdvancedConfigMenu, { configState: documentationState.searchConfigurationState }) }), !searchText ? (_jsx("div", { className: "models-documentation__search__input__search__icon", children: _jsx(SearchIcon, {}) })) : (_jsx("button", { className: "models-documentation__search__input__clear-btn", tabIndex: -1, onClick: clearSearchText, title: "Clear", children: _jsx(TimesIcon, {}) }))] }));
});
const ProductWikiPlaceholder = (props) => (_jsx("div", { className: "models-documentation__viewer__wiki__placeholder", children: props.message }));
export const ModelsDocumentation = observer((props) => {
const { modelsDocumentationState, applicationStore, title, queryModel } = props;
const sectionRef = useRef(null);
const elementDocs = modelsDocumentationState.elementDocs;
useCommands(modelsDocumentationState);
const toggleFilterPanel = () => modelsDocumentationState.setShowFilterPanel(!modelsDocumentationState.showFilterPanel);
return (_jsxs("div", { ref: sectionRef, className: "models-documentation__viewer__wiki__section", children: [_jsxs("div", { className: "models-documentation__viewer__wiki__section__header", children: [_jsxs("div", { className: "models-documentation__viewer__wiki__section__header__label", children: [title ?? 'Models Documentation', _jsx("button", { className: "models-documentation__viewer__wiki__section__header__anchor", tabIndex: -1, children: _jsx(AnchorLinkIcon, {}) })] }), queryModel && (_jsxs("button", { className: "models-documentation__viewer__wiki__section__header__query-btn", tabIndex: -1, onClick: queryModel, title: "Query", children: [_jsx(PlayIcon, {}), "Query"] }))] }), _jsxs("div", { className: "models-documentation__viewer__wiki__section__content", children: [elementDocs.length > 0 && (_jsxs("div", { className: "models-documentation", children: [_jsxs("div", { className: "models-documentation__header", children: [_jsxs("button", { className: "models-documentation__filter__toggler", title: "Toggle Filter Panel", tabIndex: -1, onClick: toggleFilterPanel, children: [_jsx("div", { className: "models-documentation__filter__toggler__arrow", children: modelsDocumentationState.showFilterPanel ? (_jsx(CaretLeftIcon, {})) : (_jsx(CaretRightIcon, {})) }), _jsx("div", { className: "models-documentation__filter__toggler__icon", children: _jsx(FilterIcon, {}) })] }), _jsx(ModelsDocumentationSearchBar, { modelsDocumentationState: modelsDocumentationState })] }), _jsxs("div", { className: "models-documentation__content", children: [modelsDocumentationState.showFilterPanel && (_jsx(ModelsDocumentationFilterPanel, { modelsDocumentationState: modelsDocumentationState })), _jsx(ModelsDocumentationGridPanel, { modelsDocumentationState: modelsDocumentationState, applicationStore: applicationStore })] })] })), elementDocs.length === 0 && (_jsx(ProductWikiPlaceholder, { message: "(not specified)" }))] })] }));
});
//# sourceMappingURL=ModelDocumentationViewer.js.map