@clickview/lite 0.103.1 → 0.103.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/.vite/manifest.json +271 -271
  2. package/dist/bundles.json +1 -1
  3. package/dist/en.json +1 -1
  4. package/dist/scripts/{igSDXA6g.chunk.js → 1WHinyQW.chunk.js} +2 -2
  5. package/dist/scripts/{igSDXA6g.chunk.js.map → 1WHinyQW.chunk.js.map} +1 -1
  6. package/dist/scripts/{kMWvzbRv2.chunk.js → B1ag1ah72.chunk.js} +2 -2
  7. package/dist/scripts/{kMWvzbRv2.chunk.js.map → B1ag1ah72.chunk.js.map} +1 -1
  8. package/dist/scripts/{D2_GYzlb.chunk.js → B6Pc3q-u.chunk.js} +2 -2
  9. package/dist/scripts/{D2_GYzlb.chunk.js.map → B6Pc3q-u.chunk.js.map} +1 -1
  10. package/dist/scripts/{sCuSDiER2.chunk.js → BPbjSFkC2.chunk.js} +2 -2
  11. package/dist/scripts/{sCuSDiER2.chunk.js.map → BPbjSFkC2.chunk.js.map} +1 -1
  12. package/dist/scripts/{CNm_4jj62.chunk.js → BZFomoIH2.chunk.js} +2 -2
  13. package/dist/scripts/BZFomoIH2.chunk.js.map +1 -0
  14. package/dist/scripts/{CW_rYB-i2.chunk.js → BazdM9Ah2.chunk.js} +2 -2
  15. package/dist/scripts/{CW_rYB-i2.chunk.js.map → BazdM9Ah2.chunk.js.map} +1 -1
  16. package/dist/scripts/{BcPrUEuC2.chunk.js → CNPnPJMp2.chunk.js} +2 -2
  17. package/dist/scripts/{BcPrUEuC2.chunk.js.map → CNPnPJMp2.chunk.js.map} +1 -1
  18. package/dist/scripts/{Dd23z1_x2.chunk.js → CUp7_5gE2.chunk.js} +2 -2
  19. package/dist/scripts/{Dd23z1_x2.chunk.js.map → CUp7_5gE2.chunk.js.map} +1 -1
  20. package/dist/scripts/{C-zUHAyD.chunk.js → CajcIz6S.chunk.js} +2 -2
  21. package/dist/scripts/{C-zUHAyD.chunk.js.map → CajcIz6S.chunk.js.map} +1 -1
  22. package/dist/scripts/{Drx3PvJj.chunk.js → Cc9f2ux0.chunk.js} +2 -2
  23. package/dist/scripts/{Drx3PvJj.chunk.js.map → Cc9f2ux0.chunk.js.map} +1 -1
  24. package/dist/scripts/Cj_F4Lv92.chunk.js +2 -0
  25. package/dist/scripts/{C8l37H7t2.chunk.js.map → Cj_F4Lv92.chunk.js.map} +1 -1
  26. package/dist/scripts/{DFrz_upP2.chunk.js → CtBGtgb32.chunk.js} +2 -2
  27. package/dist/scripts/{DFrz_upP2.chunk.js.map → CtBGtgb32.chunk.js.map} +1 -1
  28. package/dist/scripts/{BpiZZWnJ2.chunk.js → CtWAorP42.chunk.js} +2 -2
  29. package/dist/scripts/{BpiZZWnJ2.chunk.js.map → CtWAorP42.chunk.js.map} +1 -1
  30. package/dist/scripts/{C3Qd_bbV2.chunk.js → D8mi6CVp2.chunk.js} +2 -2
  31. package/dist/scripts/{C3Qd_bbV2.chunk.js.map → D8mi6CVp2.chunk.js.map} +1 -1
  32. package/dist/scripts/{3K2h5K5-.chunk.js → DJfIirut.chunk.js} +2 -2
  33. package/dist/scripts/{3K2h5K5-.chunk.js.map → DJfIirut.chunk.js.map} +1 -1
  34. package/dist/scripts/{Cc63s6rS2.chunk.js → DaaQ5htA2.chunk.js} +2 -2
  35. package/dist/scripts/{Cc63s6rS2.chunk.js.map → DaaQ5htA2.chunk.js.map} +1 -1
  36. package/dist/scripts/{CHwPLUZK.chunk.js → DkFP4cXM.chunk.js} +2 -2
  37. package/dist/scripts/{CHwPLUZK.chunk.js.map → DkFP4cXM.chunk.js.map} +1 -1
  38. package/dist/scripts/{izXlxhJf.chunk.js → Dzy1nQk7.chunk.js} +2 -2
  39. package/dist/scripts/{izXlxhJf.chunk.js.map → Dzy1nQk7.chunk.js.map} +1 -1
  40. package/dist/scripts/{DGy8Ldlr.chunk.js → FIUOppmy.chunk.js} +2 -2
  41. package/dist/scripts/{DGy8Ldlr.chunk.js.map → FIUOppmy.chunk.js.map} +1 -1
  42. package/dist/scripts/{CPBvCqVK.chunk.js → H511PXuG.chunk.js} +2 -2
  43. package/dist/scripts/{CPBvCqVK.chunk.js.map → H511PXuG.chunk.js.map} +1 -1
  44. package/dist/scripts/{D8Op6EUa2.chunk.js → IYIY9hIU2.chunk.js} +2 -2
  45. package/dist/scripts/{D8Op6EUa2.chunk.js.map → IYIY9hIU2.chunk.js.map} +1 -1
  46. package/dist/scripts/{app-BHlllGhO.js → app-DvYKGw_S.js} +3 -3
  47. package/dist/scripts/{app-BHlllGhO.js.map → app-DvYKGw_S.js.map} +1 -1
  48. package/dist/scripts/{2HZlmQRs2.chunk.js → lJ6ZVpyv2.chunk.js} +2 -2
  49. package/dist/scripts/{2HZlmQRs2.chunk.js.map → lJ6ZVpyv2.chunk.js.map} +1 -1
  50. package/package.json +1 -1
  51. package/dist/scripts/C8l37H7t2.chunk.js +0 -2
  52. package/dist/scripts/CNm_4jj62.chunk.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"D2_GYzlb.chunk.js","names":[],"sources":["../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-header-details/ClassificationHeaderDetails.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/empty-state/CuratedClassificationEmptyState.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/table-of-contents/table-of-contents.module.scss","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/table-of-contents/TableOfContents.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/teacher-only/TeacherOnlyEmptyState.tsx","../../../../libs/shared/src/apps/subjects/hooks/useGetTopicsWidgets.ts","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-coming-soon/ClassificationComingSoon.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/audiences/ClassificationDashboardAudiences.tsx","../../../../libs/shared/src/images/svg/widgets/WidgetSeriesSvg.tsx","../../../../libs/shared/src/apps/subjects/hooks/useDirectoryTabProductTipSwitcher.ts","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-tabs/classification-tabs.module.scss","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-tabs/ClassificationTabs.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-dashboard-nav/ClassificationDashboardNav.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/ClassificationDashboard.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard.tsx","../../../../libs/shared/src/flight-requests/FollowRequests.ts","../../src/shared/hooks/use-follow-classification/use-follow-classification.module.scss","../../src/shared/hooks/use-follow-classification/useFollowClassification.ts","../../src/apps/subjects/errors/TopicNotFoundError.ts","../../src/apps/subjects/hooks/useFetchClassificationDashboard.ts","../../src/apps/subjects/views/classification/curated-classification/CuratedClassificationView.tsx","../../src/apps/subjects/views/classification/live-classification/LiveClassificationView.tsx","../../src/apps/subjects/views/classification/BaseClassificationView.tsx"],"sourcesContent":["import React from 'react';\n\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Classification } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nconst namespace = 'subject.classificationHeaderDetails';\n\nconst Separator = ({ className }: { className: string }) =>\n <span className={className}>&bull;</span>;\n\ninterface ClassificationHeaderDetailsProps {\n classification: Classification;\n}\n\nexport function ClassificationHeaderDetails(props: ClassificationHeaderDetailsProps): React.ReactElement {\n const {\n dashboardVideoCount,\n childDashboardVideoCount,\n dashboardResourceCount,\n childDashboardResourceCount,\n childClassificationCount\n } = TopicsHelper.getCounts(props.classification);\n\n const videoCount = dashboardVideoCount + childDashboardVideoCount;\n const resourceCount = dashboardResourceCount + childDashboardResourceCount;\n\n return (\n <p className='mb-n1 font-size-normal fw-normal mt-1'>\n {!!childClassificationCount && (\n <Text\n namespace={namespace}\n phrase='topics'\n options={{ count: childClassificationCount.toLocaleString(), smartCount: childClassificationCount }}\n />\n )}\n\n {!!videoCount && (\n <>\n {childClassificationCount > 0 && <Separator className='mx-2' />}\n <Text\n namespace={namespace}\n phrase='videos'\n options={{ count: videoCount.toLocaleString(), smartCount: videoCount }}\n />\n </>\n )}\n {!!resourceCount && (\n <>\n <Separator className='mx-2' />\n <Text\n namespace={namespace}\n phrase='resources'\n options={{ count: resourceCount.toLocaleString(), smartCount: resourceCount }}\n />\n </>\n )}\n </p>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { PlusSvg } from 'libs/shared/images/svg/actions/PlusSvg';\nimport { CuratedDashboard, DashboardStatus } from 'libs/shared/interfaces';\n\nconst namespace = 'subjects.curatedClassificationEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface CuratedClassificationEmptyStateProps {\n dashboard: CuratedDashboard;\n imageUrl: string;\n isReadonly: boolean;\n addWidgetApplink?: () => Core.AppLink;\n}\n\nexport function CuratedClassificationEmptyState(props: CuratedClassificationEmptyStateProps): JSX.Element {\n const isArchived = props.dashboard?.status === DashboardStatus.Archived;\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('headingForNP')} />\n {!props.isReadonly ? (\n <EmptyState.Heading>\n <Text phrase='headingForNP' />\n </EmptyState.Heading>\n ) : (\n <>\n <EmptyState.Heading>\n <Text namespace={namespace} phrase='headingForCurator' />\n </EmptyState.Heading>\n <EmptyState.Info>\n <Text namespace={namespace} phrase='info' />\n </EmptyState.Info>\n <Tooltip title={isArchived ? LanguageService.getPhrase(namespace, 'archivedCtaTooltip') : ''} spanHack>\n <EmptyState.Cta\n text={LanguageService.getPhrase(namespace, 'add')}\n appLink={props.addWidgetApplink?.()}\n className='btn btn-dark'\n icon={PlusSvg}\n disabled={isArchived}\n />\n </Tooltip>\n </>\n )}\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","$top-nav-height: 4.1875rem;\n$cv-banner-height: calc(100vw * 22 / 120);\n$filters-area: 7.87rem;\n\n.container {\n position: sticky;\n top: 6.25rem;\n z-index: 80;\n}\n\n.mobile {\n position: fixed;\n top: calc($top-nav-height + $cv-banner-height + $filters-area);\n z-index: 80;\n right: 0;\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, HashObject, LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { TableOfContentsList } from 'libs/shared/components/table-of-contents-list/TableOfContentsList';\nimport { TableOfContentsSvg } from 'libs/shared/images/svg/objects/TableOfContentsSvg';\nimport { CuratedWidget } from 'libs/shared/interfaces';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nimport styles from './table-of-contents.module.scss';\n\ninterface TableOfContentsContainerProps {\n widgets: CuratedWidget[];\n title: string;\n activeId: string;\n appLink?: Core.AppLink;\n clickable?: boolean;\n analyticsData?: HashObject;\n setControlledId: (arg: string) => void;\n isSmallScreen?: boolean;\n}\ninterface TableOfContentsProps extends TableOfContentsContainerProps {\n getAppLink: (widget: CuratedWidget) => Core.AppLink;\n}\n\nfunction TableOfContentsMobile(props: TableOfContentsProps) {\n const [ isExpanded, setIsExpanded ] = React.useState(false);\n\n function logUserAction() {\n const analyticsOptions = {\n actionType: !isExpanded ? UserAction.Open : UserAction.Hide,\n entity: EntityType.TableOfContents,\n location: LocationContext.Dashboard\n };\n\n AnalyticsHelper.logUserAction(props.analyticsData, analyticsOptions);\n }\n\n function onClickIcon() {\n setIsExpanded(!isExpanded);\n logUserAction();\n }\n\n return (\n <div className={`${styles.mobile} d-inline-flex gap-1`}>\n \n {isExpanded && (\n <div className='bg-white px-3 pt-3 pb-2 border border-dark rounded-1 ps-3'>\n <h2 className='h5'>{props.title}</h2>\n <TableOfContentsList\n items={props.widgets.map(widget => (\n { name: widget.name, id: widget.id, tocIndentation: widget.metadata.tocIndentation }\n ))}\n activeId={props.activeId}\n appLink={props.appLink}\n analyticsData={props.analyticsData}\n setControlledId={props.setControlledId}\n getAppLink={props.getAppLink}\n onItemClick={() => setIsExpanded(false)}\n />\n </div>\n )}\n <div className={styles.container}>\n <IconButton\n className='btn btn-outline-dark'\n svg={TableOfContentsSvg}\n onClick={onClickIcon}\n />\n </div>\n </div>\n );\n}\n\nfunction TableOfContents(props: TableOfContentsProps): JSX.Element {\n return (\n <aside className='col-3 order-1'>\n <div className={`${styles.container} ps-3`}>\n <h2 className='h5'>{props.title}</h2>\n \n <TableOfContentsList\n items={props.widgets.map(widget => (\n { name: widget.name, id: widget.id, tocIndentation: widget.metadata.tocIndentation }\n ))}\n activeId={props.activeId}\n appLink={props.appLink}\n analyticsData={props.analyticsData}\n setControlledId={props.setControlledId}\n getAppLink={props.getAppLink}\n />\n </div>\n </aside>\n );\n}\n\nexport function TableOfContentsContainer(props: TableOfContentsContainerProps): JSX.Element {\n function getAppLink(widget: CuratedWidget): Core.AppLink {\n const currentAppLink = ContextService.getCurrentRoute().appLink;\n \n const params: HashObject = currentAppLink.params ?\n { ...(currentAppLink.params as HashObject) } :\n {};\n\n params.tocId = widget.id;\n\n return {\n ...currentAppLink,\n params\n };\n }\n\n return (\n <>\n {!props.isSmallScreen ?\n <TableOfContents {...props} getAppLink={getAppLink} /> :\n <TableOfContentsMobile {...props} getAppLink={getAppLink} />\n }\n </>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\n\nconst namespace = 'subjects.teacherOnlyEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface TeacherOnlyEmptyStateProps {\n imageUrl: string;\n ctaAppLink?: () => Core.AppLink;\n}\n\nexport function TeacherOnlyEmptyState(props: TeacherOnlyEmptyStateProps): JSX.Element {\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('heading')} />\n <EmptyState.Heading>\n <Text phrase='heading' />\n </EmptyState.Heading>\n <EmptyState.Info>\n <Text phrase='info' />\n </EmptyState.Info>\n\n <EmptyState.Cta\n text={getPhrase('cta')}\n appLink={props.ctaAppLink?.()}\n className='btn btn-dark'\n />\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/react/index';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { WidgetTypeId } from 'libs/shared/enums/WidgetTypeId';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { CuratedDashboard, CuratedMediaWidget, CuratedWidget, PresentationAudience, Video } from 'libs/shared/interfaces';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\n\nexport interface Response {\n widgets: CuratedWidget[];\n\n videoList?: Video[];\n videoListWidgetId?: string;\n}\n\n/**\n * This hook helps us with custom logic for to display system generated dashboards in a slightly\n * different way.\n */\nexport function useGetTopicsWidgets(dashboard: CuratedDashboard, activeAudiences: PresentationAudience[]): Response {\n const {\n isSystemGeneratedDashboard,\n systemGeneratedVideoWidget\n } = React.useMemo(() => {\n if (!dashboard) {\n return {\n isSystemGeneratedDashboard: false,\n systemGeneratedVideoWidget: null\n };\n }\n\n const isSystemGeneratedDashboard = CuratedDashboardHelper.isSystemGeneratedDashboard(dashboard.widgets);\n\n return {\n isSystemGeneratedDashboard,\n systemGeneratedVideoWidget: dashboard.widgets.find(widget => {\n return (\n widget.widgetId === WidgetTypeId.ClassificationPinnedVideos &&\n widget.templateId !== WidgetTemplate.ThumbnailVerticalList\n );\n })\n };\n }, [dashboard?.id]);\n\n const systemGeneratedVideoContent = Flight.useBasicFetch<CuratedMediaWidget<Video[]>>(\n !!systemGeneratedVideoWidget &&\n DashboardRequests.dashboardWidgetContent(\n systemGeneratedVideoWidget?.id,\n CuratedDashboardHelper.getWidgetParams(\n systemGeneratedVideoWidget.widgetId,\n systemGeneratedVideoWidget.templateId,\n CuratedDashboardHelper.getDashboardTargetType(dashboard),\n activeAudiences?.map(a => a.masterId)\n ),\n systemGeneratedVideoWidget?.templateId\n )\n );\n\n // Non system generated dashboards are returned as per usual\n if (!isSystemGeneratedDashboard)\n return { widgets: ArrayHelper.sortBy(dashboard?.widgets, 'index') };\n\n // System generated dashboard have the video widget removed and returned as a separate video list\n return {\n widgets: dashboard?.widgets?.filter(widget => {\n if (widget.widgetId !== WidgetTypeId.ClassificationPinnedVideos)\n return true;\n\n if (widget.templateId === WidgetTemplate.ThumbnailVerticalList)\n return true;\n\n return false;\n }) ?? [],\n videoList: systemGeneratedVideoContent.data?.content ?? [],\n videoListWidgetId: systemGeneratedVideoWidget?.id\n };\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EntityType, LocationContext, SignUpDescriptors, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { ActionButton } from 'libs/shared/components/actions/ActionButton';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { BellFilledSvg } from 'libs/shared/images/svg/objects/BellFilledSvg';\nimport { BellSvg } from 'libs/shared/images/svg/objects/BellSvg';\nimport { Classification } from 'libs/shared/interfaces';\n\nconst namespace = 'subjects.classificationComingSoon';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface ComingSoonProps {\n data: Classification;\n onToggleFollow?: () => void;\n canFollowSubjects: boolean;\n imageUrl: string;\n showFollowButtonSpinner: boolean;\n showSignUp: boolean;\n signUpAppLink: Core.AppLink;\n}\n\nexport function ClassificationComingSoon(props: ComingSoonProps): JSX.Element {\n const isFollowing = !!props.data.followers?.data?.length;\n function onClick(): void {\n props.onToggleFollow?.();\n }\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState className='pt-0'>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('comingSoon')} />\n\n <EmptyState.Heading>\n <Text phrase='comingSoon' />\n </EmptyState.Heading>\n\n <EmptyState.Info>\n <Text phrase={props.showSignUp ? 'infoAnon' : 'info'} />\n </EmptyState.Info>\n\n {props.canFollowSubjects && (\n <ActionButton\n svg={isFollowing ? BellFilledSvg : BellSvg}\n onClick={onClick}\n showSpinner={props.showFollowButtonSpinner}\n className={`btn follow-btn me-2 ${isFollowing ? 'btn-outline-dark' : 'btn-dark'}`}\n >\n <Text phrase={isFollowing ? 'following' : 'follow'} />\n </ActionButton>\n )}\n\n {props.showSignUp && !props.canFollowSubjects && (\n <AppLink\n appLink={props.signUpAppLink}\n className='btn btn-dark d-none d-lg-inline-block'\n analyticsOptions={{\n actionType: UserAction.Click,\n location: LocationContext.ClassificationComingSoon,\n entity: EntityType.AppLink,\n workflowPhase: WorkflowPhase.Start,\n descriptor: SignUpDescriptors.SignUp\n }}\n analyticsData={{}}\n tag='button'\n >\n {getPhrase('signUp')}\n </AppLink>\n )}\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/core';\n\nimport { AudienceFilter } from 'libs/shared/apps/subjects/components/audience-filter/AudienceFilter';\nimport { PresentationAudience } from 'libs/shared/interfaces';\n\ninterface ClassificationDashboardAudiencesProps {\n audiences: PresentationAudience[];\n activeAudiences: PresentationAudience[];\n appLink: Core.AppLink;\n disabled: boolean;\n disablePersist: boolean;\n tooltip: string;\n}\n\nexport function ClassificationDashboardAudiences(props: ClassificationDashboardAudiencesProps): JSX.Element {\n return (\n <AudienceFilter\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n disabled={props.disabled}\n appLink={props.appLink}\n disablePersist={props.disablePersist}\n tooltip={props.tooltip}\n />\n );\n}\n","import React from 'react';\n\nexport function WidgetSeriesSvg(props: React.SVGProps<SVGSVGElement>) {\n return (\n <svg {...props}>\n <path\n d='M4.5 4a.5.5 0 0 0 0 1h16a.5.5 0 0 1 .5.5v12a.5.5 0 0 0 1 0v-12A1.5 1.5 0 0 0 20.5 4zM9 10.26a.256.256 0 0 1 .39-.218l4.482 2.74a.256.256 0 0 1 0 .437L9.39 15.958A.256.256 0 0 1 9 15.739zM18.5 6A1.5 1.5 0 0 1 20 7.5v11a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 2 18.5v-11A1.5 1.5 0 0 1 3.5 6zm-15 1a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5z'\n fill='currentColor'\n />\n </svg>\n );\n}\n","import React from 'react';\n\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { ClassificationTab } from '../components/classification-dashboard/classification-tabs/ClassificationTabs';\n\ninterface ViewModel {\n tab: ClassificationTab;\n on: boolean;\n}\n\nexport function useDirectoryTabProductTipSwitcher(initialTab?: ClassificationTab) {\n const initialState: ViewModel = {\n on: false,\n tab: initialTab || 'new-releases'\n };\n\n const [ viewModel, setViewModel ] = useViewModel<ViewModel>('directory:product:tip:switcher', initialState);\n\n React.useEffect(() => {\n if (!initialTab)\n return;\n\n setViewModel('tab', initialTab);\n }, [initialTab]);\n\n React.useEffect(() => {\n let interval: number = null;\n\n if (viewModel.on) {\n interval = window.setInterval(() => {\n if (viewModel.tab === 'new-releases' || viewModel.tab === 'all-topics')\n setViewModel('tab', viewModel.tab === 'new-releases' ? 'all-topics' : 'new-releases');\n else\n setViewModel('tab', viewModel.tab === 'curated-topic' ? 'video-list' : 'curated-topic');\n }, 2000);\n }\n\n return () => {\n window.clearInterval(interval);\n };\n }, [ viewModel.on, viewModel.tab ]);\n\n return {\n tab: viewModel.tab,\n isHighlighting: viewModel.on,\n start: () => setViewModel('on', true),\n stop: () => {\n setViewModel({\n on: false,\n tab: initialTab || viewModel.tab\n });\n }\n };\n}\n",":local {\n .curatedTopicTab {\n min-width: 6rem !important;\n }\n \n .tabTransition {\n transition: background-color .5s ease-in-out;\n }\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EntityType, LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { PillTab, PillTabSelector } from 'libs/shared/components/pill-tab-selector/PillTabSelector';\nimport { Breakpoints, useBreakpoints } from 'libs/shared/hooks/useBreakpoints';\nimport { GridSvg } from 'libs/shared/images/svg/objects/GridSvg';\nimport { RectanglesSvg } from 'libs/shared/images/svg/objects/RectanglesSvg';\nimport { SparkleSvg } from 'libs/shared/images/svg/objects/SparkleSvg';\nimport { WidgetSeriesSvg } from 'libs/shared/images/svg/widgets/WidgetSeriesSvg';\nimport { Classification, Presentation } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { useDirectoryTabProductTipSwitcher } from '../../../hooks/useDirectoryTabProductTipSwitcher';\n\nimport styles from './classification-tabs.module.scss';\n\nconst namespace = 'shared.classificationDashboard';\n\nexport type ClassificationTab = 'new-releases' | 'all-topics' | 'curated-topic' | 'curriculum';\n\nfunction getTabs(\n props: ClassificationTabsProps,\n breakpoints: Breakpoints,\n activeTab: ClassificationTab,\n isHighlighting: boolean\n): PillTab[] {\n const showText = breakpoints.lg || breakpoints.xl || breakpoints.xxl || breakpoints.xs;\n\n function getTopicTabClassName(): string {\n let className = isHighlighting ? styles.tabTransition : '';\n\n if (breakpoints.xs)\n return className + ' w-100';\n\n if (showText)\n return className = ` ${styles.curatedTopicTab}`;\n\n return className;\n }\n\n if (TopicsHelper.isTopLevelTopic(props.classification)) {\n return [{\n name: showText ? LanguageService.getPhrase(namespace, 'newReleases') : '',\n appLink: props.appLinks?.classification?.(props.classification),\n active: activeTab === 'new-releases',\n svg: SparkleSvg,\n analyticsData: {\n id: 'new-releases',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'newReleases'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classification?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }, {\n name: showText ? LanguageService.getPhrase(namespace, 'allTopics') : '',\n appLink: props.appLinks?.classificationDirectory?.(props.classification),\n active: activeTab === 'all-topics',\n svg: GridSvg,\n analyticsData: {\n id: 'all-topics',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'allTopics'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classificationDirectory?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }];\n }\n\n return [{\n name: showText ? LanguageService.getPhrase(namespace, 'topic') : '',\n appLink: props.appLinks?.classification?.(props.classification),\n active: activeTab === 'curated-topic',\n svg: RectanglesSvg,\n analyticsData: {\n id: 'curated-topic',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'topic'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classification?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: getTopicTabClassName()\n }, {\n name: showText ? LanguageService.getPhrase(namespace, 'curriculum') : '',\n appLink: props.appLinks?.classificationCurriculum?.(props.classification),\n active: activeTab === 'curriculum',\n svg: WidgetSeriesSvg,\n analyticsData: {\n id: 'curriculum',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'curriculum'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classificationCurriculum?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }];\n}\n\ninterface ClassificationTabsProps {\n classification: Classification;\n presentation: Presentation;\n appLinks: {\n classification: (classification: Classification | null) => Core.AppLink,\n classificationDirectory: (classification: Classification) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink\n };\n activeTab: ClassificationTab;\n}\n\nexport function ClassificationTabs(props: ClassificationTabsProps): JSX.Element {\n const breakpoints = useBreakpoints();\n const { tab, isHighlighting } = useDirectoryTabProductTipSwitcher(props.activeTab);\n\n return (\n <PillTabSelector\n borderRadius='sm'\n className={breakpoints.xs ? 'w-100' : ''}\n listClassName='d-flex flex-nowrap'\n tabs={getTabs(props, breakpoints, tab, isHighlighting)}\n />\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { Breadcrumb, Breadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { useBreakpoints } from 'libs/shared/hooks/useBreakpoints';\nimport { Classification, CuratedDashboard, Presentation, PresentationAudience } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { ClassificationDashboardAudiences } from '../audiences/ClassificationDashboardAudiences';\nimport { ClassificationTab, ClassificationTabs } from '../classification-tabs/ClassificationTabs';\n\nfunction shouldHideAudiences(\n audiences: PresentationAudience[],\n activeAudiences: PresentationAudience[],\n activeTab: ClassificationTab,\n isEmpty: boolean,\n isComingSoon: boolean\n): boolean {\n if (isComingSoon)\n return true;\n\n if (isEmpty && !activeAudiences?.length)\n return true;\n\n if (!AudienceHelper.shouldShowAudiences(audiences))\n return true;\n\n if (activeTab === 'curriculum')\n return true;\n\n return false;\n}\n\ninterface ClassificationDashboardNavProps {\n dashboard: CuratedDashboard;\n classification: Classification;\n presentation: Presentation;\n appLinks: {\n audience: () => Core.AppLink,\n classification: (classification: Classification | null) => Core.AppLink,\n classificationDirectory: (classification: Classification) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink\n };\n activeTab: ClassificationTab;\n audiences: PresentationAudience[];\n activeAudiences: PresentationAudience[];\n getBreadcrumbs: () => Breadcrumb[];\n\n hasTopicDirectoryDashboard: boolean;\n hasTopicCurriculumDashboard: boolean;\n isComingSoon: boolean;\n isEmpty: boolean;\n isViewingCurrentPresentation: boolean;\n disableAudiences: boolean;\n audienceTooltip: string;\n\n // Forces audiences to be hidden regardless of shouldHideAudiences' own rules (e.g. channel topic dashboards)\n forceHideAudiences?: boolean;\n}\n\nexport function ClassificationDashboardNav(props: ClassificationDashboardNavProps): JSX.Element {\n const breakpoints = useBreakpoints();\n\n const hideAudiences = props.forceHideAudiences || shouldHideAudiences(\n props.audiences,\n props.activeAudiences,\n props.activeTab,\n props.isEmpty,\n props.isComingSoon\n );\n\n function canShowTabs(): boolean {\n if (!props.classification || !props.dashboard)\n return false;\n\n if (CuratedDashboardHelper.isSystemGeneratedDashboard(props.dashboard.widgets))\n return false;\n\n /**\n * For our top-level topics, we can show the topic tab if the topic has a directory dashboard.\n */\n if (TopicsHelper.isTopLevelTopic(props.classification))\n return props.hasTopicDirectoryDashboard;\n\n /**\n * For our curated topics, we can show the curriculum tab if the topic has one, which it should\n */\n if (props.classification.externalMetadata?.isCurated && props.hasTopicCurriculumDashboard)\n return true;\n\n return false;\n }\n\n function getContainerClass(): string {\n let className = 'd-flex flex-column py-3 mb-3';\n\n if (!props.isComingSoon)\n className += ' border-bottom';\n\n if ((canShowTabs() || hideAudiences) && !breakpoints.xs)\n return className;\n\n return className + ' row-gap-3';\n }\n\n function getTopRowClass(): string {\n if (hideAudiences) {\n if (breakpoints.xs)\n return 'd-flex flex-column justify-content-between row-gap-3';\n\n return 'd-flex align-items-center justify-content-between';\n }\n\n let className = '';\n\n className += 'd-flex align-items-center justify-content-between mb-1';\n\n if (breakpoints.xs)\n className += ' row-gap-3 mb-0';\n\n return className;\n }\n\n function getBottomRowClass(): string {\n let className = 'd-flex align-items-end justify-content-between';\n\n if (breakpoints.xs)\n className += ' row-gap-3 flex-wrap';\n\n return className;\n }\n\n return (\n <div className={getContainerClass()}>\n <div className={getTopRowClass()}>\n <Breadcrumbs breadcrumbs={props.getBreadcrumbs?.()} />\n\n {canShowTabs() && hideAudiences && (\n <ClassificationTabs\n classification={props.classification}\n activeTab={props.activeTab}\n appLinks={props.appLinks}\n presentation={props.presentation}\n />\n )}\n </div>\n\n <div className={getBottomRowClass()}>\n {!hideAudiences && (\n <ClassificationDashboardAudiences\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n appLink={props.appLinks.audience?.()}\n disabled={props.disableAudiences}\n tooltip={props.audienceTooltip}\n disablePersist={!props.isViewingCurrentPresentation}\n />\n )}\n\n {canShowTabs() && !hideAudiences && (\n <ClassificationTabs\n classification={props.classification}\n activeTab={props.activeTab}\n appLinks={props.appLinks}\n presentation={props.presentation}\n />\n )}\n </div>\n </div>\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsOptions, HashObject, LocationContext } from 'libs/analytics/interfaces';\n\nimport { ClassificationHeaderDetails } from 'libs/shared/apps/subjects/components/classification-dashboard/classification-header-details/ClassificationHeaderDetails';\nimport { CuratedClassificationEmptyState } from 'libs/shared/apps/subjects/components/classification-dashboard/empty-state/CuratedClassificationEmptyState';\nimport { TableOfContentsContainer } from 'libs/shared/apps/subjects/components/classification-dashboard/table-of-contents/TableOfContents';\nimport { TeacherOnlyEmptyState } from 'libs/shared/apps/subjects/components/classification-dashboard/teacher-only/TeacherOnlyEmptyState';\nimport { useGetTopicsWidgets } from 'libs/shared/apps/subjects/hooks/useGetTopicsWidgets';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { BannerHeader } from 'libs/shared/components/banner-header/BannerHeader';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { ExpandableTextInline } from 'libs/shared/components/expandable-text-inline/ExpandableTextInline';\nimport { DashboardFeedbackData } from 'libs/shared/components/feedback-form/FeedbackForm';\nimport { VideoList } from 'libs/shared/components/video-list/VideoList';\nimport { WidgetHeader } from 'libs/shared/components/widgets/curated-widgets/components/header/WidgetHeader';\nimport { InfiniteWidgetContainerView } from 'libs/shared/components/widgets/curated-widgets/InfiniteWidgetContainerView';\nimport { WidgetContainerView } from 'libs/shared/components/widgets/curated-widgets/WidgetContainerView';\nimport { AllClassificationWidgetTemplates } from 'libs/shared/components/widgets/curated-widgets/WidgetProps';\nimport { ClassificationType } from 'libs/shared/enums/ClassificationType';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { LocalPermissionName } from 'libs/shared/enums/PermissionName';\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { WidgetTypeId } from 'libs/shared/enums/WidgetTypeId';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { HasLocalPermissionsFunc, HasPermissionsFunc } from 'libs/shared/hooks/usePermissions';\nimport { useTableOfContentsActiveHeading } from 'libs/shared/hooks/useTableOfContentsActiveHeading';\nimport { useTableOfContentsScroll } from 'libs/shared/hooks/useTableOfContentsScroll';\nimport { CalendarEvent, CalendarEventContentType, Classification, CuratedDashboard, CuratedWidget, CuratedWidgetQueryParams, CurriculumData, DashboardStatus, DashboardTargetType, InteractiveMetadata, PartnerProfile, Presentation, PresentationAudience, Resource } from 'libs/shared/interfaces';\nimport { CommonVideoProps } from 'libs/shared/interfaces/CommonVideoProps';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\nimport { WidgetHelper } from 'libs/shared/utils/WidgetHelper';\n\nimport { ClassificationComingSoon } from './classification-coming-soon/ClassificationComingSoon';\nimport { ClassificationDashboardNav } from './classification-dashboard-nav/ClassificationDashboardNav';\nimport { ClassificationTab } from './classification-tabs/ClassificationTabs';\n\nconst namespace = 'shared.classificationDashboard';\n\nfunction isHeadingWidget(widget: CuratedWidget) {\n return widget.widgetId === WidgetTypeId.Blurb && widget.templateId === WidgetTemplate.Heading;\n}\n\nfunction isTopicWidget(widget: CuratedWidget) {\n return widget.widgetId === WidgetTypeId.CuratedClassifications || widget.widgetId === WidgetTypeId.Classifications;\n}\n\n// ClassificationAllVideos is the only widget type that supports infinite-scroll pagination so far\nconst InfiniteFetchWidgetIds: WidgetTypeId[] = [WidgetTypeId.ClassificationAllVideos];\n\nfunction shouldInfiniteFetch(widgets: CuratedWidget[], index: number): boolean {\n const currentWidget = widgets[index];\n\n if (!currentWidget) return false;\n\n return InfiniteFetchWidgetIds.includes(currentWidget.widgetId) && index === widgets.length - 1;\n}\n\n/**\n * Mirrors WidgetHelper's per-widget empty check (which InfiniteWidgetContainerView can't infer\n * on its own, since a completed fetch always returns one \"page\" object regardless of whether the\n * widget's own content is empty).\n */\nfunction isWidgetContentEmpty(widgets: CuratedWidget[]): boolean {\n const widget = widgets?.[0];\n\n if (!widget) return true;\n\n if (WidgetHelper.hasNoContent(widget.widgetId)) return false;\n\n if (!widget.content) return true;\n\n return Array.isArray(widget.content) && !widget.content.length;\n}\n\nexport interface ClassificationDashboardProps {\n dashboard: CuratedDashboard;\n classification: Classification;\n presentation: Presentation;\n hasPermissions: HasPermissionsFunc;\n hasLocalPermissions: HasLocalPermissionsFunc;\n resourceThumbnailFallbackImageUrl: string;\n hasTopicDirectoryDashboard: boolean;\n hasTopicCurriculumDashboard: boolean;\n isTertiaryCustomerWithoutExchange: boolean;\n tab: ClassificationTab;\n specialEvent?: CalendarEvent;\n curriculums: CurriculumData;\n channel?: PartnerProfile;\n\n audiences: PresentationAudience[];\n activeAudiences?: PresentationAudience[];\n\n getWidgetContentRequest: (\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate\n ) => Flight.Request;\n\n /**\n * Only needed by consumers that support cursor-paginated widgets (currently just\n * WidgetTypeId.ClassificationAllVideos). If omitted, that widget type falls back to fetching\n * its first page only via `getWidgetContentRequest`, with no \"load more\" pagination.\n */\n getWidgetContentRequestWithCursor?: (\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate,\n cursor?: string\n ) => Flight.Request;\n\n getBannerActions?: () => ActionOptions[];\n getBreadcrumbs?: () => Breadcrumb[];\n onToggleFollow?: (classification: Classification, locationContext: LocationContext) => void;\n canFollowSubjects: boolean;\n onSubmitFeedback?: (feedback: DashboardFeedbackData) => Promise<void>;\n onDownloadAllClick?: (resources: Resource[], fileName: string, analyticsData?: HashObject) => void;\n\n appLinks?: AllClassificationWidgetTemplates['appLinks'] & {\n signUp: () => Core.AppLink,\n widgetWizard: () => Core.AppLink,\n previewQuestions: (interactive: InteractiveMetadata) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink,\n audience: () => Core.AppLink\n };\n\n imageCdnUrl: string;\n imageUrls?: AllClassificationWidgetTemplates['imageUrls'];\n emptyImageUrl: string;\n comingSoonImageUrl?: string;\n\n analyticsOptions?: AnalyticsOptions;\n analyticsData?: HashObject;\n\n scrollToWidgetId?: string;\n tableOfContentsId?: string;\n\n // Means the dashboard contains no linked or working filters\n isReadonly?: boolean;\n\n // Means the dashboard is being previewed by ClickView staff either in product or in curator\n isPreviewing?: boolean;\n\n // Means the parent topic for the dashboard has a status of \"Coming Soon\"\n isComingSoon?: boolean;\n\n showFollowButtonSpinner?: boolean;\n \n isViewCurrentPresentation?: boolean;\n\n // By default widgets will always be lazyloaded. We override this behaviour only in extenuating \n // circumstances, such as dynamic rendering for SEO.\n lazyLoad?: boolean;\n\n moviesAndTv?: boolean;\n\n isTeacherOnly?: boolean;\n \n contentType?: CalendarEventContentType;\n\n isBot?: boolean;\n\n settings?: AllClassificationWidgetTemplates['settings'];\n\n commonVideoProps: CommonVideoProps;\n}\n\nClassificationDashboard.defaultProps = {\n appLinks: {}\n};\n\nexport function ClassificationDashboard(props: ClassificationDashboardProps): JSX.Element {\n const { widgets, videoList, videoListWidgetId } = useGetTopicsWidgets(props.dashboard, props.activeAudiences);\n\n const isSmallScreen = useMediaQuery(MediaQueryStrings.LGDown);\n const headingRef = React.useRef<Set<Element>>(new Set());\n\n const initialEmptyWidgets = React.useMemo(() => {\n return widgets.reduce((acc: HashObject<boolean>, widget) => {\n acc[widget.id] = false;\n return acc;\n }, {});\n }, [widgets?.length]);\n\n const [ emptyWidgets, setEmptyWidgets ] = React.useState(initialEmptyWidgets);\n\n const [ controlledId, setControlledId ] = React.useState(props.tableOfContentsId);\n\n const [ tableOfContentActiveId, setTableOfContentActiveId ] = React.useState<string>('');\n\n const headingElements = Array.from(headingRef.current);\n useTableOfContentsScroll(headingElements, controlledId);\n useTableOfContentsActiveHeading({\n setActiveId: setTableOfContentActiveId,\n headingElements,\n controlledId,\n setControlledId\n });\n\n const isHubDashboard = props.classification.type === ClassificationType.Hub;\n const isChannelTopic = !!props.dashboard?.metadata?.channelId;\n\n function shouldShowEmptyState(): boolean {\n if (props.isComingSoon)\n return false;\n\n if (props.isTeacherOnly)\n return false;\n\n if (!props.dashboard)\n return true;\n\n if (props.dashboard.status === DashboardStatus.Archived && !props.isReadonly)\n return true;\n\n if (props.dashboard.status === DashboardStatus.Draft && !props.isPreviewing)\n return true;\n\n if (!widgets?.length)\n return true;\n\n if (videoList && videoList.length)\n return false;\n\n return Object.values(emptyWidgets).every(state => !!state);\n }\n\n function getWidgetContentRequest(\n id: string,\n widgetTypeId: WidgetTypeId,\n template: WidgetTemplate,\n cursor?: string\n ): Flight.Request {\n const params = CuratedDashboardHelper.getWidgetParams(\n widgetTypeId,\n template,\n CuratedDashboardHelper.getDashboardTargetType(props.dashboard),\n props.activeAudiences?.map(a => a.masterId),\n props.curriculums.preferredCurriculum?.id\n );\n\n if (cursor && props.getWidgetContentRequestWithCursor)\n return props.getWidgetContentRequestWithCursor(id, params, template, cursor);\n\n return props.getWidgetContentRequest(id, params, template);\n }\n\n const showEmptyState = shouldShowEmptyState();\n\n React.useEffect(() => {\n /**\n * When we add the first widget of the dashboard, the showEmptyState is `true`, the WidgetContainer is not going to be rendered to lazyload the `content`\n * so we set the emptyWidget to initial make sure the widget container is rendered to lazyload `widget.content`\n * and let the WidgetContainer to re-set the empty state based on the actual `widget.content` from backend\n */\n if (showEmptyState) {\n setEmptyWidgets(initialEmptyWidgets);\n }\n }, [widgets?.length]);\n\n const onSetIsEmpty = React.useCallback((widgetId: string, isEmpty: boolean) => {\n if (emptyWidgets[widgetId] === isEmpty)\n return;\n\n const newEmptyState = {\n ...emptyWidgets,\n [widgetId]: isEmpty\n };\n\n // The logic beneath this if-block doesn't apply to classification directories. This is because\n // classification directories don't support audience filtering, so widgets should never be empty,\n // meaning headings should never be hidden.\n if (CuratedDashboardHelper.isType(props.dashboard, DashboardTargetType.ClassificationDirectory)) {\n setEmptyWidgets(newEmptyState);\n return;\n }\n\n let index = 0;\n\n /**\n * Every time a widget is identified as empty, we check each heading blurb widget\n * to see if it should be hidden. This will be the case when all widgets beneath a heading\n * (up until the next heading) are empty.\n */\n while (index < widgets.length) {\n const currentWidget = widgets[index];\n\n if (!isHeadingWidget(currentWidget)) {\n index++;\n continue;\n }\n\n let isHeadingEmpty = true;\n let subWidgetIndex = index + 1;\n\n while (isHeadingEmpty && subWidgetIndex < widgets.length) {\n const headingSubWidget = widgets[subWidgetIndex];\n\n if (isHeadingWidget(headingSubWidget))\n break;\n\n if (!newEmptyState[headingSubWidget.id] && !isTopicWidget(headingSubWidget))\n isHeadingEmpty = false;\n\n subWidgetIndex++;\n }\n\n index = subWidgetIndex;\n\n newEmptyState[currentWidget.id] = isHeadingEmpty;\n }\n\n setEmptyWidgets(newEmptyState);\n }, [ emptyWidgets, widgets ]);\n\n function hideWidget(widget: CuratedWidget): boolean {\n return isHeadingWidget(widget) && emptyWidgets[widget.id];\n }\n\n function useLargeDashboardSpacing(): boolean {\n const target = CuratedDashboardHelper.getDashboardTargetType(props.dashboard);\n\n if (props.moviesAndTv || target === DashboardTargetType.ClassificationCurriculum)\n return false;\n\n return true;\n }\n\n function getWidgetHeading(widget: CuratedWidget, index: number): string {\n if (widget.widgetId === WidgetTypeId.ClassificationDashboardExternalMedia) {\n const previousWidget = widgets[index - 1];\n\n if (emptyWidgets[previousWidget.id])\n return widget.name.replace('Other videos', 'Videos');\n\n return widget.name;\n }\n\n return widget.name;\n }\n\n const widgetsInTableOfContents = widgets.filter(w => {\n return !hideWidget(w) && !!w.metadata?.showInTableOfContents;\n });\n\n const isTopicOnlyDashboard = widgets.every(isTopicWidget);\n\n const shouldShowTableOfContents = widgetsInTableOfContents.length >= 2;\n const shouldShowSideTableOfContents = shouldShowTableOfContents && !isSmallScreen;\n\n const shouldShowTopicCounts = (\n props.settings?.hasTopicDirectories &&\n TopicsHelper.isTopLevelTopic(props.classification) &&\n !props.isTertiaryCustomerWithoutExchange &&\n !isHubDashboard\n );\n\n /**\n * We don't put the .topic-dashboard class when we're in a movies and tv classification\n * because we don't want the extra padding between widgets.\n */\n return (\n <div className={`bg-white px-4 ${useLargeDashboardSpacing() ? 'dashboard-spacing-lg' : ''}`}>\n\n <BannerHeader\n type={isChannelTopic ? 'channel-topic' : 'default'}\n logo={isChannelTopic && props.channel?._logo.value}\n logoBgColour={isChannelTopic && props.channel?._colour.value}\n heading={props.classification.name}\n banner={props.classification.banner}\n imageCdnUrl={props.imageCdnUrl}\n actions={props.getBannerActions?.()}\n actionsDropdownClassName='btn btn-outline-dark'\n specialEvent={props.specialEvent}\n calendarTheme={{\n background: 'bg-light-blue',\n border: 'border-light-blue'\n }}\n showComingSoon={props.isComingSoon}\n detailsComponent={shouldShowTopicCounts ?\n () => <ClassificationHeaderDetails classification={props.classification} /> :\n null\n }\n />\n\n {!isHubDashboard ? (\n <ClassificationDashboardNav\n forceHideAudiences={isChannelTopic}\n dashboard={props.dashboard}\n classification={props.classification}\n presentation={props.presentation}\n appLinks={props.appLinks}\n activeTab={props.tab}\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n getBreadcrumbs={props.getBreadcrumbs}\n hasTopicDirectoryDashboard={props.hasTopicDirectoryDashboard}\n hasTopicCurriculumDashboard={props.hasTopicCurriculumDashboard}\n isComingSoon={props.isComingSoon}\n isEmpty={showEmptyState}\n isViewingCurrentPresentation={props.isViewCurrentPresentation}\n disableAudiences={isTopicOnlyDashboard || props.isReadonly}\n audienceTooltip={isTopicOnlyDashboard ? LanguageService.getPhrase(namespace, 'audienceTooltip') : ''}\n />\n ) : (\n <div className='py-3 mb-3 border-bottom'>\n <div className='mt-3'>\n <ExpandableTextInline>\n {() => (\n <p className='mb-0'>{props.classification.description}</p>\n )}\n </ExpandableTextInline>\n </div>\n </div>\n )}\n\n {props.isComingSoon && (\n <ClassificationComingSoon\n imageUrl={props.comingSoonImageUrl}\n data={props.classification}\n canFollowSubjects={props.canFollowSubjects}\n showFollowButtonSpinner={props.showFollowButtonSpinner}\n onToggleFollow={() => props.onToggleFollow(props.classification, LocationContext.ClassificationComingSoon)}\n showSignUp={!props.hasLocalPermissions(LocalPermissionName.FollowComingSoonTopics)}\n signUpAppLink={props.appLinks.signUp?.()}\n />\n )}\n\n {!props.isComingSoon && (\n <div className={`${shouldShowSideTableOfContents ? 'row no-wrap' : ''}`}>\n {shouldShowTableOfContents && (\n <TableOfContentsContainer\n widgets={widgetsInTableOfContents}\n title={props.classification.name}\n activeId={tableOfContentActiveId}\n clickable={!props.isReadonly}\n analyticsData={props.analyticsData}\n setControlledId={setControlledId}\n isSmallScreen={isSmallScreen}\n />\n )}\n\n <div className={shouldShowSideTableOfContents ? 'col-9 order-0' : ''}>\n {widgets.map((widget, idx) => {\n if (hideWidget(widget))\n return <React.Fragment key={widget.id}></React.Fragment>;\n\n if (InfiniteFetchWidgetIds.includes(widget.widgetId)) {\n return (\n <InfiniteWidgetContainerView<CuratedWidget, CuratedWidget, AllClassificationWidgetTemplates>\n index={idx}\n key={widget.id}\n item={widget}\n infiniteFetch={shouldInfiniteFetch(widgets, idx) && !!props.getWidgetContentRequestWithCursor}\n dashboardTarget={CuratedDashboardHelper.getDashboardTargetType(props.dashboard)}\n\n getName={w => getWidgetHeading(w, idx)}\n getWidgetMetadata={w => w.metadata}\n getContent={w => w.content}\n getCursor={w => w.cursor}\n getRequest={cursor => (\n getWidgetContentRequest(widget.id, widget.widgetId, widget.templateId, cursor)\n )}\n isEmptyPredicate={isWidgetContentEmpty}\n\n audiences={props.audiences}\n appLinks={props.appLinks}\n commonVideoProps={props.commonVideoProps}\n hasPermissions={props.hasPermissions}\n hasLocalPermissions={props.hasLocalPermissions}\n resultsTransformers={WidgetHelper.getWidgetResultsTransformers()}\n\n presentation={props.presentation}\n analyticsData={props.analyticsData}\n imageCdnUrl={props.imageCdnUrl}\n imageUrls={props.imageUrls}\n resourceThumbnailFallbackImageUrl={props.resourceThumbnailFallbackImageUrl}\n lazyLoad={props.lazyLoad}\n\n headingElementRef={headingRef}\n hasTableOfContents={shouldShowSideTableOfContents}\n isScrollToTargetWidget={props.scrollToWidgetId === widget.id}\n isBot={props.isBot}\n isPreviewing={props.isReadonly}\n isEditing={props.isReadonly}\n curriculums={props.curriculums}\n contentType={props.contentType}\n\n setIsEmpty={isEmpty => onSetIsEmpty(widget.id, isEmpty)}\n\n getSelectedItems={null}\n appLinkOptions={null}\n />\n );\n }\n\n return (\n <WidgetContainerView\n widgetCollection={DashboardTargetType.Classification}\n headingElementRef={headingRef}\n key={widget.id}\n id={widget.id}\n name={getWidgetHeading(widget, idx)}\n description={widget.description}\n classification={props.classification}\n templateId={widget.templateId}\n widgetTypeId={widget.widgetId}\n audiences={props.audiences}\n getContentRequest={getWidgetContentRequest}\n setIsEmpty={onSetIsEmpty}\n appLinks={props.appLinks}\n presentation={props.presentation}\n analyticsData={props.analyticsData}\n isScrollToTargetWidget={props.scrollToWidgetId === widget.id}\n imageCdnUrl={props.imageCdnUrl}\n imageUrls={props.imageUrls}\n onSubmitFeedback={props.onSubmitFeedback}\n onDownloadAllClick={props.onDownloadAllClick}\n metadata={widget.metadata}\n isBot={props.isBot}\n hasTableOfContents={shouldShowSideTableOfContents}\n lazyLoad={props.lazyLoad}\n dashboardTarget={CuratedDashboardHelper.getDashboardTargetType(props.dashboard)}\n widgetIndex={idx}\n hasPermissions={props.hasPermissions}\n hasLocalPermissions={props.hasLocalPermissions}\n isPreviewing={props.isReadonly}\n contentType={props.contentType}\n resourceThumbnailFallbackImageUrl={props.resourceThumbnailFallbackImageUrl}\n onToggleFollowClassification={props.onToggleFollow}\n settings={props.settings}\n isEditing={props.isReadonly}\n isTertiaryCustomerWithoutExchange={props.isTertiaryCustomerWithoutExchange}\n commonVideoProps={props.commonVideoProps}\n curriculums={props.curriculums}\n\n // TODO: Do we actually need this shit if it wasn't even being passed in?\n limitTotalItems={false}\n seeMoreLink={null}\n onClickRemoveItem={null}\n badgeComponent={null}\n />\n );\n })}\n </div>\n\n {!!videoList?.length && (\n <>\n <WidgetHeader name={LanguageService.getPhrase(namespace, 'videos')} />\n <VideoList\n videos={videoList}\n getVideoAppLink={(video, opts) => props.appLinks.videoType(\n video,\n { ...opts, contextId: videoListWidgetId, includeContext: opts.includeContext }\n )}\n hasPermissions={props.hasPermissions}\n presentationAudiences={props.audiences}\n getPreviewQuestionsAppLink={props.appLinks.previewQuestions}\n commonVideoProps={props.commonVideoProps}\n />\n </>\n )}\n </div>\n )}\n\n {showEmptyState && (\n <CuratedClassificationEmptyState\n dashboard={props.dashboard}\n isReadonly={props.isReadonly}\n imageUrl={props.emptyImageUrl}\n addWidgetApplink={props.appLinks.widgetWizard}\n />\n )}\n\n {props.isTeacherOnly && (\n <TeacherOnlyEmptyState\n imageUrl={props.emptyImageUrl}\n ctaAppLink={() => props.appLinks.allTopics(props.classification.presentationId)}\n />\n )}\n </div>\n );\n}\n","import React from 'react';\n\nimport { PartialAudienceFilter } from 'libs/shared/apps/subjects/components/audience-filter/AudienceFilter';\nimport { PartialBannerHeader } from 'libs/shared/components/banner-header/BannerHeader';\nimport { PartialBreadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\n\nexport function PartialClassificationDashboard(): JSX.Element {\n return (\n <div className='bg-white px-4'>\n <PartialBannerHeader />\n\n <div className='d-flex flex-column row-gap-3 py-3 mb-3 border-bottom'>\n <PartialBreadcrumbs />\n <PartialAudienceFilter />\n </div>\n </div>\n );\n}\n","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\n\nconst endpoints = {\n follow: () => `{gateway}/v1/users/me/classifications/following`,\n unfollow: (ids: string[]) => UrlHelper.urlBuilder('{gateway}/v1/users/me/classifications/following', { id: ids })\n};\n\nexport const FollowRequests = {\n /**\n * @param data - array of object ids the user is going to follow\n */\n follow(ids: string[], userId: string, success?: (data: string[]) => void, error?: () => void): Flight.Request {\n return {\n url: endpoints.follow(),\n key: `follow:${ids.join(',')}`,\n type: HttpVerbs.POST,\n data: ids,\n formatData: () => {\n return ids.map(id => ({\n id,\n followers: {\n data: [userId]\n }\n }));\n },\n success,\n error,\n invalidationKeys: [ ...ids.map(id => `classification:${id}`), 'my:subject:preferences', 'classifications' ]\n };\n },\n\n unfollow(ids: string[], userId: string, success?: () => void, error?: () => void): Flight.Request {\n return {\n url: endpoints.unfollow(ids),\n key: `unfollow:${ids.join(',')}`,\n type: HttpVerbs.DELETE,\n formatData: () => {\n return ids.map(id => ({\n id,\n followers: {\n data: [] as string[]\n }\n }));\n },\n success,\n error,\n invalidationKeys: [ ...ids.map(id => `classification:${id}`), 'my:subject:preferences', 'classifications' ]\n };\n }\n};\n","@import '~styles/utils/include-media';\n\n.followButton {\n @include media('<=sm') {\n min-width: 2.5rem;\n min-height: 2.5rem;\n }\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, HashObject, LocationContext, ToggleDescriptor, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { FollowRequests } from 'libs/shared/flight-requests/FollowRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { BellFilledSvg } from 'libs/shared/images/svg/objects/BellFilledSvg';\nimport { BellSvg } from 'libs/shared/images/svg/objects/BellSvg';\nimport { Classification, CurrentUser } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport styles from './use-follow-classification.module.scss';\n\nconst getPhrase = LanguageService.encloseNamespace('subjects.classification');\n\ninterface UseFollowClassificationOptions {\n classification: Classification;\n analyticsData: HashObject;\n}\n\ninterface UseFollowClassificationResult {\n canFollowSubjects: boolean;\n showFollowButtonSpinner: boolean;\n onToggleFollow: (classification: Classification, location: LocationContext) => void;\n getFollowBannerActions: () => ActionOptions[];\n}\n\nexport function useFollowClassification(\n options: UseFollowClassificationOptions\n): UseFollowClassificationResult {\n const { classification, analyticsData } = options;\n\n const [ showFollowButtonSpinner, setShowFollowButtonSpinner ] = React.useState<boolean>(false);\n\n const alerts = useAlerts();\n const fetchAsync = Flight.useGetFetchAsync();\n const { hasPermissions } = usePermissions();\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const isSmallScreen = useMediaQuery(MediaQueryStrings.MDDown);\n const isMobile = useMediaQuery(MediaQueryStrings.SMDown);\n\n const canFollowSubjects = hasPermissions(PermissionName.FollowSubjects);\n\n function onToggleFollow(followedClassification: Classification, location: LocationContext) {\n if (!canFollowSubjects || !classification)\n return;\n\n const isTogglingCurrentTopic = followedClassification.id.toString() === classification.id?.toString();\n\n if (isTogglingCurrentTopic)\n setShowFollowButtonSpinner(true);\n\n const isFollowing = TopicsHelper.isFollowing(followedClassification);\n\n const request = isFollowing ?\n FollowRequests.unfollow :\n FollowRequests.follow;\n\n fetchAsync(request([followedClassification.id], currentUser.data?.id))\n .then(() => {\n AnalyticsHelper.logUserAction(analyticsData, {\n location,\n actionType: UserAction.Follow,\n workflowPhase: WorkflowPhase.Complete,\n descriptor: isFollowing ? ToggleDescriptor.Off : ToggleDescriptor.On,\n entity: EntityType.Classification\n });\n\n if (!isTogglingCurrentTopic) {\n alerts.success(getPhrase(isFollowing ? 'unfollowed' : 'followed', { name: followedClassification.name }));\n }\n })\n .finally(() => {\n if (isTogglingCurrentTopic)\n setShowFollowButtonSpinner(false);\n });\n }\n\n function getFollowBannerActions(): ActionOptions[] {\n if (!canFollowSubjects || !classification)\n return [];\n\n const isFollowing = !!classification.followers?.data?.length;\n\n return [{\n label: isMobile ? '' : getPhrase(isFollowing ? 'following' : 'follow'),\n onClick: () => onToggleFollow(classification, LocationContext.Banner),\n svg: isFollowing ? BellFilledSvg : BellSvg,\n className: `btn follow-btn ${isFollowing ? 'btn-outline-dark' : 'btn-dark'} ${styles.followButton}`,\n button: true,\n tooltip: (isFollowing || isSmallScreen) ? undefined : getPhrase('followBtnTooltip'),\n showSpinner: showFollowButtonSpinner\n }];\n }\n\n return {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n };\n}\n","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { ErrorCta, ErrorPageError } from 'libs/shared/errors/primitives/ErrorPageError';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nconst namespace = 'subjects.topicNotFoundError';\n\nexport class TopicNotFoundError extends ErrorPageError {\n constructor() {\n super('Topic doesn\\'t exist');\n }\n\n // @ts-ignore\n public get name(): string {\n return 'TopicNotFoundError';\n }\n\n // @ts-ignore\n public get heading(): string {\n return LanguageService.getPhrase(namespace, 'heading');\n }\n\n // @ts-ignore\n public get description(): string {\n return LanguageService.getPhrase(namespace, 'description');\n }\n\n // @ts-ignore\n public get cta(): ErrorCta {\n return {\n text: LanguageService.getPhrase(namespace, 'cta'),\n appLink: {\n application: AppChannels.SUBJECT,\n action: Actions.Subjects.PRESENTATION_TOPICS,\n args: [null]\n }\n };\n }\n}\n","import { useSettings } from 'libs/shared/hooks/useSettings';\nimport { DashboardTargetType } from 'libs/shared/interfaces';\n\nimport { useFetchCuratedDashboard } from 'shared/utils/DashboardHelper';\n\nimport { ClassificationViewQueryParams } from '../views/classification/ClassificationViewUtils';\n\nexport function useFetchClassificationDashboard(\n id: string,\n queryParams: ClassificationViewQueryParams,\n targetType: DashboardTargetType\n) {\n const { hasTopicDirectories, hasTopicVideoListFeature } = useSettings(null);\n\n const {\n dashboard: curatedTopicDashboard,\n isPreviewing,\n isTeacherOnly\n } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.Classification\n });\n\n const { dashboard: directoryDashboard } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.ClassificationDirectory\n });\n\n const { dashboard: curriculumDashboard } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.ClassificationCurriculum\n });\n\n function getDashboard() {\n switch (targetType) {\n case DashboardTargetType.Classification:\n return curatedTopicDashboard;\n case DashboardTargetType.ClassificationDirectory:\n return directoryDashboard;\n case DashboardTargetType.ClassificationCurriculum:\n return curriculumDashboard;\n }\n }\n\n return {\n dashboard: getDashboard(),\n hasTopicDirectoryDashboard: hasTopicDirectories && !!directoryDashboard.data,\n hasTopicCurriculumDashboard: hasTopicVideoListFeature && !!curriculumDashboard.data,\n isTeacherOnly,\n isPreviewing\n };\n}\n","import React from 'react';\n\nimport { LocationUtils } from 'libs/common/backbone/core';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, LocationContext, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { CalendarRequests } from 'libs/shared/apps/calendar/flight-request/CalendarRequests';\nimport { LibraryHelper } from 'libs/shared/apps/libraries/utils/LibraryHelper';\nimport { ClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/ClassificationDashboard';\nimport { PartialClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard';\nimport { PreviewBanner } from 'libs/shared/apps/subjects/components/preview-banner/PreviewBanner';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { DashboardFeedbackData } from 'libs/shared/components/feedback-form/FeedbackForm';\nimport { VideoActionsContext } from 'libs/shared/context/VideoActionsContext';\nimport { ClassificationStatus } from 'libs/shared/enums/ClassificationStatus';\nimport { ClassificationType } from 'libs/shared/enums/ClassificationType';\nimport { FeedbackType } from 'libs/shared/enums/FeedbackType';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { ProductId } from 'libs/shared/enums/ProductId';\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClassificationRequests } from 'libs/shared/flight-requests/ClassificationRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { CustomerRequests } from 'libs/shared/flight-requests/CustomerRequests';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { FeedbackRequests } from 'libs/shared/flight-requests/FeedbackRequests';\nimport { LibraryRequests } from 'libs/shared/flight-requests/LibraryRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useBreadcrumbs } from 'libs/shared/hooks/useBreadcrumbs';\nimport { useCurationStudio } from 'libs/shared/hooks/useCurationStudio';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useProducts } from 'libs/shared/hooks/UseProducts';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { CalendarEvent, Classification, Config, CuratedWidgetQueryParams, CurrentUser, Customer, DashboardTargetType, Library, Presentation, PresentationAudience, RegionAlternative } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { FeedbackFormHelper } from 'libs/shared/utils/FeedbackFormHelper';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { DashboardWidgetImageUrls } from 'shared/constants/DashboardWidgetImageUrls';\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { ContentPartnersRequests } from 'shared/flight-requests/ContentPartnersRequests';\nimport { useAvailablePresentations } from 'shared/hooks/presentations/useAvailablePresentations';\nimport { useFollowClassification } from 'shared/hooks/use-follow-classification/useFollowClassification';\nimport { useVideoActions, VideoActionsLocation } from 'shared/hooks/use-video-actions/useVideoActions';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDeepLinks } from 'shared/hooks/useDeepLinks';\nimport { useDownloadAllResources } from 'shared/hooks/useDownloadAllResources';\nimport { ClassificationAppLinkHelper } from 'shared/utils/ClassificationAppLinkHelper';\nimport { InteractiveHelpers } from 'shared/utils/InteractiveHelper';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\n\nimport { useIsTertiary } from 'apps/onboarding/hooks/useIsTertiary';\nimport { SignUpHelper } from 'apps/sign-up/utils/SignUpHelper';\nimport { TopicNotFoundError } from 'apps/subjects/errors/TopicNotFoundError';\nimport { useFetchClassificationDashboard } from 'apps/subjects/hooks/useFetchClassificationDashboard';\nimport {\n ClassificationViewQueryParams,\n getClassificationAppLinks\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\n\ninterface CuratedClassificationViewProps {\n presentationSlug: string | null;\n id: string;\n queryParams?: ClassificationViewQueryParams;\n targetType: DashboardTargetType;\n}\n\nCuratedClassificationView.defaultProps = {\n queryParams: {}\n};\n\nconst namespace = 'subjects.classification';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function CuratedClassificationView(props: CuratedClassificationViewProps): React.ReactElement {\n const fetchAsync = Flight.useGetFetchAsync();\n const { hasPermissions, hasLocalPermissions } = usePermissions();\n const settings = useSettings(null);\n const onDownloadAllClick = useDownloadAllResources();\n\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const { openInCurationStudioLabel, isUserCurator, getOpenInCurationStudioLink } = useCurationStudio();\n const curriculums = useCurriculums();\n\n const customer = Flight.useBasicFetch<Customer>(\n hasPermissions(PermissionName.CanSubmitFeedback) &&\n currentUser.data?.isAuthenticated &&\n CustomerRequests.customer(currentUser.data.customerId)\n );\n\n const classification = Flight.useBasicFetch<Classification>(\n ClassificationRequests.classification(props.id, currentUser.data?.id)\n );\n\n const isHubDashboard = classification.data?.type === ClassificationType.Hub;\n // Once inside a hub topic's dashboard, every generated app link should carry\n // its id forward so navigating deeper (series/videos/sub-topics) keeps that context.\n const hubTopicId = isHubDashboard ? classification.data?.id : props.queryParams.hubTopic;\n\n const presentation = Flight.useBasicFetch<Presentation>(\n classification.data &&\n ClassificationRequests.presentationById(classification.data.presentationId)\n );\n\n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n classification.data &&\n AudienceRequests.audiencesByPresentationId(classification.data.presentationId)\n );\n\n const specialEvent = Flight.useBasicFetch<CalendarEvent>(\n classification.data &&\n CalendarRequests.nextTopicSpecialEvent(props.id, classification.data.presentationId)\n );\n\n const libraries = Flight.useBasicFetch<Library[]>(\n currentUser.data?.isAuthenticated &&\n LibraryRequests.libraries()\n );\n\n const {\n availablePresentations,\n canAccessPresentation\n } = useAvailablePresentations();\n\n const path = Flight.useBasicFetch<Classification[]>(ClassificationRequests.path(props.id));\n\n const {\n dashboard,\n hasTopicDirectoryDashboard,\n hasTopicCurriculumDashboard,\n isPreviewing,\n isTeacherOnly\n } = useFetchClassificationDashboard(props.id, props.queryParams, props.targetType);\n\n const isTertiary = useIsTertiary();\n const products = useProducts();\n\n const regionAlternatives = Flight.useBasicFetch<RegionAlternative[]>(\n ClassificationRequests.regionAlternatives(props.id)\n );\n\n const preferredRegionAlternative = SeoHelper.getPreferredRegionAlternative(\n regionAlternatives.data,\n currentUser.data?.contentRegion\n );\n useSetPageMetadata(PageMetadataHelper.getClassificationMetadata({\n content: { classification: classification.data, dashboard: dashboard.data },\n\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: ClassificationAppLinkHelper.getAppLink({\n ...classification.data,\n name: preferredRegionAlternative?.name || classification.data?.name\n }, props.queryParams, availablePresentations),\n hrefTransformer: SeoHelper.createRegionHrefTransformer(\n regionAlternatives.data,\n currentUser.data?.contentRegion\n )\n }),\n allowIndexing: SeoHelper.allowIndexing(),\n hrefLang: SeoHelper.getContentHrefLang(regionAlternatives.data, () => (\n ClassificationAppLinkHelper.getAppLink(classification.data, {}, availablePresentations)\n ))\n }));\n\n useHandleObjectError(classification, {\n notFound: TopicNotFoundError\n });\n useDeepLinks({ id: props.id, app: 'topics' });\n \n const { commonVideoProps } = useCommonVideoProps({\n locationContext: LocationContext.VideoThumbnail,\n mtv: props.queryParams.mtv,\n hubTopic: hubTopicId\n });\n const videoActions = useVideoActions({\n location: VideoActionsLocation.VideoItem,\n presentationSlug: props.presentationSlug\n });\n\n const activeAudiences = React.useMemo(\n () => AudienceHelper.getActiveAudiencesFromParams(audiences.data, props.queryParams),\n [ audiences.data, props.queryParams ]\n );\n const activeAudienceIds = activeAudiences?.map(a => a.masterId) ?? [];\n\n const analyticsData = {\n presentationId: presentation.data?.id,\n presentationName: presentation.data?.name,\n currentClassificationId: classification.data?.id,\n currentClassificationName: classification.data?.name,\n followingCurrentClassification: !!classification.data?.followers?.data?.length,\n activeAudienceNames: activeAudiences?.length ? activeAudiences.map(a => a.name) : null,\n activeAudienceIds: activeAudienceIds.length ? activeAudienceIds : null\n };\n\n const {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n } = useFollowClassification({\n classification: classification.data,\n analyticsData\n });\n\n const isComingSoon = (\n classification.data?.status === ClassificationStatus.ComingSoon &&\n !isPreviewing\n );\n\n const targetType = CuratedDashboardHelper.getDashboardTargetType(dashboard.data);\n\n async function onSubmitFeedback(feedback: DashboardFeedbackData): Promise<void> {\n const promise = await fetchAsync<void>(FeedbackRequests.submitFeedback({\n type: FeedbackType.Footer,\n user: FeedbackFormHelper.getUserInfo(currentUser.data, customer.data),\n tags: FeedbackFormHelper.getTags(\n currentUser.data,\n ProductId.Primary,\n hasPermissions(PermissionName.StudentExperience),\n [ 'topics', 'in product feedback' ]\n )\n }, {\n reaction: feedback.type,\n feedback: feedback.content,\n location: 'Topic Footer',\n presentationName: presentation.data.description,\n presentationId: presentation.data.id,\n dashboardName: dashboard.data.name,\n dashboardId: dashboard.data.id,\n classificationName: classification.data.name,\n classificationId: classification.data.id,\n currentPageUrl: LocationUtils.GetCurrentUrl()\n }));\n\n AnalyticsHelper.logUserAction({\n feedbackType: feedback.type,\n content: feedback.content,\n presentationId: presentation.data.id,\n classificationId: classification.data.id,\n dashboardId: dashboard.data.id\n }, {\n actionType: UserAction.Submit,\n location: LocationContext.ClassificationFooter,\n entity: EntityType.Feedback,\n workflowPhase: WorkflowPhase.Complete\n });\n\n return promise;\n }\n\n function getBannerActions(): ActionOptions[] {\n if (isHubDashboard || isChannelTopic) {\n return [];\n }\n\n const followActions = getFollowBannerActions();\n\n if (!isUserCurator)\n return followActions;\n\n return [\n ...followActions.map(action => ({ ...action, className: `${action.className} me-2` })),\n {\n label: openInCurationStudioLabel,\n href: getOpenInCurationStudioLink(MasterType.Subject, classification.data?.id, presentation.data?.id),\n openInNewTab: true\n }\n ];\n }\n\n const appLinks = getClassificationAppLinks(\n classification.data,\n targetType,\n { ...props.queryParams, hubTopic: hubTopicId },\n currentUser.data,\n props.presentationSlug,\n availablePresentations\n );\n\n const breadcrumbs = useBreadcrumbs({ name: classification.data?.name });\n function getBreadcrumbs(): () => Breadcrumb[] {\n if (!canAccessPresentation(presentation.data?.id))\n return;\n\n return () => breadcrumbs;\n }\n\n function getWidgetContentRequest(\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate,\n cursor?: string\n ): Flight.Request {\n const { hasTwig, hasTigtag } = LibraryHelper.hasTwigOrTigtag(libraries.data, currentUser.data);\n\n return DashboardRequests.dashboardWidgetContent(\n id,\n params,\n widgetTemplate,\n presentation.data,\n { hideTigTag: !hasTigtag, hideTwig: !hasTwig, cursor }\n );\n }\n\n const isChannelTopic = dashboard.data?.metadata?.channelId;\n const channel = Flight.useBasicFetch(isChannelTopic\n && ContentPartnersRequests.partnerProfile(dashboard.data?.metadata?.channelId));\n\n const dataLoaded = !!config.data\n && dashboard.hasCompleted\n && !!classification.data\n && !!presentation.data\n && !!path.data\n && !!availablePresentations\n && !!audiences.data\n && specialEvent.hasCompleted\n && (!isChannelTopic || channel.hasCompleted);\n\n if (!dataLoaded && !isHubDashboard)\n return <PartialClassificationDashboard />;\n\n return (\n <VideoActionsContext.Provider value={videoActions}>\n <div className='position-relative'>\n {!!(isPreviewing && dashboard.data) && <PreviewBanner status={dashboard.data.status} type='topic' />}\n <ClassificationDashboard\n dashboard={dashboard.data}\n classification={classification.data}\n channel={channel.data}\n getWidgetContentRequest={getWidgetContentRequest}\n getWidgetContentRequestWithCursor={getWidgetContentRequest}\n getBreadcrumbs={getBreadcrumbs()}\n hasPermissions={hasPermissions}\n hasLocalPermissions={hasLocalPermissions}\n presentation={presentation.data}\n curriculums={curriculums}\n onToggleFollow={onToggleFollow}\n getBannerActions={getBannerActions}\n audiences={props.queryParams.mtv ? null : audiences.data}\n activeAudiences={activeAudiences}\n analyticsData={analyticsData}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrls={DashboardWidgetImageUrls}\n resourceThumbnailFallbackImageUrl={ImageUrls.Fallbacks.RESOURCE_THUMBNAIL}\n emptyImageUrl={isTeacherOnly ? ImageUrls.EmptyStates.Topics.TEACHER_ONLY : ImageUrls.EmptyStates.Topics.TOPIC}\n isComingSoon={isComingSoon}\n showFollowButtonSpinner={showFollowButtonSpinner}\n comingSoonImageUrl={ImageUrls.EmptyStates.Topics.COMING_SOON}\n appLinks={{\n ...appLinks,\n signUp: SignUpHelper.getSignUpAppLink,\n widgetWizard: () => null,\n previewQuestions: interactive => InteractiveHelpers.getPreviewQuestionsAppLink(interactive)\n }}\n isPreviewing={isPreviewing}\n canFollowSubjects={canFollowSubjects}\n onSubmitFeedback={\n hasPermissions(PermissionName.CanSubmitFeedback) &&\n onSubmitFeedback\n }\n tableOfContentsId={props.queryParams.tocId}\n lazyLoad={!SeoHelper.isBot()}\n moviesAndTv={props.queryParams.mtv}\n isTeacherOnly={isTeacherOnly}\n specialEvent={specialEvent.data}\n isBot={SeoHelper.isBot()}\n hasTopicDirectoryDashboard={hasTopicDirectoryDashboard}\n hasTopicCurriculumDashboard={hasTopicCurriculumDashboard}\n tab={TopicsHelper.getActiveTopicTab(classification.data, props.targetType)}\n // just... one... more.. prop....\n settings={settings}\n isTertiaryCustomerWithoutExchange={isTertiary && !products?.hasProduct(ProductId.Exchange)}\n commonVideoProps={commonVideoProps}\n onDownloadAllClick={onDownloadAllClick}\n />\n </div>\n </VideoActionsContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { ClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/ClassificationDashboard';\nimport { PartialClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard';\nimport { PreviewBanner } from 'libs/shared/apps/subjects/components/preview-banner/PreviewBanner';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { VideoActionsContext } from 'libs/shared/context/VideoActionsContext';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { PresentationType } from 'libs/shared/enums/PresentationType';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClassificationRequests } from 'libs/shared/flight-requests/ClassificationRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useCurationStudio } from 'libs/shared/hooks/useCurationStudio';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { CalendarEventContentType, Classification, Config, CurrentUser, DashboardTargetType, PresentationAudience } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\n\nimport { DashboardWidgetImageUrls } from 'shared/constants/DashboardWidgetImageUrls';\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { useFollowClassification } from 'shared/hooks/use-follow-classification/useFollowClassification';\nimport { useVideoActions, VideoActionsLocation } from 'shared/hooks/use-video-actions/useVideoActions';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDownloadAllResources } from 'shared/hooks/useDownloadAllResources';\nimport { useFetchCuratedDashboard } from 'shared/utils/DashboardHelper';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\n\nimport { TopicNotFoundError } from 'apps/subjects/errors/TopicNotFoundError';\nimport {\n ClassificationViewQueryParams,\n getLiveClassificationAppLinks,\n getLiveClassificationBreadcrumbs\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\n\nconst namespace = 'liveClassification.classificationView';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface LiveClassificationViewProps {\n presentationSlug: string | null;\n id: string;\n queryParams?: ClassificationViewQueryParams;\n}\n\nLiveClassificationView.defaultProps = {\n queryParams: {}\n};\n\nexport function LiveClassificationView(\n props: LiveClassificationViewProps\n): JSX.Element {\n const { commonVideoProps } = useCommonVideoProps({ locationContext: LocationContext.VideoThumbnail });\n const videoActions = useVideoActions({\n location: VideoActionsLocation.VideoItem,\n presentationSlug: props.presentationSlug\n });\n const curriculums = useCurriculums();\n const onDownloadAllClick = useDownloadAllResources();\n\n const { openInCurationStudioLabel, isUserCurator, getOpenInCurationStudioLink } = useCurationStudio('clickview-live');\n\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const classification = Flight.useBasicFetch<Classification>(\n ClassificationRequests.classification(props.id, currentUser.data?.id)\n );\n\n const { dashboard, presentation, isPreviewing } = useFetchCuratedDashboard({\n targetType: DashboardTargetType.Classification,\n classificationId: props.id,\n queryParams: props.queryParams\n });\n\n // ClickView audiences are typed differently from Subject audiences for the same presentation id;\n // Fetch with the explicit Live type so we get the correct grade set.\n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n presentation &&\n AudienceRequests.presentationAudiences(PresentationType.StreamableLearning, presentation.id)\n );\n\n const path = Flight.useBasicFetch<Classification[]>(\n ClassificationRequests.path(props.id, PresentationType.StreamableLearning)\n );\n\n const appLinks = getLiveClassificationAppLinks(\n classification.data,\n props.queryParams,\n props.presentationSlug\n );\n\n useSetPageMetadata(PageMetadataHelper.getClassificationMetadata({\n content: { classification: classification.data, dashboard: dashboard.data },\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: appLinks.classification(classification.data)\n }),\n allowIndexing: SeoHelper.allowIndexing()\n }));\n\n useHandleObjectError(classification, {\n notFound: TopicNotFoundError\n });\n\n const activeAudiences = React.useMemo(\n () => AudienceHelper.getActiveAudiencesFromParams(audiences.data, props.queryParams),\n [ audiences.data, props.queryParams ]\n );\n const activeAudienceIds = activeAudiences?.map(a => a.masterId) ?? [];\n\n const analyticsData = {\n presentationId: presentation?.id,\n presentationName: presentation?.name,\n currentClassificationId: classification.data?.id,\n currentClassificationName: classification.data?.name,\n followingCurrentClassification: !!classification.data?.followers?.data?.length,\n activeAudienceNames: activeAudiences?.length ? activeAudiences.map(a => a.name) : null,\n activeAudienceIds: activeAudienceIds.length ? activeAudienceIds : null\n };\n\n const {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n } = useFollowClassification({\n classification: classification.data,\n analyticsData\n });\n\n function getBannerActions(): ActionOptions[] {\n const followActions = getFollowBannerActions();\n\n if (!isUserCurator)\n return followActions;\n\n return [\n ...followActions.map(action => ({ ...action, className: `${action.className} me-2` })),\n {\n label: openInCurationStudioLabel,\n href: getOpenInCurationStudioLink(MasterType.Subject, classification.data?.id, presentation?.id),\n openInNewTab: true\n }\n ];\n }\n\n function getBreadcrumbs(): () => Breadcrumb[] {\n return () => getLiveClassificationBreadcrumbs({\n appLinks,\n classification: classification.data,\n path: path.data,\n presentationSlug: props.presentationSlug\n });\n }\n\n const dataLoaded = !!config.data\n && dashboard.hasCompleted\n && !!classification.data\n && !!presentation\n && !!path.data\n && !!audiences.data;\n\n if (!dataLoaded)\n return <PartialClassificationDashboard />;\n \n return (\n <VideoActionsContext.Provider value={videoActions}>\n <div className='position-relative'>\n {!!(isPreviewing && dashboard.data) && (\n <PreviewBanner status={dashboard.data.status} type='topic' />\n )}\n <ClassificationDashboard\n dashboard={dashboard.data}\n classification={classification.data}\n getWidgetContentRequest={DashboardRequests.dashboardWidgetContent}\n getBreadcrumbs={getBreadcrumbs()}\n hasPermissions={() => false}\n hasLocalPermissions={() => false}\n presentation={presentation}\n getBannerActions={getBannerActions}\n onToggleFollow={onToggleFollow}\n showFollowButtonSpinner={showFollowButtonSpinner}\n audiences={audiences.data}\n activeAudiences={activeAudiences}\n analyticsData={analyticsData}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrls={DashboardWidgetImageUrls}\n resourceThumbnailFallbackImageUrl={ImageUrls.Live.Fallbacks.RESOURCE_THUMBNAIL}\n emptyImageUrl={ImageUrls.Live.EmptyStates.Topics.TOPIC}\n appLinks={appLinks}\n isPreviewing={isPreviewing}\n isViewCurrentPresentation\n canFollowSubjects={canFollowSubjects}\n tableOfContentsId={props.queryParams.tocId}\n lazyLoad={!SeoHelper.isBot()}\n isTeacherOnly={false}\n contentType={CalendarEventContentType.Livestream}\n hasTopicDirectoryDashboard={false}\n hasTopicCurriculumDashboard={false}\n isTertiaryCustomerWithoutExchange={false}\n tab='curated-topic'\n curriculums={curriculums}\n commonVideoProps={commonVideoProps}\n onDownloadAllClick={onDownloadAllClick}\n />\n </div>\n </VideoActionsContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { PresentationType } from 'libs/shared/enums/PresentationType';\nimport { DashboardTargetType } from 'libs/shared/interfaces';\n\nimport { createPresentationDispatcherView } from 'shared/utils/createPresentationDispatcherView';\n\nimport {\n ClassificationViewQueryParams\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\nimport {\n CuratedClassificationView\n} from 'apps/subjects/views/classification/curated-classification/CuratedClassificationView';\nimport {\n LiveClassificationView\n} from 'apps/subjects/views/classification/live-classification/LiveClassificationView';\n\ninterface ClassificationRouteProps {\n presentationSlug: string | null;\n id: string;\n queryParams: ClassificationViewQueryParams;\n targetType: DashboardTargetType;\n}\n\nexport const BaseClassificationView = createPresentationDispatcherView<ClassificationRouteProps>({\n [PresentationType.Subject]: ctx => (\n <CuratedClassificationView\n key={`${ctx.id}:${ctx.targetType}`}\n presentationSlug={ctx.presentationSlug}\n id={ctx.id}\n queryParams={ctx.queryParams}\n targetType={ctx.targetType}\n />\n ),\n [PresentationType.StreamableLearning]: ctx => {\n if (ctx.targetType !== DashboardTargetType.Classification)\n return null;\n\n return (\n <LiveClassificationView\n key={`${ctx.id}:${ctx.targetType}`}\n presentationSlug={ctx.presentationSlug}\n id={ctx.id}\n queryParams={ctx.queryParams}\n />\n );\n }\n});\n\nBaseClassificationView.displayName = 'BaseClassificationView';\n"],"mappings":"6lHAMM,GAAY,sCAEZ,IAAa,CAAE,gBACnB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAiB,qBAAW,GAAY,CAAA,EAM1C,SAAgB,GAA4B,EAA6D,CACvG,GAAM,CACJ,sBACA,2BACA,yBACA,8BACA,4BACE,EAAa,UAAU,EAAM,cAAc,EAEzC,EAAa,EAAsB,EACnC,EAAgB,EAAyB,EAE/C,OACE,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAU,iDAAb,CACG,CAAC,CAAC,IACD,EAAA,EAAA,IAAA,CAAC,EAAD,CACa,UAAA,GACX,OAAO,SACP,QAAS,CAAE,MAAO,EAAyB,eAAe,EAAG,WAAY,CAAyB,CACnG,CAAA,EAGF,CAAC,CAAC,IACD,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAA2B,IAAK,EAAA,EAAA,IAAA,CAAC,GAAD,CAAW,UAAU,MAAQ,CAAA,GAC9D,EAAA,EAAA,IAAA,CAAC,EAAD,CACa,UAAA,GACX,OAAO,SACP,QAAS,CAAE,MAAO,EAAW,eAAe,EAAG,WAAY,CAAW,CACvE,CAAA,CACD,CAAA,CAAA,EAEH,CAAC,CAAC,IACD,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAW,UAAU,MAAQ,CAAA,GAC7B,EAAA,EAAA,IAAA,CAAC,EAAD,CACa,UAAA,GACX,OAAO,YACP,QAAS,CAAE,MAAO,EAAc,eAAe,EAAG,WAAY,CAAc,CAC7E,CAAA,CACD,CAAA,CAAA,CAEH,GAEP,CChDA,IAAM,EAAY,2CACZ,GAAY,EAAgB,iBAAiB,CAAS,EAS5D,SAAgB,GAAgC,EAA0D,CACxG,IAAM,EAAa,EAAM,WAAW,SAAW,EAAgB,SAE/D,OACE,EAAA,EAAA,IAAA,CAAC,EAAyB,SAA1B,CAAmC,MAAO,YACxC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CAAkB,IAAK,EAAM,SAAU,QAAS,GAAU,cAAc,CAAI,CAAA,EAC1E,EAAM,YAKN,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAA,EAAW,OAAO,mBAAqB,CAAA,CACtC,CAAA,GACpB,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAA,EAAW,OAAO,MAAQ,CAAA,CAC5B,CAAA,GACjB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAS,MAAO,EAAa,EAAgB,UAAU,EAAW,oBAAoB,EAAI,GAAI,SAAA,aAC5F,EAAA,EAAA,IAAA,CAAC,EAAW,IAAZ,CACE,KAAM,EAAgB,UAAU,EAAW,KAAK,EAChD,QAAS,EAAM,mBAAmB,EAClC,UAAU,eACV,KAAM,GACN,SAAU,CACX,CAAA,CACM,CAAA,CACT,CAAA,CAAA,GApBF,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAO,cAAgB,CAAA,CACX,CAAA,CAoBZ,CAAA,CAAA,CACqB,CAAA,CAEvC,kEEzBA,SAAS,GAAsB,EAA6B,CAC1D,GAAM,CAAE,EAAY,GAAA,EAAwB,SAAS,EAAK,EAE1D,SAAS,GAAgB,CACvB,IAAM,EAAmB,CACvB,WAAa,EAA+B,EAAW,KAA7B,EAAW,KACrC,OAAQ,EAAW,gBACnB,SAAU,EAAgB,SAC5B,EAEA,GAAgB,cAAc,EAAM,cAAe,CAAgB,CACrE,CAEA,SAAS,GAAc,CACrB,EAAc,CAAC,CAAU,EACzB,EAAc,CAChB,CAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,GAAO,OAAO,+BAAjC,CAEG,IACC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,sEAAf,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,cAAM,EAAM,KAAU,CAAA,GACpC,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,IAAI,IACvB,CAAE,KAAM,EAAO,KAAM,GAAI,EAAO,GAAI,eAAgB,EAAO,SAAS,cAAe,EACpF,EACD,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,cAAe,EAAM,cACrB,gBAAiB,EAAM,gBACvB,WAAY,EAAM,WAClB,gBAAmB,EAAc,EAAK,CACvC,CAAA,CACE,KAEP,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAO,oBACrB,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAU,uBACV,IAAK,GACL,QAAS,CACV,CAAA,CACE,CAAA,CACF,GAET,CAEA,SAAS,GAAgB,EAA0C,CACjE,OACE,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAU,0BACf,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,GAAO,UAAU,gBAApC,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,cAAM,EAAM,KAAU,CAAA,GAEpC,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,IAAI,IACvB,CAAE,KAAM,EAAO,KAAM,GAAI,EAAO,GAAI,eAAgB,EAAO,SAAS,cAAe,EACpF,EACD,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,cAAe,EAAM,cACrB,gBAAiB,EAAM,gBACvB,WAAY,EAAM,UACnB,CAAA,CACE,GACA,CAAA,CAEX,CAEA,SAAgB,GAAyB,EAAmD,CAC1F,SAAS,EAAW,EAAqC,CACvD,IAAM,EAAiB,EAAe,gBAAgB,CAAC,CAAC,QAElD,EAAqB,EAAe,OACxC,CAAE,GAAI,EAAe,MAAsB,EAC3C,CAAC,EAIH,MAFA,GAAO,MAAQ,EAAO,GAEf,CACL,GAAG,EACH,QACF,CACF,CAEA,OACE,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAA,SACI,EAAM,eAEN,EAAA,EAAA,IAAA,CAAC,GAAD,CAAuB,GAAI,EAAmB,YAAa,CAAA,GAD3D,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,GAAI,EAAmB,YAAa,CAAA,CAGvD,CAAA,CAEN,CClHA,IAAM,GAAY,iCACZ,GAAY,EAAgB,iBAAiB,EAAS,EAO5D,SAAgB,GAAsB,EAAgD,CACpF,OACE,EAAA,EAAA,IAAA,CAAC,EAAyB,SAA1B,CAAmC,MAAO,aACxC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CAAkB,IAAK,EAAM,SAAU,QAAS,GAAU,SAAS,CAAI,CAAA,GACvE,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAO,SAAW,CAAA,CACN,CAAA,GACpB,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAO,MAAQ,CAAA,CACN,CAAA,GAEjB,EAAA,EAAA,IAAA,CAAC,EAAW,IAAZ,CACE,KAAM,GAAU,KAAK,EACrB,QAAS,EAAM,aAAa,EAC5B,UAAU,cACX,CAAA,CACS,CAAA,CAAA,CACqB,CAAA,CAEvC,CCdA,SAAgB,GAAoB,EAA6B,EAAmD,CAClH,GAAM,CACJ,6BACA,8BAAA,EACQ,YACH,EASE,CACL,2BAHiC,EAAuB,2BAA2B,EAAU,OAG7F,EACA,2BAA4B,EAAU,QAAQ,KAAK,GAE/C,EAAO,WAAa,EAAa,4BACjC,EAAO,aAAe,EAAe,qBAExC,CACH,EAhBS,CACL,2BAA4B,GAC5B,2BAA4B,IAC9B,EAcD,CAAC,GAAW,EAAE,CAAC,EAEZ,EAA8B,EAClC,CAAC,CAAC,GACF,GAAkB,uBAChB,GAA4B,GAC5B,EAAuB,gBACrB,EAA2B,SAC3B,EAA2B,WAC3B,EAAuB,uBAAuB,CAAS,EACvD,GAAiB,IAAI,GAAK,EAAE,QAAQ,CACtC,EACA,GAA4B,UAC9B,CACF,EAOA,OAJK,EAIE,CACL,QAAS,GAAW,SAAS,OAAO,GAC9B,EAAO,WAAa,EAAa,4BAGjC,EAAO,aAAe,EAAe,qBAI1C,GAAK,CAAC,EACP,UAAW,EAA4B,MAAM,SAAW,CAAC,EACzD,kBAAmB,GAA4B,EACjD,EAfS,CAAE,QAAS,EAAY,OAAO,GAAW,QAAS,OAAO,CAAE,CAgBtE,CChEA,IAAM,GAAY,oCACZ,GAAY,EAAgB,iBAAiB,EAAS,EAY5D,SAAgB,GAAyB,EAAqC,CAC5E,IAAM,EAAc,CAAC,CAAC,EAAM,KAAK,WAAW,MAAM,OAClD,SAAS,GAAgB,CACvB,EAAM,iBAAiB,CACzB,CAEA,OACE,EAAA,EAAA,IAAA,CAAC,EAAyB,SAA1B,CAAmC,MAAO,aACxC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAY,UAAU,gBAAtB,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CAAkB,IAAK,EAAM,SAAU,QAAS,GAAU,YAAY,CAAI,CAAA,GAE1E,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAO,YAAc,CAAA,CACT,CAAA,GAEpB,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAQ,EAAM,WAAa,WAAa,MAAS,CAAA,CACxC,CAAA,EAEhB,EAAM,oBACL,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,IAAK,EAAc,EAAgB,GAC1B,UACT,YAAa,EAAM,wBACnB,UAAW,uBAAuB,EAAc,mBAAqB,uBAErE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,OAAQ,EAAc,YAAc,QAAW,CAAA,CACzC,CAAA,EAGf,EAAM,YAAc,CAAC,EAAM,oBAC1B,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAM,cACf,UAAU,wCACV,iBAAkB,CAChB,WAAY,EAAW,MACvB,SAAU,EAAgB,yBAC1B,OAAQ,EAAW,QACnB,cAAe,EAAc,MAC7B,WAAY,EAAkB,MAChC,EACA,cAAe,CAAC,EAChB,IAAI,kBAEH,GAAU,QAAQ,CACZ,CAAA,CAED,GACqB,CAAA,CAEvC,CC9DA,SAAgB,GAAiC,EAA2D,CAC1G,OACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAM,UACjB,gBAAiB,EAAM,gBACvB,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,eAAgB,EAAM,eACtB,QAAS,EAAM,OAChB,CAAA,CAEL,CCzBA,SAAgB,GAAgB,EAAsC,CACpE,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,GAAI,YACP,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,EAAE,uXACF,KAAK,cACN,CAAA,CACE,CAAA,CAET,CCAA,SAAgB,GAAkC,EAAgC,CAMhF,GAAM,CAAE,EAAW,GAAiB,GAAwB,iCAAkC,CAJ5F,GAAI,GACJ,IAAK,GAAc,cAGyE,CAAY,EA0B1G,OAxBA,EAAM,cAAgB,CACf,GAGL,EAAa,MAAO,CAAU,CAChC,EAAG,CAAC,CAAU,CAAC,EAEf,EAAM,cAAgB,CACpB,IAAI,EAAmB,KAWvB,OATI,EAAU,KACZ,EAAW,OAAO,gBAAkB,CAC9B,EAAU,MAAQ,gBAAkB,EAAU,MAAQ,aACxD,EAAa,MAAO,EAAU,MAAQ,eAAiB,aAAe,cAAc,EAEpF,EAAa,MAAO,EAAU,MAAQ,gBAAkB,aAAe,eAAe,CAC1F,EAAG,GAAI,OAGI,CACX,OAAO,cAAc,CAAQ,CAC/B,CACF,EAAG,CAAE,EAAU,GAAI,EAAU,GAAI,CAAC,EAE3B,CACL,IAAK,EAAU,IACf,eAAgB,EAAU,GAC1B,UAAa,EAAa,KAAM,EAAI,EACpC,SAAY,CACV,EAAa,CACX,GAAI,GACJ,IAAK,GAAc,EAAU,GAC/B,CAAC,CACH,CACF,CACF,2FElCM,EAAY,iCAIlB,SAAS,GACP,EACA,EACA,EACA,EACW,CACX,IAAM,EAAW,EAAY,IAAM,EAAY,IAAM,EAAY,KAAO,EAAY,GAEpF,SAAS,GAA+B,CACtC,IAAI,EAAY,EAAiB,EAAO,cAAgB,GAQxD,OANI,EAAY,GACP,EAAY,SAEjB,EACK,EAAY,IAAI,EAAO,kBAEzB,CACT,CA8CA,OA5CI,EAAa,gBAAgB,EAAM,cAAc,EAC5C,CAAC,CACN,KAAM,EAAW,EAAgB,UAAU,EAAW,aAAa,EAAI,GACvE,QAAS,EAAM,UAAU,iBAAiB,EAAM,cAAc,EAC9D,OAAQ,IAAc,eACtB,IAAK,GACL,cAAe,CACb,GAAI,eACJ,iBAAkB,EAAM,eAAe,GACvC,mBAAoB,EAAM,eAAe,KACzC,eAAgB,EAAM,aAAa,GACnC,wBAAyB,EAAM,aAAa,YAC5C,KAAM,EAAgB,UAAU,EAAW,aAAa,EACxD,IAAA,EAAwB,QAAQ,EAAM,UAAU,iBAAiB,EAAM,cAAc,CAAC,CACxF,EACA,iBAAkB,CAChB,WAAY,EAAW,MACvB,OAAQ,EAAW,IACnB,SAAU,EAAgB,SAC5B,EACA,UAAW,GAAG,EAAY,GAAK,QAAU,GAAG,GAAG,EAAiB,EAAO,cAAgB,IACzF,EAAG,CACD,KAAM,EAAW,EAAgB,UAAU,EAAW,WAAW,EAAI,GACrE,QAAS,EAAM,UAAU,0BAA0B,EAAM,cAAc,EACvE,OAAQ,IAAc,aACtB,IAAK,EACL,cAAe,CACb,GAAI,aACJ,iBAAkB,EAAM,eAAe,GACvC,mBAAoB,EAAM,eAAe,KACzC,eAAgB,EAAM,aAAa,GACnC,wBAAyB,EAAM,aAAa,YAC5C,KAAM,EAAgB,UAAU,EAAW,WAAW,EACtD,IAAA,EAAwB,QAAQ,EAAM,UAAU,0BAA0B,EAAM,cAAc,CAAC,CACjG,EACA,iBAAkB,CAChB,WAAY,EAAW,MACvB,OAAQ,EAAW,IACnB,SAAU,EAAgB,SAC5B,EACA,UAAW,GAAG,EAAY,GAAK,QAAU,GAAG,GAAG,EAAiB,EAAO,cAAgB,IACzF,CAAC,EAGI,CAAC,CACN,KAAM,EAAW,EAAgB,UAAU,EAAW,OAAO,EAAI,GACjE,QAAS,EAAM,UAAU,iBAAiB,EAAM,cAAc,EAC9D,OAAQ,IAAc,gBACtB,IAAK,GACL,cAAe,CACb,GAAI,gBACJ,iBAAkB,EAAM,eAAe,GACvC,mBAAoB,EAAM,eAAe,KACzC,eAAgB,EAAM,aAAa,GACnC,wBAAyB,EAAM,aAAa,YAC5C,KAAM,EAAgB,UAAU,EAAW,OAAO,EAClD,IAAA,EAAwB,QAAQ,EAAM,UAAU,iBAAiB,EAAM,cAAc,CAAC,CACxF,EACA,iBAAkB,CAChB,WAAY,EAAW,MACvB,OAAQ,EAAW,IACnB,SAAU,EAAgB,SAC5B,EACA,UAAW,EAAqB,CAClC,EAAG,CACD,KAAM,EAAW,EAAgB,UAAU,EAAW,YAAY,EAAI,GACtE,QAAS,EAAM,UAAU,2BAA2B,EAAM,cAAc,EACxE,OAAQ,IAAc,aACtB,IAAK,GACL,cAAe,CACb,GAAI,aACJ,iBAAkB,EAAM,eAAe,GACvC,mBAAoB,EAAM,eAAe,KACzC,eAAgB,EAAM,aAAa,GACnC,wBAAyB,EAAM,aAAa,YAC5C,KAAM,EAAgB,UAAU,EAAW,YAAY,EACvD,IAAA,EAAwB,QAAQ,EAAM,UAAU,2BAA2B,EAAM,cAAc,CAAC,CAClG,EACA,iBAAkB,CAChB,WAAY,EAAW,MACvB,OAAQ,EAAW,IACnB,SAAU,EAAgB,SAC5B,EACA,UAAW,GAAG,EAAY,GAAK,QAAU,GAAG,GAAG,EAAiB,EAAO,cAAgB,IACzF,CAAC,CACH,CAaA,SAAgB,GAAmB,EAA6C,CAC9E,IAAM,EAAc,EAAe,EAC7B,CAAE,MAAK,kBAAmB,GAAkC,EAAM,SAAS,EAEjF,OACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,aAAa,KACb,UAAW,EAAY,GAAK,QAAU,GACtC,cAAc,qBACd,KAAM,GAAQ,EAAO,EAAa,EAAK,CAAc,CACtD,CAAA,CAEL,CC5IA,SAAS,GACP,EACA,EACA,EACA,EACA,EACS,CAaT,MAHA,GATI,GAGA,GAAW,CAAC,GAAiB,QAG7B,CAAC,EAAe,oBAAoB,CAAS,GAG7C,IAAc,aAIpB,CA6BA,SAAgB,GAA2B,EAAqD,CAC9F,IAAM,EAAc,EAAe,EAE7B,EAAgB,EAAM,oBAAsB,GAChD,EAAM,UACN,EAAM,gBACN,EAAM,UACN,EAAM,QACN,EAAM,YACR,EAEA,SAAS,GAAuB,CAmB9B,MAlBI,CAAC,EAAM,gBAAkB,CAAC,EAAM,WAGhC,EAAuB,2BAA2B,EAAM,UAAU,OAAO,EACpE,GAKL,EAAa,gBAAgB,EAAM,cAAc,EAC5C,EAAM,2BAKf,GAAI,EAAM,eAAe,kBAAkB,WAAa,EAAM,4BAIhE,CAEA,SAAS,GAA4B,CACnC,IAAI,EAAY,+BAQhB,OANK,EAAM,eACT,GAAa,mBAEV,EAAY,GAAK,IAAkB,CAAC,EAAY,GAC5C,EAEF,EAAY,YACrB,CAEA,SAAS,GAAyB,CAChC,GAAI,EAIF,OAHI,EAAY,GACP,uDAEF,oDAGT,IAAI,EAAY,GAOhB,MALA,IAAa,yDAET,EAAY,KACd,GAAa,mBAER,CACT,CAEA,SAAS,GAA4B,CACnC,IAAI,EAAY,iDAKhB,OAHI,EAAY,KACd,GAAa,wBAER,CACT,CAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAkB,WAAlC,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAe,WAA/B,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,YAAa,EAAM,iBAAiB,CAAI,CAAA,EAEpD,EAAY,GAAK,IAChB,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,eAAgB,EAAM,eACtB,UAAW,EAAM,UACjB,SAAU,EAAM,SAChB,aAAc,EAAM,YACrB,CAAA,CAEA,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAkB,WAAlC,CACG,CAAC,IACA,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAM,UACjB,gBAAiB,EAAM,gBACvB,QAAS,EAAM,SAAS,WAAW,EACnC,SAAU,EAAM,iBAChB,QAAS,EAAM,gBACf,eAAgB,CAAC,EAAM,4BACxB,CAAA,EAGF,EAAY,GAAK,CAAC,IACjB,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,eAAgB,EAAM,eACtB,UAAW,EAAM,UACjB,SAAU,EAAM,SAChB,aAAc,EAAM,YACrB,CAAA,CAEA,GACF,GAET,CCnIA,IAAM,GAAY,iCAElB,SAAS,GAAgB,EAAuB,CAC9C,OAAO,EAAO,WAAa,EAAa,OAAS,EAAO,aAAe,EAAe,OACxF,CAEA,SAAS,GAAc,EAAuB,CAC5C,OAAO,EAAO,WAAa,EAAa,wBAA0B,EAAO,WAAa,EAAa,eACrG,CAGA,IAAM,GAAyC,CAAC,EAAa,uBAAuB,EAEpF,SAAS,GAAoB,EAA0B,EAAwB,CAC7E,IAAM,EAAgB,EAAQ,GAI9B,OAFK,EAEE,GAAuB,SAAS,EAAc,QAAQ,GAAK,IAAU,EAAQ,OAAS,EAFlE,EAG7B,CAOA,SAAS,GAAqB,EAAmC,CAC/D,IAAM,EAAS,IAAU,GAQzB,OANK,EAED,EAAa,aAAa,EAAO,QAAQ,EAAU,GAEvD,CAAK,EAAO,SAEL,MAAM,QAAQ,EAAO,OAAO,GAAK,CAAC,EAAO,QAAQ,OANpC,EAOtB,CA8FA,GAAwB,aAAe,CACrC,SAAU,CAAC,CACb,EAEA,SAAgB,GAAwB,EAAkD,CACxF,GAAM,CAAE,UAAS,YAAW,qBAAsB,GAAoB,EAAM,UAAW,EAAM,eAAe,EAEtG,EAAgB,EAAc,EAAkB,MAAM,EACtD,EAAA,EAAmB,OAAqB,IAAI,GAAK,EAEjD,EAAA,EAA4B,YACzB,EAAQ,QAAQ,EAA0B,KAC/C,EAAI,EAAO,IAAM,GACV,GACN,CAAC,CAAC,EACJ,CAAC,GAAS,MAAM,CAAC,EAEd,CAAE,EAAc,GAAA,EAA0B,SAAS,CAAmB,EAEtE,CAAE,EAAc,GAAA,EAA0B,SAAS,EAAM,iBAAiB,EAE1E,CAAE,EAAwB,GAAA,EAAoC,SAAiB,EAAE,EAEjF,EAAkB,MAAM,KAAK,EAAW,OAAO,EACrD,GAAyB,EAAiB,CAAY,EACtD,GAAgC,CAC9B,YAAa,EACb,kBACA,eACA,iBACF,CAAC,EAED,IAAM,EAAiB,EAAM,eAAe,OAAS,GAAmB,IAClE,EAAiB,CAAC,CAAC,EAAM,WAAW,UAAU,UAEpD,SAAS,GAAgC,CAsBvC,OArBI,EAAM,cAGN,EAAM,cACD,GAEL,CAAC,EAAM,WAGP,EAAM,UAAU,SAAW,EAAgB,UAAY,CAAC,EAAM,YAG9D,EAAM,UAAU,SAAW,EAAgB,OAAS,CAAC,EAAM,cAG3D,CAAC,GAAS,OACL,GAEL,GAAa,EAAU,OAClB,GAEF,OAAO,OAAO,CAAY,CAAC,CAAC,MAAM,GAAS,CAAC,CAAC,CAAK,CAC3D,CAEA,SAAS,EACP,EACA,EACA,EACA,EACgB,CAChB,IAAM,EAAS,EAAuB,gBACpC,EACA,EACA,EAAuB,uBAAuB,EAAM,SAAS,EAC7D,EAAM,iBAAiB,IAAI,GAAK,EAAE,QAAQ,EAC1C,EAAM,YAAY,qBAAqB,EACzC,EAKA,OAHI,GAAU,EAAM,kCACX,EAAM,kCAAkC,EAAI,EAAQ,EAAU,CAAM,EAEtE,EAAM,wBAAwB,EAAI,EAAQ,CAAQ,CAC3D,CAEA,IAAM,EAAiB,EAAqB,EAE5C,EAAM,cAAgB,CAMhB,GACF,EAAgB,CAAmB,CAEvC,EAAG,CAAC,GAAS,MAAM,CAAC,EAEpB,IAAM,EAAA,EAAqB,aAAa,EAAkB,IAAqB,CAC7E,GAAI,EAAa,KAAc,EAC7B,OAEF,IAAM,EAAgB,CACpB,GAAG,GACF,GAAW,CACd,EAKA,GAAI,EAAuB,OAAO,EAAM,UAAW,EAAoB,uBAAuB,EAAG,CAC/F,EAAgB,CAAa,EAC7B,MACF,CAEA,IAAI,EAAQ,EAOZ,KAAO,EAAQ,EAAQ,QAAQ,CAC7B,IAAM,EAAgB,EAAQ,GAE9B,GAAI,CAAC,GAAgB,CAAa,EAAG,CACnC,IACA,QACF,CAEA,IAAI,EAAiB,GACjB,EAAiB,EAAQ,EAE7B,KAAO,GAAkB,EAAiB,EAAQ,QAAQ,CACxD,IAAM,EAAmB,EAAQ,GAEjC,GAAI,GAAgB,CAAgB,EAClC,MAEE,CAAC,EAAc,EAAiB,KAAO,CAAC,GAAc,CAAgB,IACxE,EAAiB,IAEnB,GACF,CAEA,EAAQ,EAER,EAAc,EAAc,IAAM,CACpC,CAEA,EAAgB,CAAa,CAC/B,EAAG,CAAE,EAAc,CAAQ,CAAC,EAE5B,SAAS,EAAW,EAAgC,CAClD,OAAO,GAAgB,CAAM,GAAK,EAAa,EAAO,GACxD,CAEA,SAAS,GAAoC,CAC3C,IAAM,EAAS,EAAuB,uBAAuB,EAAM,SAAS,EAK5E,MAHA,EAAI,EAAM,aAAe,IAAW,EAAoB,yBAI1D,CAEA,SAAS,EAAiB,EAAuB,EAAuB,CACtE,GAAI,EAAO,WAAa,EAAa,qCAAsC,CACzE,IAAM,EAAiB,EAAQ,EAAQ,GAKvC,OAHI,EAAa,EAAe,IACvB,EAAO,KAAK,QAAQ,eAAgB,QAAQ,EAE9C,EAAO,IAChB,CAEA,OAAO,EAAO,IAChB,CAEA,IAAM,EAA2B,EAAQ,OAAO,GACvC,CAAC,EAAW,CAAC,GAAK,CAAC,CAAC,EAAE,UAAU,qBACxC,EAEK,EAAuB,EAAQ,MAAM,EAAa,EAElD,GAA4B,EAAyB,QAAU,EAC/D,EAAgC,IAA6B,CAAC,EAE9D,GACJ,EAAM,UAAU,qBAChB,EAAa,gBAAgB,EAAM,cAAc,GACjD,CAAC,EAAM,mCACP,CAAC,EAOH,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,iBAAiB,EAAyB,EAAI,uBAAyB,cAAvF,EAEE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,KAAM,EAAiB,gBAAkB,UACzC,KAAM,GAAkB,EAAM,SAAS,MAAM,MAC7C,aAAc,GAAkB,EAAM,SAAS,QAAQ,MACvD,QAAS,EAAM,eAAe,KAC9B,OAAQ,EAAM,eAAe,OAC7B,YAAa,EAAM,YACnB,QAAS,EAAM,mBAAmB,EAClC,yBAAyB,uBACzB,aAAc,EAAM,aACpB,cAAe,CACb,WAAY,gBACZ,OAAQ,mBACV,EACA,eAAgB,EAAM,aACtB,iBAAkB,QACV,EAAA,EAAA,IAAA,CAAC,GAAD,CAA6B,eAAgB,EAAM,cAAiB,CAAA,EAC1E,IAEH,CAAA,EAEC,GAoBA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iBACb,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,cAEI,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,gBAAQ,EAAM,eAAe,WAAe,CAAA,CAEvC,CAAA,CACnB,CAAA,CACF,CAAA,GA3BL,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,mBAAoB,EACpB,UAAW,EAAM,UACjB,eAAgB,EAAM,eACtB,aAAc,EAAM,aACpB,SAAU,EAAM,SAChB,UAAW,EAAM,IACjB,UAAW,EAAM,UACjB,gBAAiB,EAAM,gBACvB,eAAgB,EAAM,eACtB,2BAA4B,EAAM,2BAClC,4BAA6B,EAAM,4BACnC,aAAc,EAAM,aACpB,QAAS,EACT,6BAA8B,EAAM,0BACpC,iBAAkB,GAAwB,EAAM,WAChD,gBAAiB,EAAuB,EAAgB,UAAU,GAAW,iBAAiB,EAAI,EACnG,CAAA,EAaF,EAAM,eACL,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,SAAU,EAAM,mBAChB,KAAM,EAAM,eACZ,kBAAmB,EAAM,kBACzB,wBAAyB,EAAM,wBAC/B,mBAAsB,EAAM,eAAe,EAAM,eAAgB,EAAgB,wBAAwB,EACzG,WAAY,CAAC,EAAM,oBAAoB,EAAoB,sBAAsB,EACjF,cAAe,EAAM,SAAS,SAAS,CACxC,CAAA,EAGF,CAAC,EAAM,eACN,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAgC,cAAgB,cAAnE,CACG,KACC,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EACT,MAAO,EAAM,eAAe,KAC5B,SAAU,EACV,UAAW,CAAC,EAAM,WAClB,cAAe,EAAM,cACJ,kBACF,eAChB,CAAA,GAGH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAgC,gBAAkB,YAC/D,EAAQ,KAAK,EAAQ,IAChB,EAAW,CAAM,GACZ,EAAA,EAAA,IAAA,CAAA,EAAO,SAAP,CAAgD,EAA3B,EAAO,EAAoB,EAErD,GAAuB,SAAS,EAAO,QAAQ,GAE/C,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAEP,KAAM,EACN,cAAe,GAAoB,EAAS,CAAG,GAAK,CAAC,CAAC,EAAM,kCAC5D,gBAAiB,EAAuB,uBAAuB,EAAM,SAAS,EAE9E,QAAS,GAAK,EAAiB,EAAG,CAAG,EACrC,kBAAmB,GAAK,EAAE,SAC1B,WAAY,GAAK,EAAE,QACnB,UAAW,GAAK,EAAE,OAClB,WAAY,GACV,EAAwB,EAAO,GAAI,EAAO,SAAU,EAAO,WAAY,CAAM,EAE/E,iBAAkB,GAElB,UAAW,EAAM,UACjB,SAAU,EAAM,SAChB,iBAAkB,EAAM,iBACxB,eAAgB,EAAM,eACtB,oBAAqB,EAAM,oBAC3B,oBAAqB,EAAa,6BAA6B,EAE/D,aAAc,EAAM,aACpB,cAAe,EAAM,cACrB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,kCAAmC,EAAM,kCACzC,SAAU,EAAM,SAEhB,kBAAmB,EACnB,mBAAoB,EACpB,uBAAwB,EAAM,mBAAqB,EAAO,GAC1D,MAAO,EAAM,MACb,aAAc,EAAM,WACpB,UAAW,EAAM,WACjB,YAAa,EAAM,YACnB,YAAa,EAAM,YAEnB,WAAY,GAAW,EAAa,EAAO,GAAI,CAAO,EAEtD,iBAAkB,KAClB,eAAgB,IACjB,EAzCM,EAAO,EAyCb,GAKH,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,iBAAkB,EAAoB,eACtC,kBAAmB,EAEnB,GAAI,EAAO,GACX,KAAM,EAAiB,EAAQ,CAAG,EAClC,YAAa,EAAO,YACpB,eAAgB,EAAM,eACtB,WAAY,EAAO,WACnB,aAAc,EAAO,SACrB,UAAW,EAAM,UACjB,kBAAmB,EACnB,WAAY,EACZ,SAAU,EAAM,SAChB,aAAc,EAAM,aACpB,cAAe,EAAM,cACrB,uBAAwB,EAAM,mBAAqB,EAAO,GAC1D,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,iBAAkB,EAAM,iBACxB,mBAAoB,EAAM,mBAC1B,SAAU,EAAO,SACjB,MAAO,EAAM,MACb,mBAAoB,EACpB,SAAU,EAAM,SAChB,gBAAiB,EAAuB,uBAAuB,EAAM,SAAS,EAC9E,YAAa,EACb,eAAgB,EAAM,eACtB,oBAAqB,EAAM,oBAC3B,aAAc,EAAM,WACpB,YAAa,EAAM,YACnB,kCAAmC,EAAM,kCACzC,6BAA8B,EAAM,eACpC,SAAU,EAAM,SAChB,UAAW,EAAM,WACjB,kCAAmC,EAAM,kCACzC,iBAAkB,EAAM,iBACxB,YAAa,EAAM,YAGnB,gBAAiB,GACjB,YAAa,KACb,kBAAmB,KACnB,eAAgB,IACjB,EAzCM,EAAO,EAyCb,CAEJ,CACE,CAAA,EAEJ,CAAC,CAAC,GAAW,SACZ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,KAAM,EAAgB,UAAU,GAAW,QAAQ,CAAI,CAAA,GACrE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EACR,iBAAkB,EAAO,IAAS,EAAM,SAAS,UAC/C,EACA,CAAE,GAAG,EAAM,UAAW,EAAmB,eAAgB,EAAK,cAAe,CAC/E,EACA,eAAgB,EAAM,eACtB,sBAAuB,EAAM,UAC7B,2BAA4B,EAAM,SAAS,iBAC3C,iBAAkB,EAAM,gBACzB,CAAA,CACD,CAAA,CAAA,CAED,IAGN,IACC,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAM,UACjB,WAAY,EAAM,WAClB,SAAU,EAAM,cAChB,iBAAkB,EAAM,SAAS,YAClC,CAAA,EAGF,EAAM,gBACL,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,SAAU,EAAM,cAChB,eAAkB,EAAM,SAAS,UAAU,EAAM,eAAe,cAAc,CAC/E,CAAA,CAEA,GAET,CCrkBA,SAAgB,IAA8C,CAC5D,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,yBAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,CAAA,GAEtB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,gEAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,CAAA,GACrB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAwB,CAAA,CACrB,GACF,GAET,CCbA,IAAM,GAAY,CAChB,WAAc,kDACd,SAAW,GAAkB,EAAU,WAAW,kDAAmD,CAAE,GAAI,CAAI,CAAC,CAClH,EAEa,GAAiB,CAI5B,OAAO,EAAe,EAAgB,EAAoC,EAAoC,CAC5G,MAAO,CACL,IAAK,GAAU,OAAO,EACtB,IAAK,UAAU,EAAI,KAAK,GAAG,IAC3B,KAAM,EAAU,KAChB,KAAM,EACN,eACS,EAAI,IAAI,IAAO,CACpB,KACA,UAAW,CACT,KAAM,CAAC,CAAM,CACf,CACF,EAAE,EAEJ,UACA,QACA,iBAAkB,CAAE,GAAG,EAAI,IAAI,GAAM,kBAAkB,GAAI,EAAG,yBAA0B,iBAAkB,CAC5G,CACF,EAEA,SAAS,EAAe,EAAgB,EAAsB,EAAoC,CAChG,MAAO,CACL,IAAK,GAAU,SAAS,CAAG,EAC3B,IAAK,YAAY,EAAI,KAAK,GAAG,IAC7B,KAAM,EAAU,OAChB,eACS,EAAI,IAAI,IAAO,CACpB,KACA,UAAW,CACT,KAAM,CAAC,CACT,CACF,EAAE,EAEJ,UACA,QACA,iBAAkB,CAAE,GAAG,EAAI,IAAI,GAAM,kBAAkB,GAAI,EAAG,yBAA0B,iBAAkB,CAC5G,CACF,CACF,4CE5BM,GAAY,EAAgB,iBAAiB,yBAAyB,EAc5E,SAAgB,GACd,EAC+B,CAC/B,GAAM,CAAE,iBAAgB,iBAAkB,EAEpC,CAAE,EAAyB,GAAA,EAAqC,SAAkB,EAAK,EAEvF,EAAS,GAAU,EACnB,EAAa,EAAwB,EACrC,CAAE,kBAAmB,GAAe,EACpC,EAAc,EAAkC,EAAa,YAAY,CAAC,EAE1E,EAAgB,EAAc,EAAkB,MAAM,EACtD,EAAW,EAAc,EAAkB,MAAM,EAEjD,EAAoB,EAAe,EAAe,cAAc,EAEtE,SAAS,EAAe,EAAwC,EAA2B,CACzF,GAAI,CAAC,GAAqB,CAAC,EACzB,OAEF,IAAM,EAAyB,EAAuB,GAAG,SAAS,IAAM,EAAe,IAAI,SAAS,EAEhG,GACF,EAA2B,EAAI,EAEjC,IAAM,EAAc,EAAa,YAAY,CAAsB,EAE7D,EAAU,EACd,GAAe,SACf,GAAe,OAEjB,EAAW,EAAQ,CAAC,EAAuB,EAAE,EAAG,EAAY,MAAM,EAAE,CAAC,CAAC,CACnE,SAAW,CACV,GAAgB,cAAc,EAAe,CAC3C,WACA,WAAY,EAAW,OACvB,cAAe,EAAc,SAC7B,WAAY,EAAc,EAAiB,IAAM,EAAiB,GAClE,OAAQ,EAAW,cACrB,CAAC,EAEI,GACH,EAAO,QAAQ,GAAU,EAAc,aAAe,WAAY,CAAE,KAAM,EAAuB,IAAK,CAAC,CAAC,CAE5G,CAAC,CAAC,CACD,YAAc,CACT,GACF,EAA2B,EAAK,CACpC,CAAC,CACL,CAEA,SAAS,GAA0C,CACjD,GAAI,CAAC,GAAqB,CAAC,EACzB,MAAO,CAAC,EAEV,IAAM,EAAc,CAAC,CAAC,EAAe,WAAW,MAAM,OAEtD,MAAO,CAAC,CACN,MAAO,EAAW,GAAK,GAAU,EAAc,YAAc,QAAQ,EACrE,YAAe,EAAe,EAAgB,EAAgB,MAAM,EACpE,IAAK,EAAc,EAAgB,GACnC,UAAW,kBAAkB,EAAc,mBAAqB,WAAW,GAAG,GAAO,eACrF,OAAQ,GACR,QAAU,GAAe,EAAiB,IAAA,GAAY,GAAU,kBAAkB,EAClF,YAAa,CACf,CAAC,CACH,CAEA,MAAO,CACL,oBACA,0BACA,iBACA,wBACF,CACF,CCzGA,IAAM,GAAY,8BAEL,GAAb,cAAwC,CAAe,CACrD,aAAc,CACZ,MAAM,qBAAsB,CAC9B,CAGA,IAAW,MAAe,CACxB,MAAO,oBACT,CAGA,IAAW,SAAkB,CAC3B,OAAO,EAAgB,UAAU,GAAW,SAAS,CACvD,CAGA,IAAW,aAAsB,CAC/B,OAAO,EAAgB,UAAU,GAAW,aAAa,CAC3D,CAGA,IAAW,KAAgB,CACzB,MAAO,CACL,KAAM,EAAgB,UAAU,GAAW,KAAK,EAChD,QAAS,CACP,YAAa,EAAY,QACzB,OAAQ,GAAQ,SAAS,oBACzB,KAAM,CAAC,IAAI,CACb,CACF,CACF,CACF,ECjCA,SAAgB,GACd,EACA,EACA,EACA,CACA,GAAM,CAAE,sBAAqB,4BAA6B,EAAY,IAAI,EAEpE,CACJ,UAAW,EACX,eACA,iBACE,EAAyB,CAC3B,iBAAkB,EACL,cACb,WAAY,EAAoB,cAClC,CAAC,EAEK,CAAE,UAAW,GAAuB,EAAyB,CACjE,iBAAkB,EACL,cACb,WAAY,EAAoB,uBAClC,CAAC,EAEK,CAAE,UAAW,GAAwB,EAAyB,CAClE,iBAAkB,EACL,cACb,WAAY,EAAoB,wBAClC,CAAC,EAED,SAAS,GAAe,CACtB,OAAQ,EAAR,CACE,KAAK,EAAoB,eACvB,OAAO,EACT,KAAK,EAAoB,wBACvB,OAAO,EACT,KAAK,EAAoB,yBACvB,OAAO,CACX,CACF,CAEA,MAAO,CACL,UAAW,EAAa,EACxB,2BAA4B,GAAuB,CAAC,CAAC,EAAmB,KACxE,4BAA6B,GAA4B,CAAC,CAAC,EAAoB,KAC/E,gBACA,cACF,CACF,CCuBA,GAA0B,aAAe,CACvC,YAAa,CAAC,CAChB,EAGA,IAAM,GAAY,EAAgB,iBAAiB,yBAAS,EAE5D,SAAgB,GAA0B,EAA2D,CACnG,IAAM,EAAa,EAAwB,EACrC,CAAE,iBAAgB,uBAAwB,GAAe,EACzD,EAAW,EAAY,IAAI,EAC3B,EAAqB,GAAwB,EAE7C,EAAS,EAA6B,GAAe,OAAO,CAAC,EAC7D,EAAc,EAAkC,EAAa,YAAY,CAAC,EAC1E,CAAE,4BAA2B,gBAAe,+BAAgC,GAAkB,EAC9F,EAAc,GAAe,EAE7B,EAAW,EACf,EAAe,EAAe,iBAAiB,GAC/C,EAAY,MAAM,iBAClB,GAAiB,SAAS,EAAY,KAAK,UAAU,CACvD,EAEM,EAAiB,EACrB,EAAuB,eAAe,EAAM,GAAI,EAAY,MAAM,EAAE,CACtE,EAEM,EAAiB,EAAe,MAAM,OAAS,GAAmB,IAGlE,EAAa,EAAiB,EAAe,MAAM,GAAK,EAAM,YAAY,SAE1E,EAAe,EACnB,EAAe,MACf,EAAuB,iBAAiB,EAAe,KAAK,cAAc,CAC5E,EAEM,EAAY,EAChB,EAAe,MACf,GAAiB,0BAA0B,EAAe,KAAK,cAAc,CAC/E,EAEM,EAAe,EACnB,EAAe,MACf,GAAiB,sBAAsB,EAAM,GAAI,EAAe,KAAK,cAAc,CACrF,EAEM,EAAY,EAChB,EAAY,MAAM,iBAChB,GAAgB,UAAU,CAC9B,EAEM,CACJ,yBACA,0BACE,GAA0B,EAExB,GAAO,EAAuC,EAAuB,KAAK,EAAM,EAAE,CAAC,EAEnF,CACJ,YACA,8BACA,+BACA,eACA,iBACE,GAAgC,EAAM,GAAI,EAAM,YAAa,EAAM,UAAU,EAE3E,EAAa,GAAc,EAC3B,GAAW,GAAY,EAEvB,EAAqB,EACzB,EAAuB,mBAAmB,EAAM,EAAE,CACpD,EAEM,GAA6B,EAAU,8BAC3C,EAAmB,KACnB,EAAY,MAAM,aACpB,EACA,GAAmB,GAAmB,0BAA0B,CAC9D,QAAS,CAAE,eAAgB,EAAe,KAAM,UAAW,EAAU,IAAK,EAE1E,cAAe,CACb,cAAe,GACf,YAAa,YACb,kBAAmB,iBACrB,EACA,cAAe,EAAU,iBAAiB,CACxC,sBAAuB,GACvB,cAAe,GAA4B,WAAW,CACpD,GAAG,EAAe,KAClB,KAAM,IAA4B,MAAQ,EAAe,MAAM,IACjE,EAAG,EAAM,YAAa,CAAsB,EAC5C,gBAAiB,EAAU,4BACzB,EAAmB,KACnB,EAAY,MAAM,aACpB,CACF,CAAC,EACD,cAAe,EAAU,cAAc,EACvC,SAAU,EAAU,mBAAmB,EAAmB,SACxD,GAA4B,WAAW,EAAe,KAAM,CAAC,EAAG,CAAsB,CACvF,CACH,CAAC,CAAC,EAEF,GAAqB,EAAgB,CACnC,SAAU,EACZ,CAAC,EACD,GAAa,CAAE,GAAI,EAAM,GAAI,IAAK,QAAS,CAAC,EAE5C,GAAM,CAAE,qBAAqB,GAAoB,CAC/C,gBAAiB,EAAgB,eACjC,IAAK,EAAM,YAAY,IACvB,SAAU,CACZ,CAAC,EACK,GAAe,GAAgB,CACnC,SAAU,GAAqB,UAC/B,iBAAkB,EAAM,gBAC1B,CAAC,EAEK,EAAA,EAAwB,YACtB,EAAe,6BAA6B,EAAU,KAAM,EAAM,WAAW,EACnF,CAAE,EAAU,KAAM,EAAM,WAAY,CACtC,EACM,EAAoB,GAAiB,IAAI,GAAK,EAAE,QAAQ,GAAK,CAAC,EAE9D,EAAgB,CACpB,eAAgB,EAAa,MAAM,GACnC,iBAAkB,EAAa,MAAM,KACrC,wBAAyB,EAAe,MAAM,GAC9C,0BAA2B,EAAe,MAAM,KAChD,+BAAgC,CAAC,CAAC,EAAe,MAAM,WAAW,MAAM,OACxE,oBAAqB,GAAiB,OAAS,EAAgB,IAAI,GAAK,EAAE,IAAI,EAAI,KAClF,kBAAmB,EAAkB,OAAS,EAAoB,IACpE,EAEM,CACJ,oBACA,2BACA,iBACA,2BACE,GAAwB,CAC1B,eAAgB,EAAe,KAC/B,eACF,CAAC,EAEK,GACJ,EAAe,MAAM,SAAW,GAAqB,YACrD,CAAC,EAGG,GAAa,EAAuB,uBAAuB,EAAU,IAAI,EAE/E,eAAe,GAAiB,EAAgD,CAC9E,IAAM,EAAU,MAAM,EAAiB,GAAiB,eAAe,CACrE,KAAM,GAAa,OACnB,KAAM,GAAmB,YAAY,EAAY,KAAM,EAAS,IAAI,EACpE,KAAM,GAAmB,QACvB,EAAY,KACZ,GAAU,QACV,EAAe,EAAe,iBAAiB,EAC/C,CAAE,SAAU,qBAAsB,CACpC,CACF,EAAG,CACD,SAAU,EAAS,KACnB,SAAU,EAAS,QACnB,SAAU,eACV,iBAAkB,EAAa,KAAK,YACpC,eAAgB,EAAa,KAAK,GAClC,cAAe,EAAU,KAAK,KAC9B,YAAa,EAAU,KAAK,GAC5B,mBAAoB,EAAe,KAAK,KACxC,iBAAkB,EAAe,KAAK,GACtC,eAAgB,EAAc,cAAc,CAC9C,CAAC,CAAC,EAeF,OAbA,GAAgB,cAAc,CAC5B,aAAc,EAAS,KACvB,QAAS,EAAS,QAClB,eAAgB,EAAa,KAAK,GAClC,iBAAkB,EAAe,KAAK,GACtC,YAAa,EAAU,KAAK,EAC9B,EAAG,CACD,WAAY,EAAW,OACvB,SAAU,EAAgB,qBAC1B,OAAQ,EAAW,SACnB,cAAe,EAAc,QAC/B,CAAC,EAEM,CACT,CAEA,SAAS,IAAoC,CAC3C,GAAI,GAAkB,EACpB,MAAO,CAAC,EAGV,IAAM,EAAgB,GAAuB,EAK7C,OAHK,EAGE,CACL,GAAG,EAAc,IAAI,IAAW,CAAE,GAAG,EAAQ,UAAW,GAAG,EAAO,UAAU,MAAO,EAAE,EACrF,CACE,MAAO,EACP,KAAM,EAA4B,EAAW,QAAS,EAAe,MAAM,GAAI,EAAa,MAAM,EAAE,EACpG,aAAc,EAChB,CACF,EATS,CAUX,CAEA,IAAM,GAAW,GACf,EAAe,KACf,GACA,CAAE,GAAG,EAAM,YAAa,SAAU,CAAW,EAC7C,EAAY,KACZ,EAAM,iBACN,CACF,EAEM,GAAc,GAAe,CAAE,KAAM,EAAe,MAAM,IAAK,CAAC,EACtE,SAAS,IAAqC,CACvC,MAAsB,EAAa,MAAM,EAAE,EAGhD,UAAa,EACf,CAEA,SAAS,GACP,EACA,EACA,EACA,EACgB,CAChB,GAAM,CAAE,UAAS,aAAc,GAAc,gBAAgB,EAAU,KAAM,EAAY,IAAI,EAE7F,OAAO,GAAkB,uBACvB,EACA,EACA,EACA,EAAa,KACb,CAAE,WAAY,CAAC,EAAW,SAAU,CAAC,EAAS,QAAO,CACvD,CACF,CAEA,IAAM,EAAiB,EAAU,MAAM,UAAU,UAC3C,GAAU,EAAqB,GAChC,GAAwB,eAAe,EAAU,MAAM,UAAU,SAAS,CAAC,EAehF,MAHI,EAViB,EAAO,MACvB,EAAU,cACR,EAAe,MACf,EAAa,MACb,GAAK,MACL,GACA,EAAU,MACZ,EAAa,eACZ,CAAC,GAAkB,GAAQ,gBAEd,CAAC,GACX,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiC,CAAA,GAGxC,EAAA,EAAA,IAAA,CAAC,GAAoB,SAArB,CAA8B,MAAO,aACnC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,CACG,CAAC,EAAE,GAAgB,EAAU,QAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAe,OAAQ,EAAU,KAAK,OAAQ,KAAK,OAAS,CAAA,GACnG,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAU,KACrB,eAAgB,EAAe,KAC/B,QAAS,GAAQ,KACQ,2BACzB,kCAAmC,GACnC,eAAgB,GAAe,EACf,iBACK,sBACrB,aAAc,EAAa,KACd,cACG,iBACE,oBAClB,UAAW,EAAM,YAAY,IAAM,KAAO,EAAU,KACnC,kBACF,gBACf,YAAa,EAAO,KAAK,YACzB,UAAW,GACX,kCAAmC,EAAU,UAAU,mBACvD,cAAe,EAAgB,EAAU,YAAY,OAAO,aAAe,EAAU,YAAY,OAAO,MAC1F,gBACW,2BACzB,mBAAoB,EAAU,YAAY,OAAO,YACjD,SAAU,CACR,GAAG,GACH,OAAQ,GAAa,iBACrB,iBAAoB,KACpB,iBAAkB,GAAe,GAAmB,2BAA2B,CAAW,CAC5F,EACc,eACK,oBACnB,iBACE,EAAe,EAAe,iBAAiB,GAC/C,GAEF,kBAAmB,EAAM,YAAY,MACrC,SAAU,CAAC,EAAU,MAAM,EAC3B,YAAa,EAAM,YAAY,IAChB,gBACf,aAAc,EAAa,KAC3B,MAAO,EAAU,MAAM,EACK,8BACC,+BAC7B,IAAK,EAAa,kBAAkB,EAAe,KAAM,EAAM,UAAU,EAE/D,WACV,kCAAmC,GAAc,CAAC,IAAU,WAAW,GAAU,QAAQ,EACvE,oBACE,oBACrB,CAAA,CACE,GACuB,CAAA,CAElC,CC/VA,IAAM,GAAY,EAAgB,iBAAiB,uCAAS,EAQ5D,GAAuB,aAAe,CACpC,YAAa,CAAC,CAChB,EAEA,SAAgB,GACd,EACa,CACb,GAAM,CAAE,oBAAqB,GAAoB,CAAE,gBAAiB,EAAgB,cAAe,CAAC,EAC9F,EAAe,GAAgB,CACnC,SAAU,GAAqB,UAC/B,iBAAkB,EAAM,gBAC1B,CAAC,EACK,EAAc,GAAe,EAC7B,EAAqB,GAAwB,EAE7C,CAAE,4BAA2B,gBAAe,+BAAgC,GAAkB,gBAAgB,EAE9G,EAAS,EAA6B,GAAe,OAAO,CAAC,EAC7D,EAAc,EAAkC,EAAa,YAAY,CAAC,EAE1E,EAAiB,EACrB,EAAuB,eAAe,EAAM,GAAI,EAAY,MAAM,EAAE,CACtE,EAEM,CAAE,YAAW,eAAc,gBAAiB,EAAyB,CACzE,WAAY,EAAoB,eAChC,iBAAkB,EAAM,GACxB,YAAa,EAAM,WACrB,CAAC,EAIK,EAAY,EAChB,GACA,GAAiB,sBAAsB,EAAiB,mBAAoB,EAAa,EAAE,CAC7F,EAEM,EAAO,EACX,EAAuB,KAAK,EAAM,GAAI,EAAiB,kBAAkB,CAC3E,EAEM,EAAW,GACf,EAAe,KACf,EAAM,YACN,EAAM,gBACR,EAEA,GAAmB,GAAmB,0BAA0B,CAC9D,QAAS,CAAE,eAAgB,EAAe,KAAM,UAAW,EAAU,IAAK,EAC1E,cAAe,CACb,cAAe,GACf,YAAa,YACb,kBAAmB,iBACrB,EACA,cAAe,EAAU,iBAAiB,CACxC,sBAAuB,GACvB,cAAe,EAAS,eAAe,EAAe,IAAI,CAC5D,CAAC,EACD,cAAe,EAAU,cAAc,CACzC,CAAC,CAAC,EAEF,GAAqB,EAAgB,CACnC,SAAU,EACZ,CAAC,EAED,IAAM,EAAA,EAAwB,YACtB,EAAe,6BAA6B,EAAU,KAAM,EAAM,WAAW,EACnF,CAAE,EAAU,KAAM,EAAM,WAAY,CACtC,EACM,EAAoB,GAAiB,IAAI,GAAK,EAAE,QAAQ,GAAK,CAAC,EAE9D,EAAgB,CACpB,eAAgB,GAAc,GAC9B,iBAAkB,GAAc,KAChC,wBAAyB,EAAe,MAAM,GAC9C,0BAA2B,EAAe,MAAM,KAChD,+BAAgC,CAAC,CAAC,EAAe,MAAM,WAAW,MAAM,OACxE,oBAAqB,GAAiB,OAAS,EAAgB,IAAI,GAAK,EAAE,IAAI,EAAI,KAClF,kBAAmB,EAAkB,OAAS,EAAoB,IACpE,EAEM,CACJ,qBACA,0BACA,iBACA,0BACE,GAAwB,CAC1B,eAAgB,EAAe,KAC/B,eACF,CAAC,EAED,SAAS,GAAoC,CAC3C,IAAM,EAAgB,EAAuB,EAK7C,OAHK,EAGE,CACL,GAAG,EAAc,IAAI,IAAW,CAAE,GAAG,EAAQ,UAAW,GAAG,EAAO,UAAU,MAAO,EAAE,EACrF,CACE,MAAO,EACP,KAAM,EAA4B,EAAW,QAAS,EAAe,MAAM,GAAI,GAAc,EAAE,EAC/F,aAAc,EAChB,CACF,EATS,CAUX,CAEA,SAAS,GAAqC,CAC5C,UAAa,GAAiC,CAC5C,WACA,eAAgB,EAAe,KAC/B,KAAM,EAAK,KACX,iBAAkB,EAAM,gBAC1B,CAAC,CACH,CAYA,OAVqB,EAAO,MACvB,EAAU,cACR,EAAe,MACf,GACA,EAAK,MACL,EAAU,MAMf,EAAA,EAAA,IAAA,CAAC,GAAoB,SAArB,CAA8B,MAAO,YACnC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,CACG,CAAC,EAAE,GAAgB,EAAU,QAC5B,EAAA,EAAA,IAAA,CAAC,GAAD,CAAe,OAAQ,EAAU,KAAK,OAAQ,KAAK,OAAS,CAAA,GAE9D,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAU,KACrB,eAAgB,EAAe,KAC/B,wBAAyB,GAAkB,uBAC3C,eAAgB,EAAe,EAC/B,mBAAsB,GACtB,wBAA2B,GACb,eACI,mBACF,iBACS,0BACzB,UAAW,EAAU,KACJ,kBACF,gBACf,YAAa,EAAO,KAAK,YACzB,UAAW,GACX,kCAAmC,EAAU,KAAK,UAAU,mBAC5D,cAAe,EAAU,KAAK,YAAY,OAAO,MACvC,WACI,eACd,0BAAA,GACmB,qBACnB,kBAAmB,EAAM,YAAY,MACrC,SAAU,CAAC,EAAU,MAAM,EAC3B,cAAe,GACf,YAAa,EAAyB,WACtC,2BAA4B,GAC5B,4BAA6B,GAC7B,kCAAmC,GACnC,IAAI,gBACS,cACK,mBACE,oBACrB,CAAA,CACE,GACuB,CAAA,GA3CvB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiC,CAAA,CA6C5C,CCtMA,IAAa,GAAyB,GAA2D,EAC9F,EAAiB,SAAU,IAC1B,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,iBAAkB,EAAI,iBACtB,GAAI,EAAI,GACR,YAAa,EAAI,YACjB,WAAY,EAAI,UACjB,EALM,GAAG,EAAI,GAAG,GAAG,EAAI,YAKvB,GAEF,EAAiB,oBAAqB,GACjC,EAAI,aAAe,EAAoB,gBAIzC,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,iBAAkB,EAAI,iBACtB,GAAI,EAAI,GACR,YAAa,EAAI,WAClB,EAJM,GAAG,EAAI,GAAG,GAAG,EAAI,YAIvB,EARM,IAWb,CAAC,EAED,GAAuB,YAAc"}
