/** * 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 { type MappingElement, 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, type SetImplementation, type EnumerationMapping, } from '@finos/legend-graph'; import { useApplicationNavigationContext, useApplicationStore, } from '@finos/legend-application'; import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js'; import type { MappingEditorTabState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingTabManagerState.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: React.FC = () => { 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 (
); }; const MappingEditorHeaderTabContextMenu = observer( forwardRef< HTMLDivElement, { tabState: MappingEditorTabState; } >(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 = (): void => mappingEditorState.closeAllTabs(); return ( Close Close Others Close All ); }), ); const getMappingElementTargetIcon = ( mappingElement: MappingElement, ): React.ReactNode => { const target = getMappingElementTarget(mappingElement); if (target instanceof Class) { return ; } else if (target instanceof Enumeration) { return ; } else if (target instanceof Association) { return ; } return ; }; 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 = (): React.ReactNode => { if (currentTabState instanceof DEPRECATED__MappingTestState) { return ( ); } else if (currentTabState instanceof MappingElementState) { const currentMappingElement = currentTabState.mappingElement; switch (getMappingElementType(currentMappingElement)) { case MAPPING_ELEMENT_TYPE.CLASS: return ( ); case MAPPING_ELEMENT_TYPE.ENUMERATION: return ( ); case MAPPING_ELEMENT_TYPE.ASSOCIATION: // we will not support association mapping default: return
Unsupported mapping type
; } } else if (currentTabState instanceof MappingExecutionState) { return ( ); } return ; }; const closeTab = (tabState: MappingEditorTabState) => (): void => { flowResult(mappingEditorState.closeTab(tabState)).catch( applicationStore.alertUnhandledError, ); }; const closeTabOnMiddleClick = (tabState: MappingEditorTabState): React.MouseEventHandler => (event): void => { if (event.nativeEvent.button === 1) { flowResult(mappingEditorState.closeTab(tabState)).catch( applicationStore.alertUnhandledError, ); } }; const openTab = (tabState: MappingEditorTabState): (() => void) => applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.openTab(tabState)), ); useApplicationNavigationContext( LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MAPPING_EDITOR, ); return (
{mappingEditorState.openedTabStates.map((tabState) => (
} > {tabState instanceof DEPRECATED__MappingTestState && ( <> )} {tabState instanceof MappingElementState && ( <>
{getMappingElementTargetIcon( tabState.mappingElement, )}
)} {tabState instanceof MappingExecutionState && ( <> )}
))}
{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: MAPPING_EDITOR_TAB): (() => void) => (): void => mappingEditorState.setSelectedTab(tab); return (
{isReadOnly && (
)}
mapping
{mapping.name}
{Object.values(MAPPING_EDITOR_TAB).map((tab) => (
{prettyCONSTName(tab)} {tab === MAPPING_EDITOR_TAB.TEST_SUITES && ( )}
))}
{selectedTab === MAPPING_EDITOR_TAB.CLASS_MAPPINGS && ( )} {selectedTab === MAPPING_EDITOR_TAB.TEST_SUITES && ( )} {mappingEditorState.migrationState && ( )}
); });