@openedx/frontend-base 2.0.0-alpha.1 → 2.0.0-alpha.3

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 (70) hide show
  1. package/dist/runtime/config/index.js +2 -0
  2. package/dist/runtime/config/index.js.map +1 -1
  3. package/dist/runtime/i18n/index.d.ts +6 -8
  4. package/dist/runtime/i18n/index.js +6 -8
  5. package/dist/runtime/i18n/index.js.map +1 -1
  6. package/dist/runtime/i18n/lib.d.ts +38 -8
  7. package/dist/runtime/i18n/lib.js +88 -22
  8. package/dist/runtime/i18n/lib.js.map +1 -1
  9. package/dist/runtime/i18n/updateSiteLanguage.d.ts +17 -0
  10. package/dist/runtime/i18n/updateSiteLanguage.js +91 -0
  11. package/dist/runtime/i18n/updateSiteLanguage.js.map +1 -0
  12. package/dist/runtime/index.d.ts +1 -1
  13. package/dist/runtime/index.js +1 -1
  14. package/dist/runtime/index.js.map +1 -1
  15. package/dist/runtime/logging/types.js.map +1 -1
  16. package/dist/runtime/react/CombinedAppProvider.js.map +1 -1
  17. package/dist/runtime/react/CurrentAppContext.js.map +1 -1
  18. package/dist/runtime/react/CurrentAppProvider.js.map +1 -1
  19. package/dist/runtime/react/SiteContext.js.map +1 -1
  20. package/dist/runtime/react/SiteProvider.js.map +1 -1
  21. package/dist/runtime/react/hooks/theme/useThemeVariants.js.map +1 -1
  22. package/dist/runtime/slots/Slot.js.map +1 -1
  23. package/dist/runtime/slots/SlotContext.js.map +1 -1
  24. package/dist/runtime/slots/layout/types.js.map +1 -1
  25. package/dist/runtime/slots/types.js.map +1 -1
  26. package/dist/runtime/slots/widget/WidgetContext.js.map +1 -1
  27. package/dist/runtime/slots/widget/WidgetProvider.js.map +1 -1
  28. package/dist/runtime/slots/widget/iframe/IFrameContentWrapper.js.map +1 -1
  29. package/dist/runtime/slots/widget/iframe/IFrameWidget.js.map +1 -1
  30. package/dist/runtime/slots/widget/iframe/hooks.js.map +1 -1
  31. package/dist/runtime/slots/widget/iframe/types.js.map +1 -1
  32. package/dist/runtime/slots/widget/types.js.map +1 -1
  33. package/dist/runtime/testing/initializeMockApp.js.map +1 -1
  34. package/dist/shell/Logo.js.map +1 -1
  35. package/dist/shell/dev/devHeader/BarContext.js.map +1 -1
  36. package/dist/shell/dev/devHeader/BarProvider.js.map +1 -1
  37. package/dist/shell/dev/devHeader/FooContext.js.map +1 -1
  38. package/dist/shell/dev/devHeader/FooProvider.js.map +1 -1
  39. package/dist/shell/dev/slotShowcase/SlotShowcasePage.js.map +1 -1
  40. package/dist/shell/dev/slotShowcase/app.js.map +1 -1
  41. package/dist/shell/footer/CopyrightNotice.js.map +1 -1
  42. package/dist/shell/footer/LanguageMenu.js +36 -6
  43. package/dist/shell/footer/LanguageMenu.js.map +1 -1
  44. package/dist/shell/footer/LanguageMenuItem.d.ts +4 -1
  45. package/dist/shell/footer/LanguageMenuItem.js +4 -5
  46. package/dist/shell/footer/LanguageMenuItem.js.map +1 -1
  47. package/dist/shell/footer/messages.d.ts +8 -0
  48. package/dist/shell/footer/messages.js +10 -0
  49. package/dist/shell/footer/messages.js.map +1 -0
  50. package/dist/shell/header/AuthenticatedMenu.js.map +1 -1
  51. package/dist/shell/header/HelpButton.js.map +1 -1
  52. package/dist/shell/header/anonymous-menu/AnonymousMenu.js.map +1 -1
  53. package/dist/shell/header/course-bar/data/service.js.map +1 -1
  54. package/dist/shell/header/course-bar/masquerade/StudioLink.js.map +1 -1
  55. package/dist/shell/header/course-bar/masquerade/data/api.js.map +1 -1
  56. package/dist/shell/header/course-bar/masquerade/hooks.js.map +1 -1
  57. package/dist/shell/header/course-bar/masquerade/masquerade-widget/MasqueradeUserNameInput.js.map +1 -1
  58. package/dist/shell/header/course-bar/masquerade/masquerade-widget/MasqueradeWidgetOption.js.map +1 -1
  59. package/dist/shell/header/course-bar/navigation/CourseTabsNavigation.js.map +1 -1
  60. package/dist/shell/header/helpButtonSlotOperation.js.map +1 -1
  61. package/dist/shell/menus/LinkMenuItem.js.map +1 -1
  62. package/dist/shell/menus/NavDropdownMenuSlot.js.map +1 -1
  63. package/dist/shell/menus/ProfileLinkMenuItem.js.map +1 -1
  64. package/dist/tools/eslint/base.eslint.config.js +2 -2
  65. package/dist/types.d.ts +2 -0
  66. package/dist/types.js.map +1 -1
  67. package/package.json +1 -1
  68. package/dist/shell/footer/data/api.d.ts +0 -1
  69. package/dist/shell/footer/data/api.js +0 -45
  70. package/dist/shell/footer/data/api.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SlotShowcasePage.js","sourceRoot":"","sources":["../../../../shell/dev/slotShowcase/SlotShowcasePage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ReactNode } from 'react';\nimport { Card, Container } from '@openedx/paragon';\nimport { Slot } from '../../../runtime';\nimport HorizontalSlotLayout from './HorizontalSlotLayout';\nimport LayoutWithOptions from './LayoutWithOptions';\nimport ToggleByRoleLayout from './ToggleByRoleLayout';\nimport './SlotShowcase.scss';\n\nfunction SlotContainer({ children }: { children: ReactNode }) {\n return (\n <Card className=\"showcase-slot\">\n <Card.Body>\n {children}\n </Card.Body>\n </Card>\n );\n}\n\nfunction Section({ title, children }: { title: string, children: ReactNode }) {\n return (\n <div>\n <h3 className=\"text-primary-500\">{title}</h3>\n {children}\n </div>\n );\n}\n\nexport default function SlotShowcasePage() {\n return (\n <Container fluid size=\"xl\" className=\"showcase-page py-4\">\n <div className=\"showcase-full-width\">\n <h1>Slot Showcase</h1>\n <p>As a best practice, widgets should pass additional props (<code>...props</code>) to their rendered HTMLElement. This allows custom layouts to add <code>className</code> and <code>style</code> props as necessary for the layout.</p>\n </div>\n\n <Section title=\"Simple slot with default layout\">\n <p>This slot has no opinionated layout, it just renders its children.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseSimple\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Simple slot with default content and props\">\n <p>This slot has default content, and it exposes a slot prop to widgets.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent\" aSlotProp=\"hello!\">\n <div className=\"showcase-widget\">Look, I&apos;m default content!</div>\n </Slot>\n </SlotContainer>\n </Section>\n\n <h2 className=\"showcase-divider\">UI Layout Operations</h2>\n\n <Section title=\"Slot with custom layout (component)\">\n <p>This slot uses a horizontal flexbox layout from a component.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustom\" layout={HorizontalSlotLayout} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with custom layout (element)\">\n <p>This slot uses a horizontal flexbox layout from a JSX element.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustom\" layout={<HorizontalSlotLayout />} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with override custom layout\">\n <p>This slot uses a horizontal flexbox layout, but it was added by a layout replace operation.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustomConfig\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with layout options (default)\">\n <p>This slot uses a custom layout that takes options. It shows the default title.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault\" layout={LayoutWithOptions} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with layout options (configured)\">\n <p>Same layout, but the title option is set to &quot;Bar&quot;.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions\" layout={LayoutWithOptions} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with widget filtering by role\">\n <p>This slot has four widgets, two with a &quot;highlighted&quot; role. The layout uses <code>widgets.byRole()</code> to toggle between all and highlighted.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseFilterByRole\" layout={ToggleByRoleLayout} />\n </SlotContainer>\n </Section>\n\n <h2 className=\"showcase-divider\">UI Widget Operations</h2>\n\n <Section title=\"Slot with prepended element\">\n <p>This slot has a prepended element (and two appended elements).</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcasePrepending\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with inserted elements\">\n <p>This slot has elements inserted before and after the second element. The insert operations are declared <em>before</em> the related element, but can still insert themselves relative to it.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseInserting\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with replaced element\">\n <p>This slot has an element replacing element two.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseReplacing\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with removed element\">\n <p>This slot has removed element two (<code>WidgetOperationTypes.REMOVE</code>).</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseRemoving\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with widget options (default)\">\n <p>This widget accepts options. It shows the default title.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions\" />\n </SlotContainer>\n </Section>\n\n </Container>\n );\n}\n"]}
