/** * 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 { HelpOutlineIcon, MenuContentDivider, MoonIcon, OpenNewTabIcon, ShoppingCartOutlineIcon, SimpleCalendarIcon, SunFilledIcon, UserCircleIcon, } from '@finos/legend-art'; import { observer } from 'mobx-react-lite'; import { Avatar, Box, IconButton, Link, Menu, MenuItem } from '@mui/material'; import { useEffect, useRef, useState } from 'react'; import { assertErrorThrown, isNonNullable, LegendUser, LogEvent, } from '@finos/legend-shared'; import { LEGEND_APPLICATION_COLOR_THEME } from '@finos/legend-application'; import { LEGEND_MARKETPLACE_ROUTE_PATTERN } from '../../__lib__/LegendMarketplaceNavigation.js'; import { LegendMarketplaceAppInfo } from './LegendMarketplaceAppInfo.js'; import { useLegendMarketplaceBaseStore } from '../../application/providers/LegendMarketplaceFrameworkProvider.js'; import { CartDrawer } from '../AddToCart/CartDrawer.js'; import { CartBadge } from './CartBadge.js'; import { useAuth } from 'react-oidc-context'; import { V1_pendingTasksResponseModelSchema } from '@finos/legend-graph'; import { LEGEND_MARKETPLACE_APP_EVENT } from '../../__lib__/LegendMarketplaceAppEvent.js'; import { deserialize } from 'serializr'; import { ICON_TOOLBAR_TYPE, LegendMarketplaceTelemetryHelper, } from '../../__lib__/LegendMarketplaceTelemetryHelper.js'; export const LegendMarketplaceIconToolbar = observer(() => { const marketplaceStore = useLegendMarketplaceBaseStore(); const applicationStore = marketplaceStore.applicationStore; const auth = useAuth(); const userId = applicationStore.identityService.currentUser; const [userData, setUserData] = useState(); const [pendingTasksCount, setPendingTasksCount] = useState(0); const showDevFeatures = applicationStore.config.options.showDevFeatures; const tokenRef = useRef(auth.user?.access_token); tokenRef.current = auth.user?.access_token; useEffect(() => { const fetchUserData = async (): Promise => { if (userId) { try { const user = await marketplaceStore.userSearchService?.getOrFetchUser(userId); setUserData(user); } catch (error) { assertErrorThrown(error); if (applicationStore.config.options.showDevFeatures) { applicationStore.notificationService.notifyError( error, `Failed to fetch user data: ${error.name}\n${error.message}\n${error.cause}\n${error.stack}`, ); } else { applicationStore.notificationService.notifyError( `Failed to fetch user data: ${error.message}`, ); } } } }; // eslint-disable-next-line no-void void fetchUserData(); const fetchPendingTasks = async (): Promise => { if (userId) { try { const pendingTasks = await marketplaceStore.pendingTasksCache.fetch( userId, tokenRef.current, ); const tasks = deserialize( V1_pendingTasksResponseModelSchema, pendingTasks, ); const privilegeManagerCount = tasks.privilegeManager.length; const dataOwnerCount = tasks.dataOwner.length; const totalPendingTasksCount = privilegeManagerCount + dataOwnerCount; setPendingTasksCount(totalPendingTasksCount); } catch (error) { assertErrorThrown(error); applicationStore.logService.error( LogEvent.create( LEGEND_MARKETPLACE_APP_EVENT.FETCH_PENDING_TASKS_FAILURE, ), error, ); } } }; // eslint-disable-next-line no-void void fetchPendingTasks(); }, [ userId, applicationStore.notificationService, marketplaceStore.userSearchService, marketplaceStore.pendingTasksCache, applicationStore.logService, applicationStore.config.options.showDevFeatures, ]); const imgSrc = applicationStore.config.marketplaceUserProfileImageUrl?.replace( '{userId}', userId, ); const userDirectoryLink = `${applicationStore.config.lakehouseEntitlementsConfig?.applicationDirectoryUrl}/${userId}`; const userName = userData instanceof LegendUser && userData.displayName ? userData.displayName : userId; const adjacentEnvState = marketplaceStore.adjacentEnvState; const adjacentUrl = applicationStore.config.adjacentEnvUrl; const UserIconRenderer = () => { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); return ( <> setAnchorEl(event.currentTarget)} className="legend-marketplace-header__menu__icon" >
{imgSrc ? ( ) : ( )} {pendingTasksCount > 0 && ( {pendingTasksCount} )}
setAnchorEl(null)}> Hello,{' '} {userName} {adjacentEnvState && adjacentUrl && ( {`${adjacentEnvState.label} Env`} )} {adjacentEnvState && adjacentUrl && } { LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.USER, 'View Terminal Subscriptions', ); }} > View Terminal Subscriptions { LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.USER, 'View Orders', ); }} > View Orders { LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.USER, 'View Lakehouse Entitlements', ); }} > View Lakehouse Entitlements {pendingTasksCount > 0 && ( {pendingTasksCount} )} ); }; const CartIconRenderer = () => { const cartStore = marketplaceStore.cartStore; return ( { // eslint-disable-next-line no-void void cartStore.initialize(); cartStore.setOpen(true); }} > ); }; const HelpIconRenderer = () => { const [anchorEl, setAnchorEl] = useState(null); const [openAppInfo, setOpenAppInfo] = useState(false); const open = Boolean(anchorEl); const additionalHelpMenuItems = applicationStore.pluginManager .getApplicationPlugins() .flatMap((plugin) => plugin.getAdditionalHelpMenuItemConfigs?.(marketplaceStore), ) .filter(isNonNullable); const handleShowDemo = (): void => { marketplaceStore.setDemoModal(true); setAnchorEl(null); }; const handleNewsletterClick = (): void => { const newsletterUrl = applicationStore.config.options.newsletterUrl; if (newsletterUrl) { applicationStore.navigationService.navigator.visitAddress( newsletterUrl, ); applicationStore.telemetryService.logEvent( LEGEND_MARKETPLACE_APP_EVENT.CLICK_SUBSCRIBE_TO_NEWSLETTER, {}, ); } setAnchorEl(null); }; const handleHistoricalNewslettersClick = (): void => { const historicalNewsletterUrl = applicationStore.config.options.historicalNewsletterUrl; if (historicalNewsletterUrl) { applicationStore.navigationService.navigator.visitAddress( historicalNewsletterUrl, ); applicationStore.telemetryService.logEvent( LEGEND_MARKETPLACE_APP_EVENT.CLICK_BROWSE_HISTORICAL_NEWSLETTERS, {}, ); } setAnchorEl(null); }; const handleDocumentationClick = (): void => { const documentationUrl = applicationStore.config.options.documentationUrl; if (documentationUrl) { applicationStore.navigationService.navigator.visitAddress( documentationUrl, ); applicationStore.telemetryService.logEvent( LEGEND_MARKETPLACE_APP_EVENT.CLICK_DOCUMENTATION, {}, ); } setAnchorEl(null); }; return ( <> setAnchorEl(event.currentTarget)} className="legend-marketplace-header__menu__icon" > setAnchorEl(null)}> {showDevFeatures && ( Schedule a Demo )} {applicationStore.config.options.newsletterUrl && ( Subscribe to our Newsletter )} {applicationStore.config.options.historicalNewsletterUrl && ( Browse Historical Newsletters )} {(showDevFeatures || applicationStore.config.options.newsletterUrl || applicationStore.config.options.historicalNewsletterUrl) && ( )} { setOpenAppInfo(true); setAnchorEl(null); LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.HELP, 'About', ); }} > About {applicationStore.config.options.documentationUrl && ( Documentation )} {adjacentEnvState && adjacentUrl && ( { LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.HELP, adjacentEnvState.label, ); }} > {`${adjacentEnvState.label} Env`} )} {adjacentEnvState && adjacentUrl && } { setAnchorEl(null); LegendMarketplaceTelemetryHelper.logEvent_ClickToolbarMenu( applicationStore.telemetryService, ICON_TOOLBAR_TYPE.HELP, 'Admin', ); }} > Admin {additionalHelpMenuItems.length > 0 && } {additionalHelpMenuItems.length > 0 && additionalHelpMenuItems.map((item) => ( { setAnchorEl(null); item.onClick?.(); }} component={item.href ? 'a' : 'li'} href={item.href} target={item.href ? '_blank' : undefined} rel={item.href ? 'noopener noreferrer' : undefined} > {item.label} ))} setOpenAppInfo(false)} /> ); }; const layoutService = applicationStore.layoutService; const isDarkMode = !layoutService.TEMPORARY__isLightColorThemeEnabled; const handleThemeToggle = () => { const newTheme = isDarkMode ? LEGEND_APPLICATION_COLOR_THEME.HIGH_CONTRAST_LIGHT : LEGEND_APPLICATION_COLOR_THEME.HIGH_CONTRAST_DARK; layoutService.setColorTheme(newTheme, { persist: true }); LegendMarketplaceTelemetryHelper.logEvent_ToggleThemeMode( applicationStore.telemetryService, newTheme === LEGEND_APPLICATION_COLOR_THEME.HIGH_CONTRAST_DARK, ); }; const renderThemeToggle = () => { return ( {isDarkMode ? : } ); }; const toolbarIcons = [ { title: 'Theme', renderer: renderThemeToggle, }, { title: 'Profile', renderer: UserIconRenderer, }, { title: 'Cart', renderer: CartIconRenderer, }, { title: 'Help', renderer: HelpIconRenderer, }, ]; return ( <> {toolbarIcons.map((item) => (
{item.renderer()}
))}
); });