@finos/legend-application-studio
Version:
Legend Studio application core
129 lines • 12.8 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 { forwardRef, useEffect, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { prettyCONSTName, toSentenceCase } from '@finos/legend-shared';
import { clsx, ContextMenu, FlaskIcon, MapIcon, PlayIcon, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, TimesIcon, PURE_UnknownElementTypeIcon, PURE_ClassIcon, PURE_EnumerationIcon, PURE_AssociationIcon, Panel, useResizeDetector, MenuContentItem, MenuContent, LockIcon, } from '@finos/legend-art';
import { ClassMappingEditor } from './ClassMappingEditor.js';
import { EnumerationMappingEditor } from './EnumerationMappingEditor.js';
import { MappingEditorState, getMappingElementTarget, getMappingElementType, MAPPING_ELEMENT_TYPE, getMappingElementLabel, MAPPING_EDITOR_TAB, } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js';
import { MappingElementState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingElementState.js';
import { MappingExplorer } from './MappingExplorer.js';
import { DEPRECATED__MappingTestEditor } from './legacy/DEPRECATED__MappingTestEditor.js';
import { DEPRECATED__MappingTestState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/legacy/DEPRECATED__MappingTestState.js';
import { MappingTestsExplorer } from './MappingTestsExplorer.js';
import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
import { MappingExecutionState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingExecutionState.js';
import { MappingExecutionBuilder } from './MappingExecutionBuilder.js';
import { flowResult } from 'mobx';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { Class, Enumeration, Association, } from '@finos/legend-graph';
import { useApplicationNavigationContext, useApplicationStore, } from '@finos/legend-application';
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
import { MappingTestableEditor } from './MappingTestableEditor.js';
import { DocumentationLink } from '@finos/legend-lego/application';
import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../../../__lib__/LegendStudioDocumentation.js';
import { MappingTestMigrationTool } from './legacy/MappingTestMigrationTool.js';
export const MappingEditorSplashScreen = () => {
const logoWidth = 280;
const logoHeight = 270;
const [showLogo, setShowLogo] = useState(false);
const { ref, height, width } = useResizeDetector();
useEffect(() => {
setShowLogo((width ?? 0) > logoWidth && (height ?? 0) > logoHeight);
}, [height, width]);
return (_jsx("div", { ref: ref, className: "mapping-editor__splash-screen", children: _jsx("div", { className: clsx('mapping-editor__splash-screen__logo', {
'mapping-editor__splash-screen__logo--hidden': !showLogo,
}), children: _jsx(MapIcon, {}) }) }));
};
const MappingEditorHeaderTabContextMenu = observer(forwardRef(function MappingEditorHeaderTabContextMenu(props, ref) {
const { tabState } = props;
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
const close = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.closeTab(tabState)));
const closeOthers = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.closeAllOtherTabs(tabState)));
const closeAll = () => mappingEditorState.closeAllTabs();
return (_jsxs(MenuContent, { ref: ref, children: [_jsx(MenuContentItem, { onClick: close, children: "Close" }), _jsx(MenuContentItem, { disabled: mappingEditorState.openedTabStates.length < 2, onClick: closeOthers, children: "Close Others" }), _jsx(MenuContentItem, { onClick: closeAll, children: "Close All" })] }));
}));
const getMappingElementTargetIcon = (mappingElement) => {
const target = getMappingElementTarget(mappingElement);
if (target instanceof Class) {
return _jsx(PURE_ClassIcon, {});
}
else if (target instanceof Enumeration) {
return _jsx(PURE_EnumerationIcon, {});
}
else if (target instanceof Association) {
return _jsx(PURE_AssociationIcon, {});
}
return _jsx(PURE_UnknownElementTypeIcon, {});
};
const MappingClassMappingEditor = observer(() => {
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
const isReadOnly = mappingEditorState.isReadOnly;
const currentTabState = mappingEditorState.currentTabState;
const renderActiveMappingElementTab = () => {
if (currentTabState instanceof DEPRECATED__MappingTestState) {
return (_jsx(DEPRECATED__MappingTestEditor, { testState: currentTabState, isReadOnly: isReadOnly }, currentTabState.uuid));
}
else if (currentTabState instanceof MappingElementState) {
const currentMappingElement = currentTabState.mappingElement;
switch (getMappingElementType(currentMappingElement)) {
case MAPPING_ELEMENT_TYPE.CLASS:
return (_jsx(ClassMappingEditor, { setImplementation: currentMappingElement, isReadOnly: isReadOnly }));
case MAPPING_ELEMENT_TYPE.ENUMERATION:
return (_jsx(EnumerationMappingEditor, { enumerationMapping: currentMappingElement, isReadOnly: isReadOnly }));
case MAPPING_ELEMENT_TYPE.ASSOCIATION: // we will not support association mapping
default:
return _jsx("div", { children: "Unsupported mapping type" });
}
}
else if (currentTabState instanceof MappingExecutionState) {
return (_jsx(MappingExecutionBuilder, { executionState: currentTabState }, currentTabState.uuid));
}
return _jsx(MappingEditorSplashScreen, {});
};
const closeTab = (tabState) => () => {
flowResult(mappingEditorState.closeTab(tabState)).catch(applicationStore.alertUnhandledError);
};
const closeTabOnMiddleClick = (tabState) => (event) => {
if (event.nativeEvent.button === 1) {
flowResult(mappingEditorState.closeTab(tabState)).catch(applicationStore.alertUnhandledError);
}
};
const openTab = (tabState) => applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.openTab(tabState)));
useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MAPPING_EDITOR);
return (_jsx("div", { className: clsx('mapping-editor', 'mapping__theme__dark'), children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 300, minSize: 300, children: _jsx("div", { className: "mapping-editor__side-bar", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 400, minSize: 28, children: _jsx(MappingExplorer, { isReadOnly: isReadOnly }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-light-grey-400)" }) }), _jsx(ResizablePanel, { minSize: 36, children: _jsx(MappingTestsExplorer, { isReadOnly: isReadOnly }) })] }) }) }), _jsx(ResizablePanelSplitter, {}), _jsx(ResizablePanel, { children: _jsxs(Panel, { children: [_jsx("div", { className: "panel__header mapping-editor__header", children: _jsx("div", { "data-testid": LEGEND_STUDIO_TEST_ID.EDITOR__TABS__HEADER, className: "mapping-editor__header__tabs", children: mappingEditorState.openedTabStates.map((tabState) => (_jsx("div", { onMouseUp: closeTabOnMiddleClick(tabState), className: clsx('mapping-editor__header__tab', {
'mapping-editor__header__tab--active': tabState === mappingEditorState.currentTabState,
}), children: _jsxs(ContextMenu, { className: "mapping-editor__header__tab__content", content: _jsx(MappingEditorHeaderTabContextMenu, { tabState: tabState }), children: [tabState instanceof DEPRECATED__MappingTestState && (_jsxs(_Fragment, { children: [_jsx(FlaskIcon, { className: "mapping-editor__header__tab__icon--test" }), _jsx("button", { className: "mapping-editor__header__tab__element__name", tabIndex: -1, onClick: openTab(tabState), children: tabState.test.name })] })), tabState instanceof MappingElementState && (_jsxs(_Fragment, { children: [_jsx("div", { className: `mapping-editor__header__tab__element__type icon color--${getMappingElementType(tabState.mappingElement).toLowerCase()}`, children: getMappingElementTargetIcon(tabState.mappingElement) }), _jsx("button", { className: "mapping-editor__header__tab__element__name", tabIndex: -1, onClick: openTab(tabState), title: `${toSentenceCase(getMappingElementType(tabState.mappingElement)).toLowerCase()} mapping '${tabState.mappingElement.id.value}' for '${getMappingElementTarget(tabState.mappingElement)
.name}'`, children: getMappingElementLabel(tabState.mappingElement, editorStore).value })] })), tabState instanceof MappingExecutionState && (_jsxs(_Fragment, { children: [_jsx(PlayIcon, { className: "mapping-editor__header__tab__icon--execution" }), _jsx("button", { className: "mapping-editor__header__tab__element__name", tabIndex: -1, onClick: openTab(tabState), children: tabState.name })] })), _jsx("button", { className: "mapping-editor__header__tab__close-btn", onClick: closeTab(tabState), tabIndex: -1, title: "Close", children: _jsx(TimesIcon, {}) })] }) }, tabState.uuid))) }) }), _jsx("div", { className: "panel__content mapping-editor__content", children: renderActiveMappingElementTab() })] }) })] }) }));
});
export const MappingEditor = observer(() => {
const editorStore = useEditorStore();
const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
const isReadOnly = mappingEditorState.isReadOnly;
const mapping = mappingEditorState.mapping;
const selectedTab = mappingEditorState.selectedTab;
const changeTab = (tab) => () => mappingEditorState.setSelectedTab(tab);
return (_jsx("div", { "data-testid": LEGEND_STUDIO_TEST_ID.MAPPING_EDITOR, className: "service-editor", children: _jsxs("div", { className: "panel", children: [_jsx("div", { className: "panel__header", children: _jsxs("div", { className: "panel__header__title", children: [isReadOnly && (_jsx("div", { className: "uml-element-editor__header__lock", children: _jsx(LockIcon, {}) })), _jsx("div", { className: "panel__header__title__label", children: "mapping" }), _jsx("div", { className: "panel__header__title__content", children: mapping.name })] }) }), _jsx("div", { className: "panel__header service-editor__header--with-tabs", children: _jsx("div", { className: "uml-element-editor__tabs", children: Object.values(MAPPING_EDITOR_TAB).map((tab) => (_jsxs("div", { onClick: changeTab(tab), className: clsx('service-editor__tab', {
'service-editor__tab--active': tab === selectedTab,
}), children: [prettyCONSTName(tab), tab === MAPPING_EDITOR_TAB.TEST_SUITES && (_jsx(DocumentationLink, { documentationKey: LEGEND_STUDIO_DOCUMENTATION_KEY.QUESTION_HOW_TO_WRITE_A_MAPPING_TEST }))] }, tab))) }) }), _jsxs("div", { className: "panel__content service-editor__content", children: [selectedTab === MAPPING_EDITOR_TAB.CLASS_MAPPINGS && (_jsx(MappingClassMappingEditor, {})), selectedTab === MAPPING_EDITOR_TAB.TEST_SUITES && (_jsx(MappingTestableEditor, { mappingTestableState: mappingEditorState.mappingTestableState })), mappingEditorState.migrationState && (_jsx(MappingTestMigrationTool, { mappingEditorState: mappingEditorState, migrationState: mappingEditorState.migrationState }))] })] }) }));
});
//# sourceMappingURL=MappingEditor.js.map