/** * 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 { observer } from 'mobx-react-lite'; import { useEditorStore } from '../../EditorStoreProvider.js'; import { Dialog, Modal, ModalBody, ModalFooter, ModalFooterButton, ModalHeader, ModalTitle, PanelContent, PanelHeader, PanelHeaderActions, EyeIcon, ModalHeaderActions, CustomSelectorInput, FlaskIcon, SQLIcon, clsx, PanelLoadingIndicator, CubeIcon, CaretDownIcon, ControlledDropdownMenu, MenuContent, MenuContentItem, } from '@finos/legend-art'; import { INGEST_DEFINITION_TAB, IngestDefinitionEditorState, } from '../../../../stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js'; import { CodeEditor } from '@finos/legend-lego/code-editor'; import React, { useEffect, useState } from 'react'; import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor'; import { flowResult } from 'mobx'; import { useApplicationNavigationContext } from '@finos/legend-application'; import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js'; import { LINEAGE_VIEW_MODE, LineageViewerContent, IngestionDefinitionArtifactViewer, } from '@finos/legend-query-builder'; import type { MatViewDataSet } from '@finos/legend-graph'; import { IngestTestableEditor } from './testable/IngestTestableEditor.js'; import { getIngestMaterializedViews } from '../../../../stores/graph-modifier/DSL_Ingest_GraphModifierHelper.js'; export const IngestLineageModal = observer( (props: { ingestDefinitionEditorState: IngestDefinitionEditorState }) => { const { ingestDefinitionEditorState } = props; const matviewFunctions = ingestDefinitionEditorState.ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS; const matviewNames = ingestDefinitionEditorState.ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS?.map( (dataset) => dataset.name, ) ?? []; const [selectedMatview, setSelectedMatview] = useState< MatViewDataSet | undefined >(undefined); useEffect(() => { if (!selectedMatview && matviewFunctions && matviewFunctions.length > 0) { setSelectedMatview(matviewFunctions[0]); } }, [matviewFunctions, selectedMatview]); useEffect(() => { ingestDefinitionEditorState.lineageState.setSelectedTab( LINEAGE_VIEW_MODE.DATABASE_LINEAGE, ); }, [ingestDefinitionEditorState.lineageState]); if (!matviewFunctions || matviewFunctions.length === 0) { return null; } const isDarkMode = !ingestDefinitionEditorState.lineageState.applicationStore.layoutService .TEMPORARY__isLightColorThemeEnabled; const closeLineageViewer = (): void => { ingestDefinitionEditorState.lineageState.setLineageData(undefined); ingestDefinitionEditorState.lineageState.setSelectedTab( LINEAGE_VIEW_MODE.DATABASE_LINEAGE, ); ingestDefinitionEditorState.lineageState.clearPropertySelections(); }; type DatasetOption = { label: string; value: MatViewDataSet; }; const datasetOptions: DatasetOption[] = matviewNames .map((name, index) => { const dataset = matviewFunctions[index]; if (dataset) { return { label: name, value: dataset, }; } return null; }) .filter((option): option is DatasetOption => option !== null); const handleDatasetChange = (option: DatasetOption | null): void => { if (option?.value) { setSelectedMatview(option.value); flowResult( ingestDefinitionEditorState.generateLineage(option.value), ).catch( ingestDefinitionEditorState.editorStore.applicationStore .alertUnhandledError, ); } }; return ( <>
); }, ); export const IngestDefinitionEditor = observer(() => { const editorStore = useEditorStore(); const ingestDefinitionEditorState = editorStore.tabManagerState.getCurrentEditorState( IngestDefinitionEditorState, ); const ingestDef = ingestDefinitionEditorState.ingest; // the views Cube can open to edit (Edit MatView, PLAN ยง11.18) const materializedViews = getIngestMaterializedViews(ingestDef); const isValidForLineage = ingestDefinitionEditorState.validForLineageViewer; const selectedTab = ingestDefinitionEditorState.selectedTab; const sidebarTabs = [ { label: INGEST_DEFINITION_TAB.DEFINITION, icon: , }, { label: INGEST_DEFINITION_TAB.TESTING, icon: , }, ]; useEffect(() => { ingestDefinitionEditorState.generateElementGrammar(); }, [ingestDefinitionEditorState]); useApplicationNavigationContext( LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.INGEST_DEFINITION_EDITOR, ); const viewLineage = () => { const firstMatViewQuery = ingestDefinitionEditorState.ingest .TEMPORARY_MATVIEW_FUNCTION_DATA_SETS?.[0]; if (firstMatViewQuery) { flowResult( ingestDefinitionEditorState.generateLineage(firstMatViewQuery), ).catch(editorStore.applicationStore.alertUnhandledError); } else { editorStore.applicationStore.notificationService.notifyError( 'No MatView datasets available for lineage generation', ); } }; const viewSQL = () => { if ( ingestDefinitionEditorState.ingest.TEMPORARY_MATVIEW_FUNCTION_DATA_SETS ?.length ) { flowResult(ingestDefinitionEditorState.generateArtifact()).catch( editorStore.applicationStore.alertUnhandledError, ); } else { editorStore.applicationStore.notificationService.notifyError( 'No MatView datasets available for artifact generation', ); } }; return (
{sidebarTabs.map((activity) => ( ))}
{selectedTab === INGEST_DEFINITION_TAB.DEFINITION && (
{isValidForLineage && (
)} {/* sized to its label, longer than the other buttons' */}
{materializedViews.length > 0 && ( {materializedViews.map(({ name }) => ( editorStore.embeddedCubeState.open( ingestDef, name, ) } > {`Edit MatView ${name}`} ))} } menuProps={{ anchorOrigin: { vertical: 'bottom', horizontal: 'right', }, transformOrigin: { vertical: 'top', horizontal: 'right', }, }} > )}
ingestDefinitionEditorState.setIngestionArtifact(undefined) } darkMode={ !editorStore.applicationStore.layoutService .TEMPORARY__isLightColorThemeEnabled } />
)} {selectedTab === INGEST_DEFINITION_TAB.TESTING && ( )}
); });