@clickview/lite 0.57.2-rc.0 → 0.57.2-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/bundles.json +2 -2
  2. package/dist/css/{3918-lite-9bd35b2c4c.chunk.css → 3918-lite-88ef54ffc6.chunk.css} +3 -1
  3. package/dist/css/{1057-lite-04173a371f.chunk.css → 8849-lite-1ad0b22428.chunk.css} +2 -1
  4. package/dist/css/{lite-app-5335e8e07a.css → lite-app-560655620c.css} +1 -1
  5. package/dist/languages/en.json +1 -1
  6. package/dist/scripts/1734-f5ffd39591-lite.chunk.js +2 -0
  7. package/dist/scripts/1734-f5ffd39591-lite.chunk.js.map +1 -0
  8. package/dist/scripts/2506-aee0b1f275-lite.chunk.js +2 -0
  9. package/dist/scripts/2506-aee0b1f275-lite.chunk.js.map +1 -0
  10. package/dist/scripts/{2564-cd82320188-lite.chunk.js → 2564-98ba0d782a-lite.chunk.js} +3 -3
  11. package/dist/scripts/{2564-cd82320188-lite.chunk.js.map → 2564-98ba0d782a-lite.chunk.js.map} +1 -1
  12. package/dist/scripts/2615-e9b2938c18-lite.chunk.js +3 -0
  13. package/dist/scripts/2615-e9b2938c18-lite.chunk.js.map +1 -0
  14. package/dist/scripts/2788-86687fd69d-lite.chunk.js +2 -0
  15. package/dist/scripts/2788-86687fd69d-lite.chunk.js.map +1 -0
  16. package/dist/scripts/2820-b3d1688da0-lite.chunk.js +2 -0
  17. package/dist/scripts/2820-b3d1688da0-lite.chunk.js.map +1 -0
  18. package/dist/scripts/2978-b7bcc3eac4-lite.chunk.js +2 -0
  19. package/dist/scripts/2978-b7bcc3eac4-lite.chunk.js.map +1 -0
  20. package/dist/scripts/3391-5e26ca5ece-lite.chunk.js +2 -0
  21. package/dist/scripts/3391-5e26ca5ece-lite.chunk.js.map +1 -0
  22. package/dist/scripts/{3667-f9f546136c-lite.chunk.js → 3667-149e98454c-lite.chunk.js} +3 -3
  23. package/dist/scripts/{3667-f9f546136c-lite.chunk.js.map → 3667-149e98454c-lite.chunk.js.map} +1 -1
  24. package/dist/scripts/3918-43b95cb315-lite.chunk.js +2 -0
  25. package/dist/scripts/3918-43b95cb315-lite.chunk.js.map +1 -0
  26. package/dist/scripts/4113-d6411052c4-lite.chunk.js +2 -0
  27. package/dist/scripts/4113-d6411052c4-lite.chunk.js.map +1 -0
  28. package/dist/scripts/4137-bef0be4a57-lite.chunk.js +3 -0
  29. package/dist/scripts/4137-bef0be4a57-lite.chunk.js.map +1 -0
  30. package/dist/scripts/4266-42463e0c33-lite.chunk.js +3 -0
  31. package/dist/scripts/4266-42463e0c33-lite.chunk.js.map +1 -0
  32. package/dist/scripts/5817-84b8e83c19-lite.chunk.js +3 -0
  33. package/dist/scripts/5817-84b8e83c19-lite.chunk.js.map +1 -0
  34. package/dist/scripts/{6433-ff27a3c867-lite.chunk.js → 6433-ad3992c23a-lite.chunk.js} +2 -2
  35. package/dist/scripts/{6433-ff27a3c867-lite.chunk.js.map → 6433-ad3992c23a-lite.chunk.js.map} +1 -1
  36. package/dist/scripts/7434-34137ad94a-lite.chunk.js +2 -0
  37. package/dist/scripts/7434-34137ad94a-lite.chunk.js.map +1 -0
  38. package/dist/scripts/{7556-79099a07fc-lite.chunk.js → 7556-69f8cb3b20-lite.chunk.js} +3 -3
  39. package/dist/scripts/7556-69f8cb3b20-lite.chunk.js.map +1 -0
  40. package/dist/scripts/{8095-777a5c5ddf-lite.chunk.js → 8095-afb976fac0-lite.chunk.js} +2 -2
  41. package/dist/scripts/8095-afb976fac0-lite.chunk.js.map +1 -0
  42. package/dist/scripts/839-f8478d27f8-lite.chunk.js +2 -0
  43. package/dist/scripts/839-f8478d27f8-lite.chunk.js.map +1 -0
  44. package/dist/scripts/8489-7779fd40b3-lite.chunk.js +3 -0
  45. package/dist/scripts/8489-7779fd40b3-lite.chunk.js.map +1 -0
  46. package/dist/scripts/8849-020bfd8cdd-lite.chunk.js +2 -0
  47. package/dist/scripts/8849-020bfd8cdd-lite.chunk.js.map +1 -0
  48. package/dist/scripts/bundle-fb8200eefd.min.js +3 -0
  49. package/dist/scripts/bundle-fb8200eefd.min.js.map +1 -0
  50. package/package.json +1 -1
  51. package/dist/scripts/1057-3c48d4553a-lite.chunk.js +0 -2
  52. package/dist/scripts/1057-3c48d4553a-lite.chunk.js.map +0 -1
  53. package/dist/scripts/1683-57c0175d4e-lite.chunk.js +0 -2
  54. package/dist/scripts/1683-57c0175d4e-lite.chunk.js.map +0 -1
  55. package/dist/scripts/1734-bbca52585c-lite.chunk.js +0 -2
  56. package/dist/scripts/1734-bbca52585c-lite.chunk.js.map +0 -1
  57. package/dist/scripts/232-278263e5f8-lite.chunk.js +0 -3
  58. package/dist/scripts/232-278263e5f8-lite.chunk.js.map +0 -1
  59. package/dist/scripts/2615-90d4cdd835-lite.chunk.js +0 -3
  60. package/dist/scripts/2615-90d4cdd835-lite.chunk.js.map +0 -1
  61. package/dist/scripts/2788-013bbba554-lite.chunk.js +0 -2
  62. package/dist/scripts/2788-013bbba554-lite.chunk.js.map +0 -1
  63. package/dist/scripts/312-2458059ebb-lite.chunk.js +0 -2
  64. package/dist/scripts/312-2458059ebb-lite.chunk.js.map +0 -1
  65. package/dist/scripts/3918-2855f0da2a-lite.chunk.js +0 -2
  66. package/dist/scripts/3918-2855f0da2a-lite.chunk.js.map +0 -1
  67. package/dist/scripts/4137-f0ac17da1f-lite.chunk.js +0 -3
  68. package/dist/scripts/4137-f0ac17da1f-lite.chunk.js.map +0 -1
  69. package/dist/scripts/4654-6fedfb863f-lite.chunk.js +0 -2
  70. package/dist/scripts/4654-6fedfb863f-lite.chunk.js.map +0 -1
  71. package/dist/scripts/5817-900efca702-lite.chunk.js +0 -3
  72. package/dist/scripts/5817-900efca702-lite.chunk.js.map +0 -1
  73. package/dist/scripts/7237-86c18f2701-lite.chunk.js +0 -2
  74. package/dist/scripts/7237-86c18f2701-lite.chunk.js.map +0 -1
  75. package/dist/scripts/7434-366d4ae5e0-lite.chunk.js +0 -2
  76. package/dist/scripts/7434-366d4ae5e0-lite.chunk.js.map +0 -1
  77. package/dist/scripts/7556-79099a07fc-lite.chunk.js.map +0 -1
  78. package/dist/scripts/8095-777a5c5ddf-lite.chunk.js.map +0 -1
  79. package/dist/scripts/839-889090dc50-lite.chunk.js +0 -2
  80. package/dist/scripts/839-889090dc50-lite.chunk.js.map +0 -1
  81. package/dist/scripts/8489-6e8c4dd60f-lite.chunk.js +0 -3
  82. package/dist/scripts/8489-6e8c4dd60f-lite.chunk.js.map +0 -1
  83. package/dist/scripts/897-399a877281-lite.chunk.js +0 -2
  84. package/dist/scripts/897-399a877281-lite.chunk.js.map +0 -1
  85. package/dist/scripts/9201-899c885914-lite.chunk.js +0 -2
  86. package/dist/scripts/9201-899c885914-lite.chunk.js.map +0 -1
  87. package/dist/scripts/bundle-4b58e56927.min.js +0 -3
  88. package/dist/scripts/bundle-4b58e56927.min.js.map +0 -1
  89. /package/dist/css/{1683-lite-bdd5b6edf8.chunk.css → 2506-lite-bdd5b6edf8.chunk.css} +0 -0
  90. /package/dist/css/{7237-lite-a8e87f096f.chunk.css → 2820-lite-a8e87f096f.chunk.css} +0 -0
  91. /package/dist/scripts/{2564-cd82320188-lite.chunk.js.LICENSE.txt → 2564-98ba0d782a-lite.chunk.js.LICENSE.txt} +0 -0
  92. /package/dist/scripts/{2615-90d4cdd835-lite.chunk.js.LICENSE.txt → 2615-e9b2938c18-lite.chunk.js.LICENSE.txt} +0 -0
  93. /package/dist/scripts/{3667-f9f546136c-lite.chunk.js.LICENSE.txt → 3667-149e98454c-lite.chunk.js.LICENSE.txt} +0 -0
  94. /package/dist/scripts/{4137-f0ac17da1f-lite.chunk.js.LICENSE.txt → 4137-bef0be4a57-lite.chunk.js.LICENSE.txt} +0 -0
  95. /package/dist/scripts/{232-278263e5f8-lite.chunk.js.LICENSE.txt → 4266-42463e0c33-lite.chunk.js.LICENSE.txt} +0 -0
  96. /package/dist/scripts/{5817-900efca702-lite.chunk.js.LICENSE.txt → 5817-84b8e83c19-lite.chunk.js.LICENSE.txt} +0 -0
  97. /package/dist/scripts/{6433-ff27a3c867-lite.chunk.js.LICENSE.txt → 6433-ad3992c23a-lite.chunk.js.LICENSE.txt} +0 -0
  98. /package/dist/scripts/{7556-79099a07fc-lite.chunk.js.LICENSE.txt → 7556-69f8cb3b20-lite.chunk.js.LICENSE.txt} +0 -0
  99. /package/dist/scripts/{8489-6e8c4dd60f-lite.chunk.js.LICENSE.txt → 8489-7779fd40b3-lite.chunk.js.LICENSE.txt} +0 -0
  100. /package/dist/scripts/{bundle-4b58e56927.min.js.LICENSE.txt → bundle-fb8200eefd.min.js.LICENSE.txt} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"scripts/8095-777a5c5ddf-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/apps/analytics/components/pending-indicator/PendingIndicator.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/interactions-bar/interactions-bar.scss","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/interactions-bar/InteractionsBar.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/interaction-results-summary/InteractionResultsSummary.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/interaction-results-summary/interaction-results-summary.scss","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/student-results-table/InteractionHeaderCell.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/student-results-table/StudentResultCell.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/student-results-table/StudentResultsTableUtils.tsx","file:///app/packages/libs/shared/src/apps/analytics/flight-requests/InteractiveResultsRequests.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/InteractiveUtils.ts","file:///app/packages/libs/shared/src/enums/InteractionCorrectness.ts","file:///app/packages/libs/shared/src/enums/InteractiveAnswerStatus.ts","file:///app/packages/libs/shared/src/utils/InteractiveCorrectnessHelper.ts","file:///app/packages/libs/shared/src/utils/InteractiveHelper.ts","file:///app/packages/libs/shared/src/apps/analytics/components/student-results/student-results-table/student-results-table.scss"],"sourcesContent":["import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { PercentageIndicator } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\n\nconst namespace = 'interactives.pendingIndicator';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getClassName(props: PendingIndicatorProps): string {\n let className = 'd-flex align-items-center h-100';\n\n className += props.showLabel ? ' justify-content-between' : ' justify-content-center';\n\n if (props.className)\n className += ` ${props.className}`;\n\n return className;\n}\n\ninterface PendingIndicatorProps {\n title?: string;\n className?: string;\n showLabel?: boolean;\n tooltipClassName?: string;\n}\n\nexport function PendingIndicator(props: PendingIndicatorProps): JSX.Element {\n const Indicator = () => (\n <div className={getClassName(props)}>\n {!!props.showLabel &&\n <em>{getPhrase('pending')}</em>\n }\n <PercentageIndicator />\n </div>\n );\n\n if (!props.title)\n return <Indicator />;\n\n return (\n <Tooltip title={props.title} spanHack spanHackClassName={props.tooltipClassName || 'h-100 w-100 d-flex align-items-center'}>\n <Indicator />\n </Tooltip>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"container\":\"Wf1bl\",\"interaction\":\"Fpm49\"};","import React from 'react';\n\nimport { Interaction, Interactive, Timepoint } from 'libs/shared/interfaces';\nimport { DurationHelper } from 'libs/shared/utils/DurationHelper';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport styles from './interactions-bar.scss';\n\nfunction getInteraction(timepoint: Timepoint, selectedInteraction: Interaction): Interaction {\n return timepoint.interactions.find(i => i.id === selectedInteraction.id) || timepoint.interactions[0];\n}\n\ninterface InteractionBarProps {\n interactive: Interactive;\n duration: number;\n selectedInteraction: Interaction;\n}\n\nexport function InteractionsBar(props: InteractionBarProps): React.ReactElement {\n if (!props.duration)\n return <></>;\n\n return (\n <>\n {props.interactive.timepoints.map((t, i) => {\n if (!t.interactions.length)\n return <></>;\n\n const interaction = getInteraction(t, props.selectedInteraction);\n const isSelected = interaction.id === props.selectedInteraction.id;\n\n const bgClassName = isSelected ? (InteractionTypeHelper.getTypeInfo(interaction.typeId)).bgClassName : 'bg-gray-500';\n\n const left = ((t.visibleAt / 1000) / props.duration) * 100;\n\n return (\n <div\n key={i}\n className={`${styles.container} text-center`}\n style={{ left: `${left}%` }}\n >\n <div className={`${styles.interaction} ${bgClassName}`} />\n {!!isSelected &&\n <div>\n {DurationHelper.ToDisplayDuration(t.visibleAt)}\n </div>\n }\n </div>\n );\n })}\n </>\n );\n}","import React from 'react';\nimport { Popover } from 'react-bootstrap';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InteractionsBar } from 'libs/shared/apps/analytics/components/student-results/interactions-bar/InteractionsBar';\nimport { getInteractionResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Interaction, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nimport styles from './interaction-results-summary.scss';\n\nconst namespace = 'shared.interactionResultsSummary';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getDuration(interactiveMetadata: InteractiveMetadata): number {\n if (interactiveMetadata._parentClip)\n return interactiveMetadata._parentClip.endTime - interactiveMetadata._parentClip.startTime;\n\n if (!interactiveMetadata._parentVideo.duration)\n return 0;\n\n return interactiveMetadata._parentVideo.duration / 1000;\n}\n\ninterface InteractionResultsSummaryProps {\n interaction: Interaction;\n interactive: Interactive;\n interactiveMetadata: InteractiveMetadata;\n results: InteractiveResultSet;\n}\n\nfunction InteractionResultsSummary(props: InteractionResultsSummaryProps): JSX.Element {\n const summary = React.useMemo(\n () => getInteractionResultsSummary(props.interaction, props.results),\n [ props.interaction, props.results ]\n );\n\n return (\n <div className='px-1 pt-1'>\n <div className='d-flex'>\n <InteractionLabel\n interaction={props.interaction}\n iconClassName='flex-shrink-0'\n />\n </div>\n <div className={`my-4 ${styles.bar}`}>\n <InteractionsBar\n interactive={props.interactive}\n duration={getDuration(props.interactiveMetadata)}\n selectedInteraction={props.interaction}\n />\n </div>\n <div className='row pt-1 pb-2'>\n <div className='col-6 pe-1'>\n <div className='bg-light rounded p-2 h-100'>\n {!summary.awaitingMarking &&\n <div className='d-flex align-items-center justify-content-between'>\n <strong>{getPhrase('correctlyAnswered')}</strong>\n <PercentageIndicator\n percentage={summary.percentCorrect}\n layout={PercentageIndicatorLayout.LabelOnly}\n />\n </div>\n }\n {!!summary.awaitingMarking &&\n <div className='d-flex align-items-center justify-content-center'>\n <strong>\n <em>{getPhrase('pending')}</em>\n </strong>\n </div>\n }\n </div>\n </div>\n <div className='col-6 ps-1'>\n <div className='bg-light rounded h-100 p-2 d-flex align-items-center justify-content-between'>\n <strong>{getPhrase('unanswered')}</strong>\n <span>{summary.unanswered}</span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nconst InteractionResultsSummaryPopover = React.forwardRef((\n { interaction, interactive, interactiveMetadata, results, ...popoverProps }: InteractionResultsSummaryProps,\n ref: React.MutableRefObject<HTMLElement>\n) => {\n return (\n <div className='popover-lg'>\n <Popover\n id={`interaction-results-summary-${interaction.id}`}\n ref={ref as any}\n {...popoverProps}\n >\n <Popover.Body>\n <InteractionResultsSummary\n interaction={interaction}\n interactive={interactive}\n interactiveMetadata={interactiveMetadata}\n results={results}\n />\n </Popover.Body>\n </Popover>\n </div>\n );\n});\n\nexport { InteractionResultsSummaryPopover as InteractionResultsSummary };","// extracted by mini-css-extract-plugin\nexport default {\"bar\":\"FCXQd\"};","import React from 'react';\nimport { OverlayTrigger } from 'react-bootstrap';\n\nimport { InteractionResultsSummary } from 'libs/shared/apps/analytics/components/student-results/interaction-results-summary/InteractionResultsSummary';\nimport { Interaction, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nimport styles from './student-results-table.scss';\n\ninterface InteractionHeaderCellProps {\n interaction: Interaction;\n results: InteractiveResultSet;\n interactionNumber: number;\n interactive: Interactive;\n interactiveMetadata: InteractiveMetadata;\n onMouseEnter?: () => void;\n onMouseLeave?: () => void;\n}\n\nexport function InteractionHeaderCell(props: InteractionHeaderCellProps): JSX.Element {\n return (\n <OverlayTrigger\n trigger={props.results.students?.length ? 'click' : null}\n placement='bottom'\n overlay={\n <InteractionResultsSummary\n interaction={props.interaction}\n interactive={props.interactive}\n interactiveMetadata={props.interactiveMetadata}\n results={props.results}\n />\n }\n rootClose\n >\n <div\n className={\n `text-center h-100\n d-flex align-items-center justify-content-center\n ${styles.interactionHeaderCellInner}`\n }\n onMouseEnter={props.onMouseEnter}\n onMouseLeave={props.onMouseLeave}\n >\n <div className='p-1 position-relative'>\n {props.interactionNumber}\n </div>\n </div>\n </OverlayTrigger>\n );\n}","import React from 'react';\n\nimport { PendingIndicator } from 'libs/shared/apps/analytics/components/pending-indicator/PendingIndicator';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { Interaction, StudentResults } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getStudentResult } from 'libs/shared/utils/InteractiveHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './student-results-table.scss';\n\nfunction getSvgName(correctness: InteractionCorrectness): string {\n if (correctness === InteractionCorrectness.Correct)\n return cvSvgLibrary.Check;\n\n if (correctness === InteractionCorrectness.Incorrect)\n return cvSvgLibrary.Close;\n\n if (correctness === InteractionCorrectness.UnAnswered)\n return cvSvgLibrary.Minus;\n\n return;\n}\n\nfunction getClassName(correctness: InteractionCorrectness): string {\n let className = `${styles.resultsCellInner} h-100 position-relative`;\n\n if (correctness === InteractionCorrectness.Correct)\n className += ` ${styles.correct}`;\n\n if (correctness === InteractionCorrectness.Incorrect)\n className += ` ${styles.incorrect} text-danger`;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n className += ` ${styles.awaitingMarking}`;\n\n if (correctness === InteractionCorrectness.UnAnswered)\n className += ` ${styles.unanswered} text-warning`;\n\n return className;\n}\n\ninterface StudentResultCellProps {\n interaction: Interaction;\n studentResults: StudentResults;\n}\n\nexport function StudentResultCell(props: StudentResultCellProps): JSX.Element {\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(\n props.interaction,\n getStudentResult(props.studentResults)\n );\n\n const svgName = getSvgName(correctness);\n\n return (\n <div className={getClassName(correctness)}>\n {!!svgName && <SvgContainer svgName={svgName} />}\n {correctness === InteractionCorrectness.AwaitingMarking &&\n <PendingIndicator />\n }\n </div>\n );\n}","import React from 'react';\nimport { CellProps, Column, ColumnInstance, SortingRule } from 'react-table';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { PendingIndicator } from 'libs/shared/apps/analytics/components/pending-indicator/PendingIndicator';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getStudentResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getInteractions } from 'libs/shared/utils/InteractiveHelper';\n\nimport { InteractionHeaderCell } from './InteractionHeaderCell';\nimport { StudentResultCell } from './StudentResultCell';\n\nimport styles from './student-results-table.scss';\n\nconst namespace = 'shared.studentResultsTable';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport const RESULTS_COL_WIDTH = 60;\n\ninterface CellWrapperProps {\n className?: string;\n}\n\nfunction CellWrapper(props: React.PropsWithChildren<CellWrapperProps>): JSX.Element {\n return (\n <div className={`d-flex align-items-center p-2 h-100 ${props.className ?? ''}`}>\n {props.children}\n </div>\n );\n}\n\ninterface HeaderCellProps {\n column: ColumnInstance<StudentResultsWithSummary>;\n phraseKey: string;\n}\n\nfunction HeaderCell(props: HeaderCellProps): JSX.Element {\n return (\n <CellWrapper className={props.column.isSorted && 'fw-bold'}>\n {getPhrase(props.phraseKey)}\n </CellWrapper>\n );\n}\n\nexport function useGetFixedColumns(\n results: InteractiveResultSet,\n anonymiseUsers: boolean\n): Column<StudentResultsWithSummary>[] {\n const hasResults = !!results.students?.length;\n\n return React.useMemo(() => {\n const cols: Column<StudentResultsWithSummary>[] = [\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='name' />,\n accessor: 'user',\n Cell: ({ value }) => (\n <CellWrapper>\n <span className='text-truncate'>{anonymiseUserName(value, anonymiseUsers)}</span>\n </CellWrapper>\n ),\n disableSortBy: !hasResults\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='unanswered' />,\n accessor: 'summary.unanswered' as keyof StudentResultsWithSummary,\n sortType: 'basic', // Default is 'alphanumeric' which would treat the numbers as strings\n sortDescFirst: true,\n disableSortBy: !hasResults,\n Cell: ({ value }: CellProps<StudentResultsWithSummary, any>) => <CellWrapper>{value}</CellWrapper>\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='score' />,\n accessor: 'summary',\n id: 'score',\n Cell: ({ value }) => {\n if (value.awaitingMarking) {\n return (\n <CellWrapper>\n <PendingIndicator\n title={getPhrase('markingRequired')}\n className='flex-grow-1'\n showLabel\n />\n </CellWrapper>\n );\n }\n\n return (\n <CellWrapper>\n {`${value.correct}/${value.answered + value.unanswered}`}\n </CellWrapper>\n );\n },\n width: 125,\n sortDescFirst: true,\n disableSortBy: !hasResults\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='percentage' />,\n accessor: 'summary',\n id: 'percentage',\n Cell: ({ value }) => {\n if (value.awaitingMarking) {\n return (\n <CellWrapper>\n <PendingIndicator\n title={getPhrase('markingRequired')}\n className='flex-grow-1'\n showLabel\n />\n </CellWrapper>\n );\n }\n\n return (\n <CellWrapper>\n <PercentageIndicator\n percentage={value.percentCorrect}\n layout={PercentageIndicatorLayout.LabelBefore}\n className='flex-grow-1'\n />\n </CellWrapper>\n );\n },\n width: 125,\n sortDescFirst: true,\n disableSortBy: !hasResults\n }\n ];\n\n return cols;\n }, [ anonymiseUsers, hasResults ]);\n}\n\n/**\n * Returns memoized table columns. To trigger a recalculation, toggle the value of `refreshData`.\n */\nexport function useGetResultColumns(\n interactive: Interactive,\n interactiveMetadata: InteractiveMetadata,\n results: InteractiveResultSet,\n onColumnHover: (index?: number) => void,\n refreshData: boolean\n): Column<StudentResultsWithSummary>[] {\n return React.useMemo(() => {\n const interactions = getInteractions(interactive);\n\n return interactions.map((interaction, index) => {\n const col: Column<StudentResultsWithSummary> = {\n Header: () => {\n return (\n <InteractionHeaderCell\n interaction={interaction}\n results={results}\n interactive={interactive}\n interactiveMetadata={interactiveMetadata}\n interactionNumber={index + 1}\n onMouseEnter={() => onColumnHover(index)}\n onMouseLeave={() => onColumnHover(null)}\n />\n );\n },\n accessor: 'results',\n /**\n * `onSelectStudentResponse` in `StudentResultsTable` expects the column id to the interaction id\n */\n id: interaction.id,\n disableSortBy: true,\n width: RESULTS_COL_WIDTH,\n Cell: ({ row: { original: studentResults } }) => (\n <StudentResultCell interaction={interaction} studentResults={studentResults} />\n )\n };\n return col;\n });\n }, [refreshData]);\n}\n\n/**\n * Returns memoized table data. To trigger a recalculation, toggle the value of `refreshData`.\n */\nexport function useGetResultsTableData(\n interactive: Interactive,\n results: InteractiveResultSet,\n refreshData: boolean,\n anonymiseUsers: boolean,\n sortBy?: SortingRule<StudentResultsWithSummary>\n): StudentResultsWithSummary[] {\n return React.useMemo(() => {\n const students: StudentResultsWithSummary[] = [];\n\n results.students.forEach(s => {\n students.push(({ ...s, summary: getStudentResultsSummary(interactive, s) }));\n });\n\n if (sortBy?.id === 'user') {\n const sorted = ArrayHelper.sortBy(students, student => anonymiseUserName(student.user, anonymiseUsers));\n\n return sortBy.desc ? sorted.reverse() : sorted;\n }\n\n if (sortBy?.id === 'summary.unanswered') {\n const sorted = ArrayHelper.sortBy(students, student => student.summary.unanswered);\n\n return sortBy.desc ? sorted.reverse() : sorted;\n }\n\n if (sortBy?.id === 'score' || sortBy?.id === 'percentage') {\n const sorted = ArrayHelper.sortBy(students, student => {\n if (student.summary.awaitingMarking)\n return -1;\n\n return student.summary.percentCorrect;\n });\n\n return sortBy.desc ? sorted.reverse() : sorted;\n }\n\n return students;\n }, [ refreshData, sortBy, anonymiseUsers ]);\n}\n\nexport function highlightColumns(tableEl: HTMLElement, highlightIndex?: number): void {\n if (!tableEl)\n return;\n\n const rows = tableEl.querySelectorAll(`.${styles.resultsRow}`);\n\n rows?.forEach(row => {\n row.childNodes.forEach((col: HTMLElement, colIdx: number) => {\n col.classList.remove(styles.highlightColumn);\n\n if (colIdx === highlightIndex)\n col.classList.add(styles.highlightColumn);\n });\n });\n}\n\nexport function highlightRows(tableEl: HTMLElement, highlightIndex?: number): void {\n if (!tableEl)\n return;\n\n const rows = tableEl.querySelectorAll(`.${styles.resultsRow}`);\n\n rows?.forEach((row, rowIdx) => {\n row.classList.remove(styles.highlightResultsRow);\n\n if (rowIdx === highlightIndex)\n row.classList.add(styles.highlightResultsRow);\n });\n}","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { Flight } from 'libs/common/react/index';\n\nimport { MarkInteractiveAnswer } from 'libs/shared/apps/analytics/interfaces/MarkInteractiveAnswer';\nimport { InteractiveResultsReport } from 'libs/shared/apps/analytics/interfaces/requests/InteractiveResultsReport';\nimport { InteractivesPendingReviewsRequest } from 'libs/shared/apps/analytics/interfaces/requests/InteractivesPendingReviewsRequest';\nimport { AnalyticsRequestFilter, CurrentUser, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\ninterface InteractiveResultFilters {\n currentUserId: string;\n currentCustomerId: string;\n dateRange?: { start: string, end: string }\n userIds?: string | string[];\n classroomsAndGroups?: string | string[];\n}\n\nfunction getInteractiveResultFilters(\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter\n): InteractiveResultFilters {\n return {\n currentUserId: currentUser.id,\n currentCustomerId: currentUser.customerId,\n dateRange: { start: filter.start, end: filter.end },\n userIds: filter.userId,\n classroomsAndGroups: filter.groupId\n };\n}\n\nexport const InteractiveResultsRequests = {\n /** \n * This endpoint returns data with a lot of duplicated ids,\n * e.g. student answers to the same question will have the same id.\n * Because of that, we don't normalize.\n */\n interactiveResultSet(\n interactiveId: string,\n interactiveMetadataId: string,\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter,\n success?: (data: InteractiveResultSet) => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/domain/v2/analytics/interactives/${interactiveId}/metadata/${interactiveMetadataId}`,\n key: getAnalyticsRequestKey(`interactive:result:set:${interactiveId}:${interactiveMetadataId}`, filter),\n data: getInteractiveResultFilters(currentUser, filter),\n type: HttpVerbs.POST,\n normalize: false,\n success,\n error,\n always\n };\n },\n \n /**\n * As the response from `interactiveResultSet` isn't normalised, we need to invalidate the cache\n * to update the results data.\n */\n mark(\n interactiveId: string,\n interactiveMetadataId: string,\n answerId: string,\n data: MarkInteractiveAnswer,\n success?: () => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/answers/${answerId}`,\n key: `mark:answer:${answerId}:${data.resultId}`,\n type: HttpVerbs.PUT,\n data,\n normalize: false,\n invalidationKeys: `interactive:result:set:${interactiveId}:${interactiveMetadataId}`,\n success,\n error,\n always\n };\n },\n\n pendingReviews(data: InteractivesPendingReviewsRequest): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/interactives/pending-reviews/summary`,\n key: `interactives:pending:reviews`,\n type: HttpVerbs.POST,\n data\n };\n },\n\n interactiveResultsReport(data: InteractiveResultsReport): Flight.Request {\n return {\n url: '{gateway}/v2/analytics/interactives/report',\n key: 'interactive:results:report',\n data,\n type: HttpVerbs.POST,\n normalize: false\n };\n }\n};","import { Flight } from 'libs/common/flight';\n\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { AnalyticsRequestFilter, CurrentUser, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nexport function useFetchInteractiveResults(\n interactiveMetadataId: string,\n requestFilter: AnalyticsRequestFilter\n): Flight.Response<InteractiveResultSet> {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(!!interactiveMetadataId &&\n InteractiveRequests.interactiveMetadata(interactiveMetadataId));\n\n const interactive = Flight.useBasicFetch<Interactive>(!!interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const shouldFetchResults = !!currentUser.data && !!interactive.data && (!!requestFilter);\n\n return Flight.useBasicFetch<InteractiveResultSet>(shouldFetchResults &&\n InteractiveResultsRequests.interactiveResultSet(\n interactiveMetadata.data.interactiveId,\n interactiveMetadata.data.id,\n currentUser.data,\n requestFilter\n ));\n}","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { StudentResultsWithSummary } from 'libs/shared/apps/analytics/interfaces/StudentResultsWithSummary';\nimport { ScoreThresholdDefaults } from 'libs/shared/constants/ScoreThresholds';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { Interactive, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { flattenInteractions, getInteractions, getStudentAttempt, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\ninterface StudentGroups {\n markingRequired: StudentResultsWithSummary[];\n lowScore: StudentResultsWithSummary[];\n highScore: StudentResultsWithSummary[];\n completed: StudentResultsWithSummary[];\n notCompleted: StudentResultsWithSummary[];\n}\n\nexport function groupStudents(interactive: Interactive, results: InteractiveResultSet): StudentGroups {\n const groups: StudentGroups = {\n markingRequired: [],\n lowScore: [],\n highScore: [],\n completed: [],\n notCompleted: []\n };\n\n const interactions = getInteractions(interactive);\n\n const numInteractions = interactions.length;\n \n results.students.forEach(s => {\n const withSummary = {\n ...s,\n summary: getStudentResultsSummary(interactive, s)\n };\n \n if (withSummary.summary.awaitingMarking) {\n groups.markingRequired.push(withSummary);\n return;\n }\n\n if (ArrayHelper.last(s.results).attempts.length === numInteractions) {\n groups.completed.push(withSummary);\n } else {\n groups.notCompleted.push(withSummary);\n return;\n }\n \n if (withSummary.summary.percentCorrect >= ScoreThresholdDefaults.HIGH)\n groups.highScore.push(withSummary);\n \n if (withSummary.summary.percentCorrect < ScoreThresholdDefaults.MODERATE)\n groups.lowScore.push(withSummary);\n });\n \n const sortedLowScore = ArrayHelper.sortBy(groups.lowScore, s => s.summary.percentCorrect);\n const sortedHighScore = ArrayHelper.sortBy(groups.highScore, s => s.summary.percentCorrect).reverse();\n \n return {\n ...groups,\n lowScore: sortedLowScore,\n highScore: sortedHighScore\n };\n}\n\nexport function getInteractionById(interactive: Interactive, interactionId: string): Interaction {\n const flattenedInteractions = flattenInteractions(interactive);\n return flattenedInteractions.find(i => i.id.toString() === interactionId.toString());\n}\n\n/**\n * We need to use the question and result ids as a list of one student's responses\n * to multiple questions will all have the same result id and a list of multiple\n * students responses to one question will all have the same questionId.\n */\nexport function getMarkedAnswerId(answer: StudentAnswer): string {\n return `${answer.questionId}:${answer.resultId}`;\n}\n\nexport function getMarkedStatus(\n interactionId: string,\n studentResults: StudentResults,\n markedAnswers: MarkedAnswerHash\n): InteractiveAnswerStatus {\n const result = getStudentResult(studentResults);\n const studentResponse = getStudentAttempt(interactionId, result);\n\n const isMarkedCorrect = studentResponse?.answers.every(a => {\n return markedAnswers[getMarkedAnswerId(a)]?.status === InteractiveAnswerStatus.Correct;\n });\n\n if (isMarkedCorrect)\n return InteractiveAnswerStatus.Correct;\n\n const isMarkedIncorrect = studentResponse?.answers.every(a => {\n return markedAnswers[getMarkedAnswerId(a)]?.status === InteractiveAnswerStatus.Incorrect;\n });\n\n if (isMarkedIncorrect)\n return InteractiveAnswerStatus.Incorrect;\n}\n\nexport function getInteractionResultsSummary(\n interaction: Interaction,\n results: InteractiveResultSet\n): ResultsSummary {\n const numStudents = results.students.length;\n let numCorrect = 0;\n let answered = 0;\n let unanswered = 0;\n let awaitingMarking = 0;\n let attempts = 0;\n\n results.students.forEach(s => {\n const result = getStudentResult(s);\n\n if (!result)\n return;\n\n attempts = attempts + s.results.length;\n\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(interaction, result);\n\n if (correctness === InteractionCorrectness.Correct)\n numCorrect++;\n\n if (correctness === InteractionCorrectness.UnAnswered)\n unanswered++;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n awaitingMarking++;\n\n if (correctness !== InteractionCorrectness.UnAnswered)\n answered++;\n });\n\n\n const percentCorrect = numStudents > 0\n ? numCorrect / numStudents\n : 0;\n\n return {\n percentCorrect,\n correct: numCorrect,\n answered,\n unanswered,\n awaitingMarking,\n attempts\n };\n}\n\nexport function getStudentResultsSummary(interactive: Interactive, studentResults: StudentResults): ResultsSummary {\n const result = getStudentResult(studentResults);\n\n const interactions = getInteractions(interactive);\n\n const numInteractions = interactions.length;\n\n let numCorrect = 0;\n let awaitingMarking = 0;\n\n interactions.forEach(i => {\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(i, result);\n\n if (correctness === InteractionCorrectness.Correct)\n numCorrect++;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n awaitingMarking++;\n });\n\n const percentCorrect = numInteractions > 0 ? numCorrect / numInteractions : 0;\n\n /**\n * Our interactions list has images and annotations filtered out.\n * We built a map of valid questions, so that we can calculate the unswered accurately.\n * We're doing this because of a bug that caused annotations and images to record answers in the player.\n * - Sha\n */\n const interactionIds = new Set(interactions.map(i => i.id));\n const answeredInteractions = result.attempts.filter(a => !!interactionIds.has(a?.answers[0]?.questionId)).length;\n\n return {\n answered: result.attempts.length,\n attempts: studentResults.results.length,\n unanswered: numInteractions - answeredInteractions,\n percentCorrect,\n correct: numCorrect,\n awaitingMarking\n };\n}","export enum InteractionCorrectness {\n Correct,\n Incorrect,\n AwaitingMarking,\n \n Answered,\n UnAnswered,\n NotApplicable\n}","export enum InteractiveAnswerStatus {\n Incorrect = 0,\n Correct = 1,\n PendingReview = 2\n}","import { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, InteractionTypeId, InteractiveResult, StudentAnswer } from 'libs/shared/interfaces';\n\ntype GetStudentAnswerByActionableItemId = (id: string) => string;\n\nfunction notApplicable(): InteractionCorrectness {\n return InteractionCorrectness.NotApplicable;\n}\n\nfunction awaitingMarking(): InteractionCorrectness {\n return InteractionCorrectness.AwaitingMarking;\n}\n\nfunction isMissingWordCorrect(\n interaction: Interaction,\n getStudentAnswer: GetStudentAnswerByActionableItemId\n): InteractionCorrectness {\n const items = interaction.actionableItems.filter(a => a\n .isCorrect);\n\n if (items.every(a => !getStudentAnswer(a.id)))\n return InteractionCorrectness.UnAnswered;\n\n const correct = items.every(a => a.name.trim().toLowerCase() === getStudentAnswer(a.id)?.trim().toLowerCase());\n return correct ? InteractionCorrectness.Correct : InteractionCorrectness.Incorrect;\n}\n\nfunction isMultipleChoiceCorrect(\n interaction: Interaction,\n getStudentAnswer: GetStudentAnswerByActionableItemId\n): InteractionCorrectness {\n if (interaction.actionableItems.every(a => !getStudentAnswer(a.id)))\n return InteractionCorrectness.UnAnswered;\n \n const correctItems = interaction.actionableItems.filter(a => a.isCorrect);\n\n const correct = correctItems.every(a => {\n const studentAnswer = getStudentAnswer(a.id);\n\n /**\n * In the past we've only ever checked the answer name. But since we introduced the ability to have image interactions\n * with no question text, we've need to swap to saving the id. But past submissions still have the name\n * - Sha\n */\n return studentAnswer?.toString() === a.id?.toString() || studentAnswer === a.name;\n });\n return correct ? InteractionCorrectness.Correct : InteractionCorrectness.Incorrect;\n}\n\nfunction isMarkableAnswerMarkedCorrect(\n interaction: Interaction,\n getStudentAnswer: (id: string) => StudentAnswer\n): InteractionCorrectness {\n let correctness: InteractionCorrectness;\n\n // There should only be one actionableItem\n interaction.actionableItems.forEach(item => {\n const studentAnswer = getStudentAnswer(item.id);\n\n if (!studentAnswer) {\n correctness = InteractionCorrectness.UnAnswered;\n return;\n }\n\n if (studentAnswer.status === InteractiveAnswerStatus.Correct) {\n correctness = InteractionCorrectness.Correct;\n return;\n }\n\n if (studentAnswer.status === InteractiveAnswerStatus.Incorrect) {\n correctness = InteractionCorrectness.Incorrect;\n return;\n }\n\n correctness = InteractionCorrectness.AwaitingMarking;\n });\n\n return correctness;\n}\n\ntype IsCorrectFunction = (interaction: Interaction, result: InteractiveResult) => InteractionCorrectness;\n\nfunction getGetStudentAnswer(interaction: Interaction, result: InteractiveResult): (id: string) => StudentAnswer {\n return (id: string) => {\n const attempt = result.attempts.find(a => a.id === interaction.id);\n return attempt?.answers.find(s => s.id === id);\n };\n}\n\nfunction wrapIsMissingWordCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n\n return isMissingWordCorrect(interaction, (id: string) => {\n const answer = getStudentAnswer(id);\n return answer?.text;\n });\n}\n\nfunction wrapIsMultipleChoiceCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n\n return isMultipleChoiceCorrect(interaction, (id: string) => {\n const answer = getStudentAnswer(id);\n return answer?.text;\n });\n}\n\nfunction wrapIsMarkableAnswerMarkedCorrect(\n interaction: Interaction,\n result: InteractiveResult\n): InteractionCorrectness {\n const getStudentAnswer = getGetStudentAnswer(interaction, result);\n return isMarkableAnswerMarkedCorrect(interaction, getStudentAnswer);\n}\n\nconst IsCorrectLookup: {[typeId: number]: IsCorrectFunction} = {\n [InteractionTypeId.Annotation]: notApplicable,\n [InteractionTypeId.Image]: notApplicable,\n [InteractionTypeId.MissingWord]: wrapIsMissingWordCorrect,\n [InteractionTypeId.MultipleChoice]: wrapIsMultipleChoiceCorrect,\n [InteractionTypeId.ShortAnswer]: wrapIsMarkableAnswerMarkedCorrect,\n [InteractionTypeId.TrueOrFalse]: wrapIsMultipleChoiceCorrect,\n [InteractionTypeId.Illustration]: wrapIsMarkableAnswerMarkedCorrect\n};\n\nfunction isInteractionCorrect(interaction: Interaction, result: InteractiveResult): InteractionCorrectness {\n const isCorrectFn = IsCorrectLookup[interaction.typeId];\n\n return isCorrectFn(interaction, result);\n}\n\nexport const InteractiveCorrectnessHelper = {\n notApplicable,\n awaitingMarking,\n isMissingWordCorrect,\n isMultipleChoiceCorrect,\n isInteractionCorrect\n};\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport {\n Interaction,\n InteractionTypeId,\n Interactive,\n InteractiveResult,\n StudentAttempt,\n StudentResults\n} from 'libs/shared/interfaces';\n\nfunction interactionRequiresAnswer(interaction: Interaction): boolean {\n return interaction.typeId !== InteractionTypeId.Annotation && interaction.typeId !== InteractionTypeId.Image;\n}\n\nexport function flattenInteractions(interactive: Interactive): Interaction[] {\n return ArrayHelper.flatten(interactive.timepoints.map(i => i.interactions));\n}\n\n/**\n * Centralised logic for using the most recent student result.\n */\nexport function getStudentResult(studentResults: StudentResults): InteractiveResult {\n return ArrayHelper.last(studentResults.results);\n}\n\nexport function getStudentAttempt(interactionId: string, result: InteractiveResult): StudentAttempt {\n return ArrayHelper.findWhere(result?.attempts, { id: interactionId });\n}\n\n/**\n * Returns a flat list of interactions on an interactive and filters out\n * those that don't require an answer (annotations and images).\n */\nexport function getInteractions(interactive: Interactive): Interaction [] {\n return flattenInteractions(interactive).filter(interactionRequiresAnswer);\n}","// extracted by mini-css-extract-plugin\nexport default {\"header\":\"hnMke\",\"row\":\"ILLa_\",\"fixedTable\":\"_fdpt\",\"interactionHeaderCellOuter\":\"kjXYB\",\"hasResults\":\"M4qgr\",\"interactionHeaderCellInner\":\"cnFvB\",\"resultsCellOuter\":\"bdzRb\",\"correct\":\"xANR6\",\"incorrect\":\"_44sb\",\"awaitingMarking\":\"eQ9sh\",\"unanswered\":\"xRUK8\",\"highlightColumn\":\"f9Zqr\",\"resultsCellInner\":\"LAFwi\",\"highlightResultsRow\":\"TwwLO\",\"resultsRow\":\"xZ5iP\"};"],"names":["getPhrase","getClassName","props","className","showLabel","PendingIndicator","Indicator","title","spanHack","spanHackClassName","tooltipClassName","InteractionsBar","duration","interactive","timepoints","map","t","i","interactions","length","timepoint","selectedInteraction","interaction","find","id","isSelected","bgClassName","InteractionTypeHelper","typeId","left","visibleAt","key","style","DurationHelper","LanguageService","InteractionResultsSummary","interactiveMetadata","summary","results","InteractionLabel","iconClassName","_parentClip","endTime","startTime","_parentVideo","awaitingMarking","PercentageIndicator","percentage","percentCorrect","layout","unanswered","InteractionResultsSummaryPopover","ref","popoverProps","Popover","InteractionHeaderCell","OverlayTrigger","trigger","students","placement","overlay","rootClose","onMouseEnter","onMouseLeave","interactionNumber","correctness","InteractionCorrectness","StudentResultCell","InteractiveCorrectnessHelper","studentResults","svgName","getSvgName","SvgContainer","RESULTS_COL_WIDTH","CellWrapper","children","HeaderCell","column","isSorted","phraseKey","useGetFixedColumns","anonymiseUsers","hasResults","Header","accessor","Cell","value","disableSortBy","sortType","sortDescFirst","correct","answered","width","useGetResultColumns","onColumnHover","refreshData","index","row","original","useGetResultsTableData","sortBy","forEach","s","push","sorted","ArrayHelper","student","user","desc","reverse","highlightColumns","tableEl","highlightIndex","rows","querySelectorAll","childNodes","col","colIdx","classList","remove","add","highlightRows","rowIdx","getInteractiveResultFilters","currentUser","filter","currentUserId","currentCustomerId","customerId","dateRange","start","end","userIds","userId","classroomsAndGroups","groupId","InteractiveResultsRequests","interactiveResultSet","interactiveId","interactiveMetadataId","success","error","always","url","data","type","normalize","mark","answerId","resultId","invalidationKeys","pendingReviews","interactiveResultsReport","useFetchInteractiveResults","requestFilter","shouldFetchResults","I","groupStudents","groups","markingRequired","lowScore","highScore","completed","notCompleted","numInteractions","withSummary","getStudentResultsSummary","attempts","sortedLowScore","sortedHighScore","getInteractionById","interactionId","toString","getMarkedAnswerId","answer","questionId","getMarkedStatus","markedAnswers","result","studentResponse","answers","every","a","status","getInteractionResultsSummary","numStudents","numCorrect","interactionIds","Set","answeredInteractions","has","InteractiveAnswerStatus","notApplicable","isMissingWordCorrect","getStudentAnswer","items","actionableItems","isCorrect","name","trim","toLowerCase","isMultipleChoiceCorrect","studentAnswer","getGetStudentAnswer","attempt","wrapIsMultipleChoiceCorrect","text","wrapIsMarkableAnswerMarkedCorrect","item","isMarkableAnswerMarkedCorrect","IsCorrectLookup","isInteractionCorrect","isCorrectFn","interactionRequiresAnswer","flattenInteractions","getStudentResult","getStudentAttempt","getInteractions"],"sourceRoot":""}
