@finos/legend-application-studio
Version:
Legend Studio application core
437 lines • 36.6 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 { useState, useEffect, useCallback, forwardRef } from 'react';
import { observer } from 'mobx-react-lite';
import { LakehouseRuntimeEditorState, PackageableRuntimeEditorState, RuntimeEditorRuntimeTabState, IdentifiedConnectionsEditorTabState, IdentifiedConnectionsPerClassEditorTabState, IdentifiedConnectionsPerStoreEditorTabState, LakehouseRuntimeType, } from '../../../stores/editor/editor-state/element-editor-state/RuntimeEditorState.js';
import { clsx, Dialog, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, TreeView, ContextMenu, CustomSelectorInput, createFilter, BlankPanelContent, MenuContent, MenuContentItem, BlankPanelPlaceholder, PURE_RuntimeIcon, PURE_ConnectionIcon, PURE_ModelStoreIcon, PURE_ClassIcon, PURE_MappingIcon, ChevronDownIcon, ChevronRightIcon, PlusIcon, TimesIcon, LongArrowRightIcon, CogIcon, CaretRightIcon, PanelDropZone, Panel, PanelContent, PanelHeader, ModalHeader, ModalTitle, ModalHeaderActions, ModalBody, Modal, PanelHeaderActions, PanelHeaderActionItem, LockIcon, PanelFormTextField, PanelFormSection, } from '@finos/legend-art';
import { getElementIcon } from '../../ElementIconUtils.js';
import { ConnectionEditor } from './connection-editor/ConnectionEditor.js';
import { CORE_DND_TYPE, ElementDragSource, } from '../../../stores/editor/utils/DnDUtils.js';
import { useDrop } from 'react-dnd';
import { assertErrorThrown, prettyCONSTName } from '@finos/legend-shared';
import { useEditorStore } from '../EditorStoreProvider.js';
import { Connection, ConnectionPointer, Runtime, IdentifiedConnection, RuntimePointer, ModelStore, Mapping, Class, Store, PackageableConnection, JsonModelConnection, XmlModelConnection, FlatDataConnection, RelationalDatabaseConnection, PackageableElementExplicitReference, ModelChainConnection, generateIdentifiedConnectionId, } from '@finos/legend-graph';
import { useApplicationNavigationContext, useApplicationStore, } from '@finos/legend-application';
import { buildElementOption, } from '@finos/legend-lego/graph-editor';
import { runtime_addIdentifiedConnection, runtime_deleteIdentifiedConnection, } from '../../../stores/graph-modifier/DSL_Mapping_GraphModifierHelper.js';
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../__lib__/LegendStudioApplicationNavigationContext.js';
import { CUSTOM_LABEL } from '../../../stores/editor/NewElementState.js';
import { lakehouseRuntime_setWarehouse } from '../../../stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.js';
import { useAuth } from 'react-oidc-context';
import { flowResult } from 'mobx';
const getConnectionTooltipText = (connection, editorStore) => {
const connectionValue = connection instanceof ConnectionPointer
? connection.packageableConnection.value.connectionValue
: connection;
if (connectionValue instanceof JsonModelConnection) {
return `JSON model connection \u2022 Class ${connectionValue.class.value.path}`;
}
else if (connectionValue instanceof XmlModelConnection) {
return `XML model connection \u2022 Class ${connectionValue.class.value.path}`;
}
else if (connectionValue instanceof FlatDataConnection) {
return `Flat-data connection \u2022 Flat-data store ${connectionValue.store.value.path}`;
}
else if (connectionValue instanceof RelationalDatabaseConnection) {
return connectionValue.store
? `Relational database connection \u2020 database store ${connectionValue.store.value.path}`
: `Relational database connection`;
}
else if (connectionValue instanceof ModelChainConnection) {
return `Model chain connection \u2022`;
}
const extraConnectionToolTipTexts = editorStore.pluginManager
.getApplicationPlugins()
.flatMap((plugin) => plugin.getExtraRuntimeConnectionTooltipTextBuilders?.() ?? []);
for (const builder of extraConnectionToolTipTexts) {
const tooltipText = builder(connectionValue);
if (tooltipText) {
return tooltipText;
}
}
return `Unknown connection`;
};
const IdentifiedConnectionsPerStoreExplorerContextMenu = observer(forwardRef(function IdentifiedConnectionsPerStoreExplorerContextMenu(props, ref) {
const { identifiedConnection, deleteIdentifiedConnection, createNewIdentifiedConnection, } = props;
const remove = () => deleteIdentifiedConnection?.();
return (_jsxs(MenuContent, { ref: ref, children: [identifiedConnection && (_jsx(MenuContentItem, { onClick: remove, children: "Remove" })), !identifiedConnection && (_jsx(MenuContentItem, { onClick: createNewIdentifiedConnection, children: "Create a new connection for store" }))] }));
}));
export const IdentifiedConnectionsPerStoreExplorerItem = observer((props) => {
const { identifiedConnection, currentRuntimeEditorTabState, isActive, isReadOnly, } = props;
const editorStore = useEditorStore();
const openConnection = () => currentRuntimeEditorTabState.openIdentifiedConnection(identifiedConnection);
const deleteConnection = () => currentRuntimeEditorTabState.deleteIdentifiedConnection(identifiedConnection);
const openNewConnectionModal = () => currentRuntimeEditorTabState.addIdentifiedConnection();
// context menu
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false);
const onContextMenuOpen = () => setIsSelectedFromContextMenu(true);
const onContextMenuClose = () => setIsSelectedFromContextMenu(false);
return (_jsx(ContextMenu, { className: clsx('runtime-explorer__item', {
'context-menu__trigger--on-menu-open': !isActive && isSelectedFromContextMenu,
}, { 'runtime-explorer__item--active': isActive }), disabled: isReadOnly, content: _jsx(IdentifiedConnectionsPerStoreExplorerContextMenu, { identifiedConnection: identifiedConnection, deleteIdentifiedConnection: deleteConnection, createNewIdentifiedConnection: openNewConnectionModal }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("button", { className: "runtime-explorer__item__label runtime-explorer__item__label--simple", onClick: openConnection, tabIndex: -1, title: getConnectionTooltipText(identifiedConnection.connection, editorStore), children: [_jsx("div", { className: "runtime-explorer__item__label__icon", children: _jsx(PURE_ConnectionIcon, {}) }), _jsx("div", { className: "runtime-explorer__item__label__text", children: identifiedConnection.id })] }) }));
});
const getRuntimeExplorerTreeNodeIcon = (editorStore, node) => {
if (node.data instanceof Runtime) {
return _jsx(PURE_RuntimeIcon, {});
}
else if (node.data instanceof ModelStore) {
return _jsx(PURE_ModelStoreIcon, {});
}
else if (node.data instanceof Connection) {
return _jsx(PURE_ConnectionIcon, {});
}
return getElementIcon(node.data, editorStore);
};
const getRuntimeExplorerTreeNodeTooltipText = (node) => {
if (node.data instanceof Runtime) {
return ''; // number of mapping and stores
}
else if (node.data instanceof ModelStore) {
return '';
}
else if (node.data instanceof Store) {
/* do nothing */
}
else if (node.data instanceof Class) {
// return `JSON model connection \u2022 Class ${connectionValue.class.path}`;
}
return undefined;
};
const RuntimeExplorerTreeNodeContainer = observer((props) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { runtimeEditorState, onNodeExpand } = innerProps;
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const editorStore = useEditorStore();
const isExpandable = Boolean(node.childrenIds?.length);
const nodeExpandIcon = isExpandable ? (node.isOpen ? (_jsx(ChevronDownIcon, {})) : (_jsx(ChevronRightIcon, {}))) : (_jsx("div", {}));
const selectNode = () => onNodeSelect?.(node);
const onExpandIconClick = () => onNodeExpand(node);
// Selection
const isActive = engineEditorState.isTreeNodeSelected(node);
return (_jsx("div", { className: clsx('tree-view__node__container runtime-explorer__tree__node__container', { 'runtime-explorer__item--active': isActive }), onClick: selectNode, style: {
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1) + 0.5}rem`,
display: 'flex',
}, children: _jsxs("button", { className: "runtime-explorer__item__label", tabIndex: -1, title: getRuntimeExplorerTreeNodeTooltipText(node), children: [_jsx("div", { className: "tree-view__node__expand-icon", onClick: onExpandIconClick, children: nodeExpandIcon }), _jsx("div", { className: "runtime-explorer__item__label__icon", children: getRuntimeExplorerTreeNodeIcon(editorStore, node) }), node.data instanceof Runtime && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "runtime-explorer__item__label__text", children: [node.label, " ~"] }), _jsx("div", { className: "runtime-explorer__item__label__runtime__mapping__icon", children: _jsx(PURE_MappingIcon, {}) }), _jsx("div", { className: "runtime-explorer__item__label__runtime__mapping__text", children: engineEditorState.runtimeValue.mappings.length
? engineEditorState.runtimeValue
.mappings[0].value.name
: '(no mapping)' })] })), node.data instanceof Store && (_jsx("div", { className: "runtime-explorer__item__label__text", children: node.label })), node.data instanceof Class && (_jsx("div", { className: "runtime-explorer__item__label__text", children: node.label }))] }) }));
});
const RuntimeExplorer = observer((props) => {
const { runtimeEditorState, isReadOnly } = props;
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const runtime = runtimeEditorState.runtime;
const runtimeValue = engineEditorState.runtimeValue;
const runtimeName = runtime instanceof RuntimePointer
? runtime.packageableRuntime.value.name
: CUSTOM_LABEL;
// explorer tree data
const treeData = engineEditorState.explorerTreeData;
const onNodeSelect = (node) => engineEditorState.onExplorerTreeNodeSelect(node);
const onNodeExpand = (node) => engineEditorState.onExplorerTreeNodeExpand(node);
const getTreeChildNodes = (node) => engineEditorState.getExplorerTreeChildNodes(node);
// DnD
const handleDropRuntimeSubElement = useCallback((item) => {
const element = item.data.packageableElement;
if (!isReadOnly) {
if (element instanceof PackageableConnection) {
engineEditorState.addIdentifiedConnection(new IdentifiedConnection(generateIdentifiedConnectionId(runtimeValue), new ConnectionPointer(PackageableElementExplicitReference.create(element))));
}
else if (element instanceof Mapping) {
engineEditorState.addMapping(element);
}
}
}, [engineEditorState, isReadOnly, runtimeValue]);
const [{ isRuntimeSubElementDragOver }, dropConnector] = useDrop(() => ({
accept: [
CORE_DND_TYPE.PROJECT_EXPLORER_CONNECTION,
CORE_DND_TYPE.PROJECT_EXPLORER_MAPPING,
],
drop: (item) => handleDropRuntimeSubElement(item),
collect: (monitor) => ({
isRuntimeSubElementDragOver: monitor.isOver({ shallow: true }),
}),
}), [handleDropRuntimeSubElement]);
useEffect(() => {
engineEditorState.decorateRuntimeConnections();
engineEditorState.reprocessCurrentTabState();
engineEditorState.reprocessRuntimeExplorerTree();
return () => engineEditorState.cleanUpDecoration();
}, [engineEditorState, runtimeEditorState]);
return (_jsxs(Panel, { className: "runtime-explorer", children: [_jsx(PanelHeader, { title: "runtime", children: _jsx("div", { className: "panel__header__title__content", children: runtimeName }) }), _jsx(PanelContent, { children: _jsx(PanelDropZone, { dropTargetConnector: dropConnector, isDragOver: isRuntimeSubElementDragOver, children: _jsx("div", { className: "panel__content__list", children: _jsx(TreeView, { components: {
TreeNodeContainer: RuntimeExplorerTreeNodeContainer,
}, treeData: treeData, onNodeSelect: onNodeSelect, getChildNodes: getTreeChildNodes, innerProps: {
isReadOnly,
runtimeEditorState,
onNodeExpand,
} }) }) }) })] }));
});
const IdentifiedConnectionEditor = observer((props) => {
const { runtimeEditorState, currentRuntimeEditorTabState, connectionEditorState, identifiedConnection, isReadOnly, } = props;
const applicationStore = useApplicationStore();
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const runtimeValue = engineEditorState.runtimeValue;
// TODO: add runtime connection ID
// connection pointer
const isEmbeddedConnection = !(identifiedConnection.connection instanceof ConnectionPointer);
const embeddedConnectionLabel = (_jsxs("div", { className: "runtime-connection-editor__connection-option--custom", children: [_jsx(CogIcon, {}), _jsx("div", { className: "runtime-connection-editor__connection-option--custom__label", children: CUSTOM_LABEL })] }));
// only show custom connnection option when a connnection pointer is currently selected
let connectionOptions = isEmbeddedConnection
? []
: [{ label: embeddedConnectionLabel }];
connectionOptions = connectionOptions.concat(currentRuntimeEditorTabState.packageableConnections.map((packageableConnection) => ({
label: packageableConnection.path,
value: packageableConnection,
})));
const selectedConnectionOption = identifiedConnection.connection instanceof ConnectionPointer
? {
value: identifiedConnection.connection.packageableConnection.value,
label: isEmbeddedConnection
? embeddedConnectionLabel
: identifiedConnection.connection.packageableConnection.value
.path,
}
: null;
const editorStore = useEditorStore();
const onConnectionSelectionChange = (val) => {
if (val.value === undefined) {
let customConnection;
try {
customConnection =
currentRuntimeEditorTabState.createDefaultConnection();
}
catch (error) {
assertErrorThrown(error);
applicationStore.notificationService.notifyWarning(error.message);
return;
}
const newIdentifiedConnection = new IdentifiedConnection(generateIdentifiedConnectionId(runtimeValue), customConnection);
runtime_addIdentifiedConnection(runtimeValue, newIdentifiedConnection, editorStore.changeDetectionState.observerContext);
runtime_deleteIdentifiedConnection(runtimeValue, identifiedConnection);
currentRuntimeEditorTabState.openIdentifiedConnection(newIdentifiedConnection);
}
else if (val.value instanceof PackageableConnection &&
(!(identifiedConnection.connection instanceof ConnectionPointer) ||
val.value !==
identifiedConnection.connection.packageableConnection.value)) {
const connectionPointer = new ConnectionPointer(PackageableElementExplicitReference.create(val.value));
const newIdentifiedConnection = new IdentifiedConnection(generateIdentifiedConnectionId(runtimeValue), connectionPointer);
runtime_addIdentifiedConnection(runtimeValue, newIdentifiedConnection, editorStore.changeDetectionState.observerContext);
runtime_deleteIdentifiedConnection(runtimeValue, identifiedConnection);
currentRuntimeEditorTabState.openIdentifiedConnection(newIdentifiedConnection);
}
};
const visitConnection = () => {
if (identifiedConnection.connection instanceof ConnectionPointer) {
editorStore.graphEditorMode.openElement(identifiedConnection.connection.packageableConnection.value);
}
};
return (_jsxs("div", { className: "runtime-connection-editor", children: [_jsxs("div", { className: "panel runtime-connection-editor__pointer", children: [_jsx(PanelHeader, { title: "runtime connection" }), _jsx(PanelContent, { children: _jsxs("div", { className: "runtime-connection-editor__connection-option", children: [_jsx("div", { className: "runtime-connection-editor__connection-option__label", children: _jsx(PURE_ConnectionIcon, {}) }), _jsx(CustomSelectorInput, { className: "panel__content__form__section__dropdown", disabled: isReadOnly, options: connectionOptions, onChange: onConnectionSelectionChange, value: selectedConnectionOption, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled }), !isEmbeddedConnection && (_jsx("button", { className: "btn--dark btn--sm runtime-connection-editor__connection-option__visit-btn", onClick: visitConnection, tabIndex: -1, title: "See connection", children: _jsx(LongArrowRightIcon, {}) }))] }) })] }), _jsx("div", { className: "runtime-connection-editor__embedded", children: _jsx(ConnectionEditor, { connectionEditorState: connectionEditorState, disableChangingStore: true, isReadOnly: isReadOnly }) })] }));
});
const IdentifiedConnectionsPerStoreEditor = observer((props) => {
const { isReadOnly, currentRuntimeEditorTabState, runtimeEditorState } = props;
const isEmbeddedRuntime = runtimeEditorState.isEmbeddedRuntime;
const connectionEditorState = currentRuntimeEditorTabState.getConnectionEditorState();
const identifiedConnection = currentRuntimeEditorTabState.identifiedConnectionEditorState
?.idenfitiedConnection;
// explorer
const addNewConnection = () => currentRuntimeEditorTabState.addIdentifiedConnection();
// DnD
const handleDropConnection = useCallback((item) => {
const element = item.data.packageableElement;
if (!isReadOnly &&
element instanceof PackageableConnection &&
currentRuntimeEditorTabState.packageableConnections.includes(element)) {
currentRuntimeEditorTabState.addIdentifiedConnection(element);
}
}, [currentRuntimeEditorTabState, isReadOnly]);
const [{ isConnectionDragOver, dragItem }, dropConnector] = useDrop(() => ({
accept: [CORE_DND_TYPE.PROJECT_EXPLORER_CONNECTION],
drop: (item) => handleDropConnection(item),
collect: (monitor) => ({
isConnectionDragOver: monitor.isOver({ shallow: true }),
dragItem: monitor.getItem(),
}),
}), [handleDropConnection]);
const canDropConnection = !isReadOnly &&
dragItem instanceof ElementDragSource &&
dragItem.data.packageableElement instanceof PackageableConnection &&
currentRuntimeEditorTabState.packageableConnections.includes(dragItem.data.packageableElement);
return (_jsx("div", { className: "runtime-store-connections-editor", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 300, minSize: 300, children: _jsxs(Panel, { className: "runtime-explorer", children: [_jsxs(PanelHeader, { children: [currentRuntimeEditorTabState instanceof
IdentifiedConnectionsPerStoreEditorTabState && (_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "store" }), _jsx("div", { className: "panel__header__title__content", children: currentRuntimeEditorTabState.store.name })] })), currentRuntimeEditorTabState instanceof
IdentifiedConnectionsPerClassEditorTabState && (_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "store" }), _jsx("div", { className: "panel__header__title__content", children: "ModelStore" }), _jsx("div", { className: "runtime-store-connections-editor__model-store__arrow-icon", children: _jsx(CaretRightIcon, {}) }), _jsx("div", { className: "runtime-store-connections-editor__model-store__class-icon", children: _jsx(PURE_ClassIcon, {}) }), _jsx("div", { className: "runtime-store-connections-editor__model-store__class-name", children: currentRuntimeEditorTabState.class.name })] })), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { disabled: isReadOnly, onClick: addNewConnection, title: "Add Connection...", children: _jsx(PlusIcon, {}) }) })] }), _jsx(ContextMenu, { className: "panel__content", disabled: isReadOnly, content: _jsx(IdentifiedConnectionsPerStoreExplorerContextMenu, { createNewIdentifiedConnection: addNewConnection }), menuProps: { elevation: 7 }, children: _jsxs(PanelDropZone, { dropTargetConnector: dropConnector, isDragOver: isConnectionDragOver, children: [Boolean(currentRuntimeEditorTabState.identifiedConnections.length) && (_jsx("div", { className: "panel__content__list", children: currentRuntimeEditorTabState.identifiedConnections.map((rtConnection) => (_jsx(IdentifiedConnectionsPerStoreExplorerItem, { identifiedConnection: rtConnection, currentRuntimeEditorTabState: currentRuntimeEditorTabState, isActive: rtConnection === identifiedConnection, isReadOnly: isReadOnly }, rtConnection._UUID))) })), !currentRuntimeEditorTabState.identifiedConnections
.length && (_jsx(BlankPanelPlaceholder, { text: "Add a connection", onClick: addNewConnection, clickActionType: "add", tooltipText: "Drop a connection to add it to the list, or click to add an embedded connection", isDropZoneActive: isEmbeddedRuntime ? undefined : canDropConnection, disabled: isReadOnly, previewText: "No connection" }))] }) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsxs(ResizablePanel, { children: [connectionEditorState && identifiedConnection && (_jsx(IdentifiedConnectionEditor, { runtimeEditorState: runtimeEditorState, currentRuntimeEditorTabState: currentRuntimeEditorTabState, connectionEditorState: connectionEditorState, identifiedConnection: identifiedConnection, isReadOnly: isReadOnly })), (!connectionEditorState || !identifiedConnection) && (_jsxs(Panel, { children: [_jsx(PanelHeader, { title: "runtime connection" }), _jsx(PanelContent, { children: _jsx(BlankPanelContent, { children: "No connection selected" }) })] }))] })] }) }));
});
const RuntimeMappingEditor = observer((props) => {
const { runtimeEditorState, mappingRef, isReadOnly } = props;
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const editorStore = useEditorStore();
const applicationStore = editorStore.applicationStore;
const runtimeValue = engineEditorState.runtimeValue;
const mappingOptions = editorStore.graphManagerState.graph.ownMappings
.filter((m) => !runtimeValue.mappings.map((_m) => _m.value).includes(m))
.map(buildElementOption);
const filterOption = createFilter({
ignoreCase: true,
ignoreAccents: false,
stringify: (option) => option.data.value.path,
});
const selectedMappingOption = {
value: mappingRef.value,
label: mappingRef.value.name,
};
const changeMapping = (val) => engineEditorState.changeMapping(mappingRef, val.value);
const deleteMapping = () => engineEditorState.deleteMapping(mappingRef);
const visitMapping = () => editorStore.graphEditorMode.openElement(mappingRef.value);
return (_jsxs("div", { className: "panel__content__form__section__list__item--customized runtime-mapping-editor", children: [_jsx(CustomSelectorInput, { className: "runtime-mapping-editor__mapping", disabled: isReadOnly, options: mappingOptions, onChange: changeMapping, value: selectedMappingOption, placeholder: "Choose a class", filterOption: filterOption, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }), _jsx("button", { className: "btn--dark btn__icon--dark", onClick: visitMapping, tabIndex: -1, title: "Visit Mapping", children: _jsx(LongArrowRightIcon, {}) }), !isReadOnly && (_jsx("button", { className: "btn--dark btn__icon--dark btn--caution", disabled: runtimeValue.mappings.length < 2, onClick: deleteMapping, tabIndex: -1, title: "Remove", children: _jsx(TimesIcon, {}) }))] }));
});
const RuntimeGeneralEditor = observer((props) => {
const { runtimeEditorState, isReadOnly } = props;
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const editorStore = useEditorStore();
const runtime = runtimeEditorState.runtime;
const runtimeValue = engineEditorState.runtimeValue;
const isRuntimeEmbedded = !(runtime instanceof RuntimePointer);
// mappings
const mappings = editorStore.graphManagerState.graph.ownMappings.filter((mapping) => !runtimeValue.mappings.map((m) => m.value).includes(mapping));
const allowAddingMapping = !isReadOnly && Boolean(mappings.length);
const addMapping = () => {
if (allowAddingMapping) {
engineEditorState.addMapping(mappings[0]);
}
};
const handleDropMapping = useCallback((item) => {
const element = item.data.packageableElement;
if (!isReadOnly &&
// Have to be a mapping
element instanceof Mapping &&
// Must not be an already specified mapping
!runtimeValue.mappings.map((m) => m.value).includes(element)) {
engineEditorState.addMapping(element);
}
}, [engineEditorState, isReadOnly, runtimeValue.mappings]);
const [{ isMappingDragOver }, dropConnector] = useDrop(() => ({
accept: [CORE_DND_TYPE.PROJECT_EXPLORER_MAPPING],
drop: (item) => handleDropMapping(item),
collect: (monitor) => ({
isMappingDragOver: monitor.isOver({ shallow: true }),
}),
}), [handleDropMapping]);
return (_jsxs("div", { className: "panel runtime-explorer", children: [_jsx(PanelHeader, {}), _jsx(PanelContent, { children: _jsx(PanelDropZone, { dropTargetConnector: dropConnector, isDragOver: isMappingDragOver && !isReadOnly, children: _jsx("div", { className: "panel__content__form", children: _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Mappings" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "Specifies the list of mappings covered by this runtime" }), _jsxs("div", { className: "panel__content__form__section__list", children: [runtimeValue.mappings.map((mappingRef) => (_jsx(RuntimeMappingEditor, { runtimeEditorState: runtimeEditorState, mappingRef: mappingRef, isReadOnly: isReadOnly || isRuntimeEmbedded }, mappingRef.value._UUID))), !isRuntimeEmbedded && (_jsx("div", { className: "panel__content__form__section__list__new-item__add", children: _jsx("button", { className: "panel__content__form__section__list__new-item__add-btn btn btn--dark", disabled: !allowAddingMapping, tabIndex: -1, onClick: addMapping, title: "Add Mapping", children: "Add Value" }) }))] })] }) }) }) })] }));
});
const RuntimeEditorPanel = observer((props) => {
const { runtimeEditorState, isReadOnly } = props;
const engineEditorState = runtimeEditorState.runtimeValueEditorState;
const currentRuntimeEditorTabState = engineEditorState.currentTabState;
if (currentRuntimeEditorTabState instanceof
IdentifiedConnectionsEditorTabState) {
return (_jsx(IdentifiedConnectionsPerStoreEditor, { runtimeEditorState: runtimeEditorState, currentRuntimeEditorTabState: currentRuntimeEditorTabState, isReadOnly: isReadOnly }, runtimeEditorState.uuid));
}
else if (currentRuntimeEditorTabState instanceof RuntimeEditorRuntimeTabState) {
return (_jsx(RuntimeGeneralEditor, { runtimeEditorState: runtimeEditorState, runtimeEditorTabState: currentRuntimeEditorTabState, isReadOnly: isReadOnly }, runtimeEditorState.uuid));
}
return _jsx("div", {}); // no need for splash screen since will always show at least a tab
});
export const RuntimeEditor = observer((props) => {
const { runtimeEditorState, isReadOnly } = props;
return (_jsx("div", { className: "runtime-editor", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 300, minSize: 300, children: _jsx(RuntimeExplorer, { runtimeEditorState: runtimeEditorState, isReadOnly: isReadOnly }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: _jsx(RuntimeEditorPanel, { runtimeEditorState: runtimeEditorState, isReadOnly: isReadOnly }) })] }) }));
});
export const LakehouseRuntimeEditor = observer((props) => {
const { runtimeEditorState, lakehouseRuntimeEditorState, isReadOnly } = props;
const editorStore = runtimeEditorState.editorStore;
const auth = useAuth();
const applicationStore = editorStore.applicationStore;
const lakehouseRuntime = lakehouseRuntimeEditorState.runtimeValue;
// type
const typeOptions = Object.values(LakehouseRuntimeType).map((type) => ({
label: prettyCONSTName(type),
value: type,
}));
const selectedType = {
label: prettyCONSTName(lakehouseRuntimeEditorState.lakehouseRuntimeType),
value: lakehouseRuntimeEditorState.lakehouseRuntimeType,
};
const onTypeChange = (val) => {
if (val.value !== lakehouseRuntimeEditorState.lakehouseRuntimeType) {
lakehouseRuntimeEditorState.setLakehouseRuntimeType(val.value);
}
};
const environmentOptions = lakehouseRuntimeEditorState.envOptions;
const onEnvironmentSelectionChange = (val) => {
if (!val) {
lakehouseRuntime.environment = undefined;
return;
}
if (val.value !== lakehouseRuntime.environment) {
lakehouseRuntime.environment = val.value;
}
};
const handleWarehouseChange = (val) => {
lakehouseRuntime_setWarehouse(lakehouseRuntime, val);
};
const selectedEnvironmentOption = lakehouseRuntime.environment
? {
label: lakehouseRuntime.environment,
value: lakehouseRuntime.environment,
}
: null;
const connection = lakehouseRuntime.connectionPointer?.packageableConnection.value;
const connectionOptions = editorStore.graphManagerState.usableConnections.map(buildElementOption);
const selectedConnectionOption = connection
? { label: connection.path, value: connection }
: null;
const onConnectionSelectionChange = (val) => {
if (val.value !== connection) {
lakehouseRuntime.connectionPointer = new ConnectionPointer(PackageableElementExplicitReference.create(val.value));
}
};
useEffect(() => {
flowResult(lakehouseRuntimeEditorState.fetchLakehouseSummaries(auth.user?.access_token)).catch(applicationStore.alertUnhandledError);
}, [
applicationStore.alertUnhandledError,
auth.user?.access_token,
lakehouseRuntimeEditorState,
]);
return (_jsx(_Fragment, { children: _jsx("div", { className: "data-product-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: "lakehouse runtime" })] }) }), _jsxs("div", { className: "panel", style: { padding: '1rem', flex: 0 }, children: [_jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Lakehouse Runtime Source" }), _jsx("div", { className: "explorer__new-element-modal__driver", children: _jsx(CustomSelectorInput, { className: "explorer__new-element-modal__driver__dropdown", options: typeOptions, onChange: onTypeChange, value: selectedType, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled }) })] }), lakehouseRuntimeEditorState.lakehouseRuntimeType ===
LakehouseRuntimeType.ENVIRONMENT ? (_jsxs(_Fragment, { children: [_jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Environment" }), _jsx("div", { className: "explorer__new-element-modal__driver", children: _jsx(CustomSelectorInput, { className: "explorer__new-element-modal__driver__dropdown", options: environmentOptions, onChange: onEnvironmentSelectionChange, value: selectedEnvironmentOption, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled }) })] }), _jsx(PanelFormTextField, { name: "Warehouse", value: lakehouseRuntime.warehouse, prompt: "Provide the warehouse", update: handleWarehouseChange, placeholder: "Enter warehouse" })] })) : (_jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Connection" }), _jsx("div", { className: "explorer__new-element-modal__driver", children: _jsx(CustomSelectorInput, { className: "explorer__new-element-modal__driver__dropdown", options: connectionOptions, onChange: onConnectionSelectionChange, value: selectedConnectionOption, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled }) })] }))] })] }) }) }));
});
export const PackageableRuntimeEditor = observer(() => {
const editorStore = useEditorStore();
const editorState = editorStore.tabManagerState.getCurrentEditorState(PackageableRuntimeEditorState);
const isReadOnly = editorState.isReadOnly;
const runtimeEditorState = editorState.runtimeEditorState;
const engineState = runtimeEditorState.runtimeValueEditorState;
useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.RUNTIME_EDITOR);
return engineState instanceof LakehouseRuntimeEditorState ? (_jsx(LakehouseRuntimeEditor, { lakehouseRuntimeEditorState: engineState, isReadOnly: isReadOnly, runtimeEditorState: editorState.runtimeEditorState })) : (_jsx(RuntimeEditor, { runtimeEditorState: editorState.runtimeEditorState, isReadOnly: isReadOnly }));
});
export const EmbeddedRuntimeEditor = observer((props) => {
const { runtimeEditorState, onClose, isReadOnly } = props;
const applicationStore = useApplicationStore();
const closeEditor = () => onClose();
if (!runtimeEditorState) {
return null;
}
return (_jsx(Dialog, { open: Boolean(runtimeEditorState), onClose: closeEditor, classes: {
root: 'editor-modal__root-container',
container: 'editor-modal__container',
paper: 'editor-modal__content',
}, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled, className: "editor-modal embedded-runtime-editor", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { icon: _jsx(CogIcon, {}), title: "custom runtime" }), _jsx(ModalHeaderActions, { children: _jsx("button", { className: "modal__header__action", tabIndex: -1, onClick: closeEditor, children: _jsx(TimesIcon, {}) }) })] }), _jsx(ModalBody, { className: "modal__body--footless", children: _jsx(RuntimeEditor, { runtimeEditorState: runtimeEditorState, isReadOnly: isReadOnly }) })] }) }));
});
//# sourceMappingURL=RuntimeEditor.js.map