import React from 'react' import { type BreadcrumbType } from '../Breadcrumbs/Common/BreadcrumbTypes' import { getEnvironmentName } from '../../services/apiEndpointHelpers' import { type IconStringList } from '../Icons/Icon.models' import { useMediaQuery } from '../../hooks/responsiveHooks' import { type AccountPopoverProps } from '../AccountPopover/AccountPopover' import commonStyles from './Common/_left-nav-common.module.scss' import LeftNavDesktop from './Desktop/LeftNavDesktop' import LeftNavMobile from './Mobile/LeftNavMobile' import { type LanguageSelectorProps } from './Common/LanguageSelector/LanguageSelector' export type LeftNavLinkObj = { /** The url for the page associated with this link */ link: string /** The icon that will appear to the left of the SidebarLink name */ icon: IconStringList /** The SidebarLink name */ name: string /** Optional permissions needed to view this SidebarLink */ permissions?: string[] /** Optional property - designates a link as a footer link */ footerLink?: boolean /** Optional property for exact match of url with breadcrumb link */ exactLinkMatch?: boolean } export type LeftNavProps = { /** The logo will appear in the Sidebar header */ logo: { /** The logo image url needed to display the logo */ url: string /** The Abbreviated image url */ abbreviatedUrl?: string /** The Isolated image url **/ isolatedUrl?: string /** Optional maximum height for the logo */ maxHeight?: string | number } /** The array of leftNavLinks */ leftNavLinks?: LeftNavLinkObj[] /** The array of Breadcrumbs */ breadcrumbs: BreadcrumbType[] /** Props for populating the account popover in the footer */ accountPopoverProps: Omit< AccountPopoverProps, 'expanded' | 'closeMobileDrawer' > /** Component to use for routing. We need this to be defined in each application using the LeftNav. */ routerComponent: React.ElementType /** Prop to use for routing within the routerComponent. We need this to be defined in each application using the LeftNav. */ routerProp: string /** User permission list */ userPermissions: string[] /** Function to navigate to the homepage */ navigate: () => void /** Footer element */ footer?: ({ sidebarExpanded, }: { sidebarExpanded: boolean }) => React.JSX.Element mobileProps?: { /** Optionally pass in children elements to the mobile header. */ mobileHeaderChildren?: React.ReactNode /** Optionally place the hamburger menu to the right instead of the default left corner. */ rightHamburgerMenu?: boolean } /** Optional prop to correctly calculate the height of the desktop sidebar. This is used in instances where there is an element above or below the sidebar. i.e. A banner above the application. */ heightOffset?: number /** This prop will determine which environment the user is seeing the Sidebar. This will provide visual queues to the user so they can quickly know which environment they are in. */ environment?: 'development' | 'staging' | 'demo' | 'production' /** Optional prop to configure language settings */ languageConfig?: Omit /** Optional prop to hide the logo */ hideLogo?: boolean /** Optional prop to hide the copyright */ hideCopyright?: boolean /** Optional prop to add a test id to the LeftNav for QA testing */ qaTestId?: string /** Optional prop to match a specific link segment index to the breadcrumb link */ linkSegmentIndexToMatch?: number } function getEnvForToggle(): LeftNavProps['environment'] { const environmentName = getEnvironmentName() if (environmentName === 'stage') { return 'staging' } return environmentName } // NOTE: This function filters out links if the user does not have the correct permissions to view them. const MenuFilter = (leftNavLinks: LeftNavLinkObj[], permissions: string[]) => { const filteredLinks = leftNavLinks.filter((link) => { if (!link.permissions) { return true } return link.permissions.some((permission) => permissions.includes(permission), ) }) return filteredLinks } const LeftNav = (props: LeftNavProps): React.JSX.Element => { const isMobile = useMediaQuery({ type: 'max', breakpoint: 'md' }) const { leftNavLinks, userPermissions } = props const parsedLinks = MenuFilter( leftNavLinks ? leftNavLinks : [], userPermissions, ) const leftNavProps = { // We want environment defined first so that an app has the option to override the environment prop. environment: getEnvForToggle(), ...props, // We want leftNavLinks to be the parsedLinks so it needs to be last. leftNavLinks: parsedLinks, } return isMobile ? ( ) : ( ) } const Divider = () =>
LeftNav.Divider = Divider export { LeftNav }