1
+ {"version":3,"file":"B6Pc3q-u.chunk.js","names":[],"sources":["../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-header-details/ClassificationHeaderDetails.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/empty-state/CuratedClassificationEmptyState.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/table-of-contents/table-of-contents.module.scss","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/table-of-contents/TableOfContents.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/teacher-only/TeacherOnlyEmptyState.tsx","../../../../libs/shared/src/apps/subjects/hooks/useGetTopicsWidgets.ts","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-coming-soon/ClassificationComingSoon.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/audiences/ClassificationDashboardAudiences.tsx","../../../../libs/shared/src/images/svg/widgets/WidgetSeriesSvg.tsx","../../../../libs/shared/src/apps/subjects/hooks/useDirectoryTabProductTipSwitcher.ts","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-tabs/classification-tabs.module.scss","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-tabs/ClassificationTabs.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/classification-dashboard-nav/ClassificationDashboardNav.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/ClassificationDashboard.tsx","../../../../libs/shared/src/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard.tsx","../../../../libs/shared/src/flight-requests/FollowRequests.ts","../../src/shared/hooks/use-follow-classification/use-follow-classification.module.scss","../../src/shared/hooks/use-follow-classification/useFollowClassification.ts","../../src/apps/subjects/errors/TopicNotFoundError.ts","../../src/apps/subjects/hooks/useFetchClassificationDashboard.ts","../../src/apps/subjects/views/classification/curated-classification/CuratedClassificationView.tsx","../../src/apps/subjects/views/classification/live-classification/LiveClassificationView.tsx","../../src/apps/subjects/views/classification/BaseClassificationView.tsx"],"sourcesContent":["import React from 'react';\n\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Classification } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nconst namespace = 'subject.classificationHeaderDetails';\n\nconst Separator = ({ className }: { className: string }) =>\n <span className={className}>&bull;</span>;\n\ninterface ClassificationHeaderDetailsProps {\n classification: Classification;\n}\n\nexport function ClassificationHeaderDetails(props: ClassificationHeaderDetailsProps): React.ReactElement {\n const {\n dashboardVideoCount,\n childDashboardVideoCount,\n dashboardResourceCount,\n childDashboardResourceCount,\n childClassificationCount\n } = TopicsHelper.getCounts(props.classification);\n\n const videoCount = dashboardVideoCount + childDashboardVideoCount;\n const resourceCount = dashboardResourceCount + childDashboardResourceCount;\n\n return (\n <p className='mb-n1 font-size-normal fw-normal mt-1'>\n {!!childClassificationCount && (\n <Text\n namespace={namespace}\n phrase='topics'\n options={{ count: childClassificationCount.toLocaleString(), smartCount: childClassificationCount }}\n />\n )}\n\n {!!videoCount && (\n <>\n {childClassificationCount > 0 && <Separator className='mx-2' />}\n <Text\n namespace={namespace}\n phrase='videos'\n options={{ count: videoCount.toLocaleString(), smartCount: videoCount }}\n />\n </>\n )}\n {!!resourceCount && (\n <>\n <Separator className='mx-2' />\n <Text\n namespace={namespace}\n phrase='resources'\n options={{ count: resourceCount.toLocaleString(), smartCount: resourceCount }}\n />\n </>\n )}\n </p>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { PlusSvg } from 'libs/shared/images/svg/actions/PlusSvg';\nimport { CuratedDashboard, DashboardStatus } from 'libs/shared/interfaces';\n\nconst namespace = 'subjects.curatedClassificationEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface CuratedClassificationEmptyStateProps {\n dashboard: CuratedDashboard;\n imageUrl: string;\n isReadonly: boolean;\n addWidgetApplink?: () => Core.AppLink;\n}\n\nexport function CuratedClassificationEmptyState(props: CuratedClassificationEmptyStateProps): JSX.Element {\n const isArchived = props.dashboard?.status === DashboardStatus.Archived;\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('headingForNP')} />\n {!props.isReadonly ? (\n <EmptyState.Heading>\n <Text phrase='headingForNP' />\n </EmptyState.Heading>\n ) : (\n <>\n <EmptyState.Heading>\n <Text namespace={namespace} phrase='headingForCurator' />\n </EmptyState.Heading>\n <EmptyState.Info>\n <Text namespace={namespace} phrase='info' />\n </EmptyState.Info>\n <Tooltip title={isArchived ? LanguageService.getPhrase(namespace, 'archivedCtaTooltip') : ''} spanHack>\n <EmptyState.Cta\n text={LanguageService.getPhrase(namespace, 'add')}\n appLink={props.addWidgetApplink?.()}\n className='btn btn-dark'\n icon={PlusSvg}\n disabled={isArchived}\n />\n </Tooltip>\n </>\n )}\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","$top-nav-height: 4.1875rem;\n$cv-banner-height: calc(100vw * 22 / 120);\n$filters-area: 7.87rem;\n\n.container {\n position: sticky;\n top: 6.25rem;\n z-index: 80;\n}\n\n.mobile {\n position: fixed;\n top: calc($top-nav-height + $cv-banner-height + $filters-area);\n z-index: 80;\n right: 0;\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, HashObject, LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { TableOfContentsList } from 'libs/shared/components/table-of-contents-list/TableOfContentsList';\nimport { TableOfContentsSvg } from 'libs/shared/images/svg/objects/TableOfContentsSvg';\nimport { CuratedWidget } from 'libs/shared/interfaces';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nimport styles from './table-of-contents.module.scss';\n\ninterface TableOfContentsContainerProps {\n widgets: CuratedWidget[];\n title: string;\n activeId: string;\n appLink?: Core.AppLink;\n clickable?: boolean;\n analyticsData?: HashObject;\n setControlledId: (arg: string) => void;\n isSmallScreen?: boolean;\n}\ninterface TableOfContentsProps extends TableOfContentsContainerProps {\n getAppLink: (widget: CuratedWidget) => Core.AppLink;\n}\n\nfunction TableOfContentsMobile(props: TableOfContentsProps) {\n const [ isExpanded, setIsExpanded ] = React.useState(false);\n\n function logUserAction() {\n const analyticsOptions = {\n actionType: !isExpanded ? UserAction.Open : UserAction.Hide,\n entity: EntityType.TableOfContents,\n location: LocationContext.Dashboard\n };\n\n AnalyticsHelper.logUserAction(props.analyticsData, analyticsOptions);\n }\n\n function onClickIcon() {\n setIsExpanded(!isExpanded);\n logUserAction();\n }\n\n return (\n <div className={`${styles.mobile} d-inline-flex gap-1`}>\n \n {isExpanded && (\n <div className='bg-white px-3 pt-3 pb-2 border border-dark rounded-1 ps-3'>\n <h2 className='h5'>{props.title}</h2>\n <TableOfContentsList\n items={props.widgets.map(widget => (\n { name: widget.name, id: widget.id, tocIndentation: widget.metadata.tocIndentation }\n ))}\n activeId={props.activeId}\n appLink={props.appLink}\n analyticsData={props.analyticsData}\n setControlledId={props.setControlledId}\n getAppLink={props.getAppLink}\n onItemClick={() => setIsExpanded(false)}\n />\n </div>\n )}\n <div className={styles.container}>\n <IconButton\n className='btn btn-outline-dark'\n svg={TableOfContentsSvg}\n onClick={onClickIcon}\n />\n </div>\n </div>\n );\n}\n\nfunction TableOfContents(props: TableOfContentsProps): JSX.Element {\n return (\n <aside className='col-3 order-1'>\n <div className={`${styles.container} ps-3`}>\n <h2 className='h5'>{props.title}</h2>\n \n <TableOfContentsList\n items={props.widgets.map(widget => (\n { name: widget.name, id: widget.id, tocIndentation: widget.metadata.tocIndentation }\n ))}\n activeId={props.activeId}\n appLink={props.appLink}\n analyticsData={props.analyticsData}\n setControlledId={props.setControlledId}\n getAppLink={props.getAppLink}\n />\n </div>\n </aside>\n );\n}\n\nexport function TableOfContentsContainer(props: TableOfContentsContainerProps): JSX.Element {\n function getAppLink(widget: CuratedWidget): Core.AppLink {\n const currentAppLink = ContextService.getCurrentRoute().appLink;\n \n const params: HashObject = currentAppLink.params ?\n { ...(currentAppLink.params as HashObject) } :\n {};\n\n params.tocId = widget.id;\n\n return {\n ...currentAppLink,\n params\n };\n }\n\n return (\n <>\n {!props.isSmallScreen ?\n <TableOfContents {...props} getAppLink={getAppLink} /> :\n <TableOfContentsMobile {...props} getAppLink={getAppLink} />\n }\n </>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\n\nconst namespace = 'subjects.teacherOnlyEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface TeacherOnlyEmptyStateProps {\n imageUrl: string;\n ctaAppLink?: () => Core.AppLink;\n}\n\nexport function TeacherOnlyEmptyState(props: TeacherOnlyEmptyStateProps): JSX.Element {\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('heading')} />\n <EmptyState.Heading>\n <Text phrase='heading' />\n </EmptyState.Heading>\n <EmptyState.Info>\n <Text phrase='info' />\n </EmptyState.Info>\n\n <EmptyState.Cta\n text={getPhrase('cta')}\n appLink={props.ctaAppLink?.()}\n className='btn btn-dark'\n />\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/react/index';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { WidgetTypeId } from 'libs/shared/enums/WidgetTypeId';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { CuratedDashboard, CuratedMediaWidget, CuratedWidget, PresentationAudience, Video } from 'libs/shared/interfaces';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\n\nexport interface Response {\n widgets: CuratedWidget[];\n\n videoList?: Video[];\n videoListWidgetId?: string;\n}\n\n/**\n * This hook helps us with custom logic for to display system generated dashboards in a slightly\n * different way.\n */\nexport function useGetTopicsWidgets(dashboard: CuratedDashboard, activeAudiences: PresentationAudience[]): Response {\n const {\n isSystemGeneratedDashboard,\n systemGeneratedVideoWidget\n } = React.useMemo(() => {\n if (!dashboard) {\n return {\n isSystemGeneratedDashboard: false,\n systemGeneratedVideoWidget: null\n };\n }\n\n const isSystemGeneratedDashboard = CuratedDashboardHelper.isSystemGeneratedDashboard(dashboard.widgets);\n\n return {\n isSystemGeneratedDashboard,\n systemGeneratedVideoWidget: dashboard.widgets.find(widget => {\n return (\n widget.widgetId === WidgetTypeId.ClassificationPinnedVideos &&\n widget.templateId !== WidgetTemplate.ThumbnailVerticalList\n );\n })\n };\n }, [dashboard?.id]);\n\n const systemGeneratedVideoContent = Flight.useBasicFetch<CuratedMediaWidget<Video[]>>(\n !!systemGeneratedVideoWidget &&\n DashboardRequests.dashboardWidgetContent(\n systemGeneratedVideoWidget?.id,\n CuratedDashboardHelper.getWidgetParams(\n systemGeneratedVideoWidget.widgetId,\n systemGeneratedVideoWidget.templateId,\n CuratedDashboardHelper.getDashboardTargetType(dashboard),\n activeAudiences?.map(a => a.masterId)\n ),\n systemGeneratedVideoWidget?.templateId\n )\n );\n\n // Non system generated dashboards are returned as per usual\n if (!isSystemGeneratedDashboard)\n return { widgets: ArrayHelper.sortBy(dashboard?.widgets, 'index') };\n\n // System generated dashboard have the video widget removed and returned as a separate video list\n return {\n widgets: dashboard?.widgets?.filter(widget => {\n if (widget.widgetId !== WidgetTypeId.ClassificationPinnedVideos)\n return true;\n\n if (widget.templateId === WidgetTemplate.ThumbnailVerticalList)\n return true;\n\n return false;\n }) ?? [],\n videoList: systemGeneratedVideoContent.data?.content ?? [],\n videoListWidgetId: systemGeneratedVideoWidget?.id\n };\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EntityType, LocationContext, SignUpDescriptors, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { ActionButton } from 'libs/shared/components/actions/ActionButton';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { BellFilledSvg } from 'libs/shared/images/svg/objects/BellFilledSvg';\nimport { BellSvg } from 'libs/shared/images/svg/objects/BellSvg';\nimport { Classification } from 'libs/shared/interfaces';\n\nconst namespace = 'subjects.classificationComingSoon';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface ComingSoonProps {\n data: Classification;\n onToggleFollow?: () => void;\n canFollowSubjects: boolean;\n imageUrl: string;\n showFollowButtonSpinner: boolean;\n showSignUp: boolean;\n signUpAppLink: Core.AppLink;\n}\n\nexport function ClassificationComingSoon(props: ComingSoonProps): JSX.Element {\n const isFollowing = !!props.data.followers?.data?.length;\n function onClick(): void {\n props.onToggleFollow?.();\n }\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState className='pt-0'>\n <EmptyState.Image src={props.imageUrl} altText={getPhrase('comingSoon')} />\n\n <EmptyState.Heading>\n <Text phrase='comingSoon' />\n </EmptyState.Heading>\n\n <EmptyState.Info>\n <Text phrase={props.showSignUp ? 'infoAnon' : 'info'} />\n </EmptyState.Info>\n\n {props.canFollowSubjects && (\n <ActionButton\n svg={isFollowing ? BellFilledSvg : BellSvg}\n onClick={onClick}\n showSpinner={props.showFollowButtonSpinner}\n className={`btn follow-btn me-2 ${isFollowing ? 'btn-outline-dark' : 'btn-dark'}`}\n >\n <Text phrase={isFollowing ? 'following' : 'follow'} />\n </ActionButton>\n )}\n\n {props.showSignUp && !props.canFollowSubjects && (\n <AppLink\n appLink={props.signUpAppLink}\n className='btn btn-dark d-none d-lg-inline-block'\n analyticsOptions={{\n actionType: UserAction.Click,\n location: LocationContext.ClassificationComingSoon,\n entity: EntityType.AppLink,\n workflowPhase: WorkflowPhase.Start,\n descriptor: SignUpDescriptors.SignUp\n }}\n analyticsData={{}}\n tag='button'\n >\n {getPhrase('signUp')}\n </AppLink>\n )}\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/core';\n\nimport { AudienceFilter } from 'libs/shared/apps/subjects/components/audience-filter/AudienceFilter';\nimport { PresentationAudience } from 'libs/shared/interfaces';\n\ninterface ClassificationDashboardAudiencesProps {\n audiences: PresentationAudience[];\n activeAudiences: PresentationAudience[];\n appLink: Core.AppLink;\n disabled: boolean;\n disablePersist: boolean;\n tooltip: string;\n}\n\nexport function ClassificationDashboardAudiences(props: ClassificationDashboardAudiencesProps): JSX.Element {\n return (\n <AudienceFilter\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n disabled={props.disabled}\n appLink={props.appLink}\n disablePersist={props.disablePersist}\n tooltip={props.tooltip}\n />\n );\n}\n","import React from 'react';\n\nexport function WidgetSeriesSvg(props: React.SVGProps<SVGSVGElement>) {\n return (\n <svg {...props}>\n <path\n d='M4.5 4a.5.5 0 0 0 0 1h16a.5.5 0 0 1 .5.5v12a.5.5 0 0 0 1 0v-12A1.5 1.5 0 0 0 20.5 4zM9 10.26a.256.256 0 0 1 .39-.218l4.482 2.74a.256.256 0 0 1 0 .437L9.39 15.958A.256.256 0 0 1 9 15.739zM18.5 6A1.5 1.5 0 0 1 20 7.5v11a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 2 18.5v-11A1.5 1.5 0 0 1 3.5 6zm-15 1a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5z'\n fill='currentColor'\n />\n </svg>\n );\n}\n","import React from 'react';\n\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { ClassificationTab } from '../components/classification-dashboard/classification-tabs/ClassificationTabs';\n\ninterface ViewModel {\n tab: ClassificationTab;\n on: boolean;\n}\n\nexport function useDirectoryTabProductTipSwitcher(initialTab?: ClassificationTab) {\n const initialState: ViewModel = {\n on: false,\n tab: initialTab || 'new-releases'\n };\n\n const [ viewModel, setViewModel ] = useViewModel<ViewModel>('directory:product:tip:switcher', initialState);\n\n React.useEffect(() => {\n if (!initialTab)\n return;\n\n setViewModel('tab', initialTab);\n }, [initialTab]);\n\n React.useEffect(() => {\n let interval: number = null;\n\n if (viewModel.on) {\n interval = window.setInterval(() => {\n if (viewModel.tab === 'new-releases' || viewModel.tab === 'all-topics')\n setViewModel('tab', viewModel.tab === 'new-releases' ? 'all-topics' : 'new-releases');\n else\n setViewModel('tab', viewModel.tab === 'curated-topic' ? 'video-list' : 'curated-topic');\n }, 2000);\n }\n\n return () => {\n window.clearInterval(interval);\n };\n }, [ viewModel.on, viewModel.tab ]);\n\n return {\n tab: viewModel.tab,\n isHighlighting: viewModel.on,\n start: () => setViewModel('on', true),\n stop: () => {\n setViewModel({\n on: false,\n tab: initialTab || viewModel.tab\n });\n }\n };\n}\n",":local {\n .curatedTopicTab {\n min-width: 6rem !important;\n }\n \n .tabTransition {\n transition: background-color .5s ease-in-out;\n }\n}","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EntityType, LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { PillTab, PillTabSelector } from 'libs/shared/components/pill-tab-selector/PillTabSelector';\nimport { Breakpoints, useBreakpoints } from 'libs/shared/hooks/useBreakpoints';\nimport { GridSvg } from 'libs/shared/images/svg/objects/GridSvg';\nimport { RectanglesSvg } from 'libs/shared/images/svg/objects/RectanglesSvg';\nimport { SparkleSvg } from 'libs/shared/images/svg/objects/SparkleSvg';\nimport { WidgetSeriesSvg } from 'libs/shared/images/svg/widgets/WidgetSeriesSvg';\nimport { Classification, Presentation } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { useDirectoryTabProductTipSwitcher } from '../../../hooks/useDirectoryTabProductTipSwitcher';\n\nimport styles from './classification-tabs.module.scss';\n\nconst namespace = 'shared.classificationDashboard';\n\nexport type ClassificationTab = 'new-releases' | 'all-topics' | 'curated-topic' | 'curriculum';\n\nfunction getTabs(\n props: ClassificationTabsProps,\n breakpoints: Breakpoints,\n activeTab: ClassificationTab,\n isHighlighting: boolean\n): PillTab[] {\n const showText = breakpoints.lg || breakpoints.xl || breakpoints.xxl || breakpoints.xs;\n\n function getTopicTabClassName(): string {\n let className = isHighlighting ? styles.tabTransition : '';\n\n if (breakpoints.xs)\n return className + ' w-100';\n\n if (showText)\n return className = ` ${styles.curatedTopicTab}`;\n\n return className;\n }\n\n if (TopicsHelper.isTopLevelTopic(props.classification)) {\n return [{\n name: showText ? LanguageService.getPhrase(namespace, 'newReleases') : '',\n appLink: props.appLinks?.classification?.(props.classification),\n active: activeTab === 'new-releases',\n svg: SparkleSvg,\n analyticsData: {\n id: 'new-releases',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'newReleases'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classification?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }, {\n name: showText ? LanguageService.getPhrase(namespace, 'allTopics') : '',\n appLink: props.appLinks?.classificationDirectory?.(props.classification),\n active: activeTab === 'all-topics',\n svg: GridSvg,\n analyticsData: {\n id: 'all-topics',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'allTopics'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classificationDirectory?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }];\n }\n\n return [{\n name: showText ? LanguageService.getPhrase(namespace, 'topic') : '',\n appLink: props.appLinks?.classification?.(props.classification),\n active: activeTab === 'curated-topic',\n svg: RectanglesSvg,\n analyticsData: {\n id: 'curated-topic',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'topic'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classification?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: getTopicTabClassName()\n }, {\n name: showText ? LanguageService.getPhrase(namespace, 'curriculum') : '',\n appLink: props.appLinks?.classificationCurriculum?.(props.classification),\n active: activeTab === 'curriculum',\n svg: WidgetSeriesSvg,\n analyticsData: {\n id: 'curriculum',\n classificationId: props.classification.id,\n classificationName: props.classification.name,\n presentationId: props.presentation.id,\n presentationDescription: props.presentation.description,\n name: LanguageService.getPhrase(namespace, 'curriculum'),\n url: Core.AppLinkHelper.getHref(props.appLinks?.classificationCurriculum?.(props.classification))\n },\n analyticsOptions: {\n actionType: UserAction.Click,\n entity: EntityType.Url,\n location: LocationContext.MagicTabs\n },\n className: `${breakpoints.xs ? 'w-100' : ''} ${isHighlighting ? styles.tabTransition : ''}`\n }];\n}\n\ninterface ClassificationTabsProps {\n classification: Classification;\n presentation: Presentation;\n appLinks: {\n classification: (classification: Classification | null) => Core.AppLink,\n classificationDirectory: (classification: Classification) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink\n };\n activeTab: ClassificationTab;\n}\n\nexport function ClassificationTabs(props: ClassificationTabsProps): JSX.Element {\n const breakpoints = useBreakpoints();\n const { tab, isHighlighting } = useDirectoryTabProductTipSwitcher(props.activeTab);\n\n return (\n <PillTabSelector\n borderRadius='sm'\n className={breakpoints.xs ? 'w-100' : ''}\n listClassName='d-flex flex-nowrap'\n tabs={getTabs(props, breakpoints, tab, isHighlighting)}\n />\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { Breadcrumb, Breadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { useBreakpoints } from 'libs/shared/hooks/useBreakpoints';\nimport { Classification, CuratedDashboard, Presentation, PresentationAudience } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { ClassificationDashboardAudiences } from '../audiences/ClassificationDashboardAudiences';\nimport { ClassificationTab, ClassificationTabs } from '../classification-tabs/ClassificationTabs';\n\nfunction shouldHideAudiences(\n audiences: PresentationAudience[],\n activeAudiences: PresentationAudience[],\n activeTab: ClassificationTab,\n isEmpty: boolean,\n isComingSoon: boolean\n): boolean {\n if (isComingSoon)\n return true;\n\n if (isEmpty && !activeAudiences?.length)\n return true;\n\n if (!AudienceHelper.shouldShowAudiences(audiences))\n return true;\n\n if (activeTab === 'curriculum')\n return true;\n\n return false;\n}\n\ninterface ClassificationDashboardNavProps {\n dashboard: CuratedDashboard;\n classification: Classification;\n presentation: Presentation;\n appLinks: {\n audience: () => Core.AppLink,\n classification: (classification: Classification | null) => Core.AppLink,\n classificationDirectory: (classification: Classification) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink\n };\n activeTab: ClassificationTab;\n audiences: PresentationAudience[];\n activeAudiences: PresentationAudience[];\n getBreadcrumbs: () => Breadcrumb[];\n\n hasTopicDirectoryDashboard: boolean;\n hasTopicCurriculumDashboard: boolean;\n isComingSoon: boolean;\n isEmpty: boolean;\n isViewingCurrentPresentation: boolean;\n disableAudiences: boolean;\n audienceTooltip: string;\n\n // Forces audiences to be hidden regardless of shouldHideAudiences' own rules (e.g. channel topic dashboards)\n forceHideAudiences?: boolean;\n}\n\nexport function ClassificationDashboardNav(props: ClassificationDashboardNavProps): JSX.Element {\n const breakpoints = useBreakpoints();\n\n const hideAudiences = props.forceHideAudiences || shouldHideAudiences(\n props.audiences,\n props.activeAudiences,\n props.activeTab,\n props.isEmpty,\n props.isComingSoon\n );\n\n function canShowTabs(): boolean {\n if (!props.classification || !props.dashboard)\n return false;\n\n if (CuratedDashboardHelper.isSystemGeneratedDashboard(props.dashboard.widgets))\n return false;\n\n /**\n * For our top-level topics, we can show the topic tab if the topic has a directory dashboard.\n */\n if (TopicsHelper.isTopLevelTopic(props.classification))\n return props.hasTopicDirectoryDashboard;\n\n /**\n * For our curated topics, we can show the curriculum tab if the topic has one, which it should\n */\n if (props.classification.externalMetadata?.isCurated && props.hasTopicCurriculumDashboard)\n return true;\n\n return false;\n }\n\n function getContainerClass(): string {\n let className = 'd-flex flex-column py-3 mb-3';\n\n if (!props.isComingSoon)\n className += ' border-bottom';\n\n if ((canShowTabs() || hideAudiences) && !breakpoints.xs)\n return className;\n\n return className + ' row-gap-3';\n }\n\n function getTopRowClass(): string {\n if (hideAudiences) {\n if (breakpoints.xs)\n return 'd-flex flex-column justify-content-between row-gap-3';\n\n return 'd-flex align-items-center justify-content-between';\n }\n\n let className = '';\n\n className += 'd-flex align-items-center justify-content-between mb-1';\n\n if (breakpoints.xs)\n className += ' row-gap-3 mb-0';\n\n return className;\n }\n\n function getBottomRowClass(): string {\n let className = 'd-flex align-items-end justify-content-between';\n\n if (breakpoints.xs)\n className += ' row-gap-3 flex-wrap';\n\n return className;\n }\n\n return (\n <div className={getContainerClass()}>\n <div className={getTopRowClass()}>\n <Breadcrumbs breadcrumbs={props.getBreadcrumbs?.()} />\n\n {canShowTabs() && hideAudiences && (\n <ClassificationTabs\n classification={props.classification}\n activeTab={props.activeTab}\n appLinks={props.appLinks}\n presentation={props.presentation}\n />\n )}\n </div>\n\n <div className={getBottomRowClass()}>\n {!hideAudiences && (\n <ClassificationDashboardAudiences\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n appLink={props.appLinks.audience?.()}\n disabled={props.disableAudiences}\n tooltip={props.audienceTooltip}\n disablePersist={!props.isViewingCurrentPresentation}\n />\n )}\n\n {canShowTabs() && !hideAudiences && (\n <ClassificationTabs\n classification={props.classification}\n activeTab={props.activeTab}\n appLinks={props.appLinks}\n presentation={props.presentation}\n />\n )}\n </div>\n </div>\n );\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsOptions, HashObject, LocationContext } from 'libs/analytics/interfaces';\n\nimport { ClassificationHeaderDetails } from 'libs/shared/apps/subjects/components/classification-dashboard/classification-header-details/ClassificationHeaderDetails';\nimport { CuratedClassificationEmptyState } from 'libs/shared/apps/subjects/components/classification-dashboard/empty-state/CuratedClassificationEmptyState';\nimport { TableOfContentsContainer } from 'libs/shared/apps/subjects/components/classification-dashboard/table-of-contents/TableOfContents';\nimport { TeacherOnlyEmptyState } from 'libs/shared/apps/subjects/components/classification-dashboard/teacher-only/TeacherOnlyEmptyState';\nimport { useGetTopicsWidgets } from 'libs/shared/apps/subjects/hooks/useGetTopicsWidgets';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { BannerHeader } from 'libs/shared/components/banner-header/BannerHeader';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { ExpandableTextInline } from 'libs/shared/components/expandable-text-inline/ExpandableTextInline';\nimport { DashboardFeedbackData } from 'libs/shared/components/feedback-form/FeedbackForm';\nimport { VideoList } from 'libs/shared/components/video-list/VideoList';\nimport { WidgetHeader } from 'libs/shared/components/widgets/curated-widgets/components/header/WidgetHeader';\nimport { InfiniteWidgetContainerView } from 'libs/shared/components/widgets/curated-widgets/InfiniteWidgetContainerView';\nimport { WidgetContainerView } from 'libs/shared/components/widgets/curated-widgets/WidgetContainerView';\nimport { AllClassificationWidgetTemplates } from 'libs/shared/components/widgets/curated-widgets/WidgetProps';\nimport { ClassificationType } from 'libs/shared/enums/ClassificationType';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { LocalPermissionName } from 'libs/shared/enums/PermissionName';\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { WidgetTypeId } from 'libs/shared/enums/WidgetTypeId';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { HasLocalPermissionsFunc, HasPermissionsFunc } from 'libs/shared/hooks/usePermissions';\nimport { useTableOfContentsActiveHeading } from 'libs/shared/hooks/useTableOfContentsActiveHeading';\nimport { useTableOfContentsScroll } from 'libs/shared/hooks/useTableOfContentsScroll';\nimport { CalendarEvent, CalendarEventContentType, Classification, CuratedDashboard, CuratedWidget, CuratedWidgetQueryParams, CurriculumData, DashboardStatus, DashboardTargetType, InteractiveMetadata, PartnerProfile, Presentation, PresentationAudience, Resource } from 'libs/shared/interfaces';\nimport { CommonVideoProps } from 'libs/shared/interfaces/CommonVideoProps';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\nimport { WidgetHelper } from 'libs/shared/utils/WidgetHelper';\n\nimport { ClassificationComingSoon } from './classification-coming-soon/ClassificationComingSoon';\nimport { ClassificationDashboardNav } from './classification-dashboard-nav/ClassificationDashboardNav';\nimport { ClassificationTab } from './classification-tabs/ClassificationTabs';\n\nconst namespace = 'shared.classificationDashboard';\n\nfunction isHeadingWidget(widget: CuratedWidget) {\n return widget.widgetId === WidgetTypeId.Blurb && widget.templateId === WidgetTemplate.Heading;\n}\n\nfunction isTopicWidget(widget: CuratedWidget) {\n return widget.widgetId === WidgetTypeId.CuratedClassifications || widget.widgetId === WidgetTypeId.Classifications;\n}\n\n// ClassificationAllVideos is the only widget type that supports infinite-scroll pagination so far\nconst InfiniteFetchWidgetIds: WidgetTypeId[] = [WidgetTypeId.ClassificationAllVideos];\n\nfunction shouldInfiniteFetch(widgets: CuratedWidget[], index: number): boolean {\n const currentWidget = widgets[index];\n\n if (!currentWidget) return false;\n\n return InfiniteFetchWidgetIds.includes(currentWidget.widgetId) && index === widgets.length - 1;\n}\n\n/**\n * Mirrors WidgetHelper's per-widget empty check (which InfiniteWidgetContainerView can't infer\n * on its own, since a completed fetch always returns one \"page\" object regardless of whether the\n * widget's own content is empty).\n */\nfunction isWidgetContentEmpty(widgets: CuratedWidget[]): boolean {\n const widget = widgets?.[0];\n\n if (!widget) return true;\n\n if (WidgetHelper.hasNoContent(widget.widgetId)) return false;\n\n if (!widget.content) return true;\n\n return Array.isArray(widget.content) && !widget.content.length;\n}\n\nexport interface ClassificationDashboardProps {\n dashboard: CuratedDashboard;\n classification: Classification;\n presentation: Presentation;\n hasPermissions: HasPermissionsFunc;\n hasLocalPermissions: HasLocalPermissionsFunc;\n resourceThumbnailFallbackImageUrl: string;\n hasTopicDirectoryDashboard: boolean;\n hasTopicCurriculumDashboard: boolean;\n isTertiaryCustomerWithoutExchange: boolean;\n tab: ClassificationTab;\n specialEvent?: CalendarEvent;\n curriculums: CurriculumData;\n channel?: PartnerProfile;\n\n audiences: PresentationAudience[];\n activeAudiences?: PresentationAudience[];\n\n getWidgetContentRequest: (\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate\n ) => Flight.Request;\n\n /**\n * Only needed by consumers that support cursor-paginated widgets (currently just\n * WidgetTypeId.ClassificationAllVideos). If omitted, that widget type falls back to fetching\n * its first page only via `getWidgetContentRequest`, with no \"load more\" pagination.\n */\n getWidgetContentRequestWithCursor?: (\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate,\n cursor?: string\n ) => Flight.Request;\n\n getBannerActions?: () => ActionOptions[];\n getBreadcrumbs?: () => Breadcrumb[];\n onToggleFollow?: (classification: Classification, locationContext: LocationContext) => void;\n canFollowSubjects: boolean;\n onSubmitFeedback?: (feedback: DashboardFeedbackData) => Promise<void>;\n onDownloadAllClick?: (resources: Resource[], fileName: string, analyticsData?: HashObject) => void;\n\n appLinks?: AllClassificationWidgetTemplates['appLinks'] & {\n signUp: () => Core.AppLink,\n widgetWizard: () => Core.AppLink,\n previewQuestions: (interactive: InteractiveMetadata) => Core.AppLink,\n classificationCurriculum: (classification: Classification) => Core.AppLink,\n audience: () => Core.AppLink\n };\n\n imageCdnUrl: string;\n imageUrls?: AllClassificationWidgetTemplates['imageUrls'];\n emptyImageUrl: string;\n comingSoonImageUrl?: string;\n\n analyticsOptions?: AnalyticsOptions;\n analyticsData?: HashObject;\n\n scrollToWidgetId?: string;\n tableOfContentsId?: string;\n\n // Means the dashboard contains no linked or working filters\n isReadonly?: boolean;\n\n // Means the dashboard is being previewed by ClickView staff either in product or in curator\n isPreviewing?: boolean;\n\n // Means the parent topic for the dashboard has a status of \"Coming Soon\"\n isComingSoon?: boolean;\n\n showFollowButtonSpinner?: boolean;\n \n isViewCurrentPresentation?: boolean;\n\n // By default widgets will always be lazyloaded. We override this behaviour only in extenuating \n // circumstances, such as dynamic rendering for SEO.\n lazyLoad?: boolean;\n\n moviesAndTv?: boolean;\n\n isTeacherOnly?: boolean;\n \n contentType?: CalendarEventContentType;\n\n isBot?: boolean;\n\n settings?: AllClassificationWidgetTemplates['settings'];\n\n commonVideoProps: CommonVideoProps;\n}\n\nClassificationDashboard.defaultProps = {\n appLinks: {}\n};\n\nexport function ClassificationDashboard(props: ClassificationDashboardProps): JSX.Element {\n const { widgets, videoList, videoListWidgetId } = useGetTopicsWidgets(props.dashboard, props.activeAudiences);\n\n const isSmallScreen = useMediaQuery(MediaQueryStrings.LGDown);\n const headingRef = React.useRef<Set<Element>>(new Set());\n\n const initialEmptyWidgets = React.useMemo(() => {\n return widgets.reduce((acc: HashObject<boolean>, widget) => {\n acc[widget.id] = false;\n return acc;\n }, {});\n }, [widgets?.length]);\n\n const [ emptyWidgets, setEmptyWidgets ] = React.useState(initialEmptyWidgets);\n\n const [ controlledId, setControlledId ] = React.useState(props.tableOfContentsId);\n\n const [ tableOfContentActiveId, setTableOfContentActiveId ] = React.useState<string>('');\n\n const headingElements = Array.from(headingRef.current);\n useTableOfContentsScroll(headingElements, controlledId);\n useTableOfContentsActiveHeading({\n setActiveId: setTableOfContentActiveId,\n headingElements,\n controlledId,\n setControlledId\n });\n\n const isHubDashboard = props.classification.type === ClassificationType.Hub;\n const isChannelTopic = !!props.dashboard?.metadata?.channelId;\n\n function shouldShowEmptyState(): boolean {\n if (props.isComingSoon)\n return false;\n\n if (props.isTeacherOnly)\n return false;\n\n if (!props.dashboard)\n return true;\n\n if (props.dashboard.status === DashboardStatus.Archived && !props.isReadonly)\n return true;\n\n if (props.dashboard.status === DashboardStatus.Draft && !props.isPreviewing)\n return true;\n\n if (!widgets?.length)\n return true;\n\n if (videoList && videoList.length)\n return false;\n\n return Object.values(emptyWidgets).every(state => !!state);\n }\n\n function getWidgetContentRequest(\n id: string,\n widgetTypeId: WidgetTypeId,\n template: WidgetTemplate,\n cursor?: string\n ): Flight.Request {\n const params = CuratedDashboardHelper.getWidgetParams(\n widgetTypeId,\n template,\n CuratedDashboardHelper.getDashboardTargetType(props.dashboard),\n props.activeAudiences?.map(a => a.masterId),\n props.curriculums.preferredCurriculum?.id\n );\n\n if (cursor && props.getWidgetContentRequestWithCursor)\n return props.getWidgetContentRequestWithCursor(id, params, template, cursor);\n\n return props.getWidgetContentRequest(id, params, template);\n }\n\n const showEmptyState = shouldShowEmptyState();\n\n React.useEffect(() => {\n /**\n * When we add the first widget of the dashboard, the showEmptyState is `true`, the WidgetContainer is not going to be rendered to lazyload the `content`\n * so we set the emptyWidget to initial make sure the widget container is rendered to lazyload `widget.content`\n * and let the WidgetContainer to re-set the empty state based on the actual `widget.content` from backend\n */\n if (showEmptyState) {\n setEmptyWidgets(initialEmptyWidgets);\n }\n }, [widgets?.length]);\n\n const onSetIsEmpty = React.useCallback((widgetId: string, isEmpty: boolean) => {\n if (emptyWidgets[widgetId] === isEmpty)\n return;\n\n const newEmptyState = {\n ...emptyWidgets,\n [widgetId]: isEmpty\n };\n\n // The logic beneath this if-block doesn't apply to classification directories. This is because\n // classification directories don't support audience filtering, so widgets should never be empty,\n // meaning headings should never be hidden.\n if (CuratedDashboardHelper.isType(props.dashboard, DashboardTargetType.ClassificationDirectory)) {\n setEmptyWidgets(newEmptyState);\n return;\n }\n\n let index = 0;\n\n /**\n * Every time a widget is identified as empty, we check each heading blurb widget\n * to see if it should be hidden. This will be the case when all widgets beneath a heading\n * (up until the next heading) are empty.\n */\n while (index < widgets.length) {\n const currentWidget = widgets[index];\n\n if (!isHeadingWidget(currentWidget)) {\n index++;\n continue;\n }\n\n let isHeadingEmpty = true;\n let subWidgetIndex = index + 1;\n\n while (isHeadingEmpty && subWidgetIndex < widgets.length) {\n const headingSubWidget = widgets[subWidgetIndex];\n\n if (isHeadingWidget(headingSubWidget))\n break;\n\n if (!newEmptyState[headingSubWidget.id] && !isTopicWidget(headingSubWidget))\n isHeadingEmpty = false;\n\n subWidgetIndex++;\n }\n\n index = subWidgetIndex;\n\n newEmptyState[currentWidget.id] = isHeadingEmpty;\n }\n\n setEmptyWidgets(newEmptyState);\n }, [ emptyWidgets, widgets ]);\n\n function hideWidget(widget: CuratedWidget): boolean {\n return isHeadingWidget(widget) && emptyWidgets[widget.id];\n }\n\n function useLargeDashboardSpacing(): boolean {\n const target = CuratedDashboardHelper.getDashboardTargetType(props.dashboard);\n\n if (props.moviesAndTv || target === DashboardTargetType.ClassificationCurriculum)\n return false;\n\n return true;\n }\n\n function getWidgetHeading(widget: CuratedWidget, index: number): string {\n if (widget.widgetId === WidgetTypeId.ClassificationDashboardExternalMedia) {\n const previousWidget = widgets[index - 1];\n\n if (emptyWidgets[previousWidget.id])\n return widget.name.replace('Other videos', 'Videos');\n\n return widget.name;\n }\n\n return widget.name;\n }\n\n const widgetsInTableOfContents = widgets.filter(w => {\n return !hideWidget(w) && !!w.metadata?.showInTableOfContents;\n });\n\n const isTopicOnlyDashboard = widgets.every(isTopicWidget);\n\n const shouldShowTableOfContents = widgetsInTableOfContents.length >= 2;\n const shouldShowSideTableOfContents = shouldShowTableOfContents && !isSmallScreen;\n\n const shouldShowTopicCounts = (\n props.settings?.hasTopicDirectories &&\n TopicsHelper.isTopLevelTopic(props.classification) &&\n !props.isTertiaryCustomerWithoutExchange &&\n !isHubDashboard\n );\n\n /**\n * We don't put the .topic-dashboard class when we're in a movies and tv classification\n * because we don't want the extra padding between widgets.\n */\n return (\n <div className={`bg-white px-4 ${useLargeDashboardSpacing() ? 'dashboard-spacing-lg' : ''}`}>\n\n <BannerHeader\n type={isChannelTopic ? 'channel-topic' : 'default'}\n logo={isChannelTopic && props.channel?._logo.value}\n logoBgColour={isChannelTopic && props.channel?._colour.value}\n heading={props.classification.name}\n banner={props.classification.banner}\n imageCdnUrl={props.imageCdnUrl}\n actions={props.getBannerActions?.()}\n actionsDropdownClassName='btn btn-outline-dark'\n specialEvent={props.specialEvent}\n calendarTheme={{\n background: 'bg-light-blue',\n border: 'border-light-blue'\n }}\n showComingSoon={props.isComingSoon}\n detailsComponent={shouldShowTopicCounts ?\n () => <ClassificationHeaderDetails classification={props.classification} /> :\n null\n }\n />\n\n {!isHubDashboard ? (\n <ClassificationDashboardNav\n forceHideAudiences={isChannelTopic}\n dashboard={props.dashboard}\n classification={props.classification}\n presentation={props.presentation}\n appLinks={props.appLinks}\n activeTab={props.tab}\n audiences={props.audiences}\n activeAudiences={props.activeAudiences}\n getBreadcrumbs={props.getBreadcrumbs}\n hasTopicDirectoryDashboard={props.hasTopicDirectoryDashboard}\n hasTopicCurriculumDashboard={props.hasTopicCurriculumDashboard}\n isComingSoon={props.isComingSoon}\n isEmpty={showEmptyState}\n isViewingCurrentPresentation={props.isViewCurrentPresentation}\n disableAudiences={isTopicOnlyDashboard || props.isReadonly}\n audienceTooltip={isTopicOnlyDashboard ? LanguageService.getPhrase(namespace, 'audienceTooltip') : ''}\n />\n ) : (\n <div className='py-3 mb-3 border-bottom'>\n <div className='mt-3'>\n <ExpandableTextInline>\n {() => (\n <p className='mb-0'>{props.classification.description}</p>\n )}\n </ExpandableTextInline>\n </div>\n </div>\n )}\n\n {props.isComingSoon && (\n <ClassificationComingSoon\n imageUrl={props.comingSoonImageUrl}\n data={props.classification}\n canFollowSubjects={props.canFollowSubjects}\n showFollowButtonSpinner={props.showFollowButtonSpinner}\n onToggleFollow={() => props.onToggleFollow(props.classification, LocationContext.ClassificationComingSoon)}\n showSignUp={!props.hasLocalPermissions(LocalPermissionName.FollowComingSoonTopics)}\n signUpAppLink={props.appLinks.signUp?.()}\n />\n )}\n\n {!props.isComingSoon && (\n <div className={`${shouldShowSideTableOfContents ? 'row no-wrap' : ''}`}>\n {shouldShowTableOfContents && (\n <TableOfContentsContainer\n widgets={widgetsInTableOfContents}\n title={props.classification.name}\n activeId={tableOfContentActiveId}\n clickable={!props.isReadonly}\n analyticsData={props.analyticsData}\n setControlledId={setControlledId}\n isSmallScreen={isSmallScreen}\n />\n )}\n\n <div className={shouldShowSideTableOfContents ? 'col-9 order-0' : ''}>\n {widgets.map((widget, idx) => {\n if (hideWidget(widget))\n return <React.Fragment key={widget.id}></React.Fragment>;\n\n if (InfiniteFetchWidgetIds.includes(widget.widgetId)) {\n return (\n <InfiniteWidgetContainerView<CuratedWidget, CuratedWidget, AllClassificationWidgetTemplates>\n index={idx}\n key={widget.id}\n item={widget}\n infiniteFetch={shouldInfiniteFetch(widgets, idx) && !!props.getWidgetContentRequestWithCursor}\n dashboardTarget={CuratedDashboardHelper.getDashboardTargetType(props.dashboard)}\n\n getName={w => getWidgetHeading(w, idx)}\n getWidgetMetadata={w => w.metadata}\n getContent={w => w.content}\n getCursor={w => w.cursor}\n getRequest={cursor => (\n getWidgetContentRequest(widget.id, widget.widgetId, widget.templateId, cursor)\n )}\n isEmptyPredicate={isWidgetContentEmpty}\n\n audiences={props.audiences}\n appLinks={props.appLinks}\n commonVideoProps={props.commonVideoProps}\n hasPermissions={props.hasPermissions}\n hasLocalPermissions={props.hasLocalPermissions}\n resultsTransformers={WidgetHelper.getWidgetResultsTransformers()}\n\n presentation={props.presentation}\n analyticsData={props.analyticsData}\n imageCdnUrl={props.imageCdnUrl}\n imageUrls={props.imageUrls}\n resourceThumbnailFallbackImageUrl={props.resourceThumbnailFallbackImageUrl}\n lazyLoad={props.lazyLoad}\n\n headingElementRef={headingRef}\n hasTableOfContents={shouldShowSideTableOfContents}\n isScrollToTargetWidget={props.scrollToWidgetId === widget.id}\n isBot={props.isBot}\n isPreviewing={props.isReadonly}\n isEditing={props.isReadonly}\n curriculums={props.curriculums}\n contentType={props.contentType}\n\n setIsEmpty={isEmpty => onSetIsEmpty(widget.id, isEmpty)}\n\n getSelectedItems={null}\n appLinkOptions={null}\n />\n );\n }\n\n return (\n <WidgetContainerView\n widgetCollection={DashboardTargetType.Classification}\n headingElementRef={headingRef}\n key={widget.id}\n id={widget.id}\n name={getWidgetHeading(widget, idx)}\n description={widget.description}\n classification={props.classification}\n templateId={widget.templateId}\n widgetTypeId={widget.widgetId}\n audiences={props.audiences}\n getContentRequest={getWidgetContentRequest}\n setIsEmpty={onSetIsEmpty}\n appLinks={props.appLinks}\n presentation={props.presentation}\n analyticsData={props.analyticsData}\n isScrollToTargetWidget={props.scrollToWidgetId === widget.id}\n imageCdnUrl={props.imageCdnUrl}\n imageUrls={props.imageUrls}\n onSubmitFeedback={props.onSubmitFeedback}\n onDownloadAllClick={props.onDownloadAllClick}\n metadata={widget.metadata}\n isBot={props.isBot}\n hasTableOfContents={shouldShowSideTableOfContents}\n lazyLoad={props.lazyLoad}\n dashboardTarget={CuratedDashboardHelper.getDashboardTargetType(props.dashboard)}\n widgetIndex={idx}\n hasPermissions={props.hasPermissions}\n hasLocalPermissions={props.hasLocalPermissions}\n isPreviewing={props.isReadonly}\n contentType={props.contentType}\n resourceThumbnailFallbackImageUrl={props.resourceThumbnailFallbackImageUrl}\n onToggleFollowClassification={props.onToggleFollow}\n settings={props.settings}\n isEditing={props.isReadonly}\n isTertiaryCustomerWithoutExchange={props.isTertiaryCustomerWithoutExchange}\n commonVideoProps={props.commonVideoProps}\n curriculums={props.curriculums}\n\n // TODO: Do we actually need this shit if it wasn't even being passed in?\n limitTotalItems={false}\n seeMoreLink={null}\n onClickRemoveItem={null}\n badgeComponent={null}\n />\n );\n })}\n </div>\n\n {!!videoList?.length && (\n <>\n <WidgetHeader name={LanguageService.getPhrase(namespace, 'videos')} />\n <VideoList\n videos={videoList}\n getVideoAppLink={(video, opts) => props.appLinks.videoType(\n video,\n { ...opts, contextId: videoListWidgetId, includeContext: opts.includeContext }\n )}\n hasPermissions={props.hasPermissions}\n presentationAudiences={props.audiences}\n getPreviewQuestionsAppLink={props.appLinks.previewQuestions}\n commonVideoProps={props.commonVideoProps}\n />\n </>\n )}\n </div>\n )}\n\n {showEmptyState && (\n <CuratedClassificationEmptyState\n dashboard={props.dashboard}\n isReadonly={props.isReadonly}\n imageUrl={props.emptyImageUrl}\n addWidgetApplink={props.appLinks.widgetWizard}\n />\n )}\n\n {props.isTeacherOnly && (\n <TeacherOnlyEmptyState\n imageUrl={props.emptyImageUrl}\n ctaAppLink={() => props.appLinks.allTopics(props.classification.presentationId)}\n />\n )}\n </div>\n );\n}\n","import React from 'react';\n\nimport { PartialAudienceFilter } from 'libs/shared/apps/subjects/components/audience-filter/AudienceFilter';\nimport { PartialBannerHeader } from 'libs/shared/components/banner-header/BannerHeader';\nimport { PartialBreadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\n\nexport function PartialClassificationDashboard(): JSX.Element {\n return (\n <div className='bg-white px-4'>\n <PartialBannerHeader />\n\n <div className='d-flex flex-column row-gap-3 py-3 mb-3 border-bottom'>\n <PartialBreadcrumbs />\n <PartialAudienceFilter />\n </div>\n </div>\n );\n}\n","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\n\nconst endpoints = {\n follow: () => `{gateway}/v1/users/me/classifications/following`,\n unfollow: (ids: string[]) => UrlHelper.urlBuilder('{gateway}/v1/users/me/classifications/following', { id: ids })\n};\n\nexport const FollowRequests = {\n /**\n * @param data - array of object ids the user is going to follow\n */\n follow(ids: string[], userId: string, success?: (data: string[]) => void, error?: () => void): Flight.Request {\n return {\n url: endpoints.follow(),\n key: `follow:${ids.join(',')}`,\n type: HttpVerbs.POST,\n data: ids,\n formatData: () => {\n return ids.map(id => ({\n id,\n followers: {\n data: [userId]\n }\n }));\n },\n success,\n error,\n invalidationKeys: [ ...ids.map(id => `classification:${id}`), 'my:subject:preferences', 'classifications' ]\n };\n },\n\n unfollow(ids: string[], userId: string, success?: () => void, error?: () => void): Flight.Request {\n return {\n url: endpoints.unfollow(ids),\n key: `unfollow:${ids.join(',')}`,\n type: HttpVerbs.DELETE,\n formatData: () => {\n return ids.map(id => ({\n id,\n followers: {\n data: [] as string[]\n }\n }));\n },\n success,\n error,\n invalidationKeys: [ ...ids.map(id => `classification:${id}`), 'my:subject:preferences', 'classifications' ]\n };\n }\n};\n","@import '~styles/utils/include-media';\n\n.followButton {\n @include media('<=sm') {\n min-width: 2.5rem;\n min-height: 2.5rem;\n }\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, HashObject, LocationContext, ToggleDescriptor, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { FollowRequests } from 'libs/shared/flight-requests/FollowRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { BellFilledSvg } from 'libs/shared/images/svg/objects/BellFilledSvg';\nimport { BellSvg } from 'libs/shared/images/svg/objects/BellSvg';\nimport { Classification, CurrentUser } from 'libs/shared/interfaces';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport styles from './use-follow-classification.module.scss';\n\nconst getPhrase = LanguageService.encloseNamespace('subjects.classification');\n\ninterface UseFollowClassificationOptions {\n classification: Classification;\n analyticsData: HashObject;\n}\n\ninterface UseFollowClassificationResult {\n canFollowSubjects: boolean;\n showFollowButtonSpinner: boolean;\n onToggleFollow: (classification: Classification, location: LocationContext) => void;\n getFollowBannerActions: () => ActionOptions[];\n}\n\nexport function useFollowClassification(\n options: UseFollowClassificationOptions\n): UseFollowClassificationResult {\n const { classification, analyticsData } = options;\n\n const [ showFollowButtonSpinner, setShowFollowButtonSpinner ] = React.useState<boolean>(false);\n\n const alerts = useAlerts();\n const fetchAsync = Flight.useGetFetchAsync();\n const { hasPermissions } = usePermissions();\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const isSmallScreen = useMediaQuery(MediaQueryStrings.MDDown);\n const isMobile = useMediaQuery(MediaQueryStrings.SMDown);\n\n const canFollowSubjects = hasPermissions(PermissionName.FollowSubjects);\n\n function onToggleFollow(followedClassification: Classification, location: LocationContext) {\n if (!canFollowSubjects || !classification)\n return;\n\n const isTogglingCurrentTopic = followedClassification.id.toString() === classification.id?.toString();\n\n if (isTogglingCurrentTopic)\n setShowFollowButtonSpinner(true);\n\n const isFollowing = TopicsHelper.isFollowing(followedClassification);\n\n const request = isFollowing ?\n FollowRequests.unfollow :\n FollowRequests.follow;\n\n fetchAsync(request([followedClassification.id], currentUser.data?.id))\n .then(() => {\n AnalyticsHelper.logUserAction(analyticsData, {\n location,\n actionType: UserAction.Follow,\n workflowPhase: WorkflowPhase.Complete,\n descriptor: isFollowing ? ToggleDescriptor.Off : ToggleDescriptor.On,\n entity: EntityType.Classification\n });\n\n if (!isTogglingCurrentTopic) {\n alerts.success(getPhrase(isFollowing ? 'unfollowed' : 'followed', { name: followedClassification.name }));\n }\n })\n .finally(() => {\n if (isTogglingCurrentTopic)\n setShowFollowButtonSpinner(false);\n });\n }\n\n function getFollowBannerActions(): ActionOptions[] {\n if (!canFollowSubjects || !classification)\n return [];\n\n const isFollowing = !!classification.followers?.data?.length;\n\n return [{\n label: isMobile ? '' : getPhrase(isFollowing ? 'following' : 'follow'),\n onClick: () => onToggleFollow(classification, LocationContext.Banner),\n svg: isFollowing ? BellFilledSvg : BellSvg,\n className: `btn follow-btn ${isFollowing ? 'btn-outline-dark' : 'btn-dark'} ${styles.followButton}`,\n button: true,\n tooltip: (isFollowing || isSmallScreen) ? undefined : getPhrase('followBtnTooltip'),\n showSpinner: showFollowButtonSpinner\n }];\n }\n\n return {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n };\n}\n","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { ErrorCta, ErrorPageError } from 'libs/shared/errors/primitives/ErrorPageError';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nconst namespace = 'subjects.topicNotFoundError';\n\nexport class TopicNotFoundError extends ErrorPageError {\n constructor() {\n super('Topic doesn\\'t exist');\n }\n\n // @ts-ignore\n public get name(): string {\n return 'TopicNotFoundError';\n }\n\n // @ts-ignore\n public get heading(): string {\n return LanguageService.getPhrase(namespace, 'heading');\n }\n\n // @ts-ignore\n public get description(): string {\n return LanguageService.getPhrase(namespace, 'description');\n }\n\n // @ts-ignore\n public get cta(): ErrorCta {\n return {\n text: LanguageService.getPhrase(namespace, 'cta'),\n appLink: {\n application: AppChannels.SUBJECT,\n action: Actions.Subjects.PRESENTATION_TOPICS,\n args: [null]\n }\n };\n }\n}\n","import { useSettings } from 'libs/shared/hooks/useSettings';\nimport { DashboardTargetType } from 'libs/shared/interfaces';\n\nimport { useFetchCuratedDashboard } from 'shared/utils/DashboardHelper';\n\nimport { ClassificationViewQueryParams } from '../views/classification/ClassificationViewUtils';\n\nexport function useFetchClassificationDashboard(\n id: string,\n queryParams: ClassificationViewQueryParams,\n targetType: DashboardTargetType\n) {\n const { hasTopicDirectories, hasTopicVideoListFeature } = useSettings(null);\n\n const {\n dashboard: curatedTopicDashboard,\n isPreviewing,\n isTeacherOnly\n } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.Classification\n });\n\n const { dashboard: directoryDashboard } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.ClassificationDirectory\n });\n\n const { dashboard: curriculumDashboard } = useFetchCuratedDashboard({\n classificationId: id,\n queryParams: queryParams,\n targetType: DashboardTargetType.ClassificationCurriculum\n });\n\n function getDashboard() {\n switch (targetType) {\n case DashboardTargetType.Classification:\n return curatedTopicDashboard;\n case DashboardTargetType.ClassificationDirectory:\n return directoryDashboard;\n case DashboardTargetType.ClassificationCurriculum:\n return curriculumDashboard;\n }\n }\n\n return {\n dashboard: getDashboard(),\n hasTopicDirectoryDashboard: hasTopicDirectories && !!directoryDashboard.data,\n hasTopicCurriculumDashboard: hasTopicVideoListFeature && !!curriculumDashboard.data,\n isTeacherOnly,\n isPreviewing\n };\n}\n","import React from 'react';\n\nimport { LocationUtils } from 'libs/common/backbone/core';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { EntityType, LocationContext, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { CalendarRequests } from 'libs/shared/apps/calendar/flight-request/CalendarRequests';\nimport { LibraryHelper } from 'libs/shared/apps/libraries/utils/LibraryHelper';\nimport { ClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/ClassificationDashboard';\nimport { PartialClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard';\nimport { PreviewBanner } from 'libs/shared/apps/subjects/components/preview-banner/PreviewBanner';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { DashboardFeedbackData } from 'libs/shared/components/feedback-form/FeedbackForm';\nimport { VideoActionsContext } from 'libs/shared/context/VideoActionsContext';\nimport { ClassificationStatus } from 'libs/shared/enums/ClassificationStatus';\nimport { ClassificationType } from 'libs/shared/enums/ClassificationType';\nimport { FeedbackType } from 'libs/shared/enums/FeedbackType';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { ProductId } from 'libs/shared/enums/ProductId';\nimport { WidgetTemplate } from 'libs/shared/enums/WidgetTemplate';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClassificationRequests } from 'libs/shared/flight-requests/ClassificationRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { CustomerRequests } from 'libs/shared/flight-requests/CustomerRequests';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { FeedbackRequests } from 'libs/shared/flight-requests/FeedbackRequests';\nimport { LibraryRequests } from 'libs/shared/flight-requests/LibraryRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useBreadcrumbs } from 'libs/shared/hooks/useBreadcrumbs';\nimport { useCurationStudio } from 'libs/shared/hooks/useCurationStudio';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useProducts } from 'libs/shared/hooks/UseProducts';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { CalendarEvent, Classification, Config, CuratedWidgetQueryParams, CurrentUser, Customer, DashboardTargetType, Library, Presentation, PresentationAudience, RegionAlternative } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { CuratedDashboardHelper } from 'libs/shared/utils/DashboardHelper';\nimport { FeedbackFormHelper } from 'libs/shared/utils/FeedbackFormHelper';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\nimport { TopicsHelper } from 'libs/shared/utils/topics-helper/TopicsHelper';\n\nimport { DashboardWidgetImageUrls } from 'shared/constants/DashboardWidgetImageUrls';\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { ContentPartnersRequests } from 'shared/flight-requests/ContentPartnersRequests';\nimport { useAvailablePresentations } from 'shared/hooks/presentations/useAvailablePresentations';\nimport { useFollowClassification } from 'shared/hooks/use-follow-classification/useFollowClassification';\nimport { useVideoActions, VideoActionsLocation } from 'shared/hooks/use-video-actions/useVideoActions';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDeepLinks } from 'shared/hooks/useDeepLinks';\nimport { useDownloadAllResources } from 'shared/hooks/useDownloadAllResources';\nimport { ClassificationAppLinkHelper } from 'shared/utils/ClassificationAppLinkHelper';\nimport { InteractiveHelpers } from 'shared/utils/InteractiveHelper';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\n\nimport { useIsTertiary } from 'apps/onboarding/hooks/useIsTertiary';\nimport { SignUpHelper } from 'apps/sign-up/utils/SignUpHelper';\nimport { TopicNotFoundError } from 'apps/subjects/errors/TopicNotFoundError';\nimport { useFetchClassificationDashboard } from 'apps/subjects/hooks/useFetchClassificationDashboard';\nimport {\n ClassificationViewQueryParams,\n getClassificationAppLinks\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\n\ninterface CuratedClassificationViewProps {\n presentationSlug: string | null;\n id: string;\n queryParams?: ClassificationViewQueryParams;\n targetType: DashboardTargetType;\n}\n\nCuratedClassificationView.defaultProps = {\n queryParams: {}\n};\n\nconst namespace = 'subjects.classification';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function CuratedClassificationView(props: CuratedClassificationViewProps): React.ReactElement {\n const fetchAsync = Flight.useGetFetchAsync();\n const { hasPermissions, hasLocalPermissions } = usePermissions();\n const settings = useSettings(null);\n const onDownloadAllClick = useDownloadAllResources();\n\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const { openInCurationStudioLabel, isUserCurator, getOpenInCurationStudioLink } = useCurationStudio();\n const curriculums = useCurriculums();\n\n const customer = Flight.useBasicFetch<Customer>(\n hasPermissions(PermissionName.CanSubmitFeedback) &&\n currentUser.data?.isAuthenticated &&\n CustomerRequests.customer(currentUser.data.customerId)\n );\n\n const classification = Flight.useBasicFetch<Classification>(\n ClassificationRequests.classification(props.id, currentUser.data?.id)\n );\n\n const isHubDashboard = classification.data?.type === ClassificationType.Hub;\n // Once inside a hub topic's dashboard, every generated app link should carry\n // its id forward so navigating deeper (series/videos/sub-topics) keeps that context.\n const hubTopicId = isHubDashboard ? classification.data?.id : props.queryParams.hubTopic;\n\n const presentation = Flight.useBasicFetch<Presentation>(\n classification.data &&\n ClassificationRequests.presentationById(classification.data.presentationId)\n );\n\n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n classification.data &&\n AudienceRequests.audiencesByPresentationId(classification.data.presentationId)\n );\n\n const specialEvent = Flight.useBasicFetch<CalendarEvent>(\n classification.data &&\n CalendarRequests.nextTopicSpecialEvent(props.id, classification.data.presentationId)\n );\n\n const libraries = Flight.useBasicFetch<Library[]>(\n currentUser.data?.isAuthenticated &&\n LibraryRequests.libraries()\n );\n\n const {\n availablePresentations,\n canAccessPresentation\n } = useAvailablePresentations();\n\n const path = Flight.useBasicFetch<Classification[]>(ClassificationRequests.path(props.id));\n\n const {\n dashboard,\n hasTopicDirectoryDashboard,\n hasTopicCurriculumDashboard,\n isPreviewing,\n isTeacherOnly\n } = useFetchClassificationDashboard(props.id, props.queryParams, props.targetType);\n\n const isTertiary = useIsTertiary();\n const products = useProducts();\n\n const regionAlternatives = Flight.useBasicFetch<RegionAlternative[]>(\n ClassificationRequests.regionAlternatives(props.id)\n );\n\n const preferredRegionAlternative = SeoHelper.getPreferredRegionAlternative(\n regionAlternatives.data,\n currentUser.data?.contentRegion\n );\n useSetPageMetadata(PageMetadataHelper.getClassificationMetadata({\n content: { classification: classification.data, dashboard: dashboard.data },\n\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: ClassificationAppLinkHelper.getAppLink({\n ...classification.data,\n name: preferredRegionAlternative?.name || classification.data?.name\n }, props.queryParams, availablePresentations),\n hrefTransformer: SeoHelper.createRegionHrefTransformer(\n regionAlternatives.data,\n currentUser.data?.contentRegion\n )\n }),\n allowIndexing: SeoHelper.allowIndexing(),\n hrefLang: SeoHelper.getContentHrefLang(regionAlternatives.data, () => (\n ClassificationAppLinkHelper.getAppLink(classification.data, {}, availablePresentations)\n ))\n }));\n\n useHandleObjectError(classification, {\n notFound: TopicNotFoundError\n });\n useDeepLinks({ id: props.id, app: 'topics' });\n \n const { commonVideoProps } = useCommonVideoProps({\n locationContext: LocationContext.VideoThumbnail,\n mtv: props.queryParams.mtv,\n hubTopic: hubTopicId\n });\n const videoActions = useVideoActions({\n location: VideoActionsLocation.VideoItem,\n presentationSlug: props.presentationSlug\n });\n\n const activeAudiences = React.useMemo(\n () => AudienceHelper.getActiveAudiencesFromParams(audiences.data, props.queryParams),\n [ audiences.data, props.queryParams ]\n );\n const activeAudienceIds = activeAudiences?.map(a => a.masterId) ?? [];\n\n const analyticsData = {\n presentationId: presentation.data?.id,\n presentationName: presentation.data?.name,\n currentClassificationId: classification.data?.id,\n currentClassificationName: classification.data?.name,\n followingCurrentClassification: !!classification.data?.followers?.data?.length,\n activeAudienceNames: activeAudiences?.length ? activeAudiences.map(a => a.name) : null,\n activeAudienceIds: activeAudienceIds.length ? activeAudienceIds : null\n };\n\n const {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n } = useFollowClassification({\n classification: classification.data,\n analyticsData\n });\n\n const isComingSoon = (\n classification.data?.status === ClassificationStatus.ComingSoon &&\n !isPreviewing\n );\n\n const targetType = CuratedDashboardHelper.getDashboardTargetType(dashboard.data);\n\n async function onSubmitFeedback(feedback: DashboardFeedbackData): Promise<void> {\n const promise = await fetchAsync<void>(FeedbackRequests.submitFeedback({\n type: FeedbackType.Footer,\n user: FeedbackFormHelper.getUserInfo(currentUser.data, customer.data),\n tags: FeedbackFormHelper.getTags(\n currentUser.data,\n ProductId.Primary,\n hasPermissions(PermissionName.StudentExperience),\n [ 'topics', 'in product feedback' ]\n )\n }, {\n reaction: feedback.type,\n feedback: feedback.content,\n location: 'Topic Footer',\n presentationName: presentation.data.description,\n presentationId: presentation.data.id,\n dashboardName: dashboard.data.name,\n dashboardId: dashboard.data.id,\n classificationName: classification.data.name,\n classificationId: classification.data.id,\n currentPageUrl: LocationUtils.GetCurrentUrl()\n }));\n\n AnalyticsHelper.logUserAction({\n feedbackType: feedback.type,\n content: feedback.content,\n presentationId: presentation.data.id,\n classificationId: classification.data.id,\n dashboardId: dashboard.data.id\n }, {\n actionType: UserAction.Submit,\n location: LocationContext.ClassificationFooter,\n entity: EntityType.Feedback,\n workflowPhase: WorkflowPhase.Complete\n });\n\n return promise;\n }\n\n function getBannerActions(): ActionOptions[] {\n if (isHubDashboard || isChannelTopic) {\n return [];\n }\n\n const followActions = getFollowBannerActions();\n\n if (!isUserCurator)\n return followActions;\n\n return [\n ...followActions.map(action => ({ ...action, className: `${action.className} me-2` })),\n {\n label: openInCurationStudioLabel,\n href: getOpenInCurationStudioLink(MasterType.Subject, classification.data?.id, presentation.data?.id),\n openInNewTab: true\n }\n ];\n }\n\n const appLinks = getClassificationAppLinks(\n classification.data,\n targetType,\n { ...props.queryParams, hubTopic: hubTopicId },\n currentUser.data,\n props.presentationSlug,\n availablePresentations\n );\n\n const breadcrumbs = useBreadcrumbs({ name: classification.data?.name });\n function getBreadcrumbs(): () => Breadcrumb[] {\n if (!canAccessPresentation(presentation.data?.id))\n return;\n\n return () => breadcrumbs;\n }\n\n function getWidgetContentRequest(\n id: string,\n params: CuratedWidgetQueryParams,\n widgetTemplate: WidgetTemplate,\n cursor?: string\n ): Flight.Request {\n const { hasTwig, hasTigtag } = LibraryHelper.hasTwigOrTigtag(libraries.data, currentUser.data);\n\n return DashboardRequests.dashboardWidgetContent(\n id,\n params,\n widgetTemplate,\n presentation.data,\n { hideTigTag: !hasTigtag, hideTwig: !hasTwig, cursor }\n );\n }\n\n const isChannelTopic = dashboard.data?.metadata?.channelId;\n const channel = Flight.useBasicFetch(isChannelTopic\n && ContentPartnersRequests.partnerProfile(dashboard.data?.metadata?.channelId));\n\n const dataLoaded = !!config.data\n && dashboard.hasCompleted\n && !!classification.data\n && !!presentation.data\n && !!path.data\n && !!availablePresentations\n && !!audiences.data\n && specialEvent.hasCompleted\n && (!isChannelTopic || channel.hasCompleted);\n\n if (!dataLoaded && !isHubDashboard)\n return <PartialClassificationDashboard />;\n\n return (\n <VideoActionsContext.Provider value={videoActions}>\n <div className='position-relative'>\n {!!(isPreviewing && dashboard.data) && <PreviewBanner status={dashboard.data.status} type='topic' />}\n <ClassificationDashboard\n dashboard={dashboard.data}\n classification={classification.data}\n channel={channel.data}\n getWidgetContentRequest={getWidgetContentRequest}\n getWidgetContentRequestWithCursor={getWidgetContentRequest}\n getBreadcrumbs={getBreadcrumbs()}\n hasPermissions={hasPermissions}\n hasLocalPermissions={hasLocalPermissions}\n presentation={presentation.data}\n curriculums={curriculums}\n onToggleFollow={onToggleFollow}\n getBannerActions={getBannerActions}\n audiences={props.queryParams.mtv ? null : audiences.data}\n activeAudiences={activeAudiences}\n analyticsData={analyticsData}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrls={DashboardWidgetImageUrls}\n resourceThumbnailFallbackImageUrl={ImageUrls.Fallbacks.RESOURCE_THUMBNAIL}\n emptyImageUrl={isTeacherOnly ? ImageUrls.EmptyStates.Topics.TEACHER_ONLY : ImageUrls.EmptyStates.Topics.TOPIC}\n isComingSoon={isComingSoon}\n showFollowButtonSpinner={showFollowButtonSpinner}\n comingSoonImageUrl={ImageUrls.EmptyStates.Topics.COMING_SOON}\n appLinks={{\n ...appLinks,\n signUp: SignUpHelper.getSignUpAppLink,\n widgetWizard: () => null,\n previewQuestions: interactive => InteractiveHelpers.getPreviewQuestionsAppLink(interactive)\n }}\n isPreviewing={isPreviewing}\n canFollowSubjects={canFollowSubjects}\n onSubmitFeedback={\n hasPermissions(PermissionName.CanSubmitFeedback) &&\n onSubmitFeedback\n }\n tableOfContentsId={props.queryParams.tocId}\n lazyLoad={!SeoHelper.isBot()}\n moviesAndTv={props.queryParams.mtv}\n isTeacherOnly={isTeacherOnly}\n specialEvent={specialEvent.data}\n isBot={SeoHelper.isBot()}\n hasTopicDirectoryDashboard={hasTopicDirectoryDashboard}\n hasTopicCurriculumDashboard={hasTopicCurriculumDashboard}\n tab={TopicsHelper.getActiveTopicTab(classification.data, props.targetType)}\n // just... one... more.. prop....\n settings={settings}\n isTertiaryCustomerWithoutExchange={isTertiary && !products?.hasProduct(ProductId.Exchange)}\n commonVideoProps={commonVideoProps}\n onDownloadAllClick={onDownloadAllClick}\n />\n </div>\n </VideoActionsContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { ClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/ClassificationDashboard';\nimport { PartialClassificationDashboard } from 'libs/shared/apps/subjects/components/classification-dashboard/partial-loading/PartialClassificationDashboard';\nimport { PreviewBanner } from 'libs/shared/apps/subjects/components/preview-banner/PreviewBanner';\nimport { ActionOptions } from 'libs/shared/components/actions/Actions';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { VideoActionsContext } from 'libs/shared/context/VideoActionsContext';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { PresentationType } from 'libs/shared/enums/PresentationType';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClassificationRequests } from 'libs/shared/flight-requests/ClassificationRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { DashboardRequests } from 'libs/shared/flight-requests/DashboardRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useCurationStudio } from 'libs/shared/hooks/useCurationStudio';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { CalendarEventContentType, Classification, Config, CurrentUser, DashboardTargetType, PresentationAudience } from 'libs/shared/interfaces';\nimport { AudienceHelper } from 'libs/shared/utils/audience-helper/AudienceHelper';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\n\nimport { DashboardWidgetImageUrls } from 'shared/constants/DashboardWidgetImageUrls';\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { useFollowClassification } from 'shared/hooks/use-follow-classification/useFollowClassification';\nimport { useVideoActions, VideoActionsLocation } from 'shared/hooks/use-video-actions/useVideoActions';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDownloadAllResources } from 'shared/hooks/useDownloadAllResources';\nimport { useFetchCuratedDashboard } from 'shared/utils/DashboardHelper';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\n\nimport { TopicNotFoundError } from 'apps/subjects/errors/TopicNotFoundError';\nimport {\n ClassificationViewQueryParams,\n getLiveClassificationAppLinks,\n getLiveClassificationBreadcrumbs\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\n\nconst namespace = 'liveClassification.classificationView';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface LiveClassificationViewProps {\n presentationSlug: string | null;\n id: string;\n queryParams?: ClassificationViewQueryParams;\n}\n\nLiveClassificationView.defaultProps = {\n queryParams: {}\n};\n\nexport function LiveClassificationView(\n props: LiveClassificationViewProps\n): JSX.Element {\n const { commonVideoProps } = useCommonVideoProps({ locationContext: LocationContext.VideoThumbnail });\n const videoActions = useVideoActions({\n location: VideoActionsLocation.VideoItem,\n presentationSlug: props.presentationSlug\n });\n const curriculums = useCurriculums();\n const onDownloadAllClick = useDownloadAllResources();\n\n const { openInCurationStudioLabel, isUserCurator, getOpenInCurationStudioLink } = useCurationStudio('clickview-live');\n\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const classification = Flight.useBasicFetch<Classification>(\n ClassificationRequests.classification(props.id, currentUser.data?.id)\n );\n\n const { dashboard, presentation, isPreviewing } = useFetchCuratedDashboard({\n targetType: DashboardTargetType.Classification,\n classificationId: props.id,\n queryParams: props.queryParams\n });\n\n // ClickView audiences are typed differently from Subject audiences for the same presentation id;\n // Fetch with the explicit Live type so we get the correct grade set.\n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n presentation &&\n AudienceRequests.presentationAudiences(PresentationType.StreamableLearning, presentation.id)\n );\n\n const path = Flight.useBasicFetch<Classification[]>(\n ClassificationRequests.path(props.id, PresentationType.StreamableLearning)\n );\n\n const appLinks = getLiveClassificationAppLinks(\n classification.data,\n props.queryParams,\n props.presentationSlug\n );\n\n useSetPageMetadata(PageMetadataHelper.getClassificationMetadata({\n content: { classification: classification.data, dashboard: dashboard.data },\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: appLinks.classification(classification.data)\n }),\n allowIndexing: SeoHelper.allowIndexing()\n }));\n\n useHandleObjectError(classification, {\n notFound: TopicNotFoundError\n });\n\n const activeAudiences = React.useMemo(\n () => AudienceHelper.getActiveAudiencesFromParams(audiences.data, props.queryParams),\n [ audiences.data, props.queryParams ]\n );\n const activeAudienceIds = activeAudiences?.map(a => a.masterId) ?? [];\n\n const analyticsData = {\n presentationId: presentation?.id,\n presentationName: presentation?.name,\n currentClassificationId: classification.data?.id,\n currentClassificationName: classification.data?.name,\n followingCurrentClassification: !!classification.data?.followers?.data?.length,\n activeAudienceNames: activeAudiences?.length ? activeAudiences.map(a => a.name) : null,\n activeAudienceIds: activeAudienceIds.length ? activeAudienceIds : null\n };\n\n const {\n canFollowSubjects,\n showFollowButtonSpinner,\n onToggleFollow,\n getFollowBannerActions\n } = useFollowClassification({\n classification: classification.data,\n analyticsData\n });\n\n function getBannerActions(): ActionOptions[] {\n const followActions = getFollowBannerActions();\n\n if (!isUserCurator)\n return followActions;\n\n return [\n ...followActions.map(action => ({ ...action, className: `${action.className} me-2` })),\n {\n label: openInCurationStudioLabel,\n href: getOpenInCurationStudioLink(MasterType.Subject, classification.data?.id, presentation?.id),\n openInNewTab: true\n }\n ];\n }\n\n function getBreadcrumbs(): () => Breadcrumb[] {\n return () => getLiveClassificationBreadcrumbs({\n appLinks,\n classification: classification.data,\n path: path.data,\n presentationSlug: props.presentationSlug\n });\n }\n\n const dataLoaded = !!config.data\n && dashboard.hasCompleted\n && !!classification.data\n && !!presentation\n && !!path.data\n && !!audiences.data;\n\n if (!dataLoaded)\n return <PartialClassificationDashboard />;\n \n return (\n <VideoActionsContext.Provider value={videoActions}>\n <div className='position-relative'>\n {!!(isPreviewing && dashboard.data) && (\n <PreviewBanner status={dashboard.data.status} type='topic' />\n )}\n <ClassificationDashboard\n dashboard={dashboard.data}\n classification={classification.data}\n getWidgetContentRequest={DashboardRequests.dashboardWidgetContent}\n getBreadcrumbs={getBreadcrumbs()}\n hasPermissions={() => false}\n hasLocalPermissions={() => false}\n presentation={presentation}\n getBannerActions={getBannerActions}\n onToggleFollow={onToggleFollow}\n showFollowButtonSpinner={showFollowButtonSpinner}\n audiences={audiences.data}\n activeAudiences={activeAudiences}\n analyticsData={analyticsData}\n imageCdnUrl={config.data.imageCdnUrl}\n imageUrls={DashboardWidgetImageUrls}\n resourceThumbnailFallbackImageUrl={ImageUrls.Live.Fallbacks.RESOURCE_THUMBNAIL}\n emptyImageUrl={ImageUrls.Live.EmptyStates.Topics.TOPIC}\n appLinks={appLinks}\n isPreviewing={isPreviewing}\n isViewCurrentPresentation\n canFollowSubjects={canFollowSubjects}\n tableOfContentsId={props.queryParams.tocId}\n lazyLoad={!SeoHelper.isBot()}\n isTeacherOnly={false}\n contentType={CalendarEventContentType.Livestream}\n hasTopicDirectoryDashboard={false}\n hasTopicCurriculumDashboard={false}\n isTertiaryCustomerWithoutExchange={false}\n tab='curated-topic'\n curriculums={curriculums}\n commonVideoProps={commonVideoProps}\n onDownloadAllClick={onDownloadAllClick}\n />\n </div>\n </VideoActionsContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { PresentationType } from 'libs/shared/enums/PresentationType';\nimport { DashboardTargetType } from 'libs/shared/interfaces';\n\nimport { createPresentationDispatcherView } from 'shared/utils/createPresentationDispatcherView';\n\nimport {\n ClassificationViewQueryParams\n} from 'apps/subjects/views/classification/ClassificationViewUtils';\nimport {\n CuratedClassificationView\n} from 'apps/subjects/views/classification/curated-classification/CuratedClassificationView';\nimport {\n LiveClassificationView\n} from 'apps/subjects/views/classification/live-classification/LiveClassificationView';\n\ninterface ClassificationRouteProps {\n presentationSlug: string | null;\n id: string;\n queryParams: ClassificationViewQueryParams;\n targetType: DashboardTargetType;\n}\n\nexport const BaseClassificationView = createPresentationDispatcherView<ClassificationRouteProps>({\n [PresentationType.Subject]: ctx => (\n <CuratedClassificationView\n key={`${ctx.id}:${ctx.targetType}`}\n presentationSlug={ctx.presentationSlug}\n id={ctx.id}\n queryParams={ctx.queryParams}\n targetType={ctx.targetType}\n />\n ),\n [PresentationType.StreamableLearning]: ctx => {\n if (ctx.targetType !== DashboardTargetType.Classification)\n return null;\n\n return (\n <LiveClassificationView\n key={`${ctx.id}:${ctx.targetType}`}\n presentationSlug={ctx.presentationSlug}\n id={ctx.id}\n queryParams={ctx.queryParams}\n />\n );\n }\n});\n\nBaseClassificationView.displayName = 'BaseClassificationView';\n"],"mappings":"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"}