/** * 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 React, { Suspense, useEffect } from 'react'; import { observer } from 'mobx-react-lite'; import { CubesLoadingIndicator, CubesLoadingIndicatorIcon, GhostIcon, } from '@finos/legend-art'; import { useApplicationStore, LegendTokenSync, } from '@finos/legend-application'; import { BrowserEnvironmentProvider, Outlet, Route, Routes, Navigate, } from '@finos/legend-application/browser'; import { LegendMarketplaceFrameworkProvider, useLegendMarketplaceApplicationStore, useLegendMarketplaceBaseStore, } from './providers/LegendMarketplaceFrameworkProvider.js'; import { IntelligenceCatalogStoreProvider } from './providers/IntelligenceCatalogStoreProvider.js'; import { LEGEND_MARKETPLACE_ROUTE_PATTERN } from '../__lib__/LegendMarketplaceNavigation.js'; import { type AuthProviderProps, AuthProvider, withAuthenticationRequired, } from 'react-oidc-context'; import { useLocation } from 'react-router-dom'; import type { User } from 'oidc-client-ts'; import type { LegendMarketplaceOidcConfig } from './LegendMarketplaceApplicationConfig.js'; import { MarketplaceLakehouseHeader } from '../components/Header/LegendMarketplaceHeader.js'; import { LegendMarketplacePage } from '../pages/LegendMarketplacePage.js'; import { CartToast } from '../components/Toast/CartToast.js'; import { FeedbackWidget } from '../components/Feedback/FeedbackWidget.js'; import { flowResult } from 'mobx'; // Lazy load page components for code splitting const MarketplaceLakehouseHome = React.lazy(() => import('../pages/Lakehouse/MarketplaceLakehouseHome.js').then((module) => ({ default: module.MarketplaceLakehouseHome, })), ); const LakehouseDataProduct = React.lazy(() => import('../pages/Lakehouse/dataProduct/LakehouseDataProduct.js').then( (module) => ({ default: module.LakehouseDataProduct, }), ), ); const TerminalProduct = React.lazy(() => import('../pages/Lakehouse/dataProduct/TerminalProduct.js').then( (module) => ({ default: module.TerminalProduct, }), ), ); const LegendMarketplaceDataAPIs = React.lazy(() => import('../pages/DataAPIs/LegendMarketplaceDataAPIs.js').then((module) => ({ default: module.LegendMarketplaceDataAPIs, })), ); const LakehouseEntitlements = React.lazy(() => import('../pages/Lakehouse/entitlements/LakehouseEntitlements.js').then( (module) => ({ default: module.LakehouseEntitlements, }), ), ); const LakehouseDataContractTask = React.lazy(() => import('../pages/Lakehouse/entitlements/LakehouseDataContract.js').then( (module) => ({ default: module.LakehouseDataContractTask, }), ), ); const WorkflowDataAccessRequestTask = React.lazy(() => import('../pages/Lakehouse/entitlements/WorkflowDataAccessRequest.js').then( (module) => ({ default: module.WorkflowDataAccessRequestTask, }), ), ); const PermitDataAccessRequestTask = React.lazy(() => import('../pages/Lakehouse/entitlements/PermitDataAccessRequest.js').then( (module) => ({ default: module.PermitDataAccessRequestTask, }), ), ); const LakehouseAdmin = React.lazy(() => import('../pages/Lakehouse/admin/LakehouseAdmin.js').then((module) => ({ default: module.LakehouseAdmin, })), ); const MarketplaceLakehouseOAuthCallback = React.lazy(() => import('../pages/Lakehouse/MarketplaceLakehouseOAuthCallback.js').then( (module) => ({ default: module.MarketplaceLakehouseOAuthCallback, }), ), ); const LakehouseSDLCDataProduct = React.lazy(() => import('../pages/Lakehouse/dataProduct/LakehouseSDLCDataProduct.js').then( (module) => ({ default: module.LakehouseSDLCDataProduct, }), ), ); const LegendMarketplaceSearchResults = React.lazy(() => import( '../pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.js' ).then((module) => ({ default: module.LegendMarketplaceSearchResults, })), ); const LegendMarketplaceFieldSearchResults = React.lazy(() => import( '../pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.js' ).then((module) => ({ default: module.LegendMarketplaceFieldSearchResults, })), ); const LegendMarketplaceLakehouseAccessSearchResults = React.lazy(() => import( '../pages/Lakehouse/searchResults/LegendMarketplaceLakehouseAccessSearchResults.js' ).then((module) => ({ default: module.LegendMarketplaceLakehouseAccessSearchResults, })), ); const LegacyDataProduct = React.lazy(() => import('../pages/Lakehouse/dataProduct/LegacyDataProduct.js').then( (module) => ({ default: module.LegacyDataProduct, }), ), ); const LegendMarketplaceAgents = React.lazy(() => import('../pages/Agents/LegendMarketplaceAgents.js').then((module) => ({ default: module.LegendMarketplaceAgents, })), ); const McpServerViewer = React.lazy(() => import('../pages/Agents/McpServerViewer.js').then((module) => ({ default: module.McpServerViewer, })), ); const LegendMarketplaceVendorData = React.lazy(() => import('../pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.js').then( (module) => ({ default: module.LegendMarketplaceVendorData, }), ), ); const LegendMarketplaceSubscriptions = React.lazy(() => import('../pages/Profile/LegendMarketplaceSubscriptions.js').then( (module) => ({ default: module.LegendMarketplaceSubscriptions, }), ), ); const LegendMarketplaceYourOrders = React.lazy(() => import('../pages/Profile/LegendMarketplaceYourOrders.js').then((module) => ({ default: module.LegendMarketplaceYourOrders, })), ); const RedirectPreservingParams: React.FC<{ to: string }> = ({ to }) => { const location = useLocation(); return ( ); }; const NotFoundPage = observer(() => { const applicationStore = useApplicationStore(); const currentPath = applicationStore.navigationService.navigator.getCurrentLocation(); return (
404. Not Found
The requested URL {applicationStore.navigationService.navigator.generateAddress( currentPath, )} was not found in the application
); }); const useProtectedPage = (PageComponent: React.FC): React.FC => withAuthenticationRequired(PageComponent, { OnRedirecting: () => ( ), signinRedirectArgs: { state: `${window.location.pathname}${window.location.search}${window.location.hash}`, }, }); export const LegendMarketplaceWebApplicationRouter = observer(() => { const marketplaceBaseStore = useLegendMarketplaceBaseStore(); const applicationStore = useLegendMarketplaceApplicationStore(); useEffect(() => { if (marketplaceBaseStore.initState.isInInitialState) { flowResult(marketplaceBaseStore.initialize()).catch( applicationStore.alertUnhandledError, ); } }, [applicationStore.alertUnhandledError, marketplaceBaseStore]); const ProtectedYourOrders = withAuthenticationRequired( LegendMarketplaceYourOrders, { OnRedirecting: () => ( ), signinRedirectArgs: { state: `${window.location.pathname}${window.location.search}`, }, }, ); // Loading fallback for lazy-loaded components const LazyLoadingFallback = ( ); return (
{marketplaceBaseStore.initState.hasCompleted && ( } > } /> {/* Marketplace Routes */} } /> } > } /> {/* Reroute pages */} } /> } /> } /> } /> } /> {/* Plugin additional pages */} {/* We filter out any pages with paths that exist above to avoid overwriting main pages */} {applicationStore.pluginManager .getApplicationPlugins() .flatMap( (plugin) => plugin.getAdditionalMarketplacePageConfigs?.() ?? [], ) .filter( (pageConfig) => !(pageConfig.path in LEGEND_MARKETPLACE_ROUTE_PATTERN), ) .map((pageConfig) => ( ))} } /> } /> } /> )}
); }); export const LegendMarketplaceWebApplication = observer( (props: { baseUrl: string; oidcConfig?: LegendMarketplaceOidcConfig | undefined; }) => { const { baseUrl, oidcConfig } = props; const onSigninCallback = (_user: User | undefined) => { window.location.href = (_user?.state as string | undefined) ?? '/'; }; const mergedOIDCConfig: AuthProviderProps | undefined = oidcConfig ? { ...oidcConfig.authProviderProps, redirect_uri: `${window.location.origin}${oidcConfig.redirectPath}`, silent_redirect_uri: `${window.location.origin}${oidcConfig.silentRedirectPath}`, onSigninCallback, } : undefined; return ( ); }, );