UNPKG

@finos/legend-extension-dsl-data-space

Version:
170 lines 19.5 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 { AnchorLinkIcon, CaretDownIcon, CenterFocusIcon, CircleIcon, CloseIcon, ContextMenu, CustomSelectorInput, DescriptionIcon, ControlledDropdownMenu, MenuContent, MenuContentDivider, MenuContentItem, MousePointerIcon, MoveIcon, ShapesIcon, ThinChevronDownIcon, ThinChevronLeftIcon, ThinChevronRightIcon, ThinChevronUpIcon, ZoomInIcon, ZoomOutIcon, clsx, useResizeDetector, createFilter, } from '@finos/legend-art'; import {} from '../stores/DataSpaceViewerState.js'; import { observer } from 'mobx-react-lite'; import { forwardRef, useEffect, useRef } from 'react'; import {} from '@finos/legend-extension-dsl-diagram/graph'; import { DIAGRAM_INTERACTION_MODE, DIAGRAM_RELATIONSHIP_EDIT_MODE, DIAGRAM_ZOOM_LEVELS, DiagramRenderer, } from '@finos/legend-extension-dsl-diagram/application'; import { DataSpaceWikiPlaceholder } from './DataSpacePlaceholder.js'; import { at } from '@finos/legend-shared'; import { DataSpaceMarkdownTextViewer } from './DataSpaceMarkdownTextViewer.js'; import { useCommands } from '@finos/legend-application'; import { DATA_SPACE_VIEWER_ACTIVITY_MODE, generateAnchorForActivity, generateAnchorForDiagram, } from '../stores/DataSpaceViewerNavigation.js'; const DataSpaceDiagramCanvas = observer(forwardRef(function DataSpaceDiagramCanvas(props, _ref) { const { dataSpaceViewerState, diagram } = props; const diagramViewerState = dataSpaceViewerState.diagramViewerState; const ref = _ref; const descriptionText = diagramViewerState.currentDiagram?.description; const { width, height } = useResizeDetector({ refreshMode: 'debounce', refreshRate: 50, targetRef: ref, }); useEffect(() => { diagramViewerState.setExpandDescription(false); }, [diagramViewerState, diagramViewerState.currentDiagram]); useEffect(() => { const renderer = new DiagramRenderer(ref.current, diagram); diagramViewerState.setDiagramRenderer(renderer); diagramViewerState.setupDiagramRenderer(); renderer.render({ initial: true }); }, [ref, diagramViewerState, diagram]); useEffect(() => { if (diagramViewerState.isDiagramRendererInitialized) { diagramViewerState.diagramRenderer.refresh(); } }, [diagramViewerState, width, height]); // actions const queryClass = () => { if (diagramViewerState.contextMenuClassView) { dataSpaceViewerState.queryClass(diagramViewerState.contextMenuClassView.class.value); } }; const viewClassDocumentation = () => { if (diagramViewerState.contextMenuClassView && dataSpaceViewerState.modelsDocumentationState.hasClassDocumentation(diagramViewerState.contextMenuClassView.class.value.path)) { dataSpaceViewerState.modelsDocumentationState.viewClassDocumentation(diagramViewerState.contextMenuClassView.class.value.path); dataSpaceViewerState.changeZone(generateAnchorForActivity(DATA_SPACE_VIEWER_ACTIVITY_MODE.MODELS_DOCUMENTATION)); } }; return (_jsxs(ContextMenu, { className: "data-space__viewer__diagram-viewer__canvas", content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { onClick: queryClass, disabled: !diagramViewerState.contextMenuClassView, children: "Query" }), _jsx(MenuContentItem, { onClick: viewClassDocumentation, disabled: !diagramViewerState.contextMenuClassView || !dataSpaceViewerState.modelsDocumentationState.hasClassDocumentation(diagramViewerState.contextMenuClassView.class.value.path), children: "See Model Documentation" })] }), disabled: !diagramViewerState.contextMenuClassView, menuProps: { elevation: 7 }, onClose: () => diagramViewerState.setContextMenuClassView(undefined), children: [diagramViewerState.showDescription && (_jsxs("div", { className: clsx('data-space__viewer__diagram-viewer__description', { 'data-space__viewer__diagram-viewer__description--expanded': diagramViewerState.expandDescription, }), children: [_jsx("button", { className: "data-space__viewer__diagram-viewer__description__close-btn", tabIndex: -1, title: "Hide Description", onClick: () => diagramViewerState.setShowDescription(false), children: _jsx(CloseIcon, {}) }), _jsx("div", { className: "data-space__viewer__diagram-viewer__description__title", children: diagramViewerState.currentDiagram?.title ? diagramViewerState.currentDiagram.title : 'Untitled' }), _jsx("div", { className: "data-space__viewer__diagram-viewer__description__content", children: descriptionText ? (_jsx(DataSpaceMarkdownTextViewer, { value: descriptionText })) : (_jsx("div", { className: "data-space__viewer__diagram-viewer__description__content__placeholder", children: "(not specified)" })) }), _jsx("button", { className: "data-space__viewer__diagram-viewer__description__expand-btn", tabIndex: -1, title: diagramViewerState.expandDescription ? 'Collapse' : 'Expand', onClick: () => diagramViewerState.setExpandDescription(!diagramViewerState.expandDescription), children: diagramViewerState.expandDescription ? (_jsx(ThinChevronUpIcon, {})) : (_jsx(ThinChevronDownIcon, {})) })] })), _jsx("div", { ref: ref, className: clsx('diagram-canvas', diagramViewerState.diagramCursorClass), tabIndex: 0 })] })); })); const buildDiagramOption = (diagram) => ({ label: (_jsxs("div", { className: "data-space__viewer__diagram-viewer__header__navigation__selector__label", children: [_jsx(ShapesIcon, { className: "data-space__viewer__diagram-viewer__header__navigation__selector__icon" }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__navigation__selector__title", children: diagram.title ? diagram.title : 'Untitled' })] })), value: diagram, }); const DataSpaceDiagramViewerHeader = observer((props) => { const { dataSpaceViewerState } = props; const applicationStore = dataSpaceViewerState.applicationStore; const diagramViewerState = dataSpaceViewerState.diagramViewerState; const diagramOptions = dataSpaceViewerState.dataSpaceAnalysisResult.diagrams.map(buildDiagramOption); const selectedDiagramOption = diagramViewerState.currentDiagram ? buildDiagramOption(diagramViewerState.currentDiagram) : null; const onDiagramOptionChange = (option) => { if (option.value !== diagramViewerState.currentDiagram) { diagramViewerState.setCurrentDiagram(option.value); } }; const diagramFilterOption = createFilter({ ignoreCase: true, ignoreAccents: false, stringify: (option) => option.data.value.title, }); const createModeSwitcher = (editMode, relationshipMode) => () => diagramViewerState.diagramRenderer.changeMode(editMode, relationshipMode); const createCenterZoomer = (zoomLevel) => () => { diagramViewerState.diagramRenderer.zoomCenter(zoomLevel / 100); }; const zoomToFit = () => diagramViewerState.diagramRenderer.zoomToFit(); return (_jsxs("div", { className: "data-space__viewer__diagram-viewer__header", children: [_jsxs("div", { className: "data-space__viewer__diagram-viewer__header__navigation", children: [_jsx(CustomSelectorInput, { className: "data-space__viewer__diagram-viewer__header__navigation__selector", options: diagramOptions, onChange: onDiagramOptionChange, value: selectedDiagramOption, placeholder: "Search for a diagram", darkMode: !applicationStore.layoutService .TEMPORARY__isLightColorThemeEnabled, filterOption: diagramFilterOption }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__navigation__pager", children: _jsx("input", { className: "data-space__viewer__diagram-viewer__header__navigation__pager__input input--dark", value: diagramViewerState.currentDiagramIndex, type: "number", onChange: (event) => { const value = parseInt(event.target.value, 10); if (isNaN(value) || value < 1 || value > dataSpaceViewerState.dataSpaceAnalysisResult.diagrams.length) { return; } diagramViewerState.setCurrentDiagram(at(dataSpaceViewerState.dataSpaceAnalysisResult.diagrams, value - 1)); } }) }), _jsxs("div", { className: "data-space__viewer__diagram-viewer__header__navigation__pager__count", children: ["/", dataSpaceViewerState.dataSpaceAnalysisResult.diagrams.length] })] }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__actions", children: diagramViewerState.isDiagramRendererInitialized && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "data-space__viewer__diagram-viewer__header__group", children: [_jsx("button", { className: "data-space__viewer__diagram-viewer__header__tool", tabIndex: -1, onClick: () => { if (diagramViewerState.currentDiagram) { dataSpaceViewerState.syncZoneWithNavigation(generateAnchorForDiagram(diagramViewerState.currentDiagram)); } }, title: "Copy Link", children: _jsx(AnchorLinkIcon, {}) }), _jsx("button", { className: "data-space__viewer__diagram-viewer__header__tool", tabIndex: -1, onClick: () => diagramViewerState.diagramRenderer.recenter(), title: "Recenter (R)", children: _jsx(CenterFocusIcon, { className: "data-space__viewer__diagram-viewer__icon--recenter" }) }), _jsx("button", { className: clsx('data-space__viewer__diagram-viewer__header__tool', { 'data-space__viewer__diagram-viewer__header__tool--active': diagramViewerState.showDescription, }), tabIndex: -1, onClick: () => diagramViewerState.setShowDescription(!diagramViewerState.showDescription), title: "Toggle Description (D)", children: _jsx(DescriptionIcon, { className: "data-space__viewer__diagram-viewer__icon--description" }) })] }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__group__separator" }), _jsxs("div", { className: "data-space__viewer__diagram-viewer__header__group", children: [_jsx("button", { className: clsx('data-space__viewer__diagram-viewer__header__tool', { 'data-space__viewer__diagram-viewer__header__tool--active': diagramViewerState.diagramRenderer.interactionMode === DIAGRAM_INTERACTION_MODE.LAYOUT, }), tabIndex: -1, onClick: createModeSwitcher(DIAGRAM_INTERACTION_MODE.LAYOUT, DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE), title: "View Tool (V)", children: _jsx(MousePointerIcon, { className: "data-space__viewer__diagram-viewer__icon--layout" }) }), _jsx("button", { className: clsx('data-space__viewer__diagram-viewer__header__tool', { 'data-space__viewer__diagram-viewer__header__tool--active': diagramViewerState.diagramRenderer.interactionMode === DIAGRAM_INTERACTION_MODE.PAN, }), tabIndex: -1, onClick: createModeSwitcher(DIAGRAM_INTERACTION_MODE.PAN, DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE), title: "Pan Tool (M)", children: _jsx(MoveIcon, { className: "data-space__viewer__diagram-viewer__icon--pan" }) }), _jsx("button", { className: clsx('data-space__viewer__diagram-viewer__header__tool', { 'data-space__viewer__diagram-viewer__header__tool--active': diagramViewerState.diagramRenderer.interactionMode === DIAGRAM_INTERACTION_MODE.ZOOM_IN, }), tabIndex: -1, title: "Zoom In (Z)", onClick: createModeSwitcher(DIAGRAM_INTERACTION_MODE.ZOOM_IN, DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE), children: _jsx(ZoomInIcon, { className: "data-space__viewer__diagram-viewer__icon--zoom-in" }) }), _jsx("button", { className: clsx('data-space__viewer__diagram-viewer__header__tool', { 'data-space__viewer__diagram-viewer__header__tool--active': diagramViewerState.diagramRenderer.interactionMode === DIAGRAM_INTERACTION_MODE.ZOOM_OUT, }), tabIndex: -1, title: "Zoom Out (Z)", onClick: createModeSwitcher(DIAGRAM_INTERACTION_MODE.ZOOM_OUT, DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE), children: _jsx(ZoomOutIcon, { className: "data-space__viewer__diagram-viewer__icon--zoom-out" }) })] }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__group__separator" }), _jsxs(ControlledDropdownMenu, { className: "data-space__viewer__diagram-viewer__header__group data-space__viewer__diagram-viewer__header__dropdown", title: "Zoom...", content: _jsxs(MenuContent, { children: [_jsx(MenuContentItem, { className: "data-space__viewer__diagram-viewer__header__zoomer__dropdown__menu__item", onClick: zoomToFit, children: "Fit" }), _jsx(MenuContentDivider, {}), DIAGRAM_ZOOM_LEVELS.map((zoomLevel) => (_jsxs(MenuContentItem, { className: "data-space__viewer__diagram-viewer__header__zoomer__dropdown__menu__item", onClick: createCenterZoomer(zoomLevel), children: [zoomLevel, "%"] }, zoomLevel)))] }), menuProps: { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' }, elevation: 7, }, children: [_jsxs("div", { className: "data-space__viewer__diagram-viewer__header__dropdown__label data-space__viewer__diagram-viewer__header__zoomer__dropdown__label", children: [Math.round(diagramViewerState.diagramRenderer.zoom * 100), "%"] }), _jsx("div", { className: "data-space__viewer__diagram-viewer__header__dropdown__trigger data-space__viewer__diagram-viewer__header__zoomer__dropdown__trigger", children: _jsx(CaretDownIcon, {}) })] })] })) })] })); }); export const DataSpaceDiagramViewer = observer((props) => { const { dataSpaceViewerState } = props; const diagramViewerState = dataSpaceViewerState.diagramViewerState; const analysisResult = dataSpaceViewerState.dataSpaceAnalysisResult; const sectionRef = useRef(null); const anchor = generateAnchorForActivity(DATA_SPACE_VIEWER_ACTIVITY_MODE.DIAGRAM_VIEWER); useCommands(diagramViewerState); useEffect(() => { if (sectionRef.current) { dataSpaceViewerState.layoutState.setWikiPageAnchor(anchor, sectionRef.current); } return () => dataSpaceViewerState.layoutState.unsetWikiPageAnchor(anchor); }, [dataSpaceViewerState, anchor]); const diagramCanvasRef = useRef(null); const previousDiagram = diagramViewerState.previousDiagram; const nextDiagram = diagramViewerState.nextDiagram; const showPreviousDiagram = () => { if (previousDiagram) { diagramViewerState.setCurrentDiagram(previousDiagram); dataSpaceViewerState.syncZoneWithNavigation(generateAnchorForDiagram(previousDiagram)); } }; const showNextDiagram = () => { if (nextDiagram) { diagramViewerState.setCurrentDiagram(nextDiagram); dataSpaceViewerState.syncZoneWithNavigation(generateAnchorForDiagram(nextDiagram)); } }; return (_jsxs("div", { ref: sectionRef, className: "data-space__viewer__wiki__section", children: [_jsx("div", { className: "data-space__viewer__wiki__section__header", children: _jsxs("div", { className: "data-space__viewer__wiki__section__header__label", children: ["Diagrams", _jsx("button", { className: "data-space__viewer__wiki__section__header__anchor", tabIndex: -1, onClick: () => dataSpaceViewerState.changeZone(anchor, true), children: _jsx(AnchorLinkIcon, {}) })] }) }), _jsxs("div", { className: "data-space__viewer__wiki__section__content", children: [analysisResult.diagrams.length > 0 && (_jsxs("div", { className: "data-space__viewer__diagram-viewer", children: [_jsx(DataSpaceDiagramViewerHeader, { dataSpaceViewerState: dataSpaceViewerState }), _jsx("div", { className: "data-space__viewer__diagram-viewer__carousel", children: _jsxs("div", { className: "data-space__viewer__diagram-viewer__carousel__frame", children: [_jsx("div", { className: "data-space__viewer__diagram-viewer__carousel__frame__display", children: diagramViewerState.currentDiagram && (_jsx(DataSpaceDiagramCanvas, { dataSpaceViewerState: dataSpaceViewerState, diagram: diagramViewerState.currentDiagram.diagram, ref: diagramCanvasRef })) }), _jsx("button", { className: "data-space__viewer__diagram-viewer__carousel__frame__navigator data-space__viewer__diagram-viewer__carousel__frame__navigator--back", tabIndex: -1, title: `Previous - ${previousDiagram?.title ? previousDiagram.title : '(untitled)'} (⇦)`, disabled: !previousDiagram, onClick: showPreviousDiagram, children: _jsx(ThinChevronLeftIcon, {}) }), _jsx("button", { className: "data-space__viewer__diagram-viewer__carousel__frame__navigator data-space__viewer__diagram-viewer__carousel__frame__navigator--next", tabIndex: -1, title: `Next - ${nextDiagram?.title ? nextDiagram.title : '(untitled)'} (⇨)`, disabled: !nextDiagram, onClick: showNextDiagram, children: _jsx(ThinChevronRightIcon, {}) }), _jsx("div", { className: "data-space__viewer__diagram-viewer__carousel__frame__indicators", children: _jsx("div", { className: "data-space__viewer__diagram-viewer__carousel__frame__indicators__notch", children: analysisResult.diagrams.map((diagram) => (_jsx("button", { className: clsx('data-space__viewer__diagram-viewer__carousel__frame__indicator', { 'data-space__viewer__diagram-viewer__carousel__frame__indicator--active': diagramViewerState.currentDiagram === diagram, }), title: `View Diagram - ${diagram.title ? diagram.title : '(untitled)'}`, onClick: () => { diagramViewerState.setCurrentDiagram(diagram); dataSpaceViewerState.syncZoneWithNavigation(generateAnchorForDiagram(diagram)); }, children: _jsx(CircleIcon, {}) }, diagram.uuid))) }) })] }) })] })), !analysisResult.diagrams.length && (_jsx(DataSpaceWikiPlaceholder, { message: "(not specified)" }))] })] })); }); //# sourceMappingURL=DataSpaceDiagramViewer.js.map