/** * 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 { DataCube, FormButton, type DataCubeSettingValues, DataCubePlaceholder, DataCubeNativeMenuItem, DataCubePlaceholderErrorDisplay, type DataCubeMenuItem, DataCubeSpecification, DataCubeEvent, DataCubeTitleBarMenuItems, } from '@finos/legend-data-cube'; import { useLegendDataCubeBuilderStore, withLegendDataCubeBuilderStore, } from './LegendDataCubeBuilderStoreProvider.js'; import { useParams } from '@finos/legend-application/browser'; import { LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN, type LegendDataCubeBuilderPathParams, } from '../../__lib__/LegendDataCubeNavigation.js'; import { useEffect } from 'react'; import { LegendDataCubeSettingStorageKey } from '../../__lib__/LegendDataCubeSetting.js'; import type { LegendDataCubeBuilderStore } from '../../stores/builder/LegendDataCubeBuilderStore.js'; import { ReleaseViewer } from '@finos/legend-application'; import { isNonNullable } from '@finos/legend-shared'; import { LakehouseConsumerDataCubeSource } from '../../stores/model/LakehouseConsumerDataCubeSource.js'; import { LakehouseProducerDataCubeSource } from '../../stores/model/LakehouseProducerDataCubeSource.js'; import { useAuth, type AuthContextProps } from 'react-oidc-context'; const LegendDataCubeBuilderHeader = observer(() => { const store = useLegendDataCubeBuilderStore(); return (
{store.application.pluginManager .getApplicationPlugins() .map((plugin) => plugin.builderInnerHeaderRenderer?.(store.builder))}
store.loader.display.open()}> Load DataCube store.creator.display.open()} > New DataCube store.saverDisplay.open()} > Save DataCube
); }); export const LegendDataCubeReleaseLogManager = observer( (props: { showOnlyLatestNotes: boolean }) => { const { showOnlyLatestNotes } = props; const store = useLegendDataCubeBuilderStore(); let auth: AuthContextProps | undefined; try { auth = useAuth(); } catch { auth = undefined; } const applicationStore = store.application; const releaseService = applicationStore.releaseNotesService; const releaseNotes = (showOnlyLatestNotes ? releaseService.showableVersions() : releaseService.releaseNotes) ?? []; useEffect(() => { if (auth === undefined || auth.isAuthenticated) { applicationStore.releaseNotesService.updateViewedVersion(); } }, [applicationStore, auth, auth?.isAuthenticated]); return (
New features, enhancements and bug fixes that were released
{releaseNotes.map((e) => ( ))}
); }, ); export const LegendDataCubeAbout = observer(() => { const store = useLegendDataCubeBuilderStore(); const releaseService = store.application.releaseNotesService; const config = store.application.config; return (
Environment:
{config.env}
Version:
{config.appVersion}
Revision:
{config.appVersionCommitId}
Build Time:
{config.appVersionBuildTime}
{releaseService.isConfigured && (
store.releaseLogDisplay.open()} className="my-0.5 flex cursor-pointer font-bold text-sky-500 underline" >
Details of Released Versions
)}
Engine Server:
{config.engineServerUrl}
Depot Server:
{config.depotServerUrl}
{config.engineQueryServerUrl !== undefined && (
DataCube Server:
{config.engineQueryServerUrl}
)}
); }); function generateMenuItems(store: LegendDataCubeBuilderStore) { const application = store.application; const builder = store.builder; const persistentDataCube = builder?.persistentDataCube; const isLakehouseSource = store.builder?.source instanceof LakehouseConsumerDataCubeSource || store.builder?.source instanceof LakehouseProducerDataCubeSource; const logMenuItem = (menuName: string) => { store.engine.sendTelemetry(DataCubeEvent.SELECT_ITEM_TITLE_BAR, { ...store.engine.getDataFromSource( builder?.dataCube?.getProcessedSource(), ), menuName: menuName, }); }; const docLinks = application.documentationService.links; const menuItems: (DataCubeMenuItem | DataCubeNativeMenuItem)[] = builder ? [ ...(builder.source ? [ { label: DataCubeTitleBarMenuItems.VIEW_SOURCE, action: () => { const sourceViewerHeight = store.application.pluginManager .getApplicationPlugins() .map((plugin) => plugin.getSourceViewerHeight?.(store.builder), ) .filter(isNonNullable)[0] ?? 200; store.sourceViewerDisplay.configuration.window.height = Math.min(600, sourceViewerHeight); store.sourceViewerDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.VIEW_SOURCE); }, }, { label: DataCubeTitleBarMenuItems.EDIT_SOURCE_QUERY, action: () => { store.queryEditorDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.EDIT_SOURCE_QUERY); }, disabled: !isLakehouseSource, }, ] : []), ...(persistentDataCube ? [ { label: DataCubeTitleBarMenuItems.RESET_TO_LATEST_SAVE, action: () => { const latestSpecification = DataCubeSpecification.serialization.fromJson( persistentDataCube.content, ); builder.dataCube ?.applySpecification(latestSpecification) .catch((error) => store.alertService.alertUnhandledError(error), ); logMenuItem(DataCubeTitleBarMenuItems.VIEW_SOURCE); }, }, { label: DataCubeTitleBarMenuItems.EDIT_QUERY, action: () => { store.codeEditorDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.EDIT_QUERY); }, }, { label: DataCubeTitleBarMenuItems.UPDATE_INFO, action: () => { // effectively, we open the save window to let user update the DataCube info, such as name, auto-enable caching, etc. store.saverDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.UPDATE_INFO); }, disabled: !store.canCurrentUserManageDataCube(persistentDataCube), }, { label: DataCubeTitleBarMenuItems.DELETE_DATACUBE, action: () => { store.setDataCubeToDelete(builder.persistentDataCube); store.deleteConfirmationDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.DELETE_DATACUBE); }, disabled: !store.canCurrentUserManageDataCube(persistentDataCube), }, ] : []), ] : []; return [ ...(menuItems.length ? [...menuItems, DataCubeNativeMenuItem.SEPARATOR] : []), ...(docLinks?.length ? docLinks.map((link) => ({ label: link.label, action: () => { application.navigationService.navigator.visitAddress(link.url); }, disabled: !link.url, })) : [ { label: DataCubeTitleBarMenuItems.SEE_DOCUMENTATION, action: () => { const url = application.documentationService.url; if (url) { application.navigationService.navigator.visitAddress( application.documentationService.url, ); } logMenuItem(DataCubeTitleBarMenuItems.SEE_DOCUMENTATION); }, disabled: !application.documentationService.url, }, ]), { label: DataCubeTitleBarMenuItems.ABOUT, action: () => { store.aboutDisplay.open(); logMenuItem(DataCubeTitleBarMenuItems.ABOUT); }, }, ]; } export const LegendDataCubeBuilder = withLegendDataCubeBuilderStore( observer(() => { const store = useLegendDataCubeBuilderStore(); const builder = store.builder; const application = store.application; const params = useParams(); const dataCubeId = params[LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN.DATA_CUBE_ID]; let auth: AuthContextProps | undefined; try { auth = useAuth(); } catch { auth = undefined; } useEffect(() => { application.navigationService.navigator.blockNavigation( // Only block navigation in production, in development, we should have // the flexibility to reload the page quickly // eslint-disable-next-line no-process-env [() => process.env.NODE_ENV === 'production'], ); return (): void => { application.navigationService.navigator.unblockNavigation(); }; }, [application]); useEffect(() => { store .initialize() .catch((error) => store.alertService.alertUnhandledError(error)); return () => { store .cleanUp() .catch((error) => store.alertService.alertUnhandledError(error)); }; }, [store]); useEffect(() => { store .loadDataCube(dataCubeId) .catch((error) => store.alertService.alertUnhandledError(error)); }, [store, dataCubeId]); useEffect(() => { const releaseService = application.releaseNotesService; const releaseNotes = releaseService.showableVersions(); const isOpen = releaseService.showCurrentReleaseModal; if (releaseService.isConfigured && isOpen && releaseNotes?.length) { store.releaseNotesDisplay.open(); } else if (auth === undefined || auth.isAuthenticated) { releaseService.updateViewedVersion(); } }, [application, store, auth, auth?.isAuthenticated]); if (!store.initializeState.hasSucceeded) { return ( } menuItems={generateMenuItems(store)} > {store.initializeState.isInProgress && (
Initializing...
)} {store.initializeState.hasFailed && ( )}
); } if (!builder) { return ( } menuItems={generateMenuItems(store)} >
Create a new DataCube to start
store.creator.display.open()} > New DataCube
); } return ( , getHeaderMenuItems: () => generateMenuItems(store), settingsData: { configurations: store.baseStore.settings, values: application.settingService.getObjectValue( LegendDataCubeSettingStorageKey.DATA_CUBE, ) as DataCubeSettingValues | undefined, }, onSettingsChanged(event) { application.settingService.persistValue( LegendDataCubeSettingStorageKey.DATA_CUBE, event.values, ); }, enableCache: true, }} /> ); }), );