1
+ {"version":3,"file":"SlotShowcasePage.js","sourceRoot":"","sources":["../../../../shell/dev/slotShowcase/SlotShowcasePage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ReactNode } from 'react';\nimport { Card, Container } from '@openedx/paragon';\nimport { Slot } from '../../../runtime';\nimport HorizontalSlotLayout from './HorizontalSlotLayout';\nimport LayoutWithOptions from './LayoutWithOptions';\nimport ToggleByRoleLayout from './ToggleByRoleLayout';\nimport './SlotShowcase.scss';\n\nfunction SlotContainer({ children }: { children: ReactNode }) {\n return (\n <Card className=\"showcase-slot\">\n <Card.Body>\n {children}\n </Card.Body>\n </Card>\n );\n}\n\nfunction Section({ title, children }: { title: string; children: ReactNode }) {\n return (\n <div>\n <h3 className=\"text-primary-500\">{title}</h3>\n {children}\n </div>\n );\n}\n\nexport default function SlotShowcasePage() {\n return (\n <Container fluid size=\"xl\" className=\"showcase-page py-4\">\n <div className=\"showcase-full-width\">\n <h1>Slot Showcase</h1>\n <p>As a best practice, widgets should pass additional props (<code>...props</code>) to their rendered HTMLElement. This allows custom layouts to add <code>className</code> and <code>style</code> props as necessary for the layout.</p>\n </div>\n\n <Section title=\"Simple slot with default layout\">\n <p>This slot has no opinionated layout, it just renders its children.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseSimple\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Simple slot with default content and props\">\n <p>This slot has default content, and it exposes a slot prop to widgets.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent\" aSlotProp=\"hello!\">\n <div className=\"showcase-widget\">Look, I&apos;m default content!</div>\n </Slot>\n </SlotContainer>\n </Section>\n\n <h2 className=\"showcase-divider\">UI Layout Operations</h2>\n\n <Section title=\"Slot with custom layout (component)\">\n <p>This slot uses a horizontal flexbox layout from a component.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustom\" layout={HorizontalSlotLayout} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with custom layout (element)\">\n <p>This slot uses a horizontal flexbox layout from a JSX element.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustom\" layout={<HorizontalSlotLayout />} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with override custom layout\">\n <p>This slot uses a horizontal flexbox layout, but it was added by a layout replace operation.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseCustomConfig\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with layout options (default)\">\n <p>This slot uses a custom layout that takes options. It shows the default title.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault\" layout={LayoutWithOptions} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with layout options (configured)\">\n <p>Same layout, but the title option is set to &quot;Bar&quot;.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions\" layout={LayoutWithOptions} />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with widget filtering by role\">\n <p>This slot has four widgets, two with a &quot;highlighted&quot; role. The layout uses <code>widgets.byRole()</code> to toggle between all and highlighted.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseFilterByRole\" layout={ToggleByRoleLayout} />\n </SlotContainer>\n </Section>\n\n <h2 className=\"showcase-divider\">UI Widget Operations</h2>\n\n <Section title=\"Slot with prepended element\">\n <p>This slot has a prepended element (and two appended elements).</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcasePrepending\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with inserted elements\">\n <p>This slot has elements inserted before and after the second element. The insert operations are declared <em>before</em> the related element, but can still insert themselves relative to it.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseInserting\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with replaced element\">\n <p>This slot has an element replacing element two.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseReplacing\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with removed element\">\n <p>This slot has removed element two (<code>WidgetOperationTypes.REMOVE</code>).</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseRemoving\" />\n </SlotContainer>\n </Section>\n\n <Section title=\"Slot with widget options (default)\">\n <p>This widget accepts options. It shows the default title.</p>\n <SlotContainer>\n <Slot id=\"org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions\" />\n </SlotContainer>\n </Section>\n\n </Container>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../../shell/dev/slotShowcase/app.tsx"],"names":[],"mappings":"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","sourcesContent":["import { NavDropdownMenuSlot } from '../..';\nimport LinkMenuItem from '../../menus/LinkMenuItem';\nimport { LayoutOperationTypes, WidgetOperationTypes, useSlotContext } from '../../../runtime';\nimport { App } from '../../../types';\nimport HorizontalSlotLayout from './HorizontalSlotLayout';\nimport SlotShowcasePage from './SlotShowcasePage';\nimport WidgetWithOptions from './WidgetWithOptions';\n\nfunction Widget({ title, op, className, ...props }: { title: string, op?: string, className?: string } & Record<string, unknown>) {\n return (\n <div className={`showcase-widget ${className ?? ''}`} {...props}>\n {title}\n {op && (\n <span>{' '}(<code>{op}</code>)</span>\n )}\n </div>\n );\n}\n\nfunction TakesProps({ aSlotProp }: { aSlotProp: string }) {\n return (\n <div className=\"showcase-widget\">And this is a slot prop that was passed down via props: <code>{aSlotProp}</code></div>\n );\n}\n\nfunction TakesPropsViaContext() {\n const slotContext = useSlotContext();\n const aSlotProp = typeof slotContext.aSlotProp === 'string' ? slotContext.aSlotProp : 'foo';\n return (\n <div className=\"showcase-widget\">And this is the same prop, but accessed via slot context: <code>{aSlotProp}</code></div>\n );\n}\n\nconst app: App = {\n appId: 'org.openedx.frontend.app.slotShowcase',\n routes: [{\n id: 'org.openedx.frontend.route.slotShowcase',\n path: '/slots',\n Component: SlotShowcasePage,\n handle: {\n roles: ['org.openedx.frontend.role.slotShowcase'],\n }\n }],\n slots: [\n // Simple\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild4',\n op: WidgetOperationTypes.APPEND,\n component: TakesProps\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild5',\n op: WidgetOperationTypes.APPEND,\n component: TakesPropsViaContext\n },\n\n // Custom Layout\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // Override custom layout\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n op: LayoutOperationTypes.REPLACE,\n element: <HorizontalSlotLayout />,\n },\n\n // Layout Options\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n op: LayoutOperationTypes.OPTIONS,\n options: {\n title: 'Bar',\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // TODO: Override Layout\n\n // Prepending\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" op=\"WidgetOperationTypes.APPEND\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" op=\"WidgetOperationTypes.APPEND\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild3',\n op: WidgetOperationTypes.PREPEND,\n element: (<Widget title=\"Widget Three\" op=\"WidgetOperationTypes.PREPEND\" />)\n },\n\n // Inserting\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'slot-showcase.inserting.child4',\n op: WidgetOperationTypes.INSERT_AFTER,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n element: (<Widget title=\"Widget Four\" op=\"WidgetOperationTypes.INSERT_AFTER\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'slot-showcase.inserting.child5',\n op: WidgetOperationTypes.INSERT_BEFORE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n element: (<Widget title=\"Widget Five\" op=\"WidgetOperationTypes.INSERT_BEFORE\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // Replacing\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild4',\n op: WidgetOperationTypes.REPLACE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.replacingChild2',\n element: (<Widget title=\"Widget Four\" op=\"WidgetOperationTypes.REPLACE\" />)\n },\n\n // Hiding\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n op: WidgetOperationTypes.REMOVE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.removingChild2',\n },\n\n // Widget Options\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild1',\n op: WidgetOperationTypes.APPEND,\n component: WidgetWithOptions,\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild2',\n op: WidgetOperationTypes.APPEND,\n component: WidgetWithOptions,\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n relatedId: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild2',\n op: WidgetOperationTypes.OPTIONS,\n options: {\n title: 'Bar',\n }\n },\n\n // Widget filtering by role\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild2',\n role: 'org.openedx.frontend.role.slotShowcase.highlighted',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two (highlighted)\" className=\"showcase-widget-highlighted\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild4',\n role: 'org.openedx.frontend.role.slotShowcase.highlighted',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Four (highlighted)\" className=\"showcase-widget-highlighted\" />)\n },\n\n // Header\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n relatedId: 'org.openedx.frontend.widget.slotShowcase.headerLink',\n op: WidgetOperationTypes.OPTIONS,\n options: {\n title: 'Courses (modified)',\n },\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLinkAfter3',\n op: WidgetOperationTypes.INSERT_AFTER,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.headerLink3',\n element: (<LinkMenuItem label=\"Link After 3\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerPrimaryLinksDropdownPrepend',\n op: WidgetOperationTypes.PREPEND,\n element: (\n <NavDropdownMenuSlot id=\"org.openedx.frontend.slot.header.primaryLinksDropdown.v1\" label=\"Resources\" />\n ),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase']\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinksDropdown.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerPrimaryLinksDropdownAppend',\n op: WidgetOperationTypes.APPEND,\n element: (\n <LinkMenuItem label=\"Resource 1\" url=\"#\" variant=\"dropdownItem\" />\n ),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLink3',\n op: WidgetOperationTypes.APPEND,\n element: (<LinkMenuItem label=\"Link 3\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLink4',\n op: WidgetOperationTypes.APPEND,\n element: (<LinkMenuItem label=\"Link 4\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n ]\n};\n\nexport default app;\n"]}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../../shell/dev/slotShowcase/app.tsx"],"names":[],"mappings":"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","sourcesContent":["import { NavDropdownMenuSlot } from '../..';\nimport LinkMenuItem from '../../menus/LinkMenuItem';\nimport { LayoutOperationTypes, WidgetOperationTypes, useSlotContext } from '../../../runtime';\nimport { App } from '../../../types';\nimport HorizontalSlotLayout from './HorizontalSlotLayout';\nimport SlotShowcasePage from './SlotShowcasePage';\nimport WidgetWithOptions from './WidgetWithOptions';\n\nfunction Widget({ title, op, className, ...props }: { title: string; op?: string; className?: string } & Record<string, unknown>) {\n return (\n <div className={`showcase-widget ${className ?? ''}`} {...props}>\n {title}\n {op && (\n <span>{' '}(<code>{op}</code>)</span>\n )}\n </div>\n );\n}\n\nfunction TakesProps({ aSlotProp }: { aSlotProp: string }) {\n return (\n <div className=\"showcase-widget\">And this is a slot prop that was passed down via props: <code>{aSlotProp}</code></div>\n );\n}\n\nfunction TakesPropsViaContext() {\n const slotContext = useSlotContext();\n const aSlotProp = typeof slotContext.aSlotProp === 'string' ? slotContext.aSlotProp : 'foo';\n return (\n <div className=\"showcase-widget\">And this is the same prop, but accessed via slot context: <code>{aSlotProp}</code></div>\n );\n}\n\nconst app: App = {\n appId: 'org.openedx.frontend.app.slotShowcase',\n routes: [{\n id: 'org.openedx.frontend.route.slotShowcase',\n path: '/slots',\n Component: SlotShowcasePage,\n handle: {\n roles: ['org.openedx.frontend.role.slotShowcase'],\n }\n }],\n slots: [\n // Simple\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimple',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild4',\n op: WidgetOperationTypes.APPEND,\n component: TakesProps\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseSimpleWithDefaultContent',\n id: 'org.openedx.frontend.widget.slotShowcase.simpleChild5',\n op: WidgetOperationTypes.APPEND,\n component: TakesPropsViaContext\n },\n\n // Custom Layout\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustom',\n id: 'org.openedx.frontend.widget.slotShowcase.customChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // Override custom layout\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n id: 'org.openedx.frontend.widget.slotShowcase.customConfigChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseCustomConfig',\n op: LayoutOperationTypes.REPLACE,\n element: <HorizontalSlotLayout />,\n },\n\n // Layout Options\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n op: LayoutOperationTypes.OPTIONS,\n options: {\n title: 'Bar',\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseLayoutWithOptionsDefault',\n id: 'org.openedx.frontend.widget.slotShowcase.layoutWithOptionsDefaultChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // TODO: Override Layout\n\n // Prepending\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" op=\"WidgetOperationTypes.APPEND\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" op=\"WidgetOperationTypes.APPEND\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcasePrepending',\n id: 'org.openedx.frontend.widget.slotShowcase.prependingChild3',\n op: WidgetOperationTypes.PREPEND,\n element: (<Widget title=\"Widget Three\" op=\"WidgetOperationTypes.PREPEND\" />)\n },\n\n // Inserting\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'slot-showcase.inserting.child4',\n op: WidgetOperationTypes.INSERT_AFTER,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n element: (<Widget title=\"Widget Four\" op=\"WidgetOperationTypes.INSERT_AFTER\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'slot-showcase.inserting.child5',\n op: WidgetOperationTypes.INSERT_BEFORE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n element: (<Widget title=\"Widget Five\" op=\"WidgetOperationTypes.INSERT_BEFORE\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseInserting',\n id: 'org.openedx.frontend.widget.slotShowcase.insertingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n\n // Replacing\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseReplacing',\n id: 'org.openedx.frontend.widget.slotShowcase.replacingChild4',\n op: WidgetOperationTypes.REPLACE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.replacingChild2',\n element: (<Widget title=\"Widget Four\" op=\"WidgetOperationTypes.REPLACE\" />)\n },\n\n // Hiding\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild2',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n id: 'org.openedx.frontend.widget.slotShowcase.removingChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseRemoving',\n op: WidgetOperationTypes.REMOVE,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.removingChild2',\n },\n\n // Widget Options\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild1',\n op: WidgetOperationTypes.APPEND,\n component: WidgetWithOptions,\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n id: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild2',\n op: WidgetOperationTypes.APPEND,\n component: WidgetWithOptions,\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseWidgetOptions',\n relatedId: 'org.openedx.frontend.widget.slotShowcase.widgetOptionsChild2',\n op: WidgetOperationTypes.OPTIONS,\n options: {\n title: 'Bar',\n }\n },\n\n // Widget filtering by role\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild1',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget One\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild2',\n role: 'org.openedx.frontend.role.slotShowcase.highlighted',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Two (highlighted)\" className=\"showcase-widget-highlighted\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild3',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Three\" />)\n },\n {\n slotId: 'org.openedx.frontend.slot.dev.slotShowcaseFilterByRole',\n id: 'org.openedx.frontend.widget.slotShowcase.filterChild4',\n role: 'org.openedx.frontend.role.slotShowcase.highlighted',\n op: WidgetOperationTypes.APPEND,\n element: (<Widget title=\"Widget Four (highlighted)\" className=\"showcase-widget-highlighted\" />)\n },\n\n // Header\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n relatedId: 'org.openedx.frontend.widget.slotShowcase.headerLink',\n op: WidgetOperationTypes.OPTIONS,\n options: {\n title: 'Courses (modified)',\n },\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLinkAfter3',\n op: WidgetOperationTypes.INSERT_AFTER,\n relatedId: 'org.openedx.frontend.widget.slotShowcase.headerLink3',\n element: (<LinkMenuItem label=\"Link After 3\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerPrimaryLinksDropdownPrepend',\n op: WidgetOperationTypes.PREPEND,\n element: (\n <NavDropdownMenuSlot id=\"org.openedx.frontend.slot.header.primaryLinksDropdown.v1\" label=\"Resources\" />\n ),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase']\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinksDropdown.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerPrimaryLinksDropdownAppend',\n op: WidgetOperationTypes.APPEND,\n element: (\n <LinkMenuItem label=\"Resource 1\" url=\"#\" variant=\"dropdownItem\" />\n ),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLink3',\n op: WidgetOperationTypes.APPEND,\n element: (<LinkMenuItem label=\"Link 3\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLink4',\n op: WidgetOperationTypes.APPEND,\n element: (<LinkMenuItem label=\"Link 4\" url=\"#\" variant=\"navLink\" />),\n condition: {\n active: ['org.openedx.frontend.role.slotShowcase'],\n }\n },\n ]\n};\n\nexport default app;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CopyrightNotice.js","sourceRoot":"","sources":["../../../shell/footer/CopyrightNotice.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAW9C,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,KAAK,EAAE,WAAW,EAAwB;IAClF,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,sDAAsD;IACtD,MAAM,UAAU,GAAG,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,MAAM,CAAC,QAAQ,CAAC;IAE5C,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,aAClC,2CAAmB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,cAAc,EACxD,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC3B,KAAC,SAAS,IACR,WAAW,EAAE,WAAW,EACxB,MAAM,EAAC,QAAQ,YAEd,UAAU,GACD,CACb,CAAC,CAAC,CAAC,CACF,yBAAO,UAAU,GAAQ,CAC1B,EACD,+BAAc,IACV,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { Hyperlink } from '@openedx/paragon';\n\nimport { useSiteConfig } from '../../runtime';\n\ninterface CopyrightNoticeProps {\n title?: string,\n /**\n * The URL that the copyright notice should link to when a user clicks on the title. If not set,\n * the title will not be a link.\n */\n destination?: string,\n}\n\nexport default function CopyrightNotice({ title, destination }: CopyrightNoticeProps) {\n const config = useSiteConfig();\n\n // Allow overrides via props and fallback to defaults.\n const finalTitle = title ?? config.siteName;\n\n return (\n <div className=\"text-center x-small\">\n <span>&copy;&nbsp;{new Date().getFullYear()}&nbsp;</span>\n {destination !== undefined ? (\n <Hyperlink\n destination={destination}\n target=\"_blank\"\n >\n {finalTitle}\n </Hyperlink>\n ) : (\n <span>{finalTitle}</span>\n )}\n <span>.</span>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"CopyrightNotice.js","sourceRoot":"","sources":["../../../shell/footer/CopyrightNotice.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAW9C,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,KAAK,EAAE,WAAW,EAAwB;IAClF,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,sDAAsD;IACtD,MAAM,UAAU,GAAG,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,MAAM,CAAC,QAAQ,CAAC;IAE5C,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,aAClC,2CAAmB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,cAAc,EACxD,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC3B,KAAC,SAAS,IACR,WAAW,EAAE,WAAW,EACxB,MAAM,EAAC,QAAQ,YAEd,UAAU,GACD,CACb,CAAC,CAAC,CAAC,CACF,yBAAO,UAAU,GAAQ,CAC1B,EACD,+BAAc,IACV,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { Hyperlink } from '@openedx/paragon';\n\nimport { useSiteConfig } from '../../runtime';\n\ninterface CopyrightNoticeProps {\n title?: string;\n /**\n * The URL that the copyright notice should link to when a user clicks on the title. If not set,\n * the title will not be a link.\n */\n destination?: string;\n}\n\nexport default function CopyrightNotice({ title, destination }: CopyrightNoticeProps) {\n const config = useSiteConfig();\n\n // Allow overrides via props and fallback to defaults.\n const finalTitle = title ?? config.siteName;\n\n return (\n <div className=\"text-center x-small\">\n <span>&copy;&nbsp;{new Date().getFullYear()}&nbsp;</span>\n {destination !== undefined ? (\n <Hyperlink\n destination={destination}\n target=\"_blank\"\n >\n {finalTitle}\n </Hyperlink>\n ) : (\n <span>{finalTitle}</span>\n )}\n <span>.</span>\n </div>\n );\n}\n"]}
@@ -1,16 +1,46 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Dropdown } from '@openedx/paragon';
3
- import { useContext } from 'react';
4
- import { SiteContext, getLocalizedLanguageName, getSupportedLanguageList } from '../../runtime';
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { Dropdown, Toast } from '@openedx/paragon';
12
+ import { useCallback, useContext, useState } from 'react';
13
+ import { SiteContext, getLocalizedLanguageName, getSupportedLanguageList, updateSiteLanguage, useIntl, } from '../../runtime';
5
14
  import LanguageMenuItem from './LanguageMenuItem';
15
+ import messages from './messages';
6
16
  export default function LanguageMenu() {
17
+ const { formatMessage } = useIntl();
7
18
  const { locale } = useContext(SiteContext);
19
+ const [pendingLanguage, setPendingLanguage] = useState(null);
20
+ const [errorMessage, setErrorMessage] = useState(null);
8
21
  const languages = getSupportedLanguageList();
9
- const currentLanguageName = getLocalizedLanguageName(locale);
22
+ const handleSelect = useCallback((languageCode) => __awaiter(this, void 0, void 0, function* () {
23
+ setPendingLanguage(languageCode);
24
+ setErrorMessage(null);
25
+ try {
26
+ yield updateSiteLanguage(languageCode);
27
+ }
28
+ catch (_a) {
29
+ // The UI switch is optimistic and stays in the picked language; only the
30
+ // preference save failed, so surface that without reverting.
31
+ setErrorMessage(formatMessage(messages.languageSaveError));
32
+ }
33
+ finally {
34
+ setPendingLanguage(null);
35
+ }
36
+ }), [formatMessage]);
10
37
  // Hide the menu if there's only one language.
11
38
  if (languages.length === 1) {
12
39
  return null;
13
40
  }
14
- return (_jsxs(Dropdown, { children: [_jsx(Dropdown.Toggle, { id: "language-menu-dropdown-trigger", variant: "outline-primary", size: "sm", children: currentLanguageName }), _jsx(Dropdown.Menu, { className: "overflow-auto", style: { maxHeight: '320px' }, children: languages.map((language) => (_jsx(LanguageMenuItem, { language: language }, language.code))) })] }));
41
+ const toggleLabel = pendingLanguage
42
+ ? getLocalizedLanguageName(pendingLanguage)
43
+ : getLocalizedLanguageName(locale);
44
+ return (_jsxs(_Fragment, { children: [_jsxs(Dropdown, { children: [_jsx(Dropdown.Toggle, { id: "language-menu-dropdown-trigger", variant: "outline-primary", size: "sm", children: toggleLabel }), _jsx(Dropdown.Menu, { className: "overflow-auto", style: { maxHeight: '320px' }, children: languages.map((language) => (_jsx(LanguageMenuItem, { language: language, disabled: pendingLanguage !== null, isActive: language.code === locale, onSelect: handleSelect }, language.code))) })] }), errorMessage && (_jsx(Toast, { show: true, onClose: () => setErrorMessage(null), children: errorMessage }))] }));
15
45
  }
16
46
  //# sourceMappingURL=LanguageMenu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LanguageMenu.js","sourceRoot":"","sources":["../../../shell/footer/LanguageMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,OAAO,UAAU,YAAY;IAClC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,SAAS,GAAG,wBAAwB,EAAE,CAAC;IAC7C,MAAM,mBAAmB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAE7D,8CAA8C;IAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,MAAC,QAAQ,eACP,KAAC,QAAQ,CAAC,MAAM,IAAC,EAAE,EAAC,gCAAgC,EAAC,OAAO,EAAC,iBAAiB,EAAC,IAAI,EAAC,IAAI,YACrF,mBAAmB,GACJ,EAClB,KAAC,QAAQ,CAAC,IAAI,IAAC,SAAS,EAAC,eAAe,EAAC,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,YACnE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC3B,KAAC,gBAAgB,IAAqB,QAAQ,EAAE,QAAQ,IAAjC,QAAQ,CAAC,IAAI,CAAwB,CAC7D,CAAC,GACY,IACP,CACZ,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown } from '@openedx/paragon';\nimport { useContext } from 'react';\n\nimport {\n SiteContext,\n getLocalizedLanguageName,\n getSupportedLanguageList\n} from '../../runtime';\n\nimport LanguageMenuItem from './LanguageMenuItem';\n\nexport default function LanguageMenu() {\n const { locale } = useContext(SiteContext);\n\n const languages = getSupportedLanguageList();\n const currentLanguageName = getLocalizedLanguageName(locale);\n\n // Hide the menu if there's only one language.\n if (languages.length === 1) {\n return null;\n }\n\n return (\n <Dropdown>\n <Dropdown.Toggle id=\"language-menu-dropdown-trigger\" variant=\"outline-primary\" size=\"sm\">\n {currentLanguageName}\n </Dropdown.Toggle>\n <Dropdown.Menu className=\"overflow-auto\" style={{ maxHeight: '320px' }}>\n {languages.map((language) => (\n <LanguageMenuItem key={language.code} language={language} />\n ))}\n </Dropdown.Menu>\n </Dropdown>\n );\n}\n"]}
1
+ {"version":3,"file":"LanguageMenu.js","sourceRoot":"","sources":["../../../shell/footer/LanguageMenu.tsx"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,OAAO,GACR,MAAM,eAAe,CAAC;AAEvB,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAClD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,MAAM,CAAC,OAAO,UAAU,YAAY;IAClC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEtE,MAAM,SAAS,GAAG,wBAAwB,EAAE,CAAC;IAE7C,MAAM,YAAY,GAAG,WAAW,CAAC,CAAO,YAAoB,EAAE,EAAE;QAC9D,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACjC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;QAAC,WAAM,CAAC;YACP,yEAAyE;YACzE,6DAA6D;YAC7D,eAAe,CAAC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC7D,CAAC;gBAAS,CAAC;YACT,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAA,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,8CAA8C;IAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,eAAe;QACjC,CAAC,CAAC,wBAAwB,CAAC,eAAe,CAAC;QAC3C,CAAC,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAErC,OAAO,CACL,8BACE,MAAC,QAAQ,eACP,KAAC,QAAQ,CAAC,MAAM,IAAC,EAAE,EAAC,gCAAgC,EAAC,OAAO,EAAC,iBAAiB,EAAC,IAAI,EAAC,IAAI,YACrF,WAAW,GACI,EAClB,KAAC,QAAQ,CAAC,IAAI,IAAC,SAAS,EAAC,eAAe,EAAC,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,YACnE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC3B,KAAC,gBAAgB,IAEf,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,eAAe,KAAK,IAAI,EAClC,QAAQ,EAAE,QAAQ,CAAC,IAAI,KAAK,MAAM,EAClC,QAAQ,EAAE,YAAY,IAJjB,QAAQ,CAAC,IAAI,CAKlB,CACH,CAAC,GACY,IACP,EACV,YAAY,IAAI,CACf,KAAC,KAAK,IACJ,IAAI,QACJ,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,YAEnC,YAAY,GACP,CACT,IACA,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown, Toast } from '@openedx/paragon';\nimport { useCallback, useContext, useState } from 'react';\n\nimport {\n SiteContext,\n getLocalizedLanguageName,\n getSupportedLanguageList,\n updateSiteLanguage,\n useIntl,\n} from '../../runtime';\n\nimport LanguageMenuItem from './LanguageMenuItem';\nimport messages from './messages';\n\nexport default function LanguageMenu() {\n const { formatMessage } = useIntl();\n const { locale } = useContext(SiteContext);\n\n const [pendingLanguage, setPendingLanguage] = useState<string | null>(null);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n const languages = getSupportedLanguageList();\n\n const handleSelect = useCallback(async (languageCode: string) => {\n setPendingLanguage(languageCode);\n setErrorMessage(null);\n try {\n await updateSiteLanguage(languageCode);\n } catch {\n // The UI switch is optimistic and stays in the picked language; only the\n // preference save failed, so surface that without reverting.\n setErrorMessage(formatMessage(messages.languageSaveError));\n } finally {\n setPendingLanguage(null);\n }\n }, [formatMessage]);\n\n // Hide the menu if there's only one language.\n if (languages.length === 1) {\n return null;\n }\n\n const toggleLabel = pendingLanguage\n ? getLocalizedLanguageName(pendingLanguage)\n : getLocalizedLanguageName(locale);\n\n return (\n <>\n <Dropdown>\n <Dropdown.Toggle id=\"language-menu-dropdown-trigger\" variant=\"outline-primary\" size=\"sm\">\n {toggleLabel}\n </Dropdown.Toggle>\n <Dropdown.Menu className=\"overflow-auto\" style={{ maxHeight: '320px' }}>\n {languages.map((language) => (\n <LanguageMenuItem\n key={language.code}\n language={language}\n disabled={pendingLanguage !== null}\n isActive={language.code === locale}\n onSelect={handleSelect}\n />\n ))}\n </Dropdown.Menu>\n </Dropdown>\n {errorMessage && (\n <Toast\n show\n onClose={() => setErrorMessage(null)}\n >\n {errorMessage}\n </Toast>\n )}\n </>\n );\n}\n"]}
@@ -3,6 +3,9 @@ interface LanguageMenuItemProps {
3
3
  code: string;
4
4
  name: string;
5
5
  };
6
+ disabled?: boolean;
7
+ isActive?: boolean;
8
+ onSelect: (code: string) => void;
6
9
  }
7
- export default function LanguageMenuItem({ language }: LanguageMenuItemProps): import("react/jsx-runtime").JSX.Element;
10
+ export default function LanguageMenuItem({ language, disabled, isActive, onSelect, }: LanguageMenuItemProps): import("react/jsx-runtime").JSX.Element;
8
11
  export {};
@@ -1,11 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Dropdown } from '@openedx/paragon';
3
3
  import { useCallback } from 'react';
4
- import { updateSiteLanguage } from './data/api';
5
- export default function LanguageMenuItem({ language }) {
4
+ export default function LanguageMenuItem({ language, disabled, isActive, onSelect, }) {
6
5
  const handleClick = useCallback(() => {
7
- updateSiteLanguage(language.code);
8
- }, [language.code]);
9
- return (_jsx(Dropdown.Item, { onClick: handleClick, children: language.name }, language.code));
6
+ onSelect(language.code);
7
+ }, [language.code, onSelect]);
8
+ return (_jsx(Dropdown.Item, { active: isActive, disabled: disabled, onClick: handleClick, children: language.name }, language.code));
10
9
  }
11
10
  //# sourceMappingURL=LanguageMenuItem.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LanguageMenuItem.js","sourceRoot":"","sources":["../../../shell/footer/LanguageMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAShD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,QAAQ,EAAyB;IAC1E,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpB,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IAAqB,OAAO,EAAE,WAAW,YACpD,QAAQ,CAAC,IAAI,IADI,QAAQ,CAAC,IAAI,CAEjB,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown } from '@openedx/paragon';\nimport { useCallback } from 'react';\n\nimport { updateSiteLanguage } from './data/api';\n\ninterface LanguageMenuItemProps {\n language: {\n code: string,\n name: string,\n },\n}\n\nexport default function LanguageMenuItem({ language }: LanguageMenuItemProps) {\n const handleClick = useCallback(() => {\n updateSiteLanguage(language.code);\n }, [language.code]);\n\n return (\n <Dropdown.Item key={language.code} onClick={handleClick}>\n {language.name}\n </Dropdown.Item>\n );\n}\n"]}
1
+ {"version":3,"file":"LanguageMenuItem.js","sourceRoot":"","sources":["../../../shell/footer/LanguageMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAYpC,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,QAAQ,GACc;IACtB,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE9B,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IAEZ,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,YAEnB,QAAQ,CAAC,IAAI,IALT,QAAQ,CAAC,IAAI,CAMJ,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown } from '@openedx/paragon';\nimport { useCallback } from 'react';\n\ninterface LanguageMenuItemProps {\n language: {\n code: string;\n name: string;\n };\n disabled?: boolean;\n isActive?: boolean;\n onSelect: (code: string) => void;\n}\n\nexport default function LanguageMenuItem({\n language,\n disabled,\n isActive,\n onSelect,\n}: LanguageMenuItemProps) {\n const handleClick = useCallback(() => {\n onSelect(language.code);\n }, [language.code, onSelect]);\n\n return (\n <Dropdown.Item\n key={language.code}\n active={isActive}\n disabled={disabled}\n onClick={handleClick}\n >\n {language.name}\n </Dropdown.Item>\n );\n}\n"]}
@@ -0,0 +1,8 @@
1
+ declare const messages: {
2
+ languageSaveError: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ };
8
+ export default messages;
@@ -0,0 +1,10 @@
1
+ import { defineMessages } from '../../runtime';
2
+ const messages = defineMessages({
3
+ languageSaveError: {
4
+ id: 'footer.languageMenu.error.languageSave',
5
+ defaultMessage: 'We could not save your language preference.',
6
+ description: 'Error shown when saving the site language preference fails.',
7
+ },
8
+ });
9
+ export default messages;
10
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../shell/footer/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,iBAAiB,EAAE;QACjB,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,6CAA6C;QAC7D,WAAW,EAAE,6DAA6D;KAC3E;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '../../runtime';\n\nconst messages = defineMessages({\n languageSaveError: {\n id: 'footer.languageMenu.error.languageSave',\n defaultMessage: 'We could not save your language preference.',\n description: 'Error shown when saving the site language preference fails.',\n },\n});\n\nexport default messages;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AuthenticatedMenu.js","sourceRoot":"","sources":["../../../shell/header/AuthenticatedMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACL,IAAI,EACJ,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAMvB,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,SAAS,EAA0B;IAC7E,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IAEjD,MAAM,eAAe,GAAG,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,IAAI,MAAI,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,QAAQ,CAAA,CAAC;IAE/E,OAAO,CACL,MAAC,QAAQ,IAAC,SAAS,EAAE,SAAS,aAC5B,KAAC,QAAQ,CAAC,MAAM,IACd,EAAE,EAAE,YAAY,EAChB,EAAE,EAAC,mBAAmB,EACtB,OAAO,EAAC,iBAAiB,EACzB,GAAG,EAAE,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,MAAM,YAE7B,eAAe,GACA,EAClB,KAAC,QAAQ,CAAC,IAAI,cACZ,KAAC,IAAI,IAAC,EAAE,EAAC,uDAAuD,GAAG,GACrD,IACP,CACZ,CAAC;AACJ,CAAC","sourcesContent":["import { AvatarButton, Dropdown } from '@openedx/paragon';\n\nimport {\n Slot,\n useAuthenticatedUser\n} from '../../runtime';\n\ninterface AuthenticatedMenuProps {\n className?: string,\n}\n\nexport default function AuthenticatedMenu({ className }: AuthenticatedMenuProps) {\n const authenticatedUser = useAuthenticatedUser();\n\n const displayUserName = authenticatedUser?.name || authenticatedUser?.username;\n\n return (\n <Dropdown className={className}>\n <Dropdown.Toggle\n as={AvatarButton}\n id=\"user-nav-dropdown\"\n variant=\"outline-primary\"\n src={authenticatedUser?.avatar}\n >\n {displayUserName}\n </Dropdown.Toggle>\n <Dropdown.Menu>\n <Slot id=\"org.openedx.frontend.slot.header.authenticatedMenu.v1\" />\n </Dropdown.Menu>\n </Dropdown>\n );\n}\n"]}
1
+ {"version":3,"file":"AuthenticatedMenu.js","sourceRoot":"","sources":["../../../shell/header/AuthenticatedMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACL,IAAI,EACJ,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAMvB,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,SAAS,EAA0B;IAC7E,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IAEjD,MAAM,eAAe,GAAG,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,IAAI,MAAI,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,QAAQ,CAAA,CAAC;IAE/E,OAAO,CACL,MAAC,QAAQ,IAAC,SAAS,EAAE,SAAS,aAC5B,KAAC,QAAQ,CAAC,MAAM,IACd,EAAE,EAAE,YAAY,EAChB,EAAE,EAAC,mBAAmB,EACtB,OAAO,EAAC,iBAAiB,EACzB,GAAG,EAAE,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,MAAM,YAE7B,eAAe,GACA,EAClB,KAAC,QAAQ,CAAC,IAAI,cACZ,KAAC,IAAI,IAAC,EAAE,EAAC,uDAAuD,GAAG,GACrD,IACP,CACZ,CAAC;AACJ,CAAC","sourcesContent":["import { AvatarButton, Dropdown } from '@openedx/paragon';\n\nimport {\n Slot,\n useAuthenticatedUser\n} from '../../runtime';\n\ninterface AuthenticatedMenuProps {\n className?: string;\n}\n\nexport default function AuthenticatedMenu({ className }: AuthenticatedMenuProps) {\n const authenticatedUser = useAuthenticatedUser();\n\n const displayUserName = authenticatedUser?.name || authenticatedUser?.username;\n\n return (\n <Dropdown className={className}>\n <Dropdown.Toggle\n as={AvatarButton}\n id=\"user-nav-dropdown\"\n variant=\"outline-primary\"\n src={authenticatedUser?.avatar}\n >\n {displayUserName}\n </Dropdown.Toggle>\n <Dropdown.Menu>\n <Slot id=\"org.openedx.frontend.slot.header.authenticatedMenu.v1\" />\n </Dropdown.Menu>\n </Dropdown>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HelpButton.js","sourceRoot":"","sources":["../../../shell/header/HelpButton.tsx"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,uBAAuB,CAAC;AACjD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAMzC,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,MAAM,EAAmB;IAC5D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B,GAAG,EAAE,GAAG,EACR,OAAO,EAAC,SAAS,GACjB,CACH,CAAC;AACJ,CAAC","sourcesContent":["import LinkMenuItem from '../menus/LinkMenuItem';\nimport messages from '../Shell.messages';\n\ninterface HelpButtonProps {\n getUrl: () => string | undefined,\n}\n\nexport default function HelpButton({ getUrl }: HelpButtonProps) {\n const url = getUrl();\n if (!url) return null;\n return (\n <LinkMenuItem\n label={messages['header.help']}\n url={url}\n variant=\"navLink\"\n />\n );\n}\n"]}
1
+ {"version":3,"file":"HelpButton.js","sourceRoot":"","sources":["../../../shell/header/HelpButton.tsx"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,uBAAuB,CAAC;AACjD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAMzC,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,MAAM,EAAmB;IAC5D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B,GAAG,EAAE,GAAG,EACR,OAAO,EAAC,SAAS,GACjB,CACH,CAAC;AACJ,CAAC","sourcesContent":["import LinkMenuItem from '../menus/LinkMenuItem';\nimport messages from '../Shell.messages';\n\ninterface HelpButtonProps {\n getUrl: () => string | undefined;\n}\n\nexport default function HelpButton({ getUrl }: HelpButtonProps) {\n const url = getUrl();\n if (!url) return null;\n return (\n <LinkMenuItem\n label={messages['header.help']}\n url={url}\n variant=\"navLink\"\n />\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AnonymousMenu.js","sourceRoot":"","sources":["../../../../shell/header/anonymous-menu/AnonymousMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAMxC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,SAAS,EAAsB;IACrE,OAAO,CACL,cAAK,SAAS,EAAE,UAAU,CAAC,2DAA2D,EAAE,SAAS,CAAC,YAChG,KAAC,IAAI,IAAC,EAAE,EAAC,mDAAmD,GAAG,GAC3D,CACP,CAAC;AACJ,CAAC","sourcesContent":["import classNames from 'classnames';\nimport { Slot } from '../../../runtime';\n\ninterface AnonymousMenuProps {\n className?: string,\n}\n\nexport default function AnonymousMenu({ className }: AnonymousMenuProps) {\n return (\n <div className={classNames('d-flex flex-nowrap align-items-center flex-shrink-0 gap-3', className)}>\n <Slot id=\"org.openedx.frontend.slot.header.anonymousMenu.v1\" />\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"AnonymousMenu.js","sourceRoot":"","sources":["../../../../shell/header/anonymous-menu/AnonymousMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAMxC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,SAAS,EAAsB;IACrE,OAAO,CACL,cAAK,SAAS,EAAE,UAAU,CAAC,2DAA2D,EAAE,SAAS,CAAC,YAChG,KAAC,IAAI,IAAC,EAAE,EAAC,mDAAmD,GAAG,GAC3D,CACP,CAAC;AACJ,CAAC","sourcesContent":["import classNames from 'classnames';\nimport { Slot } from '../../../runtime';\n\ninterface AnonymousMenuProps {\n className?: string;\n}\n\nexport default function AnonymousMenu({ className }: AnonymousMenuProps) {\n return (\n <div className={classNames('d-flex flex-nowrap align-items-center flex-shrink-0 gap-3', className)}>\n <Slot id=\"org.openedx.frontend.slot.header.anonymousMenu.v1\" />\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/data/service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAuBjG,SAAS,iCAAiC,CAAC,QAAqC;IAC9E,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAc,EAAE,EAAE,CAAC,CAAC;YAC/C,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK;YACzD,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAgB,2BAA2B,CAAC,QAAgB;;QAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CAAC,GAAG,aAAa,EAAE,CAAC,UAAU,oCAAoC,QAAQ,EAAE,CAAC,CAAC;QAErI,OAAO,iCAAiC,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;CAAA;AAED,MAAM,UAAU,gCAAgC,CAAC,QAAgB;IAC/D,OAAO,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAiB,EAAE,QAAgB;;IAC/D,IAAI,IAAI,GAA8C,IAAI,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC5E,IAAI,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,IAAI,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,mCAAI,IAAI,CAAC;AAC3B,CAAC","sourcesContent":["import { matchPath } from 'react-router-dom';\nimport { getSiteConfig, getAuthenticatedHttpClient, camelCaseObject } from '../../../../runtime';\n\n// Raw API response from /api/course_home/course_metadata/\ninterface RawCourseTab {\n tab_id: string,\n title: string,\n url: string,\n}\n\ninterface RawCourseHomeCourseMetadata {\n tabs: RawCourseTab[],\n}\n\nexport interface CourseTab {\n tabId: string,\n title: string,\n url: string,\n}\n\nexport interface CourseHomeCourseMetadata {\n tabs: CourseTab[],\n}\n\nfunction normalizeCourseHomeCourseMetadata(metadata: RawCourseHomeCourseMetadata): CourseHomeCourseMetadata {\n const data = camelCaseObject(metadata);\n return {\n tabs: (data.tabs || []).map((tab: CourseTab) => ({\n tabId: tab.tabId === 'courseware' ? 'outline' : tab.tabId,\n title: tab.title,\n url: tab.url,\n })),\n };\n}\n\nexport async function getCourseHomeCourseMetadata(courseId: string): Promise<CourseHomeCourseMetadata> {\n const { data } = await getAuthenticatedHttpClient().get(`${getSiteConfig().lmsBaseUrl}/api/course_home/course_metadata/${courseId}`);\n\n return normalizeCourseHomeCourseMetadata(data);\n}\n\nexport function courseHomeCourseMetadataQueryKey(courseId: string): [string, string] {\n return ['org.openedx.frontend.app.header.courseMeta', courseId];\n}\n\n/*\n * Returns the tab whose URL pathname is the longest prefix match against\n * `pathname`, or null if none match. Used by the navigation bar to mark the\n * active tab and by the masquerade redirect to decide whether the demoted\n * user can still see the page they're on.\n */\nexport function findActiveTab(tabs: CourseTab[], pathname: string): CourseTab | null {\n let best: { tab: CourseTab, length: number } | null = null;\n for (const tab of tabs) {\n const tabPathname = new URL(tab.url).pathname;\n const match = matchPath({ path: `${tabPathname}/*`, end: false }, pathname);\n if (match && (!best || tabPathname.length > best.length)) {\n best = { tab, length: tabPathname.length };\n }\n }\n return best?.tab ?? null;\n}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/data/service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAuBjG,SAAS,iCAAiC,CAAC,QAAqC;IAC9E,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAc,EAAE,EAAE,CAAC,CAAC;YAC/C,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK;YACzD,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAgB,2BAA2B,CAAC,QAAgB;;QAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CAAC,GAAG,aAAa,EAAE,CAAC,UAAU,oCAAoC,QAAQ,EAAE,CAAC,CAAC;QAErI,OAAO,iCAAiC,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;CAAA;AAED,MAAM,UAAU,gCAAgC,CAAC,QAAgB;IAC/D,OAAO,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAiB,EAAE,QAAgB;;IAC/D,IAAI,IAAI,GAA8C,IAAI,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC5E,IAAI,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,IAAI,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,mCAAI,IAAI,CAAC;AAC3B,CAAC","sourcesContent":["import { matchPath } from 'react-router-dom';\nimport { getSiteConfig, getAuthenticatedHttpClient, camelCaseObject } from '../../../../runtime';\n\n// Raw API response from /api/course_home/course_metadata/\ninterface RawCourseTab {\n tab_id: string;\n title: string;\n url: string;\n}\n\ninterface RawCourseHomeCourseMetadata {\n tabs: RawCourseTab[];\n}\n\nexport interface CourseTab {\n tabId: string;\n title: string;\n url: string;\n}\n\nexport interface CourseHomeCourseMetadata {\n tabs: CourseTab[];\n}\n\nfunction normalizeCourseHomeCourseMetadata(metadata: RawCourseHomeCourseMetadata): CourseHomeCourseMetadata {\n const data = camelCaseObject(metadata);\n return {\n tabs: (data.tabs || []).map((tab: CourseTab) => ({\n tabId: tab.tabId === 'courseware' ? 'outline' : tab.tabId,\n title: tab.title,\n url: tab.url,\n })),\n };\n}\n\nexport async function getCourseHomeCourseMetadata(courseId: string): Promise<CourseHomeCourseMetadata> {\n const { data } = await getAuthenticatedHttpClient().get(`${getSiteConfig().lmsBaseUrl}/api/course_home/course_metadata/${courseId}`);\n\n return normalizeCourseHomeCourseMetadata(data);\n}\n\nexport function courseHomeCourseMetadataQueryKey(courseId: string): [string, string] {\n return ['org.openedx.frontend.app.header.courseMeta', courseId];\n}\n\n/*\n * Returns the tab whose URL pathname is the longest prefix match against\n * `pathname`, or null if none match. Used by the navigation bar to mark the\n * active tab and by the masquerade redirect to decide whether the demoted\n * user can still see the page they're on.\n */\nexport function findActiveTab(tabs: CourseTab[], pathname: string): CourseTab | null {\n let best: { tab: CourseTab; length: number } | null = null;\n for (const tab of tabs) {\n const tabPathname = new URL(tab.url).pathname;\n const match = matchPath({ path: `${tabPathname}/*`, end: false }, pathname);\n if (match && (!best || tabPathname.length > best.length)) {\n best = { tab, length: tabPathname.length };\n }\n }\n return best?.tab ?? null;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"StudioLink.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/masquerade/StudioLink.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAOlC,SAAS,cAAc,CAAC,QAAiB,EAAE,MAAe;IACxD,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC,UAAU,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,GAAG,IAAI,cAAc,MAAM,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,WAAW,QAAQ,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAS;IACpD,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE7C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,8BACE,aAAI,SAAS,EAAC,cAAc,GAAG,EAC/B,eAAM,SAAS,EAAC,0BAA0B,YACxC,KAAC,gBAAgB,oBAAK,QAAQ,CAAC,iBAAiB,EAAI,GAC/C,EACP,eAAM,SAAS,EAAC,WAAW,YACzB,KAAC,MAAM,IAAC,OAAO,EAAC,yBAAyB,EAAC,IAAI,EAAE,GAAG,YAChD,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAC7B,GACJ,IACN,CACJ,CAAC;AACJ,CAAC;AAED,eAAe,UAAU,CAAC","sourcesContent":["import { useIntl, FormattedMessage, getSiteConfig } from '@openedx/frontend-base';\nimport { Button } from '@openedx/paragon';\n\nimport messages from './messages';\n\ninterface Props {\n courseId?: string,\n unitId?: string,\n}\n\nfunction buildStudioUrl(courseId?: string, unitId?: string): string | null {\n const base = getSiteConfig().cmsBaseUrl;\n if (!base) {\n return null;\n }\n if (unitId) {\n return `${base}/container/${unitId}`;\n }\n if (courseId) {\n return `${base}/course/${courseId}`;\n }\n return null;\n}\n\nexport function StudioLink({ courseId, unitId }: Props) {\n const { formatMessage } = useIntl();\n const url = buildStudioUrl(courseId, unitId);\n\n if (!url) {\n return null;\n }\n\n return (\n <>\n <hr className=\"border-light\" />\n <span className=\"mr-2 mt-1 col-form-label\">\n <FormattedMessage {...messages.titleViewCourseIn} />\n </span>\n <span className=\"mx-1 my-1\">\n <Button variant=\"inverse-outline-primary\" href={url}>\n {formatMessage(messages.titleStudio)}\n </Button>\n </span>\n </>\n );\n}\n\nexport default StudioLink;\n"]}
1
+ {"version":3,"file":"StudioLink.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/masquerade/StudioLink.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAOlC,SAAS,cAAc,CAAC,QAAiB,EAAE,MAAe;IACxD,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC,UAAU,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,GAAG,IAAI,cAAc,MAAM,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,WAAW,QAAQ,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAS;IACpD,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE7C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,8BACE,aAAI,SAAS,EAAC,cAAc,GAAG,EAC/B,eAAM,SAAS,EAAC,0BAA0B,YACxC,KAAC,gBAAgB,oBAAK,QAAQ,CAAC,iBAAiB,EAAI,GAC/C,EACP,eAAM,SAAS,EAAC,WAAW,YACzB,KAAC,MAAM,IAAC,OAAO,EAAC,yBAAyB,EAAC,IAAI,EAAE,GAAG,YAChD,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAC7B,GACJ,IACN,CACJ,CAAC;AACJ,CAAC;AAED,eAAe,UAAU,CAAC","sourcesContent":["import { useIntl, FormattedMessage, getSiteConfig } from '@openedx/frontend-base';\nimport { Button } from '@openedx/paragon';\n\nimport messages from './messages';\n\ninterface Props {\n courseId?: string;\n unitId?: string;\n}\n\nfunction buildStudioUrl(courseId?: string, unitId?: string): string | null {\n const base = getSiteConfig().cmsBaseUrl;\n if (!base) {\n return null;\n }\n if (unitId) {\n return `${base}/container/${unitId}`;\n }\n if (courseId) {\n return `${base}/course/${courseId}`;\n }\n return null;\n}\n\nexport function StudioLink({ courseId, unitId }: Props) {\n const { formatMessage } = useIntl();\n const url = buildStudioUrl(courseId, unitId);\n\n if (!url) {\n return null;\n }\n\n return (\n <>\n <hr className=\"border-light\" />\n <span className=\"mr-2 mt-1 col-form-label\">\n <FormattedMessage {...messages.titleViewCourseIn} />\n </span>\n <span className=\"mx-1 my-1\">\n <Button variant=\"inverse-outline-primary\" href={url}>\n {formatMessage(messages.titleStudio)}\n </Button>\n </span>\n </>\n );\n}\n\nexport default StudioLink;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAkCpG,MAAM,UAAgB,oBAAoB,CAAC,QAAgB;;;QACzD,MAAM,GAAG,GAAG,GAAG,aAAa,EAAE,CAAC,UAAU,YAAY,QAAQ,aAAa,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjE,gFAAgF;QAChF,IAAI,CAAA,MAAA,QAAQ,CAAC,OAAO,0CAAE,WAAW,KAAI,QAAQ,CAAC,OAAO,CAAC,WAAW,KAAK,GAAG,EAAE,CAAC;YAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qCAAqC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE;gBAC1G,gBAAgB,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE;aAC3C,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;CAAA;AAED,MAAM,UAAgB,qBAAqB,CAAC,QAAgB,EAAE,OAA0B;;QACtF,MAAM,GAAG,GAAG,GAAG,aAAa,EAAE,CAAC,UAAU,YAAY,QAAQ,aAAa,CAAC;QAC3E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CAAA","sourcesContent":["import { getSiteConfig, camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\n\nexport type Role = 'staff' | 'student';\n\nexport interface ActiveMasqueradeData {\n role: Role,\n userName: string | null,\n userPartitionId: number | null,\n groupId: number | null,\n groupName: string | null,\n}\n\nexport interface MasqueradeOption {\n name: string,\n role: Role,\n userName?: string,\n groupId?: number,\n userPartitionId?: number,\n}\n\nexport interface MasqueradeStatus {\n success: boolean,\n error?: string,\n active: ActiveMasqueradeData,\n available: MasqueradeOption[],\n}\n\nexport interface MasqueradePayload {\n role?: Role,\n user_name?: string,\n group_id?: number,\n user_partition_id?: number,\n}\n\nexport async function getMasqueradeOptions(courseId: string): Promise<MasqueradeStatus> {\n const url = `${getSiteConfig().lmsBaseUrl}/courses/${courseId}/masquerade`;\n const response = await getAuthenticatedHttpClient().get(url, {});\n /* The LMS 302s to /login instead of returning 403 when masquerade is denied. */\n if (response.request?.responseURL && response.request.responseURL !== url) {\n const error = Object.assign(new Error(`Masquerade endpoint redirected to ${response.request.responseURL}`), {\n customAttributes: { httpErrorStatus: 403 },\n });\n throw error;\n }\n return camelCaseObject(response.data);\n}\n\nexport async function postMasqueradeOptions(courseId: string, payload: MasqueradePayload): Promise<MasqueradeStatus> {\n const url = `${getSiteConfig().lmsBaseUrl}/courses/${courseId}/masquerade`;\n const { data } = await getAuthenticatedHttpClient().post(url, payload);\n return camelCaseObject(data);\n}\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAkCpG,MAAM,UAAgB,oBAAoB,CAAC,QAAgB;;;QACzD,MAAM,GAAG,GAAG,GAAG,aAAa,EAAE,CAAC,UAAU,YAAY,QAAQ,aAAa,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjE,gFAAgF;QAChF,IAAI,CAAA,MAAA,QAAQ,CAAC,OAAO,0CAAE,WAAW,KAAI,QAAQ,CAAC,OAAO,CAAC,WAAW,KAAK,GAAG,EAAE,CAAC;YAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qCAAqC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE;gBAC1G,gBAAgB,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE;aAC3C,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;CAAA;AAED,MAAM,UAAgB,qBAAqB,CAAC,QAAgB,EAAE,OAA0B;;QACtF,MAAM,GAAG,GAAG,GAAG,aAAa,EAAE,CAAC,UAAU,YAAY,QAAQ,aAAa,CAAC;QAC3E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CAAA","sourcesContent":["import { getSiteConfig, camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\n\nexport type Role = 'staff' | 'student';\n\nexport interface ActiveMasqueradeData {\n role: Role;\n userName: string | null;\n userPartitionId: number | null;\n groupId: number | null;\n groupName: string | null;\n}\n\nexport interface MasqueradeOption {\n name: string;\n role: Role;\n userName?: string;\n groupId?: number;\n userPartitionId?: number;\n}\n\nexport interface MasqueradeStatus {\n success: boolean;\n error?: string;\n active: ActiveMasqueradeData;\n available: MasqueradeOption[];\n}\n\nexport interface MasqueradePayload {\n role?: Role;\n user_name?: string;\n group_id?: number;\n user_partition_id?: number;\n}\n\nexport async function getMasqueradeOptions(courseId: string): Promise<MasqueradeStatus> {\n const url = `${getSiteConfig().lmsBaseUrl}/courses/${courseId}/masquerade`;\n const response = await getAuthenticatedHttpClient().get(url, {});\n /* The LMS 302s to /login instead of returning 403 when masquerade is denied. */\n if (response.request?.responseURL && response.request.responseURL !== url) {\n const error = Object.assign(new Error(`Masquerade endpoint redirected to ${response.request.responseURL}`), {\n customAttributes: { httpErrorStatus: 403 },\n });\n throw error;\n }\n return camelCaseObject(response.data);\n}\n\nexport async function postMasqueradeOptions(courseId: string, payload: MasqueradePayload): Promise<MasqueradeStatus> {\n const url = `${getSiteConfig().lmsBaseUrl}/courses/${courseId}/masquerade`;\n const { data } = await getAuthenticatedHttpClient().post(url, payload);\n return camelCaseObject(data);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/masquerade/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport type { MessageDescriptor } from 'react-intl';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport {\n ActiveMasqueradeData,\n MasqueradeOption,\n MasqueradeStatus,\n MasqueradePayload,\n getMasqueradeOptions,\n postMasqueradeOptions,\n} from './data/api';\nimport {\n CourseHomeCourseMetadata,\n courseHomeCourseMetadataQueryKey,\n findActiveTab,\n getCourseHomeCourseMetadata,\n} from '../data/service';\nimport { isClientRoute } from '../utils';\nimport messages from './messages';\n\nconst defaultActive: ActiveMasqueradeData = {\n role: 'staff',\n groupId: null,\n groupName: null,\n userName: null,\n userPartitionId: null,\n};\n\nfunction toMasqueradePayload(option: MasqueradeOption): MasqueradePayload {\n const payload: MasqueradePayload = { role: option.role };\n if (option.groupId !== undefined && option.userPartitionId !== undefined) {\n payload.group_id = option.groupId;\n payload.user_partition_id = option.userPartitionId;\n }\n return payload;\n}\n\n/*\n * Whether `option` represents the active masquerade. Three shapes:\n * - userName defined: the \"Specific Student...\" prompt; active when the\n * server says we're masquerading as some specific user.\n * - groupId defined: a group option; active when the group ids match.\n * - neither: a plain role option (e.g. Staff); active when no group/user\n * is set.\n */\nexport function isOptionSelected(option: MasqueradeOption, active: ActiveMasqueradeData): boolean {\n if (option.role !== active.role) {\n return false;\n }\n if (option.userName !== undefined) {\n return active.userName !== null;\n }\n if (option.groupId !== undefined) {\n return option.groupId === active.groupId\n && option.userPartitionId === active.userPartitionId;\n }\n return active.userName === null && active.groupId === null;\n}\n\ninterface HttpishError {\n customAttributes?: { httpErrorStatus?: number },\n}\n\nfunction getHttpStatus(error: unknown): number | undefined {\n return (error as HttpishError | null)?.customAttributes?.httpErrorStatus;\n}\n\n/*\n * Anything other than a successful load with `success: true` hides the bar:\n * 403, 200 with `success: false`, network errors, 5xx, redirected requests.\n */\nfunction isQueryDenied(query: { isError: boolean, error: unknown, data: MasqueradeStatus | undefined }): boolean {\n if (query.isError) {\n return true;\n }\n return query.data !== undefined && !query.data.success;\n}\n\n/*\n * Errors are returned as MessageDescriptors when the frontend can pick the\n * message, or as a raw string when the server's `data.error` is more specific\n * than anything we'd hand-pick. formatErrorMessage handles both at the\n * render site.\n */\nexport type MasqueradeErrorMessage = MessageDescriptor | string;\n\nexport function formatErrorMessage(\n formatMessage: (descriptor: MessageDescriptor) => string,\n error: MasqueradeErrorMessage,\n): string {\n return typeof error === 'string' ? error : formatMessage(error);\n}\n\nfunction pickErrorMessage(\n mutation: { isError: boolean, error: unknown, data: MasqueradeStatus | undefined },\n): MasqueradeErrorMessage | null {\n if (mutation.isError) {\n return getHttpStatus(mutation.error) === 404\n ? messages.noStudentFound\n : messages.genericSubmitError;\n }\n if (mutation.data && !mutation.data.success) {\n return mutation.data.error || messages.genericSubmitError;\n }\n return null;\n}\n\nexport interface MasqueradeState {\n active: ActiveMasqueradeData,\n available: MasqueradeOption[],\n pendingOption: MasqueradeOption | null,\n showUserNameInput: boolean,\n userName: string,\n setUserName: (value: string) => void,\n select: (option: MasqueradeOption) => void,\n submitUserName: () => void,\n errorMessage: MasqueradeErrorMessage | null,\n isSubmitting: boolean,\n isLoading: boolean,\n isDenied: boolean,\n}\n\nexport function useMasqueradeState(courseId: string): MasqueradeState {\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const location = useLocation();\n /*\n * Tracks the option the user just clicked, so the toggle and active-marker\n * can update before the server confirms. Cleared once a mutation succeeds\n * (the server's active state becomes the truth) or replaced when the user\n * picks something else.\n */\n const [pendingOption, setPendingOption] = useState<MasqueradeOption | null>(null);\n const [userName, setUserName] = useState('');\n\n const query = useQuery({\n queryKey: ['masquerade', courseId],\n queryFn: () => getMasqueradeOptions(courseId),\n });\n\n const mutation = useMutation({\n mutationFn: (payload: MasqueradePayload) => postMasqueradeOptions(courseId, payload),\n onSuccess: async (data, payload) => {\n if (!data?.success) {\n /* Server rejected the pick. Clear the optimistic pending state so the\n * UI snaps back to the real active option, except for userName\n * submissions where the input must stay open for retry. */\n if (payload.user_name === undefined) {\n setPendingOption(null);\n }\n return;\n }\n\n queryClient.invalidateQueries();\n\n /* The course-tabs metadata is the source of truth for \"what pages this\n * user can see in this course.\" Fetch the post-masquerade tabs and\n * redirect to the first one if the current path no longer appears. */\n const meta = await queryClient.fetchQuery<CourseHomeCourseMetadata>({\n queryKey: courseHomeCourseMetadataQueryKey(courseId),\n queryFn: () => getCourseHomeCourseMetadata(courseId),\n });\n const fallback = meta.tabs[0];\n if (!fallback) {\n return;\n }\n const stillVisible = findActiveTab(meta.tabs, location.pathname);\n if (stillVisible) {\n return;\n }\n const targetPath = new URL(fallback.url).pathname;\n if (isClientRoute(targetPath)) {\n navigate(targetPath, { replace: true });\n } else {\n window.location.assign(fallback.url);\n }\n },\n onError: (_error, payload) => {\n /* Same as the !success branch: revert the optimistic pick, but keep the\n * userName input open so the user can fix a typo and retry. */\n if (payload.user_name === undefined) {\n setPendingOption(null);\n }\n },\n });\n\n const active = (query.data?.success && query.data.active) || defaultActive;\n const available = (query.data?.success && query.data.available) || [];\n\n /*\n * Seed the input from active.userName once, on the first successful query.\n * After that the input belongs to the user — refetches (e.g. triggered by\n * a masquerade change in another tab) must not clobber what they typed.\n */\n const hasSeededRef = useRef(false);\n useEffect(() => {\n if (hasSeededRef.current || !query.isSuccess) {\n return;\n }\n hasSeededRef.current = true;\n if (active.userName) {\n setUserName(active.userName);\n }\n }, [query.isSuccess, active.userName]);\n\n /*\n * Clear pendingOption once the refetched active state actually reflects it.\n * Clearing in onSuccess instead would briefly flash the old active state\n * between mutation success and the refetch landing.\n */\n useEffect(() => {\n if (pendingOption && isOptionSelected(pendingOption, active)) {\n setPendingOption(null);\n }\n }, [pendingOption, active]);\n\n const showUserNameInput = active.userName !== null\n || pendingOption?.userName !== undefined;\n\n const errorMessage = pickErrorMessage(mutation);\n const isDenied = isQueryDenied(query);\n /* Loading until the first response (success or failure) lands. */\n const isLoading = query.isLoading;\n\n const select = (option: MasqueradeOption) => {\n /* Clear any prior mutation error so it doesn't leak into the new selection. */\n mutation.reset();\n setPendingOption(option);\n if (option.userName !== undefined) {\n setUserName(option.userName);\n return;\n }\n mutation.mutate(toMasqueradePayload(option));\n };\n\n const submitUserName = () => {\n mutation.mutate({ role: 'student', user_name: userName });\n };\n\n return {\n active,\n available,\n pendingOption,\n showUserNameInput,\n userName,\n setUserName,\n select,\n submitUserName,\n errorMessage,\n isSubmitting: mutation.isPending,\n isLoading,\n isDenied,\n };\n}\n"]}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/masquerade/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport type { MessageDescriptor } from 'react-intl';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport {\n ActiveMasqueradeData,\n MasqueradeOption,\n MasqueradeStatus,\n MasqueradePayload,\n getMasqueradeOptions,\n postMasqueradeOptions,\n} from './data/api';\nimport {\n CourseHomeCourseMetadata,\n courseHomeCourseMetadataQueryKey,\n findActiveTab,\n getCourseHomeCourseMetadata,\n} from '../data/service';\nimport { isClientRoute } from '../utils';\nimport messages from './messages';\n\nconst defaultActive: ActiveMasqueradeData = {\n role: 'staff',\n groupId: null,\n groupName: null,\n userName: null,\n userPartitionId: null,\n};\n\nfunction toMasqueradePayload(option: MasqueradeOption): MasqueradePayload {\n const payload: MasqueradePayload = { role: option.role };\n if (option.groupId !== undefined && option.userPartitionId !== undefined) {\n payload.group_id = option.groupId;\n payload.user_partition_id = option.userPartitionId;\n }\n return payload;\n}\n\n/*\n * Whether `option` represents the active masquerade. Three shapes:\n * - userName defined: the \"Specific Student...\" prompt; active when the\n * server says we're masquerading as some specific user.\n * - groupId defined: a group option; active when the group ids match.\n * - neither: a plain role option (e.g. Staff); active when no group/user\n * is set.\n */\nexport function isOptionSelected(option: MasqueradeOption, active: ActiveMasqueradeData): boolean {\n if (option.role !== active.role) {\n return false;\n }\n if (option.userName !== undefined) {\n return active.userName !== null;\n }\n if (option.groupId !== undefined) {\n return option.groupId === active.groupId\n && option.userPartitionId === active.userPartitionId;\n }\n return active.userName === null && active.groupId === null;\n}\n\ninterface HttpishError {\n customAttributes?: { httpErrorStatus?: number };\n}\n\nfunction getHttpStatus(error: unknown): number | undefined {\n return (error as HttpishError | null)?.customAttributes?.httpErrorStatus;\n}\n\n/*\n * Anything other than a successful load with `success: true` hides the bar:\n * 403, 200 with `success: false`, network errors, 5xx, redirected requests.\n */\nfunction isQueryDenied(query: { isError: boolean; error: unknown; data: MasqueradeStatus | undefined }): boolean {\n if (query.isError) {\n return true;\n }\n return query.data !== undefined && !query.data.success;\n}\n\n/*\n * Errors are returned as MessageDescriptors when the frontend can pick the\n * message, or as a raw string when the server's `data.error` is more specific\n * than anything we'd hand-pick. formatErrorMessage handles both at the\n * render site.\n */\nexport type MasqueradeErrorMessage = MessageDescriptor | string;\n\nexport function formatErrorMessage(\n formatMessage: (descriptor: MessageDescriptor) => string,\n error: MasqueradeErrorMessage,\n): string {\n return typeof error === 'string' ? error : formatMessage(error);\n}\n\nfunction pickErrorMessage(\n mutation: { isError: boolean; error: unknown; data: MasqueradeStatus | undefined },\n): MasqueradeErrorMessage | null {\n if (mutation.isError) {\n return getHttpStatus(mutation.error) === 404\n ? messages.noStudentFound\n : messages.genericSubmitError;\n }\n if (mutation.data && !mutation.data.success) {\n return mutation.data.error || messages.genericSubmitError;\n }\n return null;\n}\n\nexport interface MasqueradeState {\n active: ActiveMasqueradeData;\n available: MasqueradeOption[];\n pendingOption: MasqueradeOption | null;\n showUserNameInput: boolean;\n userName: string;\n setUserName: (value: string) => void;\n select: (option: MasqueradeOption) => void;\n submitUserName: () => void;\n errorMessage: MasqueradeErrorMessage | null;\n isSubmitting: boolean;\n isLoading: boolean;\n isDenied: boolean;\n}\n\nexport function useMasqueradeState(courseId: string): MasqueradeState {\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const location = useLocation();\n /*\n * Tracks the option the user just clicked, so the toggle and active-marker\n * can update before the server confirms. Cleared once a mutation succeeds\n * (the server's active state becomes the truth) or replaced when the user\n * picks something else.\n */\n const [pendingOption, setPendingOption] = useState<MasqueradeOption | null>(null);\n const [userName, setUserName] = useState('');\n\n const query = useQuery({\n queryKey: ['masquerade', courseId],\n queryFn: () => getMasqueradeOptions(courseId),\n });\n\n const mutation = useMutation({\n mutationFn: (payload: MasqueradePayload) => postMasqueradeOptions(courseId, payload),\n onSuccess: async (data, payload) => {\n if (!data?.success) {\n /* Server rejected the pick. Clear the optimistic pending state so the\n * UI snaps back to the real active option, except for userName\n * submissions where the input must stay open for retry. */\n if (payload.user_name === undefined) {\n setPendingOption(null);\n }\n return;\n }\n\n queryClient.invalidateQueries();\n\n /* The course-tabs metadata is the source of truth for \"what pages this\n * user can see in this course.\" Fetch the post-masquerade tabs and\n * redirect to the first one if the current path no longer appears. */\n const meta = await queryClient.fetchQuery<CourseHomeCourseMetadata>({\n queryKey: courseHomeCourseMetadataQueryKey(courseId),\n queryFn: () => getCourseHomeCourseMetadata(courseId),\n });\n const fallback = meta.tabs[0];\n if (!fallback) {\n return;\n }\n const stillVisible = findActiveTab(meta.tabs, location.pathname);\n if (stillVisible) {\n return;\n }\n const targetPath = new URL(fallback.url).pathname;\n if (isClientRoute(targetPath)) {\n navigate(targetPath, { replace: true });\n } else {\n window.location.assign(fallback.url);\n }\n },\n onError: (_error, payload) => {\n /* Same as the !success branch: revert the optimistic pick, but keep the\n * userName input open so the user can fix a typo and retry. */\n if (payload.user_name === undefined) {\n setPendingOption(null);\n }\n },\n });\n\n const active = (query.data?.success && query.data.active) || defaultActive;\n const available = (query.data?.success && query.data.available) || [];\n\n /*\n * Seed the input from active.userName once, on the first successful query.\n * After that the input belongs to the user — refetches (e.g. triggered by\n * a masquerade change in another tab) must not clobber what they typed.\n */\n const hasSeededRef = useRef(false);\n useEffect(() => {\n if (hasSeededRef.current || !query.isSuccess) {\n return;\n }\n hasSeededRef.current = true;\n if (active.userName) {\n setUserName(active.userName);\n }\n }, [query.isSuccess, active.userName]);\n\n /*\n * Clear pendingOption once the refetched active state actually reflects it.\n * Clearing in onSuccess instead would briefly flash the old active state\n * between mutation success and the refetch landing.\n */\n useEffect(() => {\n if (pendingOption && isOptionSelected(pendingOption, active)) {\n setPendingOption(null);\n }\n }, [pendingOption, active]);\n\n const showUserNameInput = active.userName !== null\n || pendingOption?.userName !== undefined;\n\n const errorMessage = pickErrorMessage(mutation);\n const isDenied = isQueryDenied(query);\n /* Loading until the first response (success or failure) lands. */\n const isLoading = query.isLoading;\n\n const select = (option: MasqueradeOption) => {\n /* Clear any prior mutation error so it doesn't leak into the new selection. */\n mutation.reset();\n setPendingOption(option);\n if (option.userName !== undefined) {\n setUserName(option.userName);\n return;\n }\n mutation.mutate(toMasqueradePayload(option));\n };\n\n const submitUserName = () => {\n mutation.mutate({ role: 'student', user_name: userName });\n };\n\n return {\n active,\n available,\n pendingOption,\n showUserNameInput,\n userName,\n setUserName,\n select,\n submitUserName,\n errorMessage,\n isSubmitting: mutation.isPending,\n isLoading,\n isDenied,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MasqueradeUserNameInput.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/masquerade-widget/MasqueradeUserNameInput.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,GAC7C,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,QAAQ,MAAM,YAAY,CAAC;AAQlC,MAAM,UAAU,uBAAuB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAS;IACzE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EACJ,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,GACpD,GAAG,oBAAoB,EAAE,CAAC;IAE3B,MAAM,YAAY,GAAG,CAAC,KAAiC,EAAE,EAAE;QACzD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,cAAc,EAAE,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,IAAI,IAAC,SAAS,EAAE,6BAA6B,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,YAAY,aACrF,KAAC,SAAS,IAAC,SAAS,EAAE,EAAE,EAAE,SAAS,EAAC,uBAAuB,YACzD,KAAC,WAAW,IACV,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,KAA0C,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GACzF,GACQ,EACZ,KAAC,cAAc,IACb,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,OAAO,EACf,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC3C,QAAQ,EAAE,CAAC,QAAQ,EACnB,MAAM,EAAE;oBACN,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACvC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC;iBAC5C,GACD,IACG,CACR,CAAC;AACJ,CAAC","sourcesContent":["import { FormEvent } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport {\n Form, FormControl, FormGroup, StatefulButton,\n} from '@openedx/paragon';\n\nimport { useMasqueradeContext } from '../MasqueradeContext';\nimport messages from './messages';\n\ninterface Props {\n id?: string,\n className?: string,\n autoFocus?: boolean,\n}\n\nexport function MasqueradeUserNameInput({ id, className, autoFocus }: Props) {\n const { formatMessage } = useIntl();\n const {\n userName, setUserName, submitUserName, isSubmitting,\n } = useMasqueradeContext();\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n submitUserName();\n };\n\n return (\n <Form className={`d-flex align-items-center ${className ?? ''}`} onSubmit={handleSubmit}>\n <FormGroup controlId={id} className=\"flex-grow-1 mb-0 mr-2\">\n <FormControl\n autoFocus={autoFocus}\n value={userName}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => setUserName(event.target.value)}\n />\n </FormGroup>\n <StatefulButton\n type=\"submit\"\n variant=\"brand\"\n state={isSubmitting ? 'pending' : 'default'}\n disabled={!userName}\n labels={{\n default: formatMessage(messages.submit),\n pending: formatMessage(messages.submitting),\n }}\n />\n </Form>\n );\n}\n"]}
1
+ {"version":3,"file":"MasqueradeUserNameInput.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/masquerade-widget/MasqueradeUserNameInput.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,GAC7C,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,QAAQ,MAAM,YAAY,CAAC;AAQlC,MAAM,UAAU,uBAAuB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAS;IACzE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EACJ,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,GACpD,GAAG,oBAAoB,EAAE,CAAC;IAE3B,MAAM,YAAY,GAAG,CAAC,KAAiC,EAAE,EAAE;QACzD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,cAAc,EAAE,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,IAAI,IAAC,SAAS,EAAE,6BAA6B,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,YAAY,aACrF,KAAC,SAAS,IAAC,SAAS,EAAE,EAAE,EAAE,SAAS,EAAC,uBAAuB,YACzD,KAAC,WAAW,IACV,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,KAA0C,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GACzF,GACQ,EACZ,KAAC,cAAc,IACb,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,OAAO,EACf,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC3C,QAAQ,EAAE,CAAC,QAAQ,EACnB,MAAM,EAAE;oBACN,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACvC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC;iBAC5C,GACD,IACG,CACR,CAAC;AACJ,CAAC","sourcesContent":["import { FormEvent } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport {\n Form, FormControl, FormGroup, StatefulButton,\n} from '@openedx/paragon';\n\nimport { useMasqueradeContext } from '../MasqueradeContext';\nimport messages from './messages';\n\ninterface Props {\n id?: string;\n className?: string;\n autoFocus?: boolean;\n}\n\nexport function MasqueradeUserNameInput({ id, className, autoFocus }: Props) {\n const { formatMessage } = useIntl();\n const {\n userName, setUserName, submitUserName, isSubmitting,\n } = useMasqueradeContext();\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n submitUserName();\n };\n\n return (\n <Form className={`d-flex align-items-center ${className ?? ''}`} onSubmit={handleSubmit}>\n <FormGroup controlId={id} className=\"flex-grow-1 mb-0 mr-2\">\n <FormControl\n autoFocus={autoFocus}\n value={userName}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => setUserName(event.target.value)}\n />\n </FormGroup>\n <StatefulButton\n type=\"submit\"\n variant=\"brand\"\n state={isSubmitting ? 'pending' : 'default'}\n disabled={!userName}\n labels={{\n default: formatMessage(messages.submit),\n pending: formatMessage(messages.submitting),\n }}\n />\n </Form>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MasqueradeWidgetOption.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/masquerade-widget/MasqueradeWidgetOption.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAO5C,MAAM,UAAU,sBAAsB,CAAC,EAAE,MAAM,EAAS;IACtD,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAEjE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;qDAEiD;IACjD,MAAM,aAAa,GAAG,aAAa,KAAK,IAAI;QAC1C,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,aAAa,CAAC,IAAI;QACpC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IACZ,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EACxC,IAAI,EAAC,GAAG,EACR,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,YAE5B,MAAM,CAAC,IAAI,GACE,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown } from '@openedx/paragon';\n\nimport { useMasqueradeContext } from '../MasqueradeContext';\nimport { isOptionSelected } from '../hooks';\nimport type { MasqueradeOption } from '../data/api';\n\ninterface Props {\n option: MasqueradeOption,\n}\n\nexport function MasqueradeWidgetOption({ option }: Props) {\n const { active, pendingOption, select } = useMasqueradeContext();\n\n if (!option.name) {\n return null;\n }\n\n /* While a click is pending, the menu mirrors the toggle: only that option\n * is highlighted. Once the server confirms (pendingOption clears), the\n * active-server-state logic takes over again. */\n const isHighlighted = pendingOption !== null\n ? option.name === pendingOption.name\n : isOptionSelected(option, active);\n\n return (\n <Dropdown.Item\n className={isHighlighted ? 'active' : ''}\n href=\"#\"\n onClick={() => select(option)}\n >\n {option.name}\n </Dropdown.Item>\n );\n}\n"]}
1
+ {"version":3,"file":"MasqueradeWidgetOption.js","sourceRoot":"","sources":["../../../../../../shell/header/course-bar/masquerade/masquerade-widget/MasqueradeWidgetOption.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAO5C,MAAM,UAAU,sBAAsB,CAAC,EAAE,MAAM,EAAS;IACtD,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAEjE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;qDAEiD;IACjD,MAAM,aAAa,GAAG,aAAa,KAAK,IAAI;QAC1C,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,aAAa,CAAC,IAAI;QACpC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IACZ,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EACxC,IAAI,EAAC,GAAG,EACR,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,YAE5B,MAAM,CAAC,IAAI,GACE,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Dropdown } from '@openedx/paragon';\n\nimport { useMasqueradeContext } from '../MasqueradeContext';\nimport { isOptionSelected } from '../hooks';\nimport type { MasqueradeOption } from '../data/api';\n\ninterface Props {\n option: MasqueradeOption;\n}\n\nexport function MasqueradeWidgetOption({ option }: Props) {\n const { active, pendingOption, select } = useMasqueradeContext();\n\n if (!option.name) {\n return null;\n }\n\n /* While a click is pending, the menu mirrors the toggle: only that option\n * is highlighted. Once the server confirms (pendingOption clears), the\n * active-server-state logic takes over again. */\n const isHighlighted = pendingOption !== null\n ? option.name === pendingOption.name\n : isOptionSelected(option, active);\n\n return (\n <Dropdown.Item\n className={isHighlighted ? 'active' : ''}\n href=\"#\"\n onClick={() => select(option)}\n >\n {option.name}\n </Dropdown.Item>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CourseTabsNavigation.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/navigation/CourseTabsNavigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { Link, useLocation, useParams } from 'react-router-dom';\nimport { useQuery } from '@tanstack/react-query';\nimport { Slot, useIntl } from '../../../../runtime';\nimport {\n CourseTab,\n courseHomeCourseMetadataQueryKey,\n findActiveTab,\n getCourseHomeCourseMetadata,\n} from '../data/service';\nimport { Container, Nav, Navbar, Skeleton } from '@openedx/paragon';\nimport messages from './messages';\nimport { isClientRoute } from '../utils';\nimport './course-tabs-navigation.scss';\n\ninterface ResolvedTab extends CourseTab {\n pathname: string,\n clientPath: string | null,\n}\n\nconst CourseTabsNavigation = () => {\n const location = useLocation();\n const { courseId = '' } = useParams();\n const intl = useIntl();\n\n const { data = { tabs: [] }, isLoading } = useQuery({\n queryKey: courseHomeCourseMetadataQueryKey(courseId),\n queryFn: () => getCourseHomeCourseMetadata(courseId),\n retry: 2,\n enabled: !!courseId,\n });\n\n const { tabs } = data;\n\n const resolvedTabs: ResolvedTab[] = useMemo(\n () => tabs.map(tab => {\n // Tab URLs from the course_home API are always absolute.\n const pathname = new URL(tab.url).pathname;\n return { ...tab, pathname, clientPath: isClientRoute(pathname) ? pathname : null };\n }),\n [tabs]\n );\n\n const currentTab = useMemo(\n () => (resolvedTabs.length > 0 ? findActiveTab(resolvedTabs, location.pathname)?.tabId ?? null : null),\n [location.pathname, resolvedTabs]\n );\n\n if (isLoading) {\n return <Skeleton className=\"lead mt-3\" />;\n }\n\n if (!courseId || resolvedTabs.length === 0) {\n return null;\n }\n\n return (\n <Navbar expand=\"sm\" className=\"course-tabs-navigation pb-0\" aria-label={intl.formatMessage(messages.courseMaterial)}>\n <Container fluid size=\"xl\">\n <Nav\n variant=\"tabs\"\n activeKey={currentTab}\n >\n <Navbar.Toggle aria-controls=\"course-nav\" />\n <Navbar.Collapse id=\"course-nav\">\n {\n resolvedTabs.map(tab => (\n <Nav.Item key={tab.tabId}>\n <Nav.Link\n {...(tab.clientPath\n ? { to: tab.clientPath, as: Link }\n : { href: tab.url }\n )}\n active={tab.tabId === currentTab}\n >\n {tab.title}\n </Nav.Link>\n </Nav.Item>\n ))\n }\n </Navbar.Collapse>\n <Slot id=\"org.openedx.frontend.slot.header.courseNavigationBar.extraContent.v1\" />\n </Nav>\n </Container>\n </Navbar>\n );\n};\n\nexport default CourseTabsNavigation;\n"]}
1
+ {"version":3,"file":"CourseTabsNavigation.js","sourceRoot":"","sources":["../../../../../shell/header/course-bar/navigation/CourseTabsNavigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { Link, useLocation, useParams } from 'react-router-dom';\nimport { useQuery } from '@tanstack/react-query';\nimport { Slot, useIntl } from '../../../../runtime';\nimport {\n CourseTab,\n courseHomeCourseMetadataQueryKey,\n findActiveTab,\n getCourseHomeCourseMetadata,\n} from '../data/service';\nimport { Container, Nav, Navbar, Skeleton } from '@openedx/paragon';\nimport messages from './messages';\nimport { isClientRoute } from '../utils';\nimport './course-tabs-navigation.scss';\n\ninterface ResolvedTab extends CourseTab {\n pathname: string;\n clientPath: string | null;\n}\n\nconst CourseTabsNavigation = () => {\n const location = useLocation();\n const { courseId = '' } = useParams();\n const intl = useIntl();\n\n const { data = { tabs: [] }, isLoading } = useQuery({\n queryKey: courseHomeCourseMetadataQueryKey(courseId),\n queryFn: () => getCourseHomeCourseMetadata(courseId),\n retry: 2,\n enabled: !!courseId,\n });\n\n const { tabs } = data;\n\n const resolvedTabs: ResolvedTab[] = useMemo(\n () => tabs.map(tab => {\n // Tab URLs from the course_home API are always absolute.\n const pathname = new URL(tab.url).pathname;\n return { ...tab, pathname, clientPath: isClientRoute(pathname) ? pathname : null };\n }),\n [tabs]\n );\n\n const currentTab = useMemo(\n () => (resolvedTabs.length > 0 ? findActiveTab(resolvedTabs, location.pathname)?.tabId ?? null : null),\n [location.pathname, resolvedTabs]\n );\n\n if (isLoading) {\n return <Skeleton className=\"lead mt-3\" />;\n }\n\n if (!courseId || resolvedTabs.length === 0) {\n return null;\n }\n\n return (\n <Navbar expand=\"sm\" className=\"course-tabs-navigation pb-0\" aria-label={intl.formatMessage(messages.courseMaterial)}>\n <Container fluid size=\"xl\">\n <Nav\n variant=\"tabs\"\n activeKey={currentTab}\n >\n <Navbar.Toggle aria-controls=\"course-nav\" />\n <Navbar.Collapse id=\"course-nav\">\n {\n resolvedTabs.map(tab => (\n <Nav.Item key={tab.tabId}>\n <Nav.Link\n {...(tab.clientPath\n ? { to: tab.clientPath, as: Link }\n : { href: tab.url }\n )}\n active={tab.tabId === currentTab}\n >\n {tab.title}\n </Nav.Link>\n </Nav.Item>\n ))\n }\n </Navbar.Collapse>\n <Slot id=\"org.openedx.frontend.slot.header.courseNavigationBar.extraContent.v1\" />\n </Nav>\n </Container>\n </Navbar>\n );\n};\n\nexport default CourseTabsNavigation;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"helpButtonSlotOperation.js","sourceRoot":"","sources":["../../../shell/header/helpButtonSlotOperation.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAyB,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,4CAA4C,CAAC;AAEzE,MAAM,UAAU,uBAAuB,CACrC,EAAE,KAAK,EAAE,IAAI,EAAmC;IAEhD,OAAO;QACL,MAAM,EAAE,oDAAoD;QAC5D,EAAE,EAAE,YAAY;QAChB,EAAE,EAAE,oBAAoB,CAAC,MAAM;QAC/B,OAAO,EAAE,CACP,KAAC,UAAU,IACT,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,WAAiC,GACnE,CACH;QACD,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;KAC9B,CAAC;AACJ,CAAC","sourcesContent":["import { getAppConfig, WidgetAppendOperation, WidgetOperationTypes } from '../../runtime';\nimport HelpButton from './HelpButton';\n\nexport const helpWidgetId = 'org.openedx.frontend.widget.header.help.v1';\n\nexport function helpButtonSlotOperation(\n { appId, role }: { appId: string, role: string },\n): WidgetAppendOperation {\n return {\n slotId: 'org.openedx.frontend.slot.header.secondaryLinks.v1',\n id: helpWidgetId,\n op: WidgetOperationTypes.APPEND,\n element: (\n <HelpButton\n getUrl={() => getAppConfig(appId).SUPPORT_URL as string | undefined}\n />\n ),\n condition: { active: [role] },\n };\n}\n"]}
1
+ {"version":3,"file":"helpButtonSlotOperation.js","sourceRoot":"","sources":["../../../shell/header/helpButtonSlotOperation.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAyB,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,4CAA4C,CAAC;AAEzE,MAAM,UAAU,uBAAuB,CACrC,EAAE,KAAK,EAAE,IAAI,EAAmC;IAEhD,OAAO;QACL,MAAM,EAAE,oDAAoD;QAC5D,EAAE,EAAE,YAAY;QAChB,EAAE,EAAE,oBAAoB,CAAC,MAAM;QAC/B,OAAO,EAAE,CACP,KAAC,UAAU,IACT,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,WAAiC,GACnE,CACH;QACD,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;KAC9B,CAAC;AACJ,CAAC","sourcesContent":["import { getAppConfig, WidgetAppendOperation, WidgetOperationTypes } from '../../runtime';\nimport HelpButton from './HelpButton';\n\nexport const helpWidgetId = 'org.openedx.frontend.widget.header.help.v1';\n\nexport function helpButtonSlotOperation(\n { appId, role }: { appId: string; role: string },\n): WidgetAppendOperation {\n return {\n slotId: 'org.openedx.frontend.slot.header.secondaryLinks.v1',\n id: helpWidgetId,\n op: WidgetOperationTypes.APPEND,\n element: (\n <HelpButton\n getUrl={() => getAppConfig(appId).SUPPORT_URL as string | undefined}\n />\n ),\n condition: { active: [role] },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"LinkMenuItem.js","sourceRoot":"","sources":["../../../shell/menus/LinkMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAI1D,OAAO,EACL,YAAY,EACb,MAAM,cAAc,CAAC;AAStB,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,WAAW,EAAqB;IACjG,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE7C,IAAI,QAAmC,CAAC;IACxC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,QAAQ,GAAG,GAAG,CAAC;IACjB,CAAC;IAED,6FAA6F;IAC7F,sDAAsD;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,OAAO,CACL,KAAC,SAAS,IAAC,WAAW,EAAE,QAAQ,YAC7B,UAAU,GACD,CACb,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CACL,KAAC,OAAO,IAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAClG,UAAU,GACH,CACX,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,iBAAiB,EAAE,CAAC;QACzC,OAAO,CACL,KAAC,WAAW,CAAC,IAAI,IAAC,IAAI,EAAE,QAAQ,YAC7B,UAAU,GACM,CACpB,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;QACtC,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IAAC,IAAI,EAAE,QAAQ,YAC1B,UAAU,GACG,CACjB,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { Dropdown, Hyperlink, NavDropdown, NavLink } from '@openedx/paragon';\nimport { useIntl } from 'react-intl';\nimport { useLocation } from 'react-router-dom';\n\nimport { getUrlByRouteRole } from '../../runtime/routing';\nimport {\n MenuItemName\n} from '../../types';\nimport {\n getItemLabel\n} from './data/utils';\n\ninterface LinkMenuItemProps {\n label: MenuItemName,\n role?: string,\n url?: string,\n variant?: 'hyperlink' | 'navLink' | 'navDropdownItem' | 'dropdownItem',\n}\n\nexport default function LinkMenuItem({ label, role, url, variant = 'hyperlink' }: LinkMenuItemProps) {\n const intl = useIntl();\n const location = useLocation();\n const finalLabel = getItemLabel(label, intl);\n\n let finalUrl: string | null | undefined;\n if (role !== undefined) {\n finalUrl = getUrlByRouteRole(role);\n } else if (url !== undefined) {\n finalUrl = url;\n }\n\n // The URL will only be null if the item is an \"app\" menu item, and if the app is not loaded.\n // We automatically hide the link if this is the case.\n if (!finalUrl) {\n return null;\n }\n\n if (variant === 'hyperlink') {\n return (\n <Hyperlink destination={finalUrl}>\n {finalLabel}\n </Hyperlink>\n );\n } else if (variant === 'navLink') {\n return (\n <NavLink href={finalUrl} active={location.pathname.replace(/\\/$/, '') === finalUrl.replace(/\\/$/, '')}>\n {finalLabel}\n </NavLink>\n );\n } else if (variant === 'navDropdownItem') {\n return (\n <NavDropdown.Item href={finalUrl}>\n {finalLabel}\n </NavDropdown.Item>\n );\n } else if (variant === 'dropdownItem') {\n return (\n <Dropdown.Item href={finalUrl}>\n {finalLabel}\n </Dropdown.Item>\n );\n }\n\n // Just return null if the item is something we haven't accounted for above.\n return null;\n}\n"]}
1
+ {"version":3,"file":"LinkMenuItem.js","sourceRoot":"","sources":["../../../shell/menus/LinkMenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAI1D,OAAO,EACL,YAAY,EACb,MAAM,cAAc,CAAC;AAStB,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,WAAW,EAAqB;IACjG,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE7C,IAAI,QAAmC,CAAC;IACxC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,QAAQ,GAAG,GAAG,CAAC;IACjB,CAAC;IAED,6FAA6F;IAC7F,sDAAsD;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,OAAO,CACL,KAAC,SAAS,IAAC,WAAW,EAAE,QAAQ,YAC7B,UAAU,GACD,CACb,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CACL,KAAC,OAAO,IAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAClG,UAAU,GACH,CACX,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,iBAAiB,EAAE,CAAC;QACzC,OAAO,CACL,KAAC,WAAW,CAAC,IAAI,IAAC,IAAI,EAAE,QAAQ,YAC7B,UAAU,GACM,CACpB,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;QACtC,OAAO,CACL,KAAC,QAAQ,CAAC,IAAI,IAAC,IAAI,EAAE,QAAQ,YAC1B,UAAU,GACG,CACjB,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { Dropdown, Hyperlink, NavDropdown, NavLink } from '@openedx/paragon';\nimport { useIntl } from 'react-intl';\nimport { useLocation } from 'react-router-dom';\n\nimport { getUrlByRouteRole } from '../../runtime/routing';\nimport {\n MenuItemName\n} from '../../types';\nimport {\n getItemLabel\n} from './data/utils';\n\ninterface LinkMenuItemProps {\n label: MenuItemName;\n role?: string;\n url?: string;\n variant?: 'hyperlink' | 'navLink' | 'navDropdownItem' | 'dropdownItem';\n}\n\nexport default function LinkMenuItem({ label, role, url, variant = 'hyperlink' }: LinkMenuItemProps) {\n const intl = useIntl();\n const location = useLocation();\n const finalLabel = getItemLabel(label, intl);\n\n let finalUrl: string | null | undefined;\n if (role !== undefined) {\n finalUrl = getUrlByRouteRole(role);\n } else if (url !== undefined) {\n finalUrl = url;\n }\n\n // The URL will only be null if the item is an \"app\" menu item, and if the app is not loaded.\n // We automatically hide the link if this is the case.\n if (!finalUrl) {\n return null;\n }\n\n if (variant === 'hyperlink') {\n return (\n <Hyperlink destination={finalUrl}>\n {finalLabel}\n </Hyperlink>\n );\n } else if (variant === 'navLink') {\n return (\n <NavLink href={finalUrl} active={location.pathname.replace(/\\/$/, '') === finalUrl.replace(/\\/$/, '')}>\n {finalLabel}\n </NavLink>\n );\n } else if (variant === 'navDropdownItem') {\n return (\n <NavDropdown.Item href={finalUrl}>\n {finalLabel}\n </NavDropdown.Item>\n );\n } else if (variant === 'dropdownItem') {\n return (\n <Dropdown.Item href={finalUrl}>\n {finalLabel}\n </Dropdown.Item>\n );\n }\n\n // Just return null if the item is something we haven't accounted for above.\n return null;\n}\n"]}