@@ -1,2 +0,0 @@
1
- "use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[839],{26136:(e,t,n)=>{n.d(t,{B:()=>l});var a=n(76198),r=n(64818);function l(e,t){return t?(0,a._8)(function(e){var t=+"".concat(e.id).concat(Math.floor((new Date).getMinutes()/5));return{dictionaries:[a.O9,a.yd],separator:" ",length:2,style:"capital",seed:t}}(e)):r.l.getFullName(e)}},74901:(e,t,n)=>{function a(e){return function(e){if(Array.isArray(e))return r(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return r(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}n.d(t,{K:()=>l});var l=function(e){var t=[],n=[];return e.users&&t.push.apply(t,a(e.users)),e.classrooms&&n.push.apply(n,a(e.classrooms)),e.classroomGroups&&n.push.apply(n,a(e.classroomGroups)),{userId:t,groupId:n}}},40003:(e,t,n)=>{n.d(t,{Hb:()=>d,NG:()=>g,W5:()=>m,eO:()=>p,nG:()=>s,wO:()=>v,zn:()=>i});var a=n(23481),r=n(110),l=n(57266),o=a.T.encloseNamespace("shared.analyticsUtils");function c(e){var t=r.O.convertDateToUTC(e);return r.O.format(t,"YYYY-MM-DDTHH:mm:ss")}function i(){return new Date(2021,0,1)}function s(){return new Date}function u(e){return e.find((function(e){return!!e.default}))}function m(e,t){if(t)return e.find((function(e){return e.name===t}))}function d(){var e=i(),t=(new Date).getFullYear(),n=t===e.getFullYear();return[{name:o("today"),startDate:new Date,endDate:new Date},{name:o("thisMonth"),startDate:new Date(t,(new Date).getMonth(),1),endDate:new Date},{name:o("lastThreeMonths"),startDate:new Date(t,(new Date).getMonth()-2,1),endDate:new Date},{name:o("lastSixMonths"),startDate:new Date(t,(new Date).getMonth()-5,1),endDate:new Date},{name:o("thisYear"),startDate:new Date(t,0,1),endDate:new Date},{name:o("lastYear"),startDate:new Date(t-1,0,1),endDate:new Date(t,0,0),disabled:n,tooltip:n?o("lastYearDisabled"):""},{name:o("allTime"),startDate:r.O.subtract(new Date,5,"years"),endDate:new Date,default:!0}]}function f(e){return r.O.format(e,"YYYY-MM-DD")}function p(e){return e.name?{rangeName:e.name}:{from:f(e.startDate),to:f(e.endDate)}}function g(e,t){var n=t.to,a=t.from,o=t.rangeName,c=m(e,o);if(c)return a||n?void l.e.updateParams(p(c),{replace:!0,merge:!0,keysToRemove:["from","to"]}):c;var d=u(e);if(a&&n&&r.O.isValid(a)&&r.O.isValid(n)){var f=!0,g=r.O.convertDateToUTC(new Date(a)),v=r.O.convertDateToUTC(new Date(n));r.O.isBefore(g,i(),"day")&&(g=i(),f=!1),r.O.isAfter(v,s(),"day")&&(v=s(),f=!1),r.O.isAfter(g,v)&&(g=d.startDate,v=d.endDate,f=!1);var b={startDate:g,endDate:v,name:f?o:""};if(f)return b;l.e.updateParams(p(b),{replace:!0,merge:!0,keysToRemove:["rangeName"]})}else l.e.updateParams(p(d),{replace:!0,merge:!0,keysToRemove:["rangeName"]})}function v(e,t){var n=function(e){return c(r.O.startOf(e,"day"))},a=function(e){return c(r.O.endOf(e,"day"))},l=m(e,t.rangeName);if(l)return{start:n(f(l.startDate)),end:a(f(l.endDate))};if(t.from&&t.to)return{start:n(t.from),end:a(t.to)};var o=u(e);return{start:n(f(o.startDate)),end:a(f(o.endDate))}}},49935:(e,t,n)=>{n.d(t,{Oo:()=>g,b2:()=>v});var a=n(32735),r=n(23481),l=n(36848),o=n(86764),c=n(3747),i=n(5859),s=n(35223),u=n(83914);function m(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var a,r,l,o,c=[],i=!0,s=!1;try{if(l=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;i=!1}else for(;!(i=(a=l.call(n)).done)&&(c.push(a.value),c.length!==t);i=!0);}catch(e){s=!0,r=e}finally{try{if(!i&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw r}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return d(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?d(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}var f=r.T.encloseNamespace("shared.breadcrumbComponent"),p=a.forwardRef((function(e,t){var n=e.breadcrumb,r=n.name,o=n.appLink,c=n.active,i=e.withBackIcon,m=r,d=null;return m.length>48&&(m=r.slice(0,48)+"...",d=r),a.createElement("li",{className:"breadcrumb-item".concat(c?" active":""),title:d},c?a.createElement("strong",null,m):a.createElement(l.F,{appLink:o,ref:t},i&&a.createElement(u.x,{svgName:s.vn.ChevronLeft,size:u.S.Small}),a.createElement("span",{className:i?"ms-2":""},m)))})),g=function(e){var t=e.breadcrumbs,n=(0,c.a)(o.r.XS),r=(null==t?void 0:t.length)||0,l=m(a.useState(!1),2),i=l[0],s=l[1],u=m(a.useState(!1),2),d=u[0],g=u[1],v=a.useRef();if(a.useEffect((function(){var e,n=null!==(e=null==t?void 0:t.reduce((function(e,t){return e+t.name.length}),0))&&void 0!==e?e:0;r>4&&n>64&&s(!0)}),[null==t?void 0:t.length]),a.useLayoutEffect((function(){var e;d&&(null===(e=v.current)||void 0===e||e.focus())}),[v.current,d]),!r||n&&r<2)return a.createElement(a.Fragment,null);if(n)return a.createElement("nav",{"aria-label":"breadcrumb"},a.createElement("ol",{className:"breadcrumb m-0 p-0"},a.createElement(p,{breadcrumb:t[r-2],withBackIcon:!0})));var b=a.createElement(p,{breadcrumb:t[0]}),y=r>2?a.createElement(p,{breadcrumb:t[1]}):a.createElement(a.Fragment,null),h=r>3?a.createElement(p,{breadcrumb:t[r-2]}):a.createElement(a.Fragment,null),E=r>1?a.createElement(p,{breadcrumb:t[r-1]}):a.createElement(a.Fragment,null),D=t.slice(2,r-2);return a.createElement("nav",{"aria-label":"breadcrumb"},a.createElement("ol",{className:"breadcrumb m-0 p-0"},b,y,i?a.createElement("li",{className:"breadcrumb-item"},a.createElement("button",{className:"btn-link",onClick:function(){s(!1),g(!0)},"aria-label":f("expand")},"...")):D.map((function(e,t){return a.createElement(p,{key:t,breadcrumb:e,ref:0===t?v:null})})),h,E))},v=a.memo((function(e){var t=e.numItems,n=void 0===t?3:t;return(0,c.a)(o.r.XS)?a.createElement("div",{className:"partial-loading-background",style:{height:"1.3125rem",width:"6rem"}}):a.createElement("nav",{"aria-label":"breadcrumb"},a.createElement("ol",{className:"breadcrumb m-0 p-0"},i.u.getPartialLoadingItems({numItems:n}).map((function(e,t){var n=e.width;return a.createElement("li",{key:t,className:"breadcrumb-item"},a.createElement("span",{className:"d-inline-block partial-loading-background",style:{width:n},dangerouslySetInnerHTML:{__html:"&nbsp"}}))}))))}))},40782:(e,t,n)=>{n.d(t,{I:()=>a,O:()=>i});var a,r=n(32735),l=n(2606),o=n(62712);function c(e){var t=r.useCallback((function(t){if(t){var n=t.r.baseVal.value,a=2*Math.PI*n,r=a-e.percentage*a;t.style.strokeDasharray="".concat(a," ").concat(a),t.style.strokeDashoffset=r.toString()}}),[e.percentage]);return r.createElement("svg",null,r.createElement("circle",{r:(0,l.pu)(e.size),className:o.Z.backgroundCircle}),!(0,l.zR)(e.percentage)&&r.createElement("circle",{ref:t,r:(0,l.pu)(e.size),className:(0,l.V4)(e.percentage,e.scoreThresholds)}))}function i(e){var t,n=(0,l.Ki)(e.percentage),i=e.layout===a.LabelInside?l.Mk.Large:l.Mk.Small,s=e.customLabel||(0,l.DV)(n);return e.layout===a.LabelOnly?r.createElement("span",{className:(0,l.IA)(n)},s):r.createElement("div",{className:"d-flex align-items-center justify-content-between ".concat(null!==(t=e.className)&&void 0!==t?t:"")},e.layout===a.LabelBefore&&r.createElement("span",{className:"me-2"},s),r.createElement("div",{className:(0,l.tw)(i,n)},r.createElement(c,{percentage:n,size:i,scoreThresholds:e.scoreThresholds}),e.layout===a.LabelInside&&r.createElement("span",{className:o.Z.centredPercentageText},s)))}!function(e){e.CircleOnly="circle_only",e.LabelOnly="label_only",e.LabelBefore="label_before",e.LabelInside="label_inside"}(a||(a={})),i.defaultProps={layout:a.CircleOnly}},2606:(e,t,n)=>{n.d(t,{DV:()=>g,IA:()=>d,Ki:()=>p,Mk:()=>a,V4:()=>m,pu:()=>u,tw:()=>f,zR:()=>v});var a,r=n(94892),l=n(62712),o=2,c=5.8,i=.2,s=.36;function u(e){var t=e===a.Large?c:o,n=e===a.Large?s:i;return"".concat(t/2-2*n,"rem")}function m(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:r.i;return e>=t.HIGH?l.Z.circleSuccess:e>=t.MODERATE?l.Z.circleWarning:l.Z.circleDanger}function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:r.i;return e>=t.HIGH?"text-success":e>=t.MODERATE?"text-warning":"text-danger"}function f(e,t){var n="d-inline-block ".concat(l.Z.circleContainer);return e===a.Large&&(n+=" ".concat(l.Z.lgCircleContainer)),v(t)&&(n+=" ".concat(l.Z.pendingCircle)),n}function p(e){if(!v(e))return+e.toFixed(2)}function g(e){return v(e)?"--%":"".concat(Math.round(100*e),"%")}function v(e){return"number"!=typeof e}!function(e){e.Small="small",e.Large="large"}(a||(a={}))},38502:(e,t,n)=>{n.d(t,{r:()=>m});var a=n(32735),r=n(49985),l=n(36848),o=n(18559),c=n(11607),i=n(83914),s=n(87432);function u(e){return a.createElement(a.Fragment,null,!!e.tab.svgName&&a.createElement("div",{className:e.tab.name?"pe-1":""},a.createElement(i.x,{svgName:e.tab.svgName})),e.tab.name,"number"==typeof e.tab.count&&a.createElement("div",{className:"ps-2"},a.createElement(o.C,{type:o.g.Count,data:e.tab.count})))}function m(e){var t;return a.createElement("nav",{className:null!==(t=e.className)&&void 0!==t?t:"",ref:e.containerRef},a.createElement("ul",{className:"\n list-unstyled d-inline-block m-0 ".concat(s.Z.pillTabSelector,"\n ").concat(e.borderRadius?s.Z.radiusSmall:"","\n ").concat(e.listClassName,"\n ")},e.tabs.map((function(e,t){return a.createElement("li",{className:"\n p-0 ".concat(s.Z.tab," ").concat(e.active?"btn btn-dark":"btn btn-outline-dark","\n ").concat(e.name?s.Z.minWidth:""," ").concat(e.className,"\n "),key:t},e.appLink?a.createElement(l.F,{appLink:e.appLink,analyticsData:e.analyticsData,analyticsOptions:e.analyticsOptions,className:"\n cursor-pointer d-flex align-items-center justify-content-center\n text-decoration-none text-reset px-2 text-nowrap ".concat(s.Z.tabLink,"\n ")},a.createElement(u,{tab:e})):a.createElement(c.L,{className:"\n cursor-pointer d-flex align-items-center justify-content-center\n text-decoration-none text-reset px-2 text-nowrap ".concat(s.Z.tabLink,"\n "),onClick:function(){return function(e){!e.active&&e.onSelect&&(e.onSelect(),e.analyticsData&&e.analyticsOptions&&r.k.logUserAction(e.analyticsData,e.analyticsOptions))}(e)}},a.createElement(u,{tab:e})))}))))}m.defaultProps={borderRadius:"lg"}},94892:(e,t,n)=>{n.d(t,{i:()=>a});var a={HIGH:.75,MODERATE:.5}},5859:(e,t,n)=>{function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}n.d(t,{u:()=>l});var r={numItems:5,minWidth:50,maxWidth:100},l={getPartialLoadingItems:function(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=Object.assign(Object.assign({},r),t);return(e=Array(n.numItems),function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return a(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?a(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()).map((function(){return{width:"".concat(Math.max(Math.floor(Math.random()*n.maxWidth),n.minWidth),"px")}}))}}},5672:(e,t,n)=>{n.d(t,{$6:()=>c,$o:()=>i,kj:()=>s});var a=n(23481),r=n(14070),l=n(97291),o=a.T.encloseNamespace("shared.insightsUtils");function c(e,t,n){return[{name:o("overview"),active:"overview"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.VIDEO_OVERVIEW,args:[e],params:n}},{name:o("heatmap"),active:"heatmap"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.VIDEO_HEATMAP,args:[e],params:n}}]}function i(e,t,n){return[{name:o("overview"),active:"overview"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.CLIP_OVERVIEW,args:[e],params:n}},{name:o("heatmap"),active:"heatmap"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.CLIP_HEATMAP,args:[e],params:n}}]}function s(e,t,n){return[{name:o("overview"),active:"overview"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.INTERACTIVE_OVERVIEW,args:[e],params:n}},{name:o("results"),active:"results"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.INTERACTIVE_RESULTS,args:[e],params:n}},{name:o("questions"),active:"questions"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.INTERACTIVE_QUESTIONS,args:[e],params:n}},{name:o("heatmap"),active:"heatmap"===t,appLink:{application:l.O.INSIGHTS,action:r.e.Insights.INTERACTIVE_HEATMAP,args:[e],params:n}}]}},83590:(e,t,n)=>{n.d(t,{m:()=>X});var a=n(32735),r=n(23481),l=n(57900),o=n(2948),c=n(40003),i=n(65961),s=n(34509),u=n(57266),m=n(34062),d=n(110),f=n(83914),p=n(35223);const g={dateInputLabel:"CLYvu",dateInput:"gnEqJ"};function v(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var a,r,l,o,c=[],i=!0,s=!1;try{if(l=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;i=!1}else for(;!(i=(a=l.call(n)).done)&&(c.push(a.value),c.length!==t);i=!0);}catch(e){s=!0,r=e}finally{try{if(!i&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw r}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return b(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?b(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}var y=r.T.encloseNamespace("shared.customDateRangeSelector"),h=2,E="DD/MM/YYYY";function D(e){var t,n,r=v(a.useState("startDate"),2),l=r[0],o=r[1],c=function(e){var t=a.useRef(),n=a.useRef();return a.useEffect((function(){var a,r;"startDate"===e&&(null===(a=t.current)||void 0===a||a.focus()),"endDate"===e&&(null===(r=n.current)||void 0===r||r.focus())}),[e]),[t,n]}(l),i=v(c,2),s=i[0],u=i[1];return a.createElement("div",{className:"d-inline-block"},a.createElement("div",{className:"d-flex align-items-center border-bottom p-3"},a.createElement("div",{className:"me-auto invisible"},a.createElement(f.x,{svgName:p.vn.Close})),a.createElement("form",{className:"d-flex align-items-center"},a.createElement("div",{className:"position-relative"},a.createElement("strong",{className:g.dateInputLabel},y("from")),a.createElement("input",{ref:s,className:"form-control cursor-pointer ".concat(g.dateInput),value:null!==(t=d.O.format(e.startDate,E))&&void 0!==t?t:"",onChange:function(){},onFocus:function(){return o("startDate")}})),a.createElement("span",{className:"px-3"},a.createElement(f.x,{svgName:p.vn.ArrowRight})),a.createElement("div",{className:"position-relative"},a.createElement("strong",{className:g.dateInputLabel},y("to")),a.createElement("input",{ref:u,className:"form-control cursor-pointer ".concat(g.dateInput),value:null!==(n=d.O.format(e.endDate,E))&&void 0!==n?n:"",onChange:function(){},onFocus:function(){return o("endDate")}}))),a.createElement("div",{className:"ms-auto cursor-pointer"},a.createElement(f.x,{svgName:p.vn.Close,onClick:e.close}))),a.createElement("div",{className:"p-3"},a.createElement(m._W,{mode:"range",numberOfMonths:h,selected:{from:e.startDate,to:e.endDate},onDayClick:function(t){"startDate"===l?(e.setDateRange({startDate:t,endDate:d.O.isAfter(t,e.endDate)?void 0:e.endDate}),o((function(e){return"endDate"===e?"startDate":"endDate"}))):(e.setDateRange({startDate:d.O.isAfter(e.startDate,t)?t:e.startDate,endDate:d.O.isAfter(e.startDate,t)?void 0:t}),d.O.isAfter(e.startDate,t)||o((function(e){return"endDate"===e?"startDate":"endDate"})))},captionLayout:"dropdown-buttons",fromDate:e.minDate,toDate:e.maxDate,modifiersClassNames:{selected:"my-selected",today:"my-today"},defaultMonth:e.startDate})),a.createElement("div",{className:"pb-3 px-3 text-end"},a.createElement("button",{className:"btn btn-outline-dark",onClick:e.onClickApply},y("apply"))))}const N={inputContainer:"YQJPT",clearButton:"w2hAw",inputBtnContainer:"iSXkk",input:"IBR6Q"};function S(e){return a.createElement(s.Z.Toggle,{as:"div",id:"date-range-dropdown",className:"no-caret ".concat(e.hideRange?"":N.inputContainer)},a.createElement("input",{className:"form-control cursor-pointer border-dark ".concat(N.input),value:e.value,onChange:function(){},onKeyDown:function(e){return e.preventDefault()},autoComplete:"off"}),a.createElement("div",{className:N.inputBtnContainer},a.createElement("div",{className:"d-inline-block cursor-pointer"},a.createElement(f.x,{svgName:p.vn.Calendar,size:f.S.Standard}))))}var O=n(36532);function I(e){return d.O.isAfter(e,new Date,"day")}function k(e){return I(e.startDate)}const w={containerWithDynamicRanges:"pvYdJ",selectedDateRange:"JU7bd",rangeList:"DBlzu"};var A=r.T.encloseNamespace("shared.presetDateRangeSelector");function C(e){var t=e.range.name===e.selectedRangeName,n=k(e.range)||e.range.disabled,r=function(){return a.createElement("button",{className:(l=t,o="btn btn-link d-flex align-items-center py-1 px-0 text-decoration-none",l?o+" fw-bold text-info ".concat(w.selectedDateRange):o+" text-body"),onClick:function(){return e.onClick(e.range)},disabled:n},t&&a.createElement(f.x,{svgName:p.vn.Check}),a.createElement("span",{className:"".concat(n?"text-secondary":""," ").concat(e.isDynamic?"fw-bold":"")},e.range.name),!!e.isDynamic&&a.createElement(a.Fragment,null," ",a.createElement("span",{className:"text-secondary"},(r=e.range,"(".concat(d.O.format(r.startDate,"ddd, D MMM"))+" - ".concat(d.O.format(r.endDate,"ddd, D MMM"),")")))));var r,l,o};return e.range.tooltip?a.createElement(O.u,{title:e.range.tooltip,placement:"left",spanHack:!0,spanHackClassName:"justify-content-start"},a.createElement(r,null)):a.createElement(r,null)}function R(e){var t;function n(t){var n=function(e){if(!k(e))return I(e.endDate)?Object.assign(Object.assign({},e),{endDate:new Date}):e}(t);n&&e.setDateRange(n)}var r=!!(null===(t=e.dynamicDateRanges)||void 0===t?void 0:t.length);return a.createElement("div",{className:r?"py-3 ".concat(w.containerWithDynamicRanges):"py-2"},a.createElement("div",{className:"row px-2"},a.createElement("div",{className:r?"col-4 pe-2 border-end":"col-12"},a.createElement("ul",{className:"list-unstyled ".concat(w.rangeList)},e.genericDateRanges.map((function(t,r){return a.createElement("li",{key:r},a.createElement(C,{range:t,onClick:n,selectedRangeName:e.selectedRangeName}))})))),r&&a.createElement("div",{className:"col-8 ps-2"},a.createElement("ul",{className:"list-unstyled ".concat(w.rangeList)},e.dynamicDateRanges.map((function(t,r){return a.createElement("li",{key:r},a.createElement(C,{range:t,onClick:n,selectedRangeName:e.selectedRangeName,isDynamic:!0}))}))))),a.createElement("div",{className:"row px-2"},a.createElement("div",{className:"col-12"},a.createElement("div",{className:r?"pe-2 text-end":w.rangeList},a.createElement("button",{className:"btn btn-link p-0",onClick:e.showCustomRangeSelector},a.createElement("strong",null,A("customRange")))))))}function T(e){return e.getFullYear()===(new Date).getFullYear()}function L(e,t){var n=t?"ddd, D MMM YYYY":"ddd, D MMM";return d.O.format(e,n)}function M(e,t,n){var a=(0,c.W5)(e,t.name)||t;if(!a.startDate||!a.endDate)return"";var r=!T(a.startDate)||!T(a.endDate),l=!n&&"".concat(L(a.startDate,r)," - ").concat(L(a.endDate,r));return a.name?"".concat(a.name).concat(n?"":" (".concat(l,")")):l}function x(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var a,r,l,o,c=[],i=!0,s=!1;try{if(l=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;i=!1}else for(;!(i=(a=l.call(n)).done)&&(c.push(a.value),c.length!==t);i=!0);}catch(e){s=!0,r=e}finally{try{if(!i&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw r}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return j(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?j(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function j(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}function H(e){var t=(0,c.NG)(e.dateRangePresets,e.dateRangeQueryParams),n=x(a.useState(t),2),r=n[0],l=n[1],o=x(a.useState("none"),2),i=o[0],m=o[1];function d(e){m("none"),u.e.updateParams((0,c.eO)(e),{merge:!0,keysToRemove:["rangeName"]})}return a.useEffect((function(){l(t)}),[!!t]),t?a.createElement("div",{className:"position-relative"},a.createElement(s.Z,{show:"preset"===i,onToggle:function(e){return m(e?"preset":"none")},className:"custom"===i?"d-none":""},a.createElement(S,{value:M(e.dateRangePresets,t,e.hideRange),hideRange:e.hideRange}),a.createElement(s.Z.Menu,{className:"p-0",align:"end"},a.createElement(R,{genericDateRanges:e.dateRangePresets,setDateRange:function(e){l(e),d(e)},showCustomRangeSelector:function(){return m("custom")},selectedRangeName:t.name}))),a.createElement(s.Z,{show:"custom"===i,onToggle:function(){m("none"),d(r)},className:"custom"===i?"":"d-none"},a.createElement(S,{value:M(e.dateRangePresets,t)}),a.createElement(s.Z.Menu,{className:"p-0",align:"end"},a.createElement(D,{startDate:null==r?void 0:r.startDate,endDate:null==r?void 0:r.endDate,setDateRange:l,maxDate:(0,c.nG)(),minDate:(0,c.zn)(),onClickApply:function(){return d(r)},close:function(){return m("none")}})))):a.createElement(a.Fragment,null)}var G=n(86509),P=n(49935),Y=n(38502),_=n(38143),F=n(14070),V=n(97291),Z=n(22490),U=n(20354),W=n(75896),B=n(93129);function z(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}var $=r.T.encloseNamespace("insights.hooks");function J(e){return function(e){if(Array.isArray(e))return Q(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||K(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function K(e,t){if(e){if("string"==typeof e)return Q(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Q(e,t):void 0}}function Q(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}var q=r.T.encloseNamespace("shared.insightsHeaderView");function X(e){var t,n,r,s,u,m,d,f,p,g,v,b,y,h,E,D=(h=(0,o.D)(_.g.ANONYMISE_USERS,!1,{storage:l.Z1.LocalStorage}),E=2,function(e){if(Array.isArray(e))return e}(h)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var a,r,l,o,c=[],i=!0,s=!1;try{if(l=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;i=!1}else for(;!(i=(a=l.call(n)).done)&&(c.push(a.value),c.length!==t);i=!0);}catch(e){s=!0,r=e}finally{try{if(!i&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw r}}return c}}(h,E)||K(h,E)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),N=D[0],S=D[1],O=(t=e.audienceAppLinkParams,m=function(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var a,r,l,o,c=[],i=!0,s=!1;try{if(l=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;i=!1}else for(;!(i=(a=l.call(n)).done)&&(c.push(a.value),c.length!==t);i=!0);}catch(e){s=!0,r=e}finally{try{if(!i&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw r}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return z(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?z(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(a.useState([]),2),d=m[0],f=m[1],p=1!==(null===(n=t.classrooms)||void 0===n?void 0:n.length)||(null===(r=t.classroomGroups)||void 0===r?void 0:r.length)?null:W.m.first(t.classrooms),g=U.a.useBasicFetch(p&&B.F.classroom(p)),v=1!==(null===(s=t.classroomGroups)||void 0===s?void 0:s.length)||(null===(u=t.classrooms)||void 0===u?void 0:u.length)?null:W.m.first(t.classroomGroups),b=U.a.useBasicFetch(v&&B.F.classroomGroup(v)),y=JSON.stringify(t),a.useEffect((function(){var e,n,a,r;(null===(e=t.classrooms)||void 0===e?void 0:e.length)||(null===(n=t.classroomGroups)||void 0===n?void 0:n.length)?(null===(a=t.classrooms)||void 0===a?void 0:a.length)>1||(null===(r=t.classroomGroups)||void 0===r?void 0:r.length)>1?f([{name:$("classrooms"),appLink:{application:V.O.CLASSROOMS,action:F.e.Classrooms.HOME}}]):g.data?f([{name:$("classrooms"),appLink:{application:V.O.CLASSROOMS,action:F.e.Classrooms.HOME}},{name:g.data.name,appLink:{application:V.O.CLASSROOMS,action:F.e.Classrooms.CLASSROOM_STUDENTS,args:[g.data.id]}}]):b.data&&f([{name:$("classrooms"),appLink:{application:V.O.CLASSROOMS,action:F.e.Classrooms.HOME}},{name:b.data.classroom.name,appLink:{application:V.O.CLASSROOMS,action:F.e.Classrooms.CLASSROOM_STUDENTS,args:[b.data.classroom.id]}}]):f([{name:$("insights"),appLink:{application:V.O.INSIGHTS,action:F.e.Insights.HOME}}])}),[y,g.data,b.data]),d);return a.createElement(a.Fragment,null,a.createElement("section",{className:"mb-3"},a.createElement("div",{className:"d-flex justify-content-between mb-2"},a.createElement("h1",{className:"mb-0"},e.video.name),a.createElement("div",{className:"d-flex gap-2"},a.createElement(i.B,null),a.createElement(H,{dateRangeQueryParams:e.dateRangeAppLinkParams,dateRangePresets:(0,c.Hb)(),hideRange:!0}),a.createElement(G.m,{dropdownToggleClassName:"btn btn-outline-dark",actions:[{label:q("generateReport"),appLink:{application:V.O.INSIGHTS,action:F.e.Insights.INTERACTIVE_GENERATE_REPORT,args:[e.video.id]}},{label:q("goTo"),appLink:Z.W.getAppLink(e.video)},{label:q(N?"showNames":"hideNames"),onClick:function(){return S(!N)}}]}))),O.length?a.createElement(P.Oo,{breadcrumbs:[].concat(J(O),[{name:e.video.name,active:!0}])}):a.createElement(P.b2,null),a.createElement("div",{className:"mb-3"}),a.createElement("div",null,a.createElement(Y.r,{tabs:e.tabs}))))}},62712:(e,t,n)=>{n.d(t,{Z:()=>a});const a={circleContainer:"p8Vgz",backgroundCircle:"asGGE",circleSuccess:"PXLNj",circleWarning:"ZckRN",circleDanger:"slBRg",lgCircleContainer:"N8KCI",pendingCircle:"DKrcq",centredPercentageText:"tpmLR"}},87432:(e,t,n)=>{n.d(t,{Z:()=>a});const a={pillTabSelector:"Hdi6o",tab:"RvNxr",minWidth:"GHSz9",radiusSmall:"VhJJa",tabLink:"WFyvo"}}}]);
2
- //# sourceMappingURL=839-889090dc50-lite.chunk.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scripts/839-889090dc50-lite.chunk.js","mappings":"6JA0BM,SAAUA,EAAkBC,EAAYC,GAC5C,OAAKA,GAGE,QAxBT,SAA8BD,GAS5B,IAAME,GAAQ,GAAD,OAAIF,EAAKG,IAAE,OAAGC,KAAKC,OAAO,IAAIC,MAAQC,aAAe,IAElE,MAAO,CACLC,aAAc,CAAE,KAAQ,MACxBC,UAAW,IACXC,OAAQ,EACRC,MAAO,UACPT,KAAAA,EAEJ,CAM8BU,CAAqBZ,IAFxC,gBAAuBA,EAGlC,C,iwBC7BO,IAAMa,EAAoB,SAACC,GAChC,IAAMC,EAAmB,GACnBC,EAAoB,GAU1B,OARIF,EAAYG,OACdF,EAAOG,KAAI,MAAXH,EAAM,EAASD,EAAYG,QAEzBH,EAAYK,YACdH,EAAQE,KAAI,MAAZF,EAAO,EAASF,EAAYK,aAE1BL,EAAYM,iBACdJ,EAAQE,KAAI,MAAZF,EAAO,EAASF,EAAYM,kBACvB,CACLL,OAAAA,EACAC,QAAAA,EAEJ,C,6HCTMK,EAAY,qBADA,yBAGZ,SAAUC,EAA+BC,GAC7C,IAAMC,EAAM,qBAA4BD,GACxC,OAAO,WAAkBC,EAAK,sBAChC,CAEM,SAAUC,IACd,OAAO,IAAInB,KAAK,KAAM,EAAG,EAC3B,CAEM,SAAUoB,IACd,OAAO,IAAIpB,IACb,CAEM,SAAUqB,EAAoBC,GAClC,OAAOA,EAAkBC,MAAK,SAAAC,GAAK,QAAMA,EAAK,OAAQ,GACxD,CAEM,SAAUC,EAAqBH,EAAgCI,GACnE,GAAKA,EAKL,OAFgBJ,EAEDC,MAAK,SAAAI,GAAC,OAAIA,EAAEC,OAASF,CAAS,GAC/C,CA6CM,SAAUG,IACd,IAAMC,EAAUX,IACVY,GAAe,IAAI/B,MAAQgC,cAE3BC,EAAoBF,IAAgBD,EAAQE,cAElD,MAAO,CACL,CACEJ,KAAMb,EAAU,SAChBmB,UAAW,IAAIlC,KACfmC,QAAS,IAAInC,MAEf,CACE4B,KAAMb,EAAU,aAChBmB,UAAW,IAAIlC,KAAK+B,GAAa,IAAI/B,MAAOoC,WAAY,GACxDD,QAAS,IAAInC,MAEf,CACE4B,KAAMb,EAAU,mBAChBmB,UAAW,IAAIlC,KAAK+B,GAAa,IAAI/B,MAAOoC,WAAa,EAAG,GAC5DD,QAAS,IAAInC,MAEf,CACE4B,KAAMb,EAAU,iBAChBmB,UAAW,IAAIlC,KAAK+B,GAAa,IAAI/B,MAAOoC,WAAa,EAAG,GAC5DD,QAAS,IAAInC,MAEf,CACE4B,KAAMb,EAAU,YAChBmB,UAAW,IAAIlC,KAAK+B,EAAa,EAAG,GACpCI,QAAS,IAAInC,MAEf,CACE4B,KAAMb,EAAU,YAChBmB,UAAW,IAAIlC,KAAK+B,EAAc,EAAG,EAAG,GACxCI,QAAS,IAAInC,KAAK+B,EAAa,EAAG,GAClCM,SAAUJ,EACVK,QAASL,EAAoBlB,EAAU,oBAAsB,IAE/D,CACEa,KAAMb,EAAU,WAChBmB,UAAW,aAAoB,IAAIlC,KAAQ,EAAG,SAC9CmC,QAAS,IAAInC,KACbuC,SAAS,GAGf,CAEM,SAAUC,EAAqBvB,GACnC,OAAO,WAAkBA,EAAM,aACjC,CAEM,SAAUwB,EAAoBC,GAClC,OAAIA,EAAUd,KACL,CAAEF,UAAWgB,EAAUd,MAEzB,CACLe,KAAMH,EAAqBE,EAAUR,WACrCU,GAAIJ,EAAqBE,EAAUP,SAEvC,CAEM,SAAUU,EACdC,EACAC,GAEA,IAAQH,EAAwBG,EAAxBH,GAAID,EAAoBI,EAApBJ,KAAMjB,EAAcqB,EAAdrB,UAEZsB,EAAcvB,EAAqBqB,EAAkBpB,GAE3D,GAAIsB,EACF,OAAKL,GAASC,OAMd,iBACEH,EAAoBO,GACpB,CAAEC,SAAS,EAAMC,OAAO,EAAMC,aAAc,CAAE,OAAQ,QAP/CH,EAYX,IAAMI,EAAmB/B,EAAoByB,GAK7C,GAAKH,GAASC,GAAO,YAAmBD,IAAU,YAAmBC,GAArE,CAQA,IAAIS,GAAwB,EAExBnB,EAAY,qBAA4B,IAAIlC,KAAK2C,IACjDR,EAAU,qBAA4B,IAAInC,KAAK4C,IAE/C,aAAoBV,EAAWf,IAAc,SAC/Ce,EAAYf,IACZkC,GAAwB,GAGtB,YAAmBlB,EAASf,IAAc,SAC5Ce,EAAUf,IACViC,GAAwB,GAGtB,YAAmBnB,EAAWC,KAChCD,EAAYkB,EAAiBlB,UAC7BC,EAAUiB,EAAiBjB,QAC3BkB,GAAwB,GAG1B,IAAMX,EAAuB,CAAER,UAAAA,EAAWC,QAAAA,EAASP,KAAMyB,EAAwB3B,EAAY,IAE7F,GAAI2B,EACF,OAAOX,EAKT,iBAA4BD,EAAoBC,GAAY,CAAEO,SAAS,EAAMC,OAAO,EAAMC,aAAc,CAAC,cA/BxG,MALC,iBACEV,EAAoBW,GACpB,CAAEH,SAAS,EAAMC,OAAO,EAAMC,aAAc,CAAC,cAmCnD,CAEM,SAAUG,EACdhC,EACAiC,GAEA,IAAMC,EAAe,SAACvC,GAAY,OAAKD,EAA+B,YAAmBC,EAAM,OAAO,EAChGwC,EAAa,SAACxC,GAAY,OAAKD,EAA+B,UAAiBC,EAAM,OAAO,EAE5F+B,EAAcvB,EAAqBH,EAAmBiC,EAAa7B,WAMzE,GAAIsB,EACF,MAAO,CACLU,MAAOF,EAAahB,EAAqBQ,EAAYd,YACrDyB,IAAKF,EAAWjB,EAAqBQ,EAAYb,WAMrD,GAAIoB,EAAaZ,MAAQY,EAAaX,GACpC,MAAO,CACLc,MAAOF,EAAaD,EAAaZ,MACjCgB,IAAKF,EAAWF,EAAaX,KAMjC,IAAMgB,EAAevC,EAAoBC,GAEzC,MAAO,CACLoC,MAAOF,EAAahB,EAAqBoB,EAAa1B,YACtDyB,IAAKF,EAAWjB,EAAqBoB,EAAazB,UAEtD,C,uoCCzOA,IACMpB,EAAY,qBADA,8BAiBL8C,EAAiB,cAAiB,SAC7CC,EACAC,GAEA,MAAgED,EAAxDE,WAAcpC,EAAI,EAAJA,KAAMqC,EAAO,EAAPA,QAASC,EAAM,EAANA,OAAUC,EAAiBL,EAAjBK,aAE3CC,EAAcxC,EACdyC,EAAgB,KASpB,OAPID,EAAYhE,OAtBS,KAuBvBgE,EAAcxC,EAAK0C,MAAM,EAvBF,IAuB2B,MAGlDD,EAAQzC,GAIR,sBACE2C,UAAS,yBAAoBL,EAAS,UAAY,IAClDG,MAAOA,GAENH,EACG,8BAASE,GACT,gBAAC,IAAO,CAACH,QAASA,EAASF,IAAKA,GAC/BI,GAAgB,gBAAC,IAAY,CAACK,QAAS,iBAA0BC,KAAM,EAAAC,EAAA,QACxE,wBAAMH,UAAWJ,EAAe,OAAS,IAAKC,IAKxD,IAMaO,EAAc,SAAH,GAAyC,IAAnCC,EAAW,EAAXA,YACtBC,GAAW,OAAc,QAEzBzE,GAASwE,aAAW,EAAXA,EAAaxE,SAAU,EAEiB,IAArB,YAAe,GAAM,GAA/C0E,EAAQ,KAAEC,EAAW,KACgC,IAArB,YAAe,GAAM,GAArDC,EAAW,KAAEC,EAAc,KAC7BC,EAAY,WAsBlB,GApBA,aAAgB,W,MACRC,EAAiF,QAA/D,EAAAP,aAAW,EAAXA,EAAaQ,QAAO,SAACC,EAAMC,GAAI,OAAKD,EAAOC,EAAK1D,KAAKxB,MAAM,GAAE,UAAE,QAAI,EAEvFA,EAAS,GAAK+E,EA9DW,IA+D3BJ,GAAY,EAChB,GAAG,CAACH,aAAW,EAAXA,EAAaxE,SAKjB,mBAAsB,W,MAChB4E,IACe,QAAjB,EAAAE,EAAUK,eAAO,SAAEC,QACvB,GAAG,CAAEN,EAAUK,QAASP,KAOnB5E,GAAWyE,GAAYzE,EAAS,EACnC,OAAO,iCAET,GAAIyE,EACF,OACE,oCAAgB,cACd,sBAAIN,UAAU,sBACZ,gBAACV,EAAc,CAACG,WAAYY,EAAYxE,EAAS,GAAI+D,cAAY,MAKzE,IAAMsB,EAAQ,gBAAC5B,EAAc,CAACG,WAAYY,EAAY,KAChDc,EAAStF,EAAS,EAAI,gBAACyD,EAAc,CAACG,WAAYY,EAAY,KAAS,iCACvEe,EAAavF,EAAS,EAAI,gBAACyD,EAAc,CAACG,WAAYY,EAAYxE,EAAS,KAAS,iCACpFwF,EAAOxF,EAAS,EAAI,gBAACyD,EAAc,CAACG,WAAYY,EAAYxE,EAAS,KAAS,iCAC9EyF,EAAOjB,EAAYN,MAAM,EAAGlE,EAAS,GAE3C,OACE,oCAAgB,cACd,sBAAImE,UAAU,sBACXkB,EACAC,EACAZ,EACC,sBAAIP,UAAU,mBACZ,0BACEA,UAAU,WACVuB,QAhCZ,WACEf,GAAY,GACZE,GAAe,EACjB,EA6BkC,aACVlE,EAAU,WAAS,QAKnC8E,EAAKE,KAAI,SAAC/B,EAAYgC,GAAG,OACvB,gBAACnC,EAAc,CACboC,IAAKD,EACLhC,WAAYA,EACZD,IAAa,IAARiC,EAAYd,EAAY,MAC7B,IAGLS,EACAC,GAIT,EAEaM,EAAqB,QAAW,YAAiD,QAAtCC,SAAAA,OAAQ,IAAG,IAAC,EAGlE,OAFiB,OAAc,QAI3B,uBAAK5B,UAAU,6BAA6BlE,MAAO,CAAE+F,OAAQ,YAAaC,MAAO,UAKnF,oCAAgB,cACd,sBAAI9B,UAAU,sBACX,2BAA4C,CAAE4B,SAAAA,IAAYJ,KAAI,WAAYC,GAAG,IAAZK,EAAK,EAALA,MAAK,OACrE,sBAAIJ,IAAKD,EAAKzB,UAAU,mBACtB,wBAAMA,UAAU,4CAA4ClE,MAAO,CAAEgG,MAAAA,GAASC,wBAAyB,CAAEC,OAAQ,WAC9G,KAKf,G,+CCjHYC,E,gCA3BZ,SAASC,EAAe3C,GACtB,IAAMC,EAAM,eAAkB,SAAC2C,GAC7B,GAAKA,EAAL,CAGA,IAAMC,EAASD,EAAOE,EAAEC,QAAQC,MAC1BC,EAAgB,EAAIjH,KAAKkH,GAAKL,EAC9BM,EAASF,EAAgBjD,EAAMoD,WAAaH,EAElDL,EAAOrG,MAAM8G,gBAAkB,GAAH,OAAMJ,EAAa,YAAIA,GACnDL,EAAOrG,MAAM+G,iBAAmBH,EAAOI,UAP/B,CAQV,GAAG,CAACvD,EAAMoD,aAEV,OACE,2BACE,0BAAQN,GAAG,QAAgB9C,EAAMW,MAAOF,UAAW,yBACjD,QAAUT,EAAMoD,aAChB,0BACEnD,IAAKA,EACL6C,GAAG,QAAgB9C,EAAMW,MACzBF,WAAW,QAAmBT,EAAMoD,WAAYpD,EAAMwD,mBAKhE,CAqBM,SAAUC,EAAoBzD,G,MAC5B0D,GAAoB,QAAqB1D,EAAMoD,YAE/CzC,EAAOX,EAAM2D,SAAWjB,EAA0BkB,YACpD,WACA,WAEEC,EAAQ7D,EAAM8D,cAAe,QAAuBJ,GAE1D,OAAI1D,EAAM2D,SAAWjB,EAA0BqB,UAE3C,wBAAMtD,WAAW,QAA0BiD,IACxCG,GAKL,uBAAKpD,UAAS,4DAAsE,QAAf,EAAAT,EAAMS,iBAAS,QAAI,KACrFT,EAAM2D,SAAWjB,EAA0BsB,aAC1C,wBAAMvD,UAAU,QACboD,GAGL,uBAAKpD,WAAW,QAA4BE,EAAM+C,IAChD,gBAACf,EAAc,CAACS,WAAYM,EAAmB/C,KAAMA,EAAM6C,gBAAiBxD,EAAMwD,kBACjFxD,EAAM2D,SAAWjB,EAA0BkB,aACxC,wBAAMnD,UAAW,2BACdoD,IAMf,EApDA,SAAYnB,GACV,2BACA,yBACA,6BACA,4BACD,CALD,CAAYA,IAAAA,EAAyB,KAerCe,EAAoBQ,aAAe,CACjCN,OAAQjB,EAA0BwB,W,sGCrDxBC,E,sBALNC,EAAe,EACfC,EAAkB,IAClBC,EAAsB,GACtBC,EAAyB,IAUzB,SAAUC,EAAgB7D,GAC9B,IAAM4B,EAAQ5B,IAASwD,EAAmBM,MAAQJ,EAAkBD,EAC9DM,EAAc/D,IAASwD,EAAmBM,MAAQF,EAAyBD,EACjF,MAAO,GAAP,OAAU/B,EAAQ,EAAkB,EAAdmC,EAAe,MACvC,CAEM,SAAUC,EACdvB,GACyD,IAAzDI,EAAA,uDAAmC,IAEnC,OAAIJ,GAAcI,EAAgBoB,KACzB,kBAELxB,GAAcI,EAAgBqB,SACzB,kBAEF,gBACT,CAEM,SAAUC,EACd1B,GACyD,IAAzDI,EAAA,uDAAmC,IAEnC,OAAIJ,GAAcI,EAAgBoB,KACzB,eAELxB,GAAcI,EAAgBqB,SACzB,eAEF,aACT,CAEM,SAAUE,EAA4BpE,EAA0ByC,GACpE,IAAI3C,EAAY,kBAAH,OAAqB,qBAQlC,OANIE,IAASwD,EAAmBM,QAC9BhE,GAAa,IAAJ,OAAQ,wBAEfuE,EAAU5B,KACZ3C,GAAa,IAAJ,OAAQ,oBAEZA,CACT,CAEM,SAAUwE,EAAqB7B,GACnC,IAAI4B,EAAU5B,GAGd,OAAQA,EAAW8B,QAAQ,EAC7B,CAEM,SAAUC,EAAuB/B,GACrC,OAAI4B,EAAU5B,GACL,MAEF,GAAP,OAAUpH,KAAKoJ,MAAmB,IAAbhC,GAAiB,IACxC,CAEM,SAAU4B,EAAU5B,GACxB,MAA6B,iBAAfA,CAChB,EApEA,SAAYe,GACV,gBACA,eACD,CAHD,CAAYA,IAAAA,EAAkB,I,oHCO9B,SAASkB,EAAYrF,GACnB,OACE,kCACKA,EAAMsF,IAAI5E,SACX,uBAAKD,UAAWT,EAAMsF,IAAIxH,KAAO,OAAS,IACxC,gBAAC,IAAY,CAAC4C,QAASV,EAAMsF,IAAI5E,WAIpCV,EAAMsF,IAAIxH,KAEmB,iBAArBkC,EAAMsF,IAAIC,OACjB,uBAAK9E,UAAU,QACb,gBAAC,IAAK,CAAC+E,KAAM,UAAiBC,KAAMzF,EAAMsF,IAAIC,SAKxD,CA8BM,SAAUG,EAAgB1F,G,MAW9B,OACE,uBAAKS,UAA0B,QAAf,EAAAT,EAAMS,iBAAS,QAAI,GAAIR,IAAKD,EAAM2F,cAChD,sBAAIlF,UAAS,qDACwB,oBAAsB,qBACvDT,EAAM4F,aAAe,gBAAqB,GAAE,qBAC5C5F,EAAM6F,cAAa,aAEpB7F,EAAM8F,KAAK7D,KAAI,SAACqD,EAAKS,GACpB,OACE,sBACEtF,UAAS,gCACD,QAAU,YAAI6E,EAAIlF,OAAS,eAAiB,uBAAsB,6BACtEkF,EAAIxH,KAAO,aAAkB,GAAE,YAAIwH,EAAI7E,UAAS,oBAEpD0B,IAAK4D,GAEJT,EAAInF,QACH,gBAAC,IAAO,CACNA,QAASmF,EAAInF,QACb6F,cAAeV,EAAIU,cACnBC,iBAAkBX,EAAIW,iBACtBxF,UAAS,sKAE4C,YAAc,yBAGnE,gBAAC4E,EAAW,CAACC,IAAKA,KAGpB,gBAAC,IAAS,CACR7E,UAAS,sKAE4C,YAAc,wBAEnEuB,QAAS,WAAF,OA5CvB,SAAqBsD,IACfA,EAAIlF,QAAWkF,EAAIY,WAGvBZ,EAAIY,WAEAZ,EAAIU,eAAiBV,EAAIW,kBAC3B,kBAA8BX,EAAIU,cAAeV,EAAIW,kBACzD,CAoC+BE,CAAYb,EAAI,GAE/B,gBAACD,EAAW,CAACC,IAAKA,KAK5B,KAIR,CA5DAI,EAAgBzB,aAAe,CAC7B2B,aAAc,K,mCC5DT,IAAMQ,EAA0C,CACrDxB,KAAM,IACNC,SAAU,G,wICPZ,IAAMwB,EAAyD,CAC7DhE,SAAU,EACViE,SAAU,GACVC,SAAU,KAaCC,EAAuB,CAClCC,uBAAsB,WAAoC,I,EAAnCC,EAAA,uDAAiC,CAAC,EACjDC,EAAO,OAAH,wBACLN,GACAK,GAKL,O,EAAWE,MAAMD,EAAKtE,U,omBAAWJ,KAAI,iBAAO,CAAEM,MAAO,GAAF,OAFhBvG,KAAK6K,IAAI7K,KAAKC,MAAMD,KAAK8K,SAAWH,EAAKJ,UAAWI,EAAKL,UAEd,MAAM,GACtF,E,0FCnBIrJ,EAAY,qBADA,wBAGZ,SAAU8J,EAAqBhL,EAAYqE,EAAgB4G,GAC/D,MAAO,CACL,CACElJ,KAAMb,EAAU,YAChBmD,OAAmB,aAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,4BACRC,KAAM,CAACpL,GACPiL,OAAAA,IAGJ,CACElJ,KAAMb,EAAU,WAChBmD,OAAmB,YAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,2BACRC,KAAM,CAACpL,GACPiL,OAAAA,IAIR,CAEM,SAAUI,EAAoBrL,EAAYqE,EAAgB4G,GAC9D,MAAO,CACL,CACElJ,KAAMb,EAAU,YAChBmD,OAAmB,aAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,2BACRC,KAAM,CAACpL,GACPiL,OAAAA,IAGJ,CACElJ,KAAMb,EAAU,WAChBmD,OAAmB,YAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,0BACRC,KAAM,CAACpL,GACPiL,OAAAA,IAIR,CAEM,SAAUK,EAA2BtL,EAAYqE,EAAgB4G,GACrE,MAAO,CACL,CACElJ,KAAMb,EAAU,YAChBmD,OAAmB,aAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,kCACRC,KAAM,CAACpL,GACPiL,OAAAA,IAGJ,CACElJ,KAAMb,EAAU,WAChBmD,OAAmB,YAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,iCACRC,KAAM,CAACpL,GACPiL,OAAAA,IAGJ,CACElJ,KAAMb,EAAU,aAChBmD,OAAmB,cAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,mCACRC,KAAM,CAACpL,GACPiL,OAAAA,IAGJ,CACElJ,KAAMb,EAAU,WAChBmD,OAAmB,YAAXA,EACRD,QAAS,CACP8G,YAAa,aACbC,OAAQ,iCACRC,KAAM,CAACpL,GACPiL,OAAAA,IAIR,C,wKCrGA,SAAgB,eAAiB,QAAQ,UAAY,S,ggCCerD,IACM/J,EAAYqK,EAAA,mBADA,kCAGZC,EAAwB,EACxBC,EAAsB,aAYtB,SAAUC,EAAwBzH,G,QACwD,IAApD,WAAwC,aAAY,GAAtF0H,EAAY,KAAEC,EAAe,KACrC,EC9BI,SAA2BD,GAC/B,IAAME,EAAoB,WACpBC,EAAkB,WAUxB,OARA,aAAgB,W,QACO,cAAjBH,IACuB,QAAzB,EAAAE,EAAkBnG,eAAO,SAAEC,SAER,YAAjBgG,IACqB,QAAvB,EAAAG,EAAgBpG,eAAO,SAAEC,QAC7B,GAAG,CAACgG,IAEG,CAAEE,EAAmBC,EAC9B,CDiBiDC,CAAiBJ,GAAa,SAArEE,EAAiB,KAAEC,EAAe,KAqB1C,OACE,uBAAKpH,UAAU,kBACb,uBAAKA,UAAU,+CACb,uBAAKA,UAAU,qBACb,gBAACsH,EAAA,EAAY,CAACrH,QAAS,cAEzB,wBAAMD,UAAU,6BACd,uBAAKA,UAAU,qBACb,0BAAQA,UAAW,kBAAwBxD,EAAU,SACrD,yBACEgD,IAAK2H,EACLnH,UAAS,sCAAiC,aAC1CuC,MAA8D,QAAvD,EAAAgF,EAAA,SAAkBhI,EAAM5B,UAAWoJ,UAAoB,QAAI,GAClES,SAAU,WAAO,EACjBC,QAAS,WAAF,OAAQP,EAAgB,YAAY,KAG/C,wBAAMlH,UAAU,QACd,gBAACsH,EAAA,EAAY,CAACrH,QAAS,mBAEzB,uBAAKD,UAAU,qBACb,0BAAQA,UAAW,kBAAwBxD,EAAU,OACrD,yBACEgD,IAAK4H,EACLpH,UAAS,sCAAiC,aAC1CuC,MAA4D,QAArD,EAAAgF,EAAA,SAAkBhI,EAAM3B,QAASmJ,UAAoB,QAAI,GAChES,SAAU,WAAO,EACjBC,QAAS,WAAF,OAAQP,EAAgB,UAAU,MAI/C,uBAAKlH,UAAU,0BACb,gBAACsH,EAAA,EAAY,CAACrH,QAAS,WAAoBsB,QAAShC,EAAMmI,UAG9D,uBAAK1H,UAAU,OACb,gBAAC,KAAS,CACR2H,KAAK,QACLC,eAAgBd,EAChBe,SAAU,CAAEzJ,KAAMmB,EAAM5B,UAAWU,GAAIkB,EAAM3B,SAC7CkK,WA3DR,SAAwBC,GACD,cAAjBd,GACF1H,EAAMyI,aAAa,CACjBrK,UAAYoK,EACZnK,QAAS2J,EAAA,UAAmBQ,EAAKxI,EAAM3B,cAAWqK,EAAY1I,EAAM3B,UAEtEsJ,GAAgB,SAAAgB,GAAC,MAAU,YAANA,EAAkB,YAAc,SAAS,MAE9D3I,EAAMyI,aAAa,CACjBrK,UAAY4J,EAAA,UAAmBhI,EAAM5B,UAAWoK,GAAOA,EAAMxI,EAAM5B,UACnEC,QAAS2J,EAAA,UAAmBhI,EAAM5B,UAAWoK,QAAOE,EAAYF,IAG7DR,EAAA,UAAmBhI,EAAM5B,UAAWoK,IACvCb,GAAgB,SAAAgB,GAAC,MAAU,YAANA,EAAkB,YAAc,SAAS,IAGpE,EA2CQC,cAAc,mBACdC,SAAU7I,EAAMhC,QAChB8K,OAAQ9I,EAAM+I,QACdC,oBAAqB,CACnBV,SAAU,cACVW,MAAO,YAETC,aAAclJ,EAAM5B,aAGxB,uBAAKqC,UAAU,sBACb,0BAAQA,UAAU,uBAAuBuB,QAAShC,EAAMmJ,cACrDlM,EAAU,WAKrB,CEhHA,SAAgB,eAAiB,QAAQ,YAAc,QAAQ,kBAAoB,QAAQ,MAAQ,SCY7F,SAAUmM,EAAepJ,GAC7B,OACE,gBAACqJ,EAAA,SAAe,CAACC,GAAG,MAAMvN,GAAG,sBAAsB0E,UAAS,mBAAeT,EAAMuJ,UAAoC,GAAxB,mBAC3F,yBACE9I,UAAS,kDAA6C,SACtDuC,MAAOhD,EAAMgD,MACbiF,SAAU,WAAO,EACjBuB,UAAW,SAACC,GAAsB,OAAKA,EAAEC,gBAAgB,EACzDC,aAAa,QAEf,uBAAKlJ,UAAW,qBACd,uBAAKA,UAAU,iCACb,gBAACsH,EAAA,EAAY,CACXrH,QAAS,cACTC,KAAMoH,EAAAnH,EAAA,aAMlB,C,eC7BA,SAASgJ,EAAezM,GACtB,OAAO6K,EAAA,UAAmB7K,EAAM,IAAIjB,KAAQ,MAC9C,CAEM,SAAU2N,EAAgBnM,GAC9B,OAAOkM,EAAelM,EAAMU,UAC9B,CCTA,SAAgB,2BAA6B,QAAQ,kBAAoB,QAAQ,UAAY,SCY7F,IACM,EAAYkJ,EAAA,mBADA,kCAmBlB,SAASwC,EAAc9J,GACrB,IAAMsI,EAAWtI,EAAMtC,MAAMI,OAASkC,EAAM+J,kBACtCC,EAAaH,EAAgB7J,EAAMtC,QAAUsC,EAAMtC,MAAMa,SAEzD0L,EAAkB,WAAH,OACnB,0BAAQxJ,WArBgByJ,EAqBc5B,EApBlC6B,EAAkB,wEAEpBD,EACKC,EAAkB,sBAAH,OAAyB,qBAE1CA,EAAkB,cAe0BnI,QAAS,WAAF,OAAQhC,EAAMgC,QAAQhC,EAAMtC,MAAM,EAAEa,SAAUyL,GACnG1B,GAAY,gBAACP,EAAA,EAAY,CAACrH,QAAS,aACpC,wBAAMD,UAAS,UAAKuJ,EAAa,iBAAmB,GAAE,YAAIhK,EAAMoK,UAAY,UAAY,KACrFpK,EAAMtC,MAAMI,QAEZkC,EAAMoK,WACP,oCAEE,wBAAM3J,UAAU,mBFjCc/C,EEiC4BsC,EAAMtC,MFhCjE,WAAIsK,EAAA,SAAkBtK,EAAMU,UAAW,eAAa,aACnD4J,EAAA,SAAkBtK,EAAMW,QAAS,cAAa,SAFlD,IAAkCX,EEIZwM,EACpBC,CA+BK,EAGX,OAAKnK,EAAMtC,MAAMc,QAIf,gBAAC6L,EAAA,EAAO,CACN9J,MAAOP,EAAMtC,MAAMc,QACnB8L,UAAU,OACVC,UAAQ,EACRC,kBAAkB,yBAElB,gBAACP,EAAe,OATX,gBAACA,EAAe,KAY3B,CAWM,SAAUQ,EAAwBzK,G,MACtC,SAAS0K,EAAahN,GACpB,IAAMiN,EF5DJ,SAAwBjN,GAC5B,IAAImM,EAAgBnM,GAGpB,OAAIkM,EAAelM,EAAMW,SAChB,OAAP,wBACKX,GAAK,CACRW,QAAS,IAAInC,OAGVwB,CACT,CEiD2BkN,CAAclN,GAEhCiN,GAGL3K,EAAMyI,aAAakC,EACrB,CAEA,IAAME,KAAgD,QAAvB,EAAA7K,EAAM8K,yBAAiB,eAAExO,QAExD,OACE,uBAAKmE,UAAWoK,EAAuB,QAAH,OAAW,8BAAsC,QACnF,uBAAKpK,UAAU,YACb,uBAAKA,UAAWoK,EAAuB,wBAA0B,UAC/D,sBAAIpK,UAAS,wBAAmB,cAC7BT,EAAM+K,kBAAkB9I,KAAI,SAACvE,EAAOwE,GAAG,OACtC,sBAAIC,IAAKD,GACP,gBAAC4H,EAAa,CACZpM,MAAOA,EACPsE,QAAS0I,EACTX,kBAAmB/J,EAAM+J,oBAExB,MAIVc,GACC,uBAAKpK,UAAU,cACb,sBAAIA,UAAS,wBAAmB,cAC7BT,EAAM8K,kBAAkB7I,KAAI,SAACvE,EAAOwE,GAAG,OACtC,sBAAIC,IAAKD,GACP,gBAAC4H,EAAa,CACZpM,MAAOA,EACPsE,QAAS0I,EACTX,kBAAmB/J,EAAM+J,kBACzBK,WAAS,IAER,OAMf,uBAAK3J,UAAU,YACb,uBAAKA,UAAU,UACb,uBAAKA,UAAWoK,EAAuB,gBAAkB,aACvD,0BAAQpK,UAAU,mBAAmBuB,QAAShC,EAAMgL,yBAClD,8BAAS,EAAU,oBAOjC,CC7HA,SAASC,EAAW9N,GAClB,OAAOA,EAAKe,iBAAmB,IAAIhC,MAAQgC,aAC7C,CAEA,SAASgN,EAAW/N,EAAYgO,GAC9B,IAAMC,EAASD,EACX,kBACA,aAEJ,OAAOnD,EAAA,SAAkB7K,EAAMiO,EACjC,CAEM,SAAUC,EAAcC,EAA8BC,EAAuBhC,GACjF,IAEMiC,GAFc,QAAqBF,EAAiBC,EAAWzN,OAEnCyN,EAElC,IAAKC,EAAWpN,YAAcoN,EAAWnN,QACvC,MAAO,GAET,IAAM8M,GAAYF,EAAWO,EAAWpN,aAAe6M,EAAWO,EAAWnN,SAEvE2E,GAASuG,GAAa,GAAJ,OAAO2B,EAAWM,EAAWpN,UAAW+M,GAAS,cAAMD,EAAWM,EAAWnN,QAAS8M,IAE9G,OAAKK,EAAW1N,KAGT,GAAP,OAAU0N,EAAW1N,MAAI,OAAIyL,EAA4B,GAAhB,KAAH,OAAQvG,EAAK,MAF1CA,CAGX,C,ggCCVM,SAAUyI,EAAsBzL,GACpC,IAAM0L,GAAsB,QAA+B1L,EAAMhB,iBAAkBgB,EAAMf,sBACK,IAA9C,WAA0ByM,GAAoB,GAAtFC,EAAe,KAAEC,EAAkB,KACsC,IAArC,WAA8B,QAAO,GAAzEC,EAAa,KAAEC,EAAgB,KAgBvC,SAASC,EAAerO,GACtBoO,EAAiB,QAEjBE,EAAA,gBAA4B,QAAoBtO,GAAQ,CAAE0B,OAAO,EAAMC,aAAc,CAAC,cACxF,CAMA,OAxBA,aAAgB,WACduM,EAAmBF,EACrB,GAAG,GAAGA,IAsBDA,EAUH,uBAAKjL,UAAU,qBACb,gBAAC4I,EAAA,EAAQ,CACP4C,KAAwB,WAAlBJ,EACNK,SAAU,SAAAD,GAAI,OAAIH,EAAiBG,EAAO,SAAW,OAAO,EAC5DxL,UAA6B,WAAlBoL,EAA6B,SAAW,IAEnD,gBAACzC,EAAc,CACbpG,MAAOqI,EAAcrL,EAAMhB,iBAAkB0M,EAAqB1L,EAAMuJ,WACxEA,UAAWvJ,EAAMuJ,YAEnB,gBAACF,EAAA,OAAa,CAAC5I,UAAU,MAAM0L,MAAM,OACnC,gBAAC1B,EAAuB,CACtBM,kBAAmB/K,EAAMhB,iBACzByJ,aA3CV,SAAiC/K,GAC/BkO,EAAmBlO,GACnBqO,EAAerO,EACjB,EAyCUsN,wBAAyB,WAAF,OAAQc,EAAiB,SAAS,EACzD/B,kBAAmB2B,EAAoB5N,SAI7C,gBAACuL,EAAA,EAAQ,CACP4C,KAAwB,WAAlBJ,EACNK,SA9CN,WACEJ,EAAiB,QACjBC,EAAeJ,EACjB,EA4CMlL,UAA6B,WAAlBoL,EAA6B,GAAK,UAE7C,gBAACzC,EAAc,CAACpG,MAAOqI,EAAcrL,EAAMhB,iBAAkB0M,KAC7D,gBAACrC,EAAA,OAAa,CAAC5I,UAAU,MAAM0L,MAAM,OACnC,gBAAC1E,EAAuB,CACtBrJ,UAAWuN,aAAe,EAAfA,EAAiBvN,UAC5BC,QAASsN,aAAe,EAAfA,EAAiBtN,QAC1BoK,aAAcmD,EACd7C,SAAS,UACT/K,SAAS,UACTmL,aAAc,WAAF,OAAQ4C,EAAeJ,EAAgB,EACnDxD,MAAO,WAAF,OAAQ2D,EAAiB,OAAO,OA1CtC,gCAgDX,C,wNCxFA,IACM,EAAYxE,EAAA,mBADA,kB,iuBCSlB,IACM,EAAYA,EAAA,mBADA,6BAUZ,SAAU8E,EAAmBpM,GACjC,IDjBsCgH,E,QACkC,EAAhElG,EAAauL,EAEfC,EAGAC,EACAC,EAGAC,EAIAC,E,ICOL,G,GAJ6C,OAC5CC,EAAA,mBACA,EACA,CAAEC,QAAS,oB,EACZ,E,unBAJOC,EAAc,KAAEC,EAAiB,KAMnCC,GDvBgC/F,ECuBehH,EAAMgN,sBDtBa,E,w5BAAA,CAAhC,WAA6B,IAAG,GAAhElM,EAAW,KAAEuL,EAAc,KAE7BC,EAA4C,KAAb,QAAjB,EAAAtF,EAAOjK,kBAAU,eAAET,UAAuC,QAAtB,EAAA0K,EAAOhK,uBAAe,eAAEV,QAE5E,KADA2Q,EAAA,QAAkBjG,EAAOjK,YAEvBwP,EAAY,kBAAgCD,GAAeY,EAAA,YAA4BZ,IACvFE,EAAsD,KAAb,QAAtB,EAAAxF,EAAOhK,uBAAe,eAAEV,UAAkC,QAAjB,EAAA0K,EAAOjK,kBAAU,eAAET,QAEjF,KADA2Q,EAAA,QAAkBjG,EAAOhK,iBAEvByP,EAAiB,kBACrBD,GAAoBU,EAAA,iBAAiCV,IAGjDE,EAAYS,KAAKC,UAAUpG,GAEjC,aAAgB,W,aACQ,QAAjB,EAAAA,EAAOjK,kBAAU,eAAET,UAAiC,QAAtB,EAAA0K,EAAOhK,uBAAe,eAAEV,SActC,QAAjB,EAAA0K,EAAOjK,kBAAU,eAAET,QAAS,IAA2B,QAAtB,EAAA0K,EAAOhK,uBAAe,eAAEV,QAAS,EACpE+P,EAAe,CACb,CACEvO,KAAM,EAAU,cAChBqC,QAAS,CACP8G,YAAa,eACbC,OAAQ,wBAOZqF,EAAU9G,KACZ4G,EAAe,CACb,CACEvO,KAAM,EAAU,cAChBqC,QAAS,CACP8G,YAAa,eACbC,OAAQ,sBAGZ,CACEpJ,KAAMyO,EAAU9G,KAAK3H,KACrBqC,QAAS,CACP8G,YAAa,eACbC,OAAQ,kCACRC,KAAM,CAACoF,EAAU9G,KAAK1J,QAO1B0Q,EAAehH,MACjB4G,EAAe,CACb,CACEvO,KAAM,EAAU,cAChBqC,QAAS,CACP8G,YAAa,eACbC,OAAQ,sBAGZ,CACEpJ,KAAM2O,EAAehH,KAAK8G,UAAUzO,KACpCqC,QAAS,CACP8G,YAAa,eACbC,OAAQ,kCACRC,KAAM,CAACsF,EAAehH,KAAK8G,UAAUxQ,QA7D3CsQ,EAAe,CACb,CACEvO,KAAM,EAAU,YAChBqC,QAAS,CACP8G,YAAa,aACbC,OAAQ,qBA8DlB,GAAG,CAAEwF,EAAWH,EAAU9G,KAAMgH,EAAehH,OAExC3E,GCpDP,OACE,gCACE,2BAASL,UAAU,QACjB,uBAAKA,UAAU,uCACb,sBAAIA,UAAU,QAAQT,EAAMqN,MAAMvP,MAClC,uBAAK2C,UAAU,gBACb,gBAAC6M,EAAA,EAAkB,MACnB,gBAAC7B,EAAqB,CACpBxM,qBAAsBe,EAAMuN,uBAC5BvO,kBAAkB,UAClBuK,WAAS,IACX,gBAACiE,EAAA,EAAe,CACdC,wBAAwB,uBACxBC,QAAS,CACP,CACE7J,MAAO,EAAU,kBACjB1D,QAAS,CACP8G,YAAa,aACbC,OAAQ,yCACRC,KAAM,CAACnH,EAAMqN,MAAMtR,MAGvB,CACE8H,MAAO,EAAU,QACjB1D,QAASwN,EAAA,aAA8B3N,EAAMqN,QAG/C,CACExJ,MAAO,EAAUgJ,EAAiB,YAAc,aAChD7K,QAAS,WAAF,OAAQ8K,GAAmBD,EAAe,QAM1DE,EAAqBzQ,OAAS,gBAACuE,EAAA,GAAW,CAACC,YA5CzC,GAAP,SACKiM,GAAoB,CACvB,CACEjP,KAAMkC,EAAMqN,MAAMvP,KAClBsC,QAAQ,OAwCwE,gBAAC,KAAkB,MACnG,uBAAKK,UAAU,SAEf,2BACE,gBAACiF,EAAA,EAAe,CAACI,KAAM9F,EAAM8F,SAKvC,C,mCC/FA,SAAgB,gBAAkB,QAAQ,iBAAmB,QAAQ,cAAgB,QAAQ,cAAgB,QAAQ,aAAe,QAAQ,kBAAoB,QAAQ,cAAgB,QAAQ,sBAAwB,Q,mCCAxN,SAAgB,gBAAkB,QAAQ,IAAM,QAAQ,SAAW,QAAQ,YAAc,QAAQ,QAAU,Q","sources":["file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AudienceUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/components/breadcrumbs/Breadcrumbs.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicator.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicatorUtils.ts","file:///app/packages/libs/shared/src/components/pill-tab-selector/PillTabSelector.tsx","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/utils/PartialLoadingHelper.ts","file:///app/packages/projects/lite/src/apps/insights/utils/InsightsAppLinkUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/custom-date-range-selector/custom-date-range-selector.scss","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/custom-date-range-selector/CustomDateRangeSelector.tsx","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/custom-date-range-selector/CustomDateRangeSelectorHooks.ts","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/date-range-input/date-range-input.scss","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/date-range-input/DateRangeInput.tsx","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/preset-date-range-selector/PresetDateRangeSelectorUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/preset-date-range-selector/preset-date-range-selector.scss","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/components/preset-date-range-selector/PresetDateRangeSelector.tsx","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/DateRangeSelectorUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/date-range-selector/DateRangeSelectorView.tsx","file:///app/packages/projects/lite/src/apps/insights/hooks/useClassroomBreadcrumbs.ts","file:///app/packages/projects/lite/src/apps/insights/views/header/InsightsHeaderView.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/percentage-indicator.scss","file:///app/packages/libs/shared/src/components/pill-tab-selector/pill-tab-selector.scss"],"sourcesContent":["import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { User } from 'libs/shared/interfaces';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\n\nfunction getUniqueNamesConfig(user: User): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${user.id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: User, shouldAnonymise: boolean): string {\n if (!shouldAnonymise)\n return UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig(user));\n}\n","import { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\n\nexport const getAudienceParams = (queryParams: AudienceQueryParams) => {\n const userId: string[] = [];\n const groupId: string[] = [];\n\n if (queryParams.users)\n userId.push(...queryParams.users);\n\n if (queryParams.classrooms)\n groupId.push(...queryParams.classrooms);\n\n if (queryParams.classroomGroups)\n groupId.push(...queryParams.classroomGroups);\n return {\n userId,\n groupId\n };\n};","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresetss: DateRange[]): DateRange {\n return dateRangePresetss.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = { startDate, endDate, name: initialDateRangeValid ? rangeName : '' };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import * as React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { PartialLoadingHelper } from 'libs/shared/utils/PartialLoadingHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { SvgContainer, SvgContainerSize } from '../svg-container/SvgContainer';\n\nconst namespace = 'shared.breadcrumbComponent';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst COLLAPSE_CHARACTER_COUNT = 64;\nconst MAX_SEGMENT_LENGTH = 48;\n\nexport interface Breadcrumb {\n name: string;\n appLink?: Core.AppLink;\n active?: boolean;\n}\n\ninterface BreadcrumbItemProps {\n breadcrumb: Breadcrumb;\n withBackIcon?: boolean;\n}\n\nexport const BreadcrumbItem = React.forwardRef((\n props: BreadcrumbItemProps,\n ref: React.ForwardedRef<HTMLElement>\n) => {\n const { breadcrumb: { name, appLink, active }, withBackIcon } = props;\n\n let trimmedName = name;\n let title: string = null;\n\n if (trimmedName.length > MAX_SEGMENT_LENGTH) {\n trimmedName = name.slice(0, MAX_SEGMENT_LENGTH) + '...';\n\n // Only setting the title when we trim, because otherwise it's really not needed - Sha\n title = name;\n }\n\n return (\n <li\n className={`breadcrumb-item${active ? ' active' : ''}`}\n title={title}\n >\n {active\n ? <strong>{trimmedName}</strong>\n : <AppLink appLink={appLink} ref={ref}>\n {withBackIcon && <SvgContainer svgName={cvSvgLibrary.ChevronLeft} size={SvgContainerSize.Small} />}\n <span className={withBackIcon ? 'ms-2' : ''}>{trimmedName}</span>\n </AppLink>\n }\n </li>\n );\n});\n\ninterface BreadcrumbsProps {\n breadcrumbs: Breadcrumb[];\n}\n\nexport const Breadcrumbs = ({ breadcrumbs }: BreadcrumbsProps) => {\n const isMobile = useMediaQuery(MediaQueryStrings.XS);\n\n const length = breadcrumbs?.length || 0;\n \n const [ collapse, setCollapse ] = React.useState(false);\n const [ shouldFocus, setShouldFocus ] = React.useState(false);\n const expandRef = React.useRef<HTMLElement>();\n\n React.useEffect(() => {\n const characterLength = breadcrumbs?.reduce((prev, next) => prev + next.name.length, 0) ?? 0;\n\n if (length > 4 && characterLength > COLLAPSE_CHARACTER_COUNT)\n setCollapse(true);\n }, [breadcrumbs?.length]);\n\n /**\n * Focus our first expanded item the first time it appears.\n */\n React.useLayoutEffect(() => {\n if (shouldFocus)\n expandRef.current?.focus();\n }, [ expandRef.current, shouldFocus ]);\n\n function onClickExpand() {\n setCollapse(false);\n setShouldFocus(true);\n }\n\n if (!length || (isMobile && length < 2))\n return <></>;\n\n if (isMobile)\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n <BreadcrumbItem breadcrumb={breadcrumbs[length - 2]} withBackIcon />\n </ol>\n </nav>\n );\n\n const first = <BreadcrumbItem breadcrumb={breadcrumbs[0]} />;\n const second = length > 2 ? <BreadcrumbItem breadcrumb={breadcrumbs[1]} /> : <></>;\n const secondLast = length > 3 ? <BreadcrumbItem breadcrumb={breadcrumbs[length - 2]} /> : <></>;\n const last = length > 1 ? <BreadcrumbItem breadcrumb={breadcrumbs[length - 1]} /> : <></>;\n const rest = breadcrumbs.slice(2, length - 2);\n\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n {first}\n {second}\n {collapse ?\n <li className='breadcrumb-item'>\n <button\n className='btn-link'\n onClick={onClickExpand}\n aria-label={getPhrase('expand')}\n >\n ...\n </button>\n </li> :\n rest.map((breadcrumb, idx) => (\n <BreadcrumbItem\n key={idx}\n breadcrumb={breadcrumb}\n ref={idx === 0 ? expandRef : null}\n />\n ))\n }\n {secondLast}\n {last}\n </ol>\n </nav>\n );\n};\n\nexport const PartialBreadcrumbs = React.memo(function({ numItems = 3 }: { numItems?: number; }) {\n const isMobile = useMediaQuery(MediaQueryStrings.XS);\n\n if (isMobile) {\n return (\n <div className='partial-loading-background' style={{ height: '1.3125rem', width: '6rem' }} />\n );\n }\n\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n {PartialLoadingHelper.getPartialLoadingItems({ numItems }).map(({ width }, idx) => (\n <li key={idx} className='breadcrumb-item'>\n <span className='d-inline-block partial-loading-background' style={{ width }} dangerouslySetInnerHTML={{ __html: '&nbsp' }} />\n </li>\n ))}\n </ol>\n </nav>\n );\n});","import React from 'react';\n\nimport { ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport {\n getCircleClassName,\n getCircleContainerClassName,\n getCircleRadius,\n getColouredLabelClassName,\n getFormattedPercentage,\n getPercentageToFixed,\n isPending,\n ProgressCircleSize\n} from './PercentageIndicatorUtils';\n\nimport styles from './percentage-indicator.scss';\n\ninterface ProgressCircleProps {\n size: ProgressCircleSize;\n scoreThresholds?: ScoreThresholds;\n percentage?: number;\n}\n\nfunction ProgressCircle(props: ProgressCircleProps): JSX.Element {\n const ref = React.useCallback((circle: SVGCircleElement) => {\n if (!circle)\n return;\n \n const radius = circle.r.baseVal.value;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - props.percentage * circumference;\n \n circle.style.strokeDasharray = `${circumference} ${circumference}`;\n circle.style.strokeDashoffset = offset.toString();\n }, [props.percentage]);\n\n return (\n <svg>\n <circle r={getCircleRadius(props.size)} className={styles.backgroundCircle} />\n {!isPending(props.percentage) &&\n <circle\n ref={ref}\n r={getCircleRadius(props.size)}\n className={getCircleClassName(props.percentage, props.scoreThresholds)}\n />\n }\n </svg>\n );\n}\n\nexport enum PercentageIndicatorLayout {\n CircleOnly = 'circle_only',\n LabelOnly = 'label_only',\n LabelBefore = 'label_before',\n LabelInside = 'label_inside'\n}\n\ninterface PercentageIndicatorProps {\n layout: PercentageIndicatorLayout;\n percentage?: number; // Between 0 and 1 or undefined for pending\n className?: string;\n customLabel?: string;\n scoreThresholds?: ScoreThresholds;\n}\n\nPercentageIndicator.defaultProps = {\n layout: PercentageIndicatorLayout.CircleOnly\n};\n\nexport function PercentageIndicator(props: PercentageIndicatorProps): JSX.Element {\n const percentageToFixed = getPercentageToFixed(props.percentage);\n\n const size = props.layout === PercentageIndicatorLayout.LabelInside\n ? ProgressCircleSize.Large\n : ProgressCircleSize.Small;\n\n const label = props.customLabel || getFormattedPercentage(percentageToFixed);\n\n if (props.layout === PercentageIndicatorLayout.LabelOnly)\n return (\n <span className={getColouredLabelClassName(percentageToFixed)}>\n {label}\n </span>\n );\n\n return (\n <div className={`d-flex align-items-center justify-content-between ${props.className ?? ''}`}>\n {props.layout === PercentageIndicatorLayout.LabelBefore &&\n <span className='me-2'>\n {label}\n </span>\n }\n <div className={getCircleContainerClassName(size, percentageToFixed)}>\n <ProgressCircle percentage={percentageToFixed} size={size} scoreThresholds={props.scoreThresholds} />\n {props.layout === PercentageIndicatorLayout.LabelInside &&\n <span className={styles.centredPercentageText}>\n {label}\n </span>\n }\n </div>\n </div>\n );\n}","import { ScoreThresholdDefaults, ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport styles from './percentage-indicator.scss';\n\n/**\n * Values for width and strokeWidth are taken from progress-circle.scss.\n * If either are changed, they must be updated in both places.\n */\nconst CIRCLE_WIDTH = 2; // rem\nconst CIRCLE_WIDTH_LG = 5.8; // rem\nconst CIRCLE_STROKE_WIDTH = 0.2; // rem\nconst CIRCLE_STROKE_WIDTH_LG = 0.36; // rem\n \nexport enum ProgressCircleSize {\n Small = 'small',\n Large = 'large'\n}\n\n/**\n * radius = width / 2 - strokeWidth * 2\n */\nexport function getCircleRadius(size: ProgressCircleSize): string {\n const width = size === ProgressCircleSize.Large ? CIRCLE_WIDTH_LG : CIRCLE_WIDTH;\n const strokeWidth = size === ProgressCircleSize.Large ? CIRCLE_STROKE_WIDTH_LG : CIRCLE_STROKE_WIDTH;\n return `${width / 2 - strokeWidth * 2}rem`;\n}\n \nexport function getCircleClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return styles.circleSuccess;\n \n if (percentage >= scoreThresholds.MODERATE)\n return styles.circleWarning;\n \n return styles.circleDanger;\n}\n \nexport function getColouredLabelClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return 'text-success';\n \n if (percentage >= scoreThresholds.MODERATE)\n return 'text-warning';\n \n return 'text-danger';\n}\n \nexport function getCircleContainerClassName(size: ProgressCircleSize, percentage?: number): string {\n let className = `d-inline-block ${styles.circleContainer}`;\n \n if (size === ProgressCircleSize.Large)\n className += ` ${styles.lgCircleContainer}`;\n\n if (isPending(percentage))\n className += ` ${styles.pendingCircle}`;\n \n return className;\n}\n\nexport function getPercentageToFixed(percentage?: number): number | undefined {\n if (isPending(percentage))\n return;\n \n return +percentage.toFixed(2);\n}\n \nexport function getFormattedPercentage(percentage?: number): string {\n if (isPending(percentage))\n return `--%`;\n\n return `${Math.round(percentage * 100)}%`;\n}\n\nexport function isPending(percentage?: number): boolean {\n return typeof percentage !== 'number';\n}","import React from 'react';\n\nimport { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { AnalyticsOptions } from 'libs/analytics/interfaces';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { Badge, BadgeType } from 'libs/shared/components/badges/Badge';\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\n\nimport { SvgContainer } from '../svg-container/SvgContainer';\n\nimport styles from './pill-tab-selector.scss';\n\ninterface TabContentsProps {\n tab: PillTab;\n}\n\nfunction TabContents(props: TabContentsProps): JSX.Element {\n return (\n <>\n {!!props.tab.svgName && (\n <div className={props.tab.name ? 'pe-1' : ''}>\n <SvgContainer svgName={props.tab.svgName} />\n </div>\n )}\n\n {props.tab.name}\n\n {typeof (props.tab.count) === 'number' && (\n <div className='ps-2'>\n <Badge type={BadgeType.Count} data={props.tab.count} />\n </div>\n )}\n </>\n );\n}\n\nexport interface PillTab {\n name: string;\n active: boolean;\n svgName?: string;\n\n className?: string;\n\n appLink?: Core.AppLink;\n onSelect?: () => void;\n\n analyticsData?: HashObject;\n analyticsOptions?: AnalyticsOptions;\n\n count?: number;\n}\n\ninterface PillTabSelectorProps {\n tabs: PillTab[];\n containerRef?: (el: HTMLElement) => void;\n listClassName?: string;\n className?: string;\n borderRadius?: 'sm' | 'lg'\n}\n\nPillTabSelector.defaultProps = {\n borderRadius: 'lg'\n};\n\nexport function PillTabSelector(props: PillTabSelectorProps): JSX.Element {\n function onSelectTab(tab: PillTab): void {\n if (tab.active || !tab.onSelect)\n return;\n\n tab.onSelect();\n\n if (tab.analyticsData && tab.analyticsOptions)\n AnalyticsHelper.logUserAction(tab.analyticsData, tab.analyticsOptions);\n }\n\n return (\n <nav className={props.className ?? ''} ref={props.containerRef}>\n <ul className={`\n list-unstyled d-inline-block m-0 ${styles.pillTabSelector}\n ${props.borderRadius ? styles.radiusSmall : ''}\n ${props.listClassName}\n `}>\n {props.tabs.map((tab, index) => {\n return (\n <li\n className={`\n p-0 ${styles.tab} ${tab.active ? 'btn btn-dark' : 'btn btn-outline-dark'}\n ${tab.name ? styles.minWidth : ''} ${tab.className}\n `}\n key={index}\n >\n {tab.appLink ? (\n <AppLink\n appLink={tab.appLink}\n analyticsData={tab.analyticsData}\n analyticsOptions={tab.analyticsOptions}\n className={`\n cursor-pointer d-flex align-items-center justify-content-center\n text-decoration-none text-reset px-2 text-nowrap ${styles.tabLink}\n `}\n >\n <TabContents tab={tab} />\n </AppLink>\n ) : (\n <DivButton\n className={`\n cursor-pointer d-flex align-items-center justify-content-center\n text-decoration-none text-reset px-2 text-nowrap ${styles.tabLink}\n `}\n onClick={() => onSelectTab(tab)}\n >\n <TabContents tab={tab} />\n </DivButton>\n )}\n </li>\n );\n })}\n </ul>\n </nav>\n );\n}\n","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};","const DEFAULT_PARTIAL_LOADING_OPTIONS: PartialLoadingOptions = {\n numItems: 5,\n minWidth: 50, // px\n maxWidth: 100 // px\n};\n\nexport interface PartialLoadingOptions {\n numItems?: number;\n minWidth?: number;\n maxWidth?: number;\n}\n\ninterface PartialLoadingItem {\n width: string;\n}\n\nexport const PartialLoadingHelper = {\n getPartialLoadingItems(options: PartialLoadingOptions = {}): PartialLoadingItem[] {\n const opts = {\n ...DEFAULT_PARTIAL_LOADING_OPTIONS,\n ...options\n };\n\n const getRandomFilterWidth = () => Math.max(Math.floor(Math.random() * opts.maxWidth), opts.minWidth);\n\n return [...Array(opts.numItems)].map(() => ({ width: `${getRandomFilterWidth()}px` }));\n }\n};","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nconst namespace = 'shared.insightsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function getInsightsVideoTabs(id: string, active: string, params: HashObject) {\n return [\n {\n name: getPhrase('overview'),\n active: active === 'overview',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.VIDEO_OVERVIEW,\n args: [id],\n params\n }\n },\n {\n name: getPhrase('heatmap'),\n active: active === 'heatmap',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.VIDEO_HEATMAP,\n args: [id],\n params\n }\n }\n ];\n}\n\nexport function getInsightsClipTabs(id: string, active: string, params: HashObject) {\n return [\n {\n name: getPhrase('overview'),\n active: active === 'overview',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.CLIP_OVERVIEW,\n args: [id],\n params\n }\n },\n {\n name: getPhrase('heatmap'),\n active: active === 'heatmap',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.CLIP_HEATMAP,\n args: [id],\n params\n }\n }\n ];\n}\n\nexport function getInsightsInteractiveTabs(id: string, active: string, params: HashObject) {\n return [\n {\n name: getPhrase('overview'),\n active: active === 'overview',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_OVERVIEW,\n args: [id],\n params\n }\n },\n {\n name: getPhrase('results'),\n active: active === 'results',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_RESULTS,\n args: [id],\n params\n }\n },\n {\n name: getPhrase('questions'),\n active: active === 'questions',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_QUESTIONS,\n args: [id],\n params\n }\n },\n {\n name: getPhrase('heatmap'),\n active: active === 'heatmap',\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_HEATMAP,\n args: [id],\n params\n }\n }\n ];\n}","// extracted by mini-css-extract-plugin\nexport default {\"dateInputLabel\":\"CLYvu\",\"dateInput\":\"gnEqJ\"};","import React from 'react';\nimport { DayPicker } from 'react-day-picker';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { useSetInputFocus } from './CustomDateRangeSelectorHooks';\n\nimport './custom-date-range-selector.scss';\nimport './day-picker-styles.scss';\nimport styles from './custom-date-range-selector.scss';\n\nconst namespace = 'shared.customDateRangeSelector';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst NUM_MONTHS_TO_DISPLAY = 2;\nconst DATE_DISPLAY_FORMAT = 'DD/MM/YYYY';\n\ninterface CustomDateRangeSelectorProps {\n startDate: Date | null;\n endDate: Date | null;\n setDateRange: (dateRange: DateRange) => void;\n minDate: Date;\n maxDate: Date;\n onClickApply: () => void;\n close: () => void;\n}\n\nexport function CustomDateRangeSelector(props: CustomDateRangeSelectorProps): JSX.Element {\n const [ focusedInput, setFocusedInput ] = React.useState<'startDate' | 'endDate'>('startDate');\n const [ startDateInputRef, endDateInputRef ] = useSetInputFocus(focusedInput);\n\n function handleDayClick(day: any) {\n if (focusedInput === 'startDate') {\n props.setDateRange({\n startDate: day,\n endDate: DateHelper.isAfter(day, props.endDate) ? undefined : props.endDate\n });\n setFocusedInput(s => s === 'endDate' ? 'startDate' : 'endDate');\n } else {\n props.setDateRange({\n startDate: DateHelper.isAfter(props.startDate, day) ? day : props.startDate,\n endDate: DateHelper.isAfter(props.startDate, day) ? undefined : day\n });\n\n if (!DateHelper.isAfter(props.startDate, day)) {\n setFocusedInput(s => s === 'endDate' ? 'startDate' : 'endDate');\n }\n }\n }\n\n return (\n <div className='d-inline-block'>\n <div className='d-flex align-items-center border-bottom p-3'>\n <div className='me-auto invisible'>\n <SvgContainer svgName={cvSvgLibrary.Close} />\n </div>\n <form className='d-flex align-items-center'>\n <div className='position-relative'>\n <strong className={styles.dateInputLabel}>{getPhrase('from')}</strong>\n <input\n ref={startDateInputRef}\n className={`form-control cursor-pointer ${styles.dateInput}`}\n value={DateHelper.format(props.startDate, DATE_DISPLAY_FORMAT) ?? ''}\n onChange={() => {}}\n onFocus={() => setFocusedInput('startDate')}\n />\n </div>\n <span className='px-3'>\n <SvgContainer svgName={cvSvgLibrary.ArrowRight} />\n </span>\n <div className='position-relative'>\n <strong className={styles.dateInputLabel}>{getPhrase('to')}</strong>\n <input\n ref={endDateInputRef}\n className={`form-control cursor-pointer ${styles.dateInput}`}\n value={DateHelper.format(props.endDate, DATE_DISPLAY_FORMAT) ?? ''}\n onChange={() => {}}\n onFocus={() => setFocusedInput('endDate')}\n />\n </div>\n </form>\n <div className='ms-auto cursor-pointer'>\n <SvgContainer svgName={cvSvgLibrary.Close} onClick={props.close} />\n </div>\n </div>\n <div className='p-3'>\n <DayPicker\n mode='range'\n numberOfMonths={NUM_MONTHS_TO_DISPLAY}\n selected={{ from: props.startDate, to: props.endDate }}\n onDayClick={handleDayClick}\n captionLayout='dropdown-buttons'\n fromDate={props.minDate}\n toDate={props.maxDate}\n modifiersClassNames={{\n selected: 'my-selected',\n today: 'my-today'\n }}\n defaultMonth={props.startDate}\n />\n </div>\n <div className='pb-3 px-3 text-end'>\n <button className='btn btn-outline-dark' onClick={props.onClickApply}>\n {getPhrase('apply')}\n </button>\n </div>\n </div>\n );\n}","import React from 'react';\n\ntype InputRef = React.MutableRefObject<HTMLInputElement>;\n\nexport function useSetInputFocus(focusedInput: 'startDate' | 'endDate'): [InputRef, InputRef] {\n const startDateInputRef = React.useRef<HTMLInputElement>();\n const endDateInputRef = React.useRef<HTMLInputElement>();\n\n React.useEffect(() => {\n if (focusedInput === 'startDate')\n startDateInputRef.current?.focus();\n\n if (focusedInput === 'endDate')\n endDateInputRef.current?.focus();\n }, [focusedInput]);\n\n return [ startDateInputRef, endDateInputRef ];\n}","// extracted by mini-css-extract-plugin\nexport default {\"inputContainer\":\"YQJPT\",\"clearButton\":\"w2hAw\",\"inputBtnContainer\":\"iSXkk\",\"input\":\"IBR6Q\"};","import React from 'react';\nimport { Dropdown } from 'react-bootstrap';\n\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './date-range-input.scss';\n\ninterface DateRangeInputProps {\n value: string;\n hideRange?: boolean;\n}\n\nexport function DateRangeInput(props: DateRangeInputProps): JSX.Element {\n return (\n <Dropdown.Toggle as='div' id='date-range-dropdown' className={`no-caret ${!props.hideRange ? styles.inputContainer : ''}`}>\n <input\n className={`form-control cursor-pointer border-dark ${styles.input}`}\n value={props.value}\n onChange={() => {}}\n onKeyDown={(e: React.KeyboardEvent) => e.preventDefault()} // Prevent keyboard input\n autoComplete='off'\n />\n <div className={styles.inputBtnContainer}>\n <div className='d-inline-block cursor-pointer'>\n <SvgContainer\n svgName={cvSvgLibrary.Calendar}\n size={SvgContainerSize.Standard}\n />\n </div>\n </div>\n </Dropdown.Toggle>\n );\n}","import { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRange } from 'libs/shared/interfaces';\n\nfunction isDateInFuture(date: Date): boolean {\n return DateHelper.isAfter(date, new Date(), 'day');\n}\n\nexport function isRangeInFuture(range: DateRange): boolean {\n return isDateInFuture(range.startDate);\n}\n\nexport function getDynamicRangeSubLabel(range: DateRange): string {\n return `(${DateHelper.format(range.startDate, 'ddd, D MMM')}`\n + ` - ${DateHelper.format(range.endDate, 'ddd, D MMM')})`;\n}\n\nexport function validateRange(range: DateRange): DateRange | null {\n if (isRangeInFuture(range))\n return;\n\n if (isDateInFuture(range.endDate))\n return {\n ...range,\n endDate: new Date()\n };\n\n return range;\n}","// extracted by mini-css-extract-plugin\nexport default {\"containerWithDynamicRanges\":\"pvYdJ\",\"selectedDateRange\":\"JU7bd\",\"rangeList\":\"DBlzu\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { getDynamicRangeSubLabel, isRangeInFuture, validateRange } from './PresetDateRangeSelectorUtils';\n\nimport styles from './preset-date-range-selector.scss';\n\nconst namespace = 'shared.presetDateRangeSelector';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getButtonClassName(isSelected: boolean): string {\n const buttonClassName = 'btn btn-link d-flex align-items-center py-1 px-0 text-decoration-none';\n\n if (isSelected)\n return buttonClassName + ` fw-bold text-info ${styles.selectedDateRange}`;\n\n return buttonClassName + ' text-body';\n}\n\ninterface DateRangeItemProps {\n range: DateRange;\n onClick: (range: DateRange) => void;\n selectedRangeName?: string;\n isDynamic?: boolean;\n}\n\nfunction DateRangeItem(props: DateRangeItemProps): JSX.Element {\n const selected = props.range.name === props.selectedRangeName;\n const isDisabled = isRangeInFuture(props.range) || props.range.disabled;\n\n const DateRangeButton = () => (\n <button className={getButtonClassName(selected)} onClick={() => props.onClick(props.range)} disabled={isDisabled}>\n {selected && <SvgContainer svgName={cvSvgLibrary.Check} />}\n <span className={`${isDisabled ? 'text-secondary' : ''} ${props.isDynamic ? 'fw-bold' : ''}`}>\n {props.range.name}\n </span>\n {!!props.isDynamic &&\n <>\n &nbsp;\n <span className='text-secondary'>{getDynamicRangeSubLabel(props.range)}</span>\n </>\n }\n </button>\n );\n\n if (!props.range.tooltip)\n return <DateRangeButton />;\n\n return (\n <Tooltip\n title={props.range.tooltip}\n placement='left'\n spanHack\n spanHackClassName='justify-content-start'\n >\n <DateRangeButton />\n </Tooltip>\n );\n}\n\n\ninterface PresetDateRangeSelectorProps {\n genericDateRanges: DateRange[];\n setDateRange: (dateRange: DateRange) => void;\n showCustomRangeSelector: () => void;\n dynamicDateRanges?: DateRange[];\n selectedRangeName?: string;\n}\n\nexport function PresetDateRangeSelector(props: PresetDateRangeSelectorProps): JSX.Element {\n function onClickRange(range: DateRange): void {\n const validatedRange = validateRange(range);\n\n if (!validatedRange)\n return;\n\n props.setDateRange(validatedRange);\n }\n\n const hasDynamicDateRanges = !!props.dynamicDateRanges?.length;\n\n return (\n <div className={hasDynamicDateRanges ? `py-3 ${styles.containerWithDynamicRanges}` : 'py-2'}>\n <div className='row px-2'>\n <div className={hasDynamicDateRanges ? 'col-4 pe-2 border-end' : 'col-12'}>\n <ul className={`list-unstyled ${styles.rangeList}`}>\n {props.genericDateRanges.map((range, idx) => (\n <li key={idx}>\n <DateRangeItem\n range={range}\n onClick={onClickRange}\n selectedRangeName={props.selectedRangeName}\n />\n </li>\n ))}\n </ul>\n </div>\n {hasDynamicDateRanges &&\n <div className='col-8 ps-2'>\n <ul className={`list-unstyled ${styles.rangeList}`}>\n {props.dynamicDateRanges.map((range, idx) => (\n <li key={idx}>\n <DateRangeItem\n range={range}\n onClick={onClickRange}\n selectedRangeName={props.selectedRangeName}\n isDynamic\n />\n </li>\n ))}\n </ul>\n </div>\n }\n </div>\n <div className='row px-2'>\n <div className='col-12'>\n <div className={hasDynamicDateRanges ? 'pe-2 text-end' : styles.rangeList}>\n <button className='btn btn-link p-0' onClick={props.showCustomRangeSelector}>\n <strong>{getPhrase('customRange')}</strong>\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}","import { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { getPresetRangeByName } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { DateRange } from 'libs/shared/interfaces';\n\n\nfunction isThisYear(date: Date): boolean {\n return date.getFullYear() === (new Date()).getFullYear();\n}\n\nfunction formatDate(date: Date, showYear: boolean): string {\n const format = showYear\n ? 'ddd, D MMM YYYY'\n : 'ddd, D MMM';\n\n return DateHelper.format(date, format);\n}\n\nexport function getInputValue(dateRangePreset: DateRange[], queryRange: DateRange, hideRange?: boolean): string {\n const presetRange = getPresetRangeByName(dateRangePreset, queryRange.name);\n\n const inputRange = presetRange || queryRange;\n\n if (!inputRange.startDate || !inputRange.endDate)\n return '';\n\n const showYear = !isThisYear(inputRange.startDate) || !isThisYear(inputRange.endDate);\n\n const value = !hideRange && `${formatDate(inputRange.startDate, showYear)} - ${formatDate(inputRange.endDate, showYear)}`;\n\n if (!inputRange.name)\n return value;\n\n return `${inputRange.name}${!hideRange ? ` (${value})` : ''}`;\n}","import React from 'react';\nimport { Dropdown } from 'react-bootstrap';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport {\n getMaxDate, getMinDate, getRouteQueryParams,\n useGetDateRangeFromQueryParams\n} from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nimport { CustomDateRangeSelector } from './components/custom-date-range-selector/CustomDateRangeSelector';\nimport { DateRangeInput } from './components/date-range-input/DateRangeInput';\nimport { PresetDateRangeSelector } from './components/preset-date-range-selector/PresetDateRangeSelector';\nimport { getInputValue } from './DateRangeSelectorUtils';\n\ntype DropdownState = 'none' | 'preset' | 'custom';\n\ninterface DateRangeSelectorViewProps {\n dateRangeQueryParams: DateRangeQueryParams;\n dateRangePresets: DateRange[];\n hideRange?: boolean;\n}\n\nexport function DateRangeSelectorView(props: DateRangeSelectorViewProps): JSX.Element {\n const queryParamDateRange = useGetDateRangeFromQueryParams(props.dateRangePresets, props.dateRangeQueryParams);\n const [ customDateRange, setCustomDateRange ] = React.useState<DateRange>(queryParamDateRange);\n const [ dropdownState, setDropdownState ] = React.useState<DropdownState>('none');\n\n React.useEffect(() => {\n setCustomDateRange(queryParamDateRange);\n }, [!!queryParamDateRange]);\n\n function onSelectPresetDateRange(range: DateRange): void {\n setCustomDateRange(range);\n applyDateRange(range);\n }\n\n function onToggleCustomDateRangeSelector(): void {\n setDropdownState('none');\n applyDateRange(customDateRange);\n }\n\n function applyDateRange(range: DateRange): void {\n setDropdownState('none');\n\n AppRouteHelper.updateParams(getRouteQueryParams(range), { merge: true, keysToRemove: ['rangeName']});\n }\n\n /**\n * If useGetDateRangeFromQueryParams doesn't return a DateRange then it will have\n * triggered an app route update with a new, valid DateRange, so we wait for that.\n */\n if (!queryParamDateRange)\n return <></>;\n\n /**\n * This is rendered as two separate dropdowns so that the menus are sized correctly.\n * The first menu is triggered by clicking on the Dropdown.Toggle in DateRangeInput\n * which fires onToggle.\n * The second menu is only accessible by clicking `Custom Range` in the first menu.\n */\n return (\n <div className='position-relative'>\n <Dropdown\n show={dropdownState === 'preset'}\n onToggle={show => setDropdownState(show ? 'preset' : 'none')}\n className={dropdownState === 'custom' ? 'd-none' : ''}\n >\n <DateRangeInput\n value={getInputValue(props.dateRangePresets, queryParamDateRange, props.hideRange)}\n hideRange={props.hideRange}\n />\n <Dropdown.Menu className='p-0' align='end'>\n <PresetDateRangeSelector\n genericDateRanges={props.dateRangePresets}\n setDateRange={onSelectPresetDateRange}\n showCustomRangeSelector={() => setDropdownState('custom')}\n selectedRangeName={queryParamDateRange.name}\n />\n </Dropdown.Menu>\n </Dropdown>\n <Dropdown\n show={dropdownState === 'custom'}\n onToggle={onToggleCustomDateRangeSelector}\n className={dropdownState === 'custom' ? '' : 'd-none'}\n >\n <DateRangeInput value={getInputValue(props.dateRangePresets, queryParamDateRange)} />\n <Dropdown.Menu className='p-0' align='end'>\n <CustomDateRangeSelector\n startDate={customDateRange?.startDate}\n endDate={customDateRange?.endDate}\n setDateRange={setCustomDateRange}\n maxDate={getMaxDate()}\n minDate={getMinDate()}\n onClickApply={() => applyDateRange(customDateRange)}\n close={() => setDropdownState('none')}\n />\n </Dropdown.Menu>\n </Dropdown>\n </div>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/react/index';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { ClassroomRequests } from 'libs/shared/apps/analytics/flight-requests/ClassroomRequests';\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { Classroom, ClassroomGroup } from 'libs/shared/interfaces';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nconst namespace = 'insights.hooks';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function useClassroomBreadcrumbs(params: AudienceQueryParams) {\n const [ breadcrumbs, setBreadcrumbs ] = React.useState<Breadcrumb[]>([]);\n\n const classroomId = params.classrooms?.length === 1 && !params.classroomGroups?.length\n ? ArrayHelper.first(params.classrooms)\n : null;\n const classroom = Flight.useBasicFetch<Classroom>(classroomId && ClassroomRequests.classroom(classroomId));\n const classroomGroupId = params.classroomGroups?.length === 1 && !params.classrooms?.length\n ? ArrayHelper.first(params.classroomGroups)\n : null;\n const classroomGroup = Flight.useBasicFetch<ClassroomGroup>(\n classroomGroupId && ClassroomRequests.classroomGroup(classroomGroupId)\n );\n \n const paramsKey = JSON.stringify(params);\n \n React.useEffect(() => {\n if (!params.classrooms?.length && !params.classroomGroups?.length) {\n setBreadcrumbs([\n {\n name: getPhrase('insights'),\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.HOME\n }\n }\n ]);\n return;\n }\n\n \n if (params.classrooms?.length > 1 || params.classroomGroups?.length > 1) {\n setBreadcrumbs([\n {\n name: getPhrase('classrooms'),\n appLink: {\n application: AppChannels.CLASSROOMS,\n action: Actions.Classrooms.HOME\n }\n }\n ]);\n return;\n }\n\n if (classroom.data) {\n setBreadcrumbs([\n {\n name: getPhrase('classrooms'),\n appLink: {\n application: AppChannels.CLASSROOMS,\n action: Actions.Classrooms.HOME\n }\n },\n {\n name: classroom.data.name,\n appLink: {\n application: AppChannels.CLASSROOMS,\n action: Actions.Classrooms.CLASSROOM_STUDENTS,\n args: [classroom.data.id]\n }\n }\n ]);\n return;\n }\n\n if (classroomGroup.data) {\n setBreadcrumbs([\n {\n name: getPhrase('classrooms'),\n appLink: {\n application: AppChannels.CLASSROOMS,\n action: Actions.Classrooms.HOME\n }\n },\n {\n name: classroomGroup.data.classroom.name,\n appLink: {\n application: AppChannels.CLASSROOMS,\n action: Actions.Classrooms.CLASSROOM_STUDENTS,\n args: [classroomGroup.data.classroom.id]\n }\n }\n ]);\n return;\n }\n }, [ paramsKey, classroom.data, classroomGroup.data ]);\n\n return breadcrumbs;\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { StorageType } from 'libs/common/backbone/utils/LocalStorageHelper';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { getInsightsDateRangePresets } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { AudienceFilterView } from 'libs/shared/apps/analytics/views/audience-filter/AudienceFilterView';\nimport { DateRangeSelectorView } from 'libs/shared/apps/analytics/views/date-range-selector/DateRangeSelectorView';\nimport { ActionsDropdown } from 'libs/shared/components/actions/ActionsDropdown';\nimport { Breadcrumbs, PartialBreadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { PillTab, PillTabSelector } from 'libs/shared/components/pill-tab-selector/PillTabSelector';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\nimport { VideoAppLinkHelper } from 'shared/utils/VideoAppLinkHelper';\n\nimport { useClassroomBreadcrumbs } from 'apps/insights/hooks/useClassroomBreadcrumbs';\n\nconst namespace = 'shared.insightsHeaderView';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightsHeaderProps {\n audienceAppLinkParams: AudienceQueryParams;\n dateRangeAppLinkParams: DateRangeQueryParams;\n video: VideoTypes;\n tabs: PillTab[];\n}\n\nexport function InsightsHeaderView(props: InsightsHeaderProps) {\n const [ anonymiseUsers, setAnonymiseUsers ] = useViewModel<boolean>(\n SharedViewModelKeys.ANONYMISE_USERS,\n false,\n { storage: StorageType.LocalStorage }\n );\n\n const classroomBreadcrumbs = useClassroomBreadcrumbs(props.audienceAppLinkParams);\n\n function getBreadcrumbs() {\n return [\n ...classroomBreadcrumbs,\n {\n name: props.video.name,\n active: true\n }\n ];\n }\n\n return (\n <>\n <section className='mb-3'>\n <div className='d-flex justify-content-between mb-2'>\n <h1 className='mb-0'>{props.video.name}</h1>\n <div className='d-flex gap-2'>\n <AudienceFilterView />\n <DateRangeSelectorView\n dateRangeQueryParams={props.dateRangeAppLinkParams}\n dateRangePresets={getInsightsDateRangePresets()}\n hideRange />\n <ActionsDropdown\n dropdownToggleClassName='btn btn-outline-dark'\n actions={[\n {\n label: getPhrase('generateReport'),\n appLink: {\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.INTERACTIVE_GENERATE_REPORT,\n args: [props.video.id]\n }\n },\n {\n label: getPhrase('goTo'),\n appLink: VideoAppLinkHelper.getAppLink(props.video)\n\n },\n {\n label: getPhrase(anonymiseUsers ? 'showNames' : 'hideNames'),\n onClick: () => setAnonymiseUsers(!anonymiseUsers)\n }\n ]}\n />\n </div>\n </div>\n {classroomBreadcrumbs.length ? <Breadcrumbs breadcrumbs={getBreadcrumbs()} /> : <PartialBreadcrumbs />}\n <div className='mb-3'>\n </div>\n <div>\n <PillTabSelector tabs={props.tabs} />\n </div>\n </section>\n </>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"circleContainer\":\"p8Vgz\",\"backgroundCircle\":\"asGGE\",\"circleSuccess\":\"PXLNj\",\"circleWarning\":\"ZckRN\",\"circleDanger\":\"slBRg\",\"lgCircleContainer\":\"N8KCI\",\"pendingCircle\":\"DKrcq\",\"centredPercentageText\":\"tpmLR\"};","// extracted by mini-css-extract-plugin\nexport default {\"pillTabSelector\":\"Hdi6o\",\"tab\":\"RvNxr\",\"minWidth\":\"GHSz9\",\"radiusSmall\":\"VhJJa\",\"tabLink\":\"WFyvo\"};"],"names":["anonymiseUserName","user","shouldAnonymise","seed","id","Math","floor","Date","getMinutes","dictionaries","separator","length","style","getUniqueNamesConfig","getAudienceParams","queryParams","userId","groupId","users","push","classrooms","classroomGroups","getPhrase","convertDateToUtcDateTimeString","date","utc","getMinDate","getMaxDate","getDefaultDateRange","dateRangePresetss","find","range","getPresetRangeByName","rangeName","p","name","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getRouteQueryParams","dateRange","from","to","useGetDateRangeFromQueryParams","dateRangePresets","dateRangeQueryParams","presetRange","replace","merge","keysToRemove","defaultDateRange","initialDateRangeValid","getStartEndParams","filterParams","getStartDate","getEndDate","start","end","defaultRange","BreadcrumbItem","props","ref","breadcrumb","appLink","active","withBackIcon","trimmedName","title","slice","className","svgName","size","S","Breadcrumbs","breadcrumbs","isMobile","collapse","setCollapse","shouldFocus","setShouldFocus","expandRef","characterLength","reduce","prev","next","current","focus","first","second","secondLast","last","rest","onClick","map","idx","key","PartialBreadcrumbs","numItems","height","width","dangerouslySetInnerHTML","__html","PercentageIndicatorLayout","ProgressCircle","circle","radius","r","baseVal","value","circumference","PI","offset","percentage","strokeDasharray","strokeDashoffset","toString","scoreThresholds","PercentageIndicator","percentageToFixed","layout","LabelInside","label","customLabel","LabelOnly","LabelBefore","defaultProps","CircleOnly","ProgressCircleSize","CIRCLE_WIDTH","CIRCLE_WIDTH_LG","CIRCLE_STROKE_WIDTH","CIRCLE_STROKE_WIDTH_LG","getCircleRadius","Large","strokeWidth","getCircleClassName","HIGH","MODERATE","getColouredLabelClassName","getCircleContainerClassName","isPending","getPercentageToFixed","toFixed","getFormattedPercentage","round","TabContents","tab","count","type","data","PillTabSelector","containerRef","borderRadius","listClassName","tabs","index","analyticsData","analyticsOptions","onSelect","onSelectTab","ScoreThresholdDefaults","DEFAULT_PARTIAL_LOADING_OPTIONS","minWidth","maxWidth","PartialLoadingHelper","getPartialLoadingItems","options","opts","Array","max","random","getInsightsVideoTabs","params","application","action","args","getInsightsClipTabs","getInsightsInteractiveTabs","LanguageService","NUM_MONTHS_TO_DISPLAY","DATE_DISPLAY_FORMAT","CustomDateRangeSelector","focusedInput","setFocusedInput","startDateInputRef","endDateInputRef","useSetInputFocus","SvgContainer","DateHelper","onChange","onFocus","close","mode","numberOfMonths","selected","onDayClick","day","setDateRange","undefined","s","captionLayout","fromDate","toDate","maxDate","modifiersClassNames","today","defaultMonth","onClickApply","DateRangeInput","Dropdown","as","hideRange","onKeyDown","e","preventDefault","autoComplete","isDateInFuture","isRangeInFuture","DateRangeItem","selectedRangeName","isDisabled","DateRangeButton","isSelected","buttonClassName","isDynamic","Tooltip","placement","spanHack","spanHackClassName","PresetDateRangeSelector","onClickRange","validatedRange","validateRange","hasDynamicDateRanges","dynamicDateRanges","genericDateRanges","showCustomRangeSelector","isThisYear","formatDate","showYear","format","getInputValue","dateRangePreset","queryRange","inputRange","DateRangeSelectorView","queryParamDateRange","customDateRange","setCustomDateRange","dropdownState","setDropdownState","applyDateRange","AppRouteHelper","show","onToggle","align","InsightsHeaderView","setBreadcrumbs","classroomId","classroom","classroomGroupId","classroomGroup","paramsKey","SharedViewModelKeys","storage","anonymiseUsers","setAnonymiseUsers","classroomBreadcrumbs","audienceAppLinkParams","ArrayHelper","ClassroomRequests","JSON","stringify","video","AudienceFilterView","dateRangeAppLinkParams","ActionsDropdown","dropdownToggleClassName","actions","VideoAppLinkHelper"],"sourceRoot":""}