import { ReactNode, useMemo } from 'react'; import { useIntl } from '@edx/frontend-platform/i18n'; import { Helmet } from 'react-helmet'; import { Breadcrumb, Container, MenuItem, SelectMenu, } from '@openedx/paragon'; import { Link } from 'react-router-dom'; import { useLibraryContext } from '../common/context/LibraryContext'; import { useSidebarContext } from '../common/context/SidebarContext'; import { useContentFromSearchIndex, useContentLibrary } from '../data/apiHooks'; import Loading from '../../generic/Loading'; import NotFoundAlert from '../../generic/NotFoundAlert'; import ErrorAlert from '../../generic/alert-error'; import { ContainerType } from '../../generic/key-utils'; import Header from '../../header'; import SubHeader from '../../generic/sub-header/SubHeader'; import { SubHeaderTitle } from '../LibraryAuthoringPage'; import { messages, subsectionMessages } from './messages'; import { LibrarySidebar } from '../library-sidebar'; import { LibraryContainerChildren } from './LibraryContainerChildren'; import { ContainerEditableTitle, FooterActions, HeaderActions } from '../containers'; import { ContainerHit } from '../../search-manager'; interface OverflowLinksProps { to: string | string[]; children: ReactNode | ReactNode[]; } const OverflowLinks = ({ children, to }: OverflowLinksProps) => { if (typeof to === 'string') { return ( {children} ); } // to is string[] that should be converted to overflow menu const items = to?.map((link, index) => ( {children?.[index]} )); return ( {items} ); }; /** Full library subsection page */ export const LibrarySubsectionPage = () => { const intl = useIntl(); const { libraryId, containerId } = useLibraryContext(); const { sidebarItemInfo } = useSidebarContext(); const { data: libraryData, isLoading: isLibLoading } = useContentLibrary(libraryId); // fetch subsectionData from index as it includes its parent sections as well. const { hits, isLoading, isError, error, } = useContentFromSearchIndex(containerId ? [containerId] : []); const subsectionData = (hits as ContainerHit[])?.[0]; const breadcrumbs = useMemo(() => { const links: Array<{ label: string | string[], to: string | string[] }> = [ { label: libraryData?.title || '', to: `/library/${libraryId}`, }, ]; const sectionLength = subsectionData?.sections?.displayName?.length || 0; if (sectionLength === 1) { links.push({ label: subsectionData.sections?.displayName?.[0] || '', to: `/library/${libraryId}/section/${subsectionData?.sections?.key?.[0]}`, }); } else if (sectionLength > 1) { // Add all sections as a single object containing list of links // This is converted to overflow menu by OverflowLinks component links.push({ label: subsectionData?.sections?.displayName || '', to: subsectionData?.sections?.key?.map((link) => `/library/${libraryId}/section/${link}`) || '', }); } else { // Adding empty breadcrumb to add the last `>` spacer. links.push({ label: '', to: '', }); } return ( ); }, [libraryData, subsectionData, libraryId]); if (!containerId || !libraryId) { // istanbul ignore next - This shouldn't be possible; it's just here to satisfy the type checker. throw new Error('Rendered without containerId or libraryId URL parameter'); } // Only show loading if section or library data is not fetched from index yet if (isLibLoading || isLoading) { return ; } if (!libraryData || !subsectionData) { return ; } // istanbul ignore if if (isError) { return ; } return (
{libraryData.title} | {subsectionData.displayName} | {process.env.SITE_NAME}
} />} breadcrumbs={breadcrumbs} headerActions={( )} hideBorder />
{!!sidebarItemInfo?.type && (
)}
); };