/** * 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 { type ElementDragSource, type UMLEditorElementDropTarget, CORE_DND_TYPE, useEditorStore, } from '@finos/legend-application-studio'; import { observer } from 'mobx-react-lite'; import { useDrop } from 'react-dnd'; import { DataSpaceEditorState } from '../stores/DataSpaceEditorState.js'; import { BlankPanelPlaceholder, clsx, ContextMenu, CustomSelectorInput, Dialog, ErrorIcon, ExclamationTriangleIcon, InputWithInlineValidation, LongArrowRightIcon, MenuContent, MenuContentItem, ModalTitle, PanelContent, PanelDropZone, PanelHeader, PanelHeaderActionItem, PanelHeaderActions, PlusIcon, PURE_MappingIcon, PURE_RuntimeIcon, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, } from '@finos/legend-art'; import { Mapping, PackageableElementExplicitReference, PackageableRuntime, validate_PureExecutionMapping, } from '@finos/legend-graph'; import { dataSpace_setExecutionContextDefaultRuntime, dataSpace_setExecutionContextMapping, dataSpace_setExecutionContextTitle, dataSpace_setExecutionContextDescription, } from '../stores/studio/DSL_DataSpace_GraphModifierHelper.js'; import { guaranteeNonNullable } from '@finos/legend-shared'; import { forwardRef, useCallback, useState } from 'react'; import type { DataSpaceExecutionContextState } from '../stores/DataSpaceExecutionContextState.js'; import type { DataSpaceExecutionContext } from '@finos/legend-extension-dsl-data-space/graph'; import { buildElementOption, type PackageableElementOption, } from '@finos/legend-lego/graph-editor'; import type { PropsValue } from 'react-select'; const DataSpaceExecutionContextConfigurationEditor = observer( (props: { executionContextState: DataSpaceExecutionContextState; executionContext: DataSpaceExecutionContext; }) => { const { executionContextState, executionContext } = props; const isReadOnly = executionContextState.dataSpaceEditorState.isReadOnly; const editorStore = executionContextState.editorStore; const applicationStore = editorStore.applicationStore; // Mapping // TODO: this is not generic error handling, as there could be other problems // with mapping, we need to genericize this const isMappingEmpty = validate_PureExecutionMapping( executionContext.mapping.value, ); const mapping = executionContext.mapping.value; const mappingOptions = editorStore.graphManagerState.usableMappings.map(buildElementOption); const noMappingLabel = (
(none)
); const selectedMappingOption = { value: mapping, label: isMappingEmpty ? noMappingLabel : mapping.path, } as PackageableElementOption; const onMappingSelectionChange = ( val: PackageableElementOption, ): void => { if (val.value !== mapping) { dataSpace_setExecutionContextMapping( executionContext, PackageableElementExplicitReference.create(val.value), ); executionContextState.autoSelectRuntimeOnMappingChange(val.value); } }; const visitMapping = (): void => editorStore.graphEditorMode.openElement(mapping); // Runtime const defaultRuntime = executionContext.defaultRuntime; // NOTE: for now, only include runtime associated with the mapping // TODO?: Should we bring the runtime compatibility check from query to here? const runtimes = editorStore.graphManagerState.graph.runtimes.filter((rt) => rt.runtimeValue.mappings.map((m) => m.value).includes(mapping), ); const runtimeOptions = runtimes.map((rt) => ({ label: rt.path, value: PackageableElementExplicitReference.create(rt), })); const runtimePointerWarning = !runtimes.includes(defaultRuntime.value) // if the runtime does not belong to the chosen mapping ? `runtime is not associated with specified mapping '${mapping.path}'` : undefined; const selectedRuntimeOption = { value: defaultRuntime, label: (
{defaultRuntime.value.path}
{runtimePointerWarning && (
)}
), } as unknown as PropsValue<{ label: string; value: PackageableElementExplicitReference; }>; const onRuntimeSelectionChange = (val: { label: string | React.ReactNode; value: | PackageableElementExplicitReference | undefined; }): void => { if ( val.value?.value !== defaultRuntime.value && val.value !== undefined ) { dataSpace_setExecutionContextDefaultRuntime( executionContext, val.value, ); } }; const visitRuntime = (): void => { editorStore.graphEditorMode.openElement(defaultRuntime.value); }; // DnD const handleMappingOrRuntimeDrop = useCallback( (item: UMLEditorElementDropTarget): void => { const element = item.data.packageableElement; if (!isReadOnly) { if (element instanceof Mapping) { dataSpace_setExecutionContextMapping( executionContext, PackageableElementExplicitReference.create(element), ); executionContextState.autoSelectRuntimeOnMappingChange(element); } else if ( element instanceof PackageableRuntime && element.runtimeValue.mappings.map((m) => m.value).includes(mapping) ) { dataSpace_setExecutionContextDefaultRuntime( executionContext, PackageableElementExplicitReference.create(element), ); } } }, [isReadOnly, mapping, executionContextState, executionContext], ); const [{ isMappingOrRuntimeDragOver }, dropConnector] = useDrop< ElementDragSource, void, { isMappingOrRuntimeDragOver: boolean } >( () => ({ accept: [ CORE_DND_TYPE.PROJECT_EXPLORER_MAPPING, CORE_DND_TYPE.PROJECT_EXPLORER_RUNTIME, ], drop: (item) => handleMappingOrRuntimeDrop(item), collect: (monitor) => ({ isMappingOrRuntimeDragOver: monitor.isOver({ shallow: true }), }), }), [handleMappingOrRuntimeDrop], ); return (
{/* Title input */}
Title
dataSpace_setExecutionContextTitle( executionContext, event.target.value, ) } />
{/* Description input */}
Description