UNPKG

@finos/legend-application-marketplace

Version:
962 lines (923 loc) 37.5 kB
/** * 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 NavigationZone, DEFAULT_TAB_SIZE, EXTERNAL_APPLICATION_NAVIGATION__generateStudioProjectViewUrl, EXTERNAL_APPLICATION_NAVIGATION__generateNewDataCubeUrl, EXTERNAL_APPLICATION_NAVIGATION__generateRegistryLineageUrl, EXTERNAL_APPLICATION_NAVIGATION__generateRegistryGovernanceUrl, } from '@finos/legend-application'; import { resolveVersion, retrieveProjectEntitiesWithDependencies, StoreProjectData, VersionedProjectData, } from '@finos/legend-server-depot'; import { action, flow, flowResult, makeObservable, observable } from 'mobx'; import type { LegendMarketplaceBaseStore } from '../LegendMarketplaceBaseStore.js'; import { type GeneratorFn, type PlainObject, ActionState, assertErrorThrown, guaranteeNonNullable, guaranteeType, stringifyQueryParams, addQueryParametersToUrl, } from '@finos/legend-shared'; import { type Class, type TDSExecutionResult, type TDSRowDataType, type V1_EntitlementsDataProductDetailsResponse, type V1_Terminal, getRowDataFromExecutionResult, GraphDataWithOrigin, GraphManagerState, LegendSDLC, V1_AdHocDeploymentDataProductOrigin, V1_DataProduct, V1_DataProductArtifact, V1_dataProductModelSchema, V1_entitlementsDataProductDetailsResponseToDataProductDetails, V1_PureGraphManager, V1_SdlcDeploymentDataProductOrigin, V1_TerminalModelSchema, } from '@finos/legend-graph'; import { buildGraphForDataProduct } from '../../utils/LakehouseUtils.js'; import { type Entity, type StoredFileGeneration, parseGAVCoordinates, parseProjectIdentifier, } from '@finos/legend-storage'; import { deserialize } from 'serializr'; import { EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl, EXTERNAL_APPLICATION_NAVIGATION__generateDataProductSampleQueryUrl, EXTERNAL_APPLICATION_NAVIGATION__generateDataSpaceQueryEditorUrl, EXTERNAL_APPLICATION_NAVIGATION__generateStudioSDLCProjectViewUrl, generateLakehouseDataProductPath, generateContractPagePath, generatePermitDataAccessRequestPagePath, } from '../../__lib__/LegendMarketplaceNavigation.js'; import { DataSpaceViewerState, EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl, } from '@finos/legend-extension-dsl-data-space/application'; import { type DataSpaceAnalysisResult, DSL_DataSpace_getGraphManagerExtension, retrieveAnalyticsResultCache, } from '@finos/legend-extension-dsl-data-space/graph'; import { DataProductDataAccessState, DataProductViewerState, TerminalProductDataAccessState, TerminalProductLayoutState, TerminalProductViewerState, DATAPRODUCT_TYPE, getDataProductFromDetails, } from '@finos/legend-extension-dsl-data-product'; import { LegendMarketplaceTelemetryHelper } from '../../__lib__/LegendMarketplaceTelemetryHelper.js'; const ARTIFACT_GENERATION_DATA_PRODUCT_KEY = 'dataProduct'; export class LegendMarketplaceProductViewerStore { readonly marketplaceBaseStore: LegendMarketplaceBaseStore; dataProductViewer: DataProductViewerState | undefined; dataProductDataAccess: DataProductDataAccessState | undefined; terminalProductViewer: TerminalProductViewerState | undefined; terminalProductDataAccess: TerminalProductDataAccessState | undefined; legacyDataProductViewer: DataSpaceViewerState | undefined; readonly loadingProductState = ActionState.create(); constructor(marketplaceBaseStore: LegendMarketplaceBaseStore) { this.marketplaceBaseStore = marketplaceBaseStore; makeObservable(this, { dataProductViewer: observable, dataProductDataAccess: observable, terminalProductViewer: observable, legacyDataProductViewer: observable, setDataProductViewer: action, setDataProductDataAccess: action, setTerminalProductDataAccess: action, setTerminalProductViewer: action, setLegacyDataProductViewer: action, initWithProduct: flow, initWithTerminal: flow, initWithSDLCProduct: flow, initWithLegacyProduct: flow, }); } setDataProductViewer(val: DataProductViewerState | undefined): void { this.dataProductViewer = val; } setDataProductDataAccess(val: DataProductDataAccessState | undefined): void { this.dataProductDataAccess = val; } setTerminalProductViewer(val: TerminalProductViewerState | undefined): void { this.terminalProductViewer = val; } setTerminalProductDataAccess( val: TerminalProductDataAccessState | undefined, ): void { this.terminalProductDataAccess = val; } setLegacyDataProductViewer(val: DataSpaceViewerState | undefined): void { this.legacyDataProductViewer = val; } *initWithTerminal(terminalId: string): GeneratorFn<void> { try { this.loadingProductState.inProgress(); const rawTerminalResponse: TDSExecutionResult = (yield this.marketplaceBaseStore.engineServerClient.getTerminalById( terminalId, )) as TDSExecutionResult; const terminalRowData: TDSRowDataType[] = getRowDataFromExecutionResult(rawTerminalResponse); const matchingRows = terminalRowData.filter( (row: TDSRowDataType) => row.id === Number(terminalId), ); const terminalProducts: V1_Terminal[] = matchingRows.map( (rowData: TDSRowDataType) => deserialize(V1_TerminalModelSchema, rowData), ); const terminalProductViewerState = new TerminalProductViewerState( this.marketplaceBaseStore.applicationStore, guaranteeNonNullable( terminalProducts[0], `No terminal found with ID ${terminalId}`, ), new TerminalProductLayoutState(), ); const terminalProductDataAccessState = new TerminalProductDataAccessState( terminalProductViewerState, this.marketplaceBaseStore.terminalAccessServerClient, this.marketplaceBaseStore.applicationStore, this.marketplaceBaseStore.userSearchService, ); this.setTerminalProductViewer(terminalProductViewerState); this.setTerminalProductDataAccess(terminalProductDataAccessState); this.loadingProductState.complete(); LegendMarketplaceTelemetryHelper.logEvent_LoadTerminal( this.marketplaceBaseStore.applicationStore.telemetryService, terminalId, undefined, ); } catch (error) { assertErrorThrown(error); const message = `Unable to load terminal ${terminalId}: ${error.message}`; this.marketplaceBaseStore.applicationStore.notificationService.notifyError( message, ); this.loadingProductState.fail(); LegendMarketplaceTelemetryHelper.logEvent_LoadTerminal( this.marketplaceBaseStore.applicationStore.telemetryService, terminalId, message, ); } } *initWithProduct( dataProductId: string, deploymentId: number, tokenProvider: () => string | undefined, ): GeneratorFn<void> { try { this.loadingProductState.inProgress(); const rawResponse = (yield this.marketplaceBaseStore.lakehouseContractServerClient.getDataProductByIdAndDID( dataProductId, deploymentId, tokenProvider(), )) as PlainObject<V1_EntitlementsDataProductDetailsResponse>; const fetchedDataProductDetails = V1_entitlementsDataProductDetailsResponseToDataProductDetails( rawResponse, ); if (fetchedDataProductDetails.length === 0) { throw new Error( `No data products found for ID ${dataProductId} and DID ${deploymentId}`, ); } else if (fetchedDataProductDetails.length > 1) { throw new Error( `Multiple data products found for ID ${dataProductId} and DID ${deploymentId}`, ); } const entitlementsDataProductDetails = guaranteeNonNullable( fetchedDataProductDetails[0], ); // Create graph manager state const graphManagerState = new GraphManagerState( this.marketplaceBaseStore.applicationStore.pluginManager, this.marketplaceBaseStore.applicationStore.logService, ); const graphManager = guaranteeType( graphManagerState.graphManager, V1_PureGraphManager, 'GraphManager must be a V1_PureGraphManager', ); yield graphManager.initialize( { env: this.marketplaceBaseStore.applicationStore.config.env, tabSize: DEFAULT_TAB_SIZE, clientConfig: { baseUrl: this.marketplaceBaseStore.applicationStore.config.engineServerUrl, }, }, { engine: this.marketplaceBaseStore.remoteEngine }, ); yield graphManagerState.initializeSystem(); // For AdHoc DataProducts, we need to build the graph so that we have the // PCMD to use for fetching access point relation types. if ( entitlementsDataProductDetails.origin instanceof V1_AdHocDeploymentDataProductOrigin ) { yield buildGraphForDataProduct( entitlementsDataProductDetails, graphManagerState, graphManager, this.marketplaceBaseStore, ); } const v1DataProduct = guaranteeType( yield getDataProductFromDetails( entitlementsDataProductDetails, graphManager, this.marketplaceBaseStore.depotServerClient, ), V1_DataProduct, `Unable to get V1_DataProduct from details for id: ${entitlementsDataProductDetails.id}`, ); const projectGAV = entitlementsDataProductDetails.origin instanceof V1_SdlcDeploymentDataProductOrigin ? { groupId: entitlementsDataProductDetails.origin.group, artifactId: entitlementsDataProductDetails.origin.artifact, versionId: entitlementsDataProductDetails.origin.version, } : undefined; const dataProductViewerState = new DataProductViewerState( v1DataProduct, this.marketplaceBaseStore.applicationStore, this.marketplaceBaseStore.engineServerClient, this.marketplaceBaseStore.depotServerClient, graphManagerState, this.marketplaceBaseStore.applicationStore.config.options.dataProductConfig, this.marketplaceBaseStore.userSearchService, projectGAV, { viewDataProductSource: () => { if ( entitlementsDataProductDetails.origin instanceof V1_SdlcDeploymentDataProductOrigin ) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateStudioProjectViewUrl( this.marketplaceBaseStore.applicationStore.config .studioApplicationUrl, entitlementsDataProductDetails.origin.group, entitlementsDataProductDetails.origin.artifact, entitlementsDataProductDetails.origin.version, v1DataProduct.path, ), ); } }, openPowerBi: (apg) => { if ( entitlementsDataProductDetails.origin instanceof V1_SdlcDeploymentDataProductOrigin ) { const { group: groupId, artifact: artifactId, version: versionId, } = entitlementsDataProductDetails.origin; const path = v1DataProduct.path; const powerBiUrl = this.marketplaceBaseStore.applicationStore.config.powerBiUrl; this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( addQueryParametersToUrl( powerBiUrl, stringifyQueryParams({ groupId, artifactId, versionId, path, apg, }), ), ); } }, openDataCube: (sourceData) => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateNewDataCubeUrl( this.marketplaceBaseStore.applicationStore.config .datacubeApplicationUrl, sourceData, ), ); }, openLineage: this.marketplaceBaseStore.applicationStore.config .registryUrl ? (dataProductName: string, accessPointName: string) => { if ( this.marketplaceBaseStore.applicationStore.config.registryUrl ) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateRegistryLineageUrl( this.marketplaceBaseStore.applicationStore.config .registryUrl, dataProductName, accessPointName, ), ); } } : undefined, openGovernance: this.marketplaceBaseStore.applicationStore.config .registryUrl ? (id: string) => { if ( this.marketplaceBaseStore.applicationStore.config.registryUrl ) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateRegistryGovernanceUrl( this.marketplaceBaseStore.applicationStore.config .registryUrl, id, ), ); } } : undefined, // TODO: improve with class opening openQuery: (gav, type, id) => { if (id) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, gav.groupId, gav.artifactId, gav.versionId, type, v1DataProduct.path, id, ), ); } }, openSampleQuery: projectGAV ? (sampleQueryId: string): void => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataProductSampleQueryUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, projectGAV.groupId, projectGAV.artifactId, projectGAV.versionId, v1DataProduct.path, sampleQueryId, ), ); } : undefined, }, this.marketplaceBaseStore.registryServerClient, ); const dataProductDataAccessState = new DataProductDataAccessState( entitlementsDataProductDetails, dataProductViewerState, this.marketplaceBaseStore.lakehouseContractServerClient, this.marketplaceBaseStore.lakehousePlatformServerClient, this.marketplaceBaseStore.lakehouseIngestServerClient, this.marketplaceBaseStore.applicationStore.pluginManager.getApplicationPlugins(), { getContractTaskUrl: (contractId: string, taskId: string) => this.marketplaceBaseStore.applicationStore.navigationService.navigator.generateAddress( generateContractPagePath(contractId, taskId), ), getDataProductUrl: (_dataProductId: string, _deploymentId: number) => this.marketplaceBaseStore.applicationStore.navigationService.navigator.generateAddress( generateLakehouseDataProductPath(_dataProductId, _deploymentId), ), getTaskPageUrl: (id: string) => this.marketplaceBaseStore.applicationStore.navigationService.navigator.generateAddress( generatePermitDataAccessRequestPagePath(id), ), }, this.marketplaceBaseStore.permitWorkflowServerClient, ); this.setDataProductViewer(dataProductViewerState); this.setDataProductDataAccess(dataProductDataAccessState); dataProductViewerState.legendAIConfig = this.marketplaceBaseStore.applicationStore.config.legendAIConfig; dataProductViewerState.init(entitlementsDataProductDetails); dataProductDataAccessState.init(tokenProvider); this.loadingProductState.complete(); const origin = entitlementsDataProductDetails.origin instanceof V1_SdlcDeploymentDataProductOrigin ? { type: DATAPRODUCT_TYPE.SDLC, groupId: entitlementsDataProductDetails.origin.group, artifactId: entitlementsDataProductDetails.origin.artifact, versionId: entitlementsDataProductDetails.origin.version, } : { type: DATAPRODUCT_TYPE.ADHOC, }; LegendMarketplaceTelemetryHelper.logEvent_LoadDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, { origin: origin, dataProductId: dataProductId, deploymentId: deploymentId, name: entitlementsDataProductDetails.dataProduct.name, environmentClassification: entitlementsDataProductDetails.lakehouseEnvironment?.type, }, undefined, ); } catch (error) { assertErrorThrown(error); const message = `Unable to load product ${dataProductId}: ${error.message}`; this.marketplaceBaseStore.applicationStore.notificationService.notifyError( message, ); this.loadingProductState.fail(); LegendMarketplaceTelemetryHelper.logEvent_LoadDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, { dataProductId: dataProductId, deploymentId: deploymentId, }, message, ); } } /** * This is a fallback to support the old data product URL with GAV and path. * We check to see if the data product has been deployed, and if so, we redirect * to the new URL format with data product ID and deployment ID. If no deploymentId * exists (meaning nativeModelAccess only, no access point groups), we render the * nativeModelAccess UI directly. * * @param gav The GAV coordinates of the product. * @param path The path to the product. */ *initWithSDLCProduct(gav: string, path: string): GeneratorFn<void> { try { this.loadingProductState.inProgress(); const projectData = VersionedProjectData.serialization.fromJson( parseGAVCoordinates(gav) as unknown as PlainObject, ); try { const storeProject = new StoreProjectData(); storeProject.groupId = projectData.groupId; storeProject.artifactId = projectData.artifactId; const entityResponse = (yield this.marketplaceBaseStore.depotServerClient.getVersionEntity( projectData.groupId, projectData.artifactId, resolveVersion(projectData.versionId), path, )) as Entity; const schema = V1_dataProductModelSchema( this.marketplaceBaseStore.applicationStore.pluginManager.getPureProtocolProcessorPlugins(), ); const v1DataProduct = deserialize(schema, entityResponse.content); const files = (yield this.marketplaceBaseStore.depotServerClient.getGenerationFilesByType( storeProject, resolveVersion(projectData.versionId), ARTIFACT_GENERATION_DATA_PRODUCT_KEY, )) as StoredFileGeneration[]; const fileGen = files.filter((e) => e.path === v1DataProduct.path)[0] ?.file.content; if (fileGen) { const content: PlainObject = JSON.parse(fileGen) as PlainObject; const dataProductInfo = content.dataProduct as | { deploymentId?: string } | undefined; if (dataProductInfo?.deploymentId) { const dataProductId = v1DataProduct.name.toUpperCase(); const deploymentId = Number(dataProductInfo.deploymentId); this.marketplaceBaseStore.applicationStore.navigationService.navigator.goToLocation( generateLakehouseDataProductPath(dataProductId, deploymentId), ); this.loadingProductState.complete(); LegendMarketplaceTelemetryHelper.logEvent_LoadSDLCDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, { origin: { type: DATAPRODUCT_TYPE.SDLC, groupId: projectData.groupId, artifactId: projectData.artifactId, versionId: projectData.versionId, path: path, }, dataProductId: dataProductId, deploymentId: deploymentId, }, undefined, ); } else { const graphManagerState = new GraphManagerState( this.marketplaceBaseStore.applicationStore.pluginManager, this.marketplaceBaseStore.applicationStore.logService, ); const graphManager = guaranteeType( graphManagerState.graphManager, V1_PureGraphManager, 'GraphManager must be a V1_PureGraphManager', ); yield graphManager.initialize( { env: this.marketplaceBaseStore.applicationStore.config.env, tabSize: DEFAULT_TAB_SIZE, clientConfig: { baseUrl: this.marketplaceBaseStore.applicationStore.config .engineServerUrl, queryBaseUrl: this.marketplaceBaseStore.applicationStore.config .engineQueryServerUrl, enableCompression: true, }, }, { engine: this.marketplaceBaseStore.remoteEngine }, ); yield graphManagerState.initializeSystem(); graphManagerState.graph.setOrigin( new LegendSDLC( projectData.groupId, projectData.artifactId, resolveVersion(projectData.versionId), ), ); const dataProductArtifact = V1_DataProductArtifact.serialization.fromJson(content); const projectGAV = { groupId: projectData.groupId, artifactId: projectData.artifactId, versionId: projectData.versionId, }; const dataProductViewerState = new DataProductViewerState( v1DataProduct, this.marketplaceBaseStore.applicationStore, this.marketplaceBaseStore.engineServerClient, this.marketplaceBaseStore.depotServerClient, graphManagerState, this.marketplaceBaseStore.applicationStore.config.options.dataProductConfig, this.marketplaceBaseStore.userSearchService, projectGAV, { viewDataProductSource: () => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateStudioProjectViewUrl( this.marketplaceBaseStore.applicationStore.config .studioApplicationUrl, projectData.groupId, projectData.artifactId, projectData.versionId, v1DataProduct.path, ), ); }, openQuery: (_gav, type, id): void => { if (id) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, _gav.groupId, _gav.artifactId, _gav.versionId, type, v1DataProduct.path, id, ), ); } }, openSampleQuery: (sampleQueryId: string): void => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataProductSampleQueryUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, projectData.groupId, projectData.artifactId, projectData.versionId, v1DataProduct.path, sampleQueryId, ), ); }, }, this.marketplaceBaseStore.registryServerClient, ); yield flowResult( dataProductViewerState.init(undefined, dataProductArtifact), ); dataProductViewerState.legendAIConfig = this.marketplaceBaseStore.applicationStore.config.legendAIConfig; this.setDataProductViewer(dataProductViewerState); this.loadingProductState.complete(); LegendMarketplaceTelemetryHelper.logEvent_LoadSDLCDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, { origin: { type: DATAPRODUCT_TYPE.SDLC, groupId: projectData.groupId, artifactId: projectData.artifactId, versionId: projectData.versionId, path: path, }, }, undefined, ); } } else { throw new Error('File generation not found'); } } catch (error) { assertErrorThrown(error); const message = `Unable to load product ${path}: ${error.message}`; this.marketplaceBaseStore.applicationStore.notificationService.notifyError( message, ); this.loadingProductState.fail(); LegendMarketplaceTelemetryHelper.logEvent_LoadSDLCDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, { origin: { type: DATAPRODUCT_TYPE.SDLC, groupId: projectData.groupId, artifactId: projectData.artifactId, versionId: projectData.versionId, path: path, }, }, message, ); } } catch (error) { assertErrorThrown(error); this.marketplaceBaseStore.applicationStore.notificationService.notifyError( `Unable to deserialize gav for product ${path}: ${error.message}`, ); this.loadingProductState.fail(); } } *initWithLegacyProduct(gav: string, path: string): GeneratorFn<void> { try { this.loadingProductState.inProgress(); const { groupId, artifactId, versionId } = parseGAVCoordinates(gav); try { // create graph manager const graphManagerState = new GraphManagerState( this.marketplaceBaseStore.applicationStore.pluginManager, this.marketplaceBaseStore.applicationStore.logService, ); const graphManager = guaranteeType( graphManagerState.graphManager, V1_PureGraphManager, 'GraphManager must be a V1_PureGraphManager', ); // initialize graph manager yield graphManager.initialize( { env: this.marketplaceBaseStore.applicationStore.config.env, tabSize: DEFAULT_TAB_SIZE, clientConfig: { baseUrl: this.marketplaceBaseStore.applicationStore.config .engineServerUrl, queryBaseUrl: this.marketplaceBaseStore.applicationStore.config .engineQueryServerUrl, enableCompression: true, }, }, { engine: this.marketplaceBaseStore.remoteEngine }, ); yield graphManagerState.initializeSystem(); // fetch project this.loadingProductState.setMessage(`Fetching project...`); const project = StoreProjectData.serialization.fromJson( (yield flowResult( this.marketplaceBaseStore.depotServerClient.getProject( groupId, artifactId, ), )) as PlainObject<StoreProjectData>, ); // set origin graphManagerState.graph.setOrigin( new LegendSDLC(groupId, artifactId, resolveVersion(versionId)), ); // analyze data product const analysisResult = (yield DSL_DataSpace_getGraphManagerExtension( graphManagerState.graphManager, ).analyzeDataSpace( path, () => retrieveProjectEntitiesWithDependencies( project, versionId, this.marketplaceBaseStore.depotServerClient, ), () => retrieveAnalyticsResultCache( project, versionId, path, this.marketplaceBaseStore.depotServerClient, ), this.loadingProductState, )) as DataSpaceAnalysisResult; const dataSpaceViewerState = new DataSpaceViewerState( this.marketplaceBaseStore.applicationStore, graphManagerState, groupId, artifactId, versionId, analysisResult, { retrieveGraphData: () => new GraphDataWithOrigin( new LegendSDLC(groupId, artifactId, versionId), ), queryDataSpace: (executionContextKey: string) => { LegendMarketplaceTelemetryHelper.logEvent_ClickQueryDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, groupId, artifactId, versionId, analysisResult.path, executionContextKey, ); this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataSpaceQueryEditorUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, groupId, artifactId, versionId, analysisResult.path, executionContextKey, undefined, undefined, ), ); }, viewProject: (entityPath: string | undefined) => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateStudioProjectViewUrl( this.marketplaceBaseStore.applicationStore.config .studioApplicationUrl, groupId, artifactId, versionId, entityPath, ), ); }, viewSDLCProject: async (entityPath: string | undefined) => { // find the matching SDLC instance const projectIDPrefix = parseProjectIdentifier( project.projectId, ).prefix; const matchingSDLCEntry = this.marketplaceBaseStore.applicationStore.config.studioInstances.find( (entry) => entry.sdlcProjectIDPrefix === projectIDPrefix, ); if (matchingSDLCEntry) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateStudioSDLCProjectViewUrl( matchingSDLCEntry.url, project.projectId, entityPath, ), ); } else { this.marketplaceBaseStore.applicationStore.notificationService.notifyWarning( `Can't find the corresponding SDLC instance to view the SDLC project`, ); } }, queryClass: (_class: Class): void => { this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateDataSpaceQueryEditorUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, groupId, artifactId, versionId, analysisResult.path, analysisResult.defaultExecutionContext.name, undefined, _class.path, ), ); }, openServiceQuery: (servicePath: string): void => { LegendMarketplaceTelemetryHelper.logEvent_ClickOpenServiceQuery( this.marketplaceBaseStore.applicationStore.telemetryService, groupId, artifactId, versionId, servicePath, ); this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress( EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl( this.marketplaceBaseStore.applicationStore.config .queryApplicationUrl, groupId, artifactId, versionId, servicePath, ), ); }, onZoneChange: (zone: NavigationZone | undefined): void => { if (zone === undefined) { this.marketplaceBaseStore.applicationStore.navigationService.navigator.resetZone(); } else { this.marketplaceBaseStore.applicationStore.navigationService.navigator.updateCurrentZone( zone, ); } }, onQuickStartTabChange: ( tabKey: string, executableTitle: string, ): void => { LegendMarketplaceTelemetryHelper.logEvent_ClickQuickStartExtensionTab( this.marketplaceBaseStore.applicationStore.telemetryService, groupId, artifactId, versionId, analysisResult.path, tabKey, executableTitle, ); }, }, ); dataSpaceViewerState.legendAIConfig = this.marketplaceBaseStore.applicationStore.config.legendAIConfig; this.setLegacyDataProductViewer(dataSpaceViewerState); this.loadingProductState.complete(); LegendMarketplaceTelemetryHelper.logEvent_LoadLegacyDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, groupId, artifactId, versionId, path, undefined, ); } catch (error) { assertErrorThrown(error); const message = `Unable to load legacy data product ${gav}::${path}: ${error.message}`; this.marketplaceBaseStore.applicationStore.notificationService.notifyError( message, ); this.loadingProductState.fail(); LegendMarketplaceTelemetryHelper.logEvent_LoadLegacyDataProduct( this.marketplaceBaseStore.applicationStore.telemetryService, groupId, artifactId, versionId, path, message, ); } } catch (error) { assertErrorThrown(error); this.marketplaceBaseStore.applicationStore.notificationService.notifyError( `Unable to parse gav for product ${path}: ${error.message}`, ); this.loadingProductState.fail(); } } }