@clickview/lite 0.70.1-dev.1 → 0.70.1-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/bundles.json +1 -1
  2. package/dist/languages/en.json +1 -1
  3. package/dist/scripts/3596-7f32e7d4c0-lite.chunk.js +3 -0
  4. package/dist/scripts/3596-7f32e7d4c0-lite.chunk.js.map +1 -0
  5. package/dist/scripts/4050-cd4d18058a-lite.chunk.js +3 -0
  6. package/dist/scripts/4050-cd4d18058a-lite.chunk.js.map +1 -0
  7. package/dist/scripts/4377-001a8ee263-lite.chunk.js +2 -0
  8. package/dist/scripts/4377-001a8ee263-lite.chunk.js.map +1 -0
  9. package/dist/scripts/549-2d591052e3-lite.chunk.js +2 -0
  10. package/dist/scripts/549-2d591052e3-lite.chunk.js.map +1 -0
  11. package/dist/scripts/5721-2141ed4fb6-lite.chunk.js +2 -0
  12. package/dist/scripts/5721-2141ed4fb6-lite.chunk.js.map +1 -0
  13. package/dist/scripts/5797-f84ce545b9-lite.chunk.js +2 -0
  14. package/dist/scripts/5797-f84ce545b9-lite.chunk.js.map +1 -0
  15. package/dist/scripts/5829-689f5be5d1-lite.chunk.js +3 -0
  16. package/dist/scripts/5829-689f5be5d1-lite.chunk.js.map +1 -0
  17. package/dist/scripts/6046-5652117548-lite.chunk.js +2 -0
  18. package/dist/scripts/6046-5652117548-lite.chunk.js.map +1 -0
  19. package/dist/scripts/{6629-3ea157aef8-lite.chunk.js → 6629-910e316a83-lite.chunk.js} +3 -3
  20. package/dist/scripts/6629-910e316a83-lite.chunk.js.map +1 -0
  21. package/dist/scripts/7042-65a932d16b-lite.chunk.js +2 -0
  22. package/dist/scripts/{7042-aaaf6e286f-lite.chunk.js.map → 7042-65a932d16b-lite.chunk.js.map} +1 -1
  23. package/dist/scripts/7428-6dd787bc07-lite.chunk.js +2 -0
  24. package/dist/scripts/7428-6dd787bc07-lite.chunk.js.map +1 -0
  25. package/dist/scripts/7757-9b72774917-lite.chunk.js +2 -0
  26. package/dist/scripts/{7757-e4d91d7fac-lite.chunk.js.map → 7757-9b72774917-lite.chunk.js.map} +1 -1
  27. package/dist/scripts/8191-ff27deee6c-lite.chunk.js +2 -0
  28. package/dist/scripts/8191-ff27deee6c-lite.chunk.js.map +1 -0
  29. package/dist/scripts/{8280-287760fb57-lite.chunk.js → 8280-8bb89d0a89-lite.chunk.js} +2 -2
  30. package/dist/scripts/8280-8bb89d0a89-lite.chunk.js.map +1 -0
  31. package/dist/scripts/8832-73ffd39e2a-lite.chunk.js +2 -0
  32. package/dist/scripts/{8832-aa3df17f66-lite.chunk.js.map → 8832-73ffd39e2a-lite.chunk.js.map} +1 -1
  33. package/dist/scripts/9973-648be9b72a-lite.chunk.js +2 -0
  34. package/dist/scripts/9973-648be9b72a-lite.chunk.js.map +1 -0
  35. package/dist/scripts/bundle-5276379bf8.min.js +3 -0
  36. package/dist/scripts/{bundle-4735d8d159.min.js.map → bundle-5276379bf8.min.js.map} +1 -1
  37. package/package.json +1 -1
  38. package/dist/scripts/3596-191624e307-lite.chunk.js +0 -3
  39. package/dist/scripts/3596-191624e307-lite.chunk.js.map +0 -1
  40. package/dist/scripts/4050-74aa5394f6-lite.chunk.js +0 -3
  41. package/dist/scripts/4050-74aa5394f6-lite.chunk.js.map +0 -1
  42. package/dist/scripts/4377-f6e641f39a-lite.chunk.js +0 -2
  43. package/dist/scripts/4377-f6e641f39a-lite.chunk.js.map +0 -1
  44. package/dist/scripts/52-d91751eafb-lite.chunk.js +0 -2
  45. package/dist/scripts/52-d91751eafb-lite.chunk.js.map +0 -1
  46. package/dist/scripts/549-f06f2dab2b-lite.chunk.js +0 -2
  47. package/dist/scripts/549-f06f2dab2b-lite.chunk.js.map +0 -1
  48. package/dist/scripts/5721-bfd734f968-lite.chunk.js +0 -2
  49. package/dist/scripts/5721-bfd734f968-lite.chunk.js.map +0 -1
  50. package/dist/scripts/5797-04d8a61b80-lite.chunk.js +0 -2
  51. package/dist/scripts/5797-04d8a61b80-lite.chunk.js.map +0 -1
  52. package/dist/scripts/5829-1c696c8446-lite.chunk.js +0 -3
  53. package/dist/scripts/5829-1c696c8446-lite.chunk.js.map +0 -1
  54. package/dist/scripts/6046-339bc1b2e1-lite.chunk.js +0 -2
  55. package/dist/scripts/6046-339bc1b2e1-lite.chunk.js.map +0 -1
  56. package/dist/scripts/6629-3ea157aef8-lite.chunk.js.map +0 -1
  57. package/dist/scripts/7042-aaaf6e286f-lite.chunk.js +0 -2
  58. package/dist/scripts/741-98a532e970-lite.chunk.js +0 -2
  59. package/dist/scripts/741-98a532e970-lite.chunk.js.map +0 -1
  60. package/dist/scripts/7757-e4d91d7fac-lite.chunk.js +0 -2
  61. package/dist/scripts/8191-d5f68d2463-lite.chunk.js +0 -2
  62. package/dist/scripts/8191-d5f68d2463-lite.chunk.js.map +0 -1
  63. package/dist/scripts/8280-287760fb57-lite.chunk.js.map +0 -1
  64. package/dist/scripts/8832-aa3df17f66-lite.chunk.js +0 -2
  65. package/dist/scripts/bundle-4735d8d159.min.js +0 -3
  66. /package/dist/css/{52-lite-e2d7497beb.chunk.css → 7428-lite-e2d7497beb.chunk.css} +0 -0
  67. /package/dist/scripts/{3596-191624e307-lite.chunk.js.LICENSE.txt → 3596-7f32e7d4c0-lite.chunk.js.LICENSE.txt} +0 -0
  68. /package/dist/scripts/{4050-74aa5394f6-lite.chunk.js.LICENSE.txt → 4050-cd4d18058a-lite.chunk.js.LICENSE.txt} +0 -0
  69. /package/dist/scripts/{5829-1c696c8446-lite.chunk.js.LICENSE.txt → 5829-689f5be5d1-lite.chunk.js.LICENSE.txt} +0 -0
  70. /package/dist/scripts/{6629-3ea157aef8-lite.chunk.js.LICENSE.txt → 6629-910e316a83-lite.chunk.js.LICENSE.txt} +0 -0
  71. /package/dist/scripts/{bundle-4735d8d159.min.js.LICENSE.txt → bundle-5276379bf8.min.js.LICENSE.txt} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"scripts/4050-74aa5394f6-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/components/interactive-questions/interactive-questions.scss","file:///app/packages/libs/shared/src/components/interactive-questions/InteractiveQuestions.tsx","file:///app/packages/libs/shared/src/enums/SupportArticle.ts","file:///app/packages/libs/shared/src/components/image-cropper/SimpleCropper.tsx","file:///app/packages/libs/shared/src/utils/CropperHelper.tsx","file:///app/packages/projects/player/src/plugins/activity-status-plugin/components/activity-status-button.ts","file:///app/packages/projects/player/src/plugins/activity-status-plugin/activity-status-plugin.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/interfaces/InteractiveMode.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/errors/ReconnectionError.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/utils/ResultsService.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/add-question-button/add-question-button.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/illustration/components/illustration-canvas/illustration-canvas.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/illustration/components/illustration-canvas/illustration-canvas.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/illustration/components/illustration-panel/illustration-panel.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/illustration/components/illustration-panel/illustration-panel.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/illustration/illustration-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/missing-word/missing-word-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/view-components.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/short-answer/short-answer-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/annotation/annotation-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/image/image-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/multiple-choice/multiple-choice-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/true-or-false/true-or-false-interaction.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interaction-summary/interaction-summary.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interaction-summary/interaction-summary.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interactions-bar/interactions-bar.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interactions-bar/interactions-bar.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/progress-summary/progress-summary.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/progress-summary/progress-summary.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/utils/helpers.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interactive-summary.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/getstudentAttempts.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/interactive-summary.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/show-summary-button/show-summary-button.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-summary/InteractiveSummaryWrapper.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/question-list/question-list-empty-state.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/question-list/question-list.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-type-selector/create-type-selector.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interaction-actions/interaction-actions.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-interaction-buttons/create-interaction-buttons.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/view-interaction-buttons/view-iteraction-buttons.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interaction-footer/interaction-footer.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-interaction-heading/create-interaction-heading.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/interactive-immersive-reader/interactive-immersive-reader.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/interactive-immersive-reader/interactive-immersive-reader.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/view-components/view-interaction-heading/view-interaction-heading.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interaction-header/interaction-header.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/utils/interactive-ajax.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-annotation/create-annotation-helpers.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-annotation/create-annotation-link.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-image/upload-image-dropzone.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-missing-word/create-missing-word.tsx","file:///app/packages/libs/shared/src/components/feedback-tooltip/FeedbackTooltip.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-image/upload-image-icon.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-multiple-choice/multiple-choice-answer.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-multiple-choice/create-multiple-choice.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-short-answer/create-short-answer.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-components.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-annotation/create-annotation.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-image/create-image.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/create-components/create-illustration/create-illustration.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/move-timepoint/move-timepoint.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/reorder-interactions/reorder-interactions.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/reorder-interactions/reorder-interactions.scss","file:///app/packages/libs/shared/src/hooks/UseGrabCursorProps.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/timepoint/timepoint-component.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/utils/getInteractionComponents.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/sliding-timepoint/sliding-timepoints.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/utils/InteractiveReducer.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/hooks/useInteractiveState.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/hooks/useStateManager.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/hooks/useInteractiveTrack.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive-actions/interactive-actions.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/interactive/interactive-component.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/hooks/useLockPlayer.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/continue-session/continue-session.tsx","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/continue-session/continue-session.scss","file:///app/packages/projects/player/src/plugins/interactive-plugin/grade-passback-plugin.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/interactive-plugin.ts","file:///app/packages/projects/player/src/players/interactive-player.ts","file:///app/packages/projects/player/src/react/InteractivePlayer.tsx","file:///app/packages/projects/player/src/utils/getProxy.ts"],"sourcesContent":["// extracted by mini-css-extract-plugin\nexport default {\"timeTag\":\"ShZvf\",\"hide\":\"FHzDr\",\"time\":\"JDp5N\",\"type\":\"AzIWg\",\"question\":\"UhEYq\",\"deleteContainer\":\"wBqoo\",\"delete\":\"OAQQu\",\"correctness\":\"W5sR9\",\"selected\":\"tfrDf\",\"row\":\"sGk59\"};","import React from 'react';\nimport { Scrollbars } from 'react-custom-scrollbars-2';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { ExperimentalInteractionTypes, Interaction, Interactive, Timepoint } from 'libs/shared/interfaces';\nimport { DurationHelper } from 'libs/shared/utils/DurationHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { InteractionLabel } from './InteractionLabel';\n\nimport styles from './interactive-questions.scss';\n\nconst namespace = 'shared.interactiveQuestions';\n\ninterface CorrectnessProps {\n interaction: Interaction;\n getCorrectness?: (interaction: Interaction) => InteractionCorrectness;\n}\n\nfunction Correctness(props: CorrectnessProps): React.ReactElement {\n const { interaction, getCorrectness } = props;\n\n const correctness = getCorrectness(interaction);\n\n switch (correctness) {\n case InteractionCorrectness.Correct:\n return <span className='text-success'><SvgContainer size={SvgContainerSize.Medium} svgName={cvSvgLibrary.Check} /></span>;\n case InteractionCorrectness.Incorrect:\n return <span className='text-danger'><SvgContainer size={SvgContainerSize.Medium} svgName={cvSvgLibrary.Close} /></span>;\n case InteractionCorrectness.AwaitingMarking:\n return <span className='text-secondary italic'><i><Text namespace={namespace} phrase='pending' /></i></span>;\n case InteractionCorrectness.UnAnswered:\n return <button className='btn btn-outline-dark'><Text namespace={namespace} phrase='answer' /></button>;\n case InteractionCorrectness.Answered:\n return <span className='text-secondary italic'><i><Text namespace={namespace} phrase='answered' /></i></span>;\n case InteractionCorrectness.NotApplicable:\n return <></>;\n }\n}\n\ninterface InteractionComponentProps {\n interaction: Interaction;\n visibleAt: number;\n goToTimepoint: (interactionId: string) => void;\n onClickDelete?: (interactionId: string) => void;\n scrollTo: (offset: number, height: number) => void;\n selectedInteractionId: string;\n isFirstInteraction: boolean;\n getCorrectness?: (interaction: Interaction) => InteractionCorrectness;\n}\n\nfunction InteractionComponent(props: InteractionComponentProps): React.ReactElement {\n const {\n interaction,\n visibleAt,\n selectedInteractionId,\n goToTimepoint,\n scrollTo,\n isFirstInteraction\n } = props;\n\n const selected = interaction.id.toString() === selectedInteractionId?.toString();\n\n const ref = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n if (!selected)\n return;\n\n if (!ref.current)\n return;\n\n const el = ref.current;\n const rect = el.getBoundingClientRect();\n const offset = rect.top - el.offsetParent.getBoundingClientRect().top;\n\n scrollTo(offset, rect.height);\n }, [selected]);\n\n function onClick(): void {\n goToTimepoint && goToTimepoint(interaction.id);\n }\n\n function onClickDelete(event: React.MouseEvent): void {\n event.stopPropagation();\n\n props.onClickDelete(interaction.id);\n }\n\n /**\n * Don't have a cursor if there is no callback function.\n * i.e. when rendered in a popup\n */\n const cursor = goToTimepoint ? 'cursor-pointer' : 'cursor-default';\n\n return (\n <div ref={ref}>\n <DivButton className={`py-2 ${cursor} ${styles.row} ${selected ? styles.selected : ''}`} onClick={selected ? () => {} : onClick}>\n <div className={`me-3 d-inline-flex rounded-pill justify-content-center align-items-center text-info fw-semibold bg-light-blue ${styles.timeTag} ${isFirstInteraction ? '' : styles.hide}`}>\n {isFirstInteraction ? DurationHelper.ToDisplayDuration(visibleAt) : ''}\n </div>\n\n <InteractionLabel\n interaction={interaction}\n showTypeName\n typeNameClassName={styles.type}\n questionClassName={styles.question}\n />\n {props.onClickDelete && (\n <DivButton onClick={onClickDelete} className={`${styles.deleteContainer}`}>\n <span className={`text-end ${styles.delete}`}>\n <SvgContainer\n size={SvgContainerSize.Medium}\n svgName={cvSvgLibrary.Delete}\n />\n </span>\n </DivButton>\n )}\n {props.getCorrectness && (\n <span className={`text-end ${styles.correctness}`}>\n <Correctness interaction={interaction} getCorrectness={props.getCorrectness} />\n </span>\n )}\n </DivButton>\n </div>\n );\n}\n\ninterface TimepointComponentProps {\n timepoint: Timepoint;\n goToTimepoint?: (timepointId: string, interactionId: string, visibleAt: number) => void;\n selectedInteractionId?: string;\n scrollTo?: (offset: number, height: number) => void;\n onClickDelete?: (interactionId: string) => void;\n getCorrectness?: (interaction: Interaction) => InteractionCorrectness;\n experimentalInteractiveQuestions?: boolean;\n}\n\nexport function TimepointComponent(props: TimepointComponentProps): React.ReactElement {\n const {\n timepoint,\n scrollTo,\n onClickDelete,\n selectedInteractionId,\n getCorrectness\n } = props;\n\n function goToTimepoint(interactionId: string): void {\n props.goToTimepoint(timepoint.id, interactionId, timepoint.visibleAt);\n }\n\n if (!timepoint.interactions)\n return <></>;\n\n return (\n <>\n {timepoint.interactions.map((interaction, i) => {\n if (!props.experimentalInteractiveQuestions && ExperimentalInteractionTypes[interaction.typeId])\n return <React.Fragment key={i} />;\n\n return (\n <InteractionComponent\n interaction={interaction}\n visibleAt={timepoint.visibleAt}\n goToTimepoint={props.goToTimepoint && goToTimepoint}\n onClickDelete={onClickDelete}\n scrollTo={scrollTo}\n selectedInteractionId={selectedInteractionId}\n isFirstInteraction={i === 0}\n getCorrectness={getCorrectness}\n key={i}\n />\n );\n })\n }\n </>\n );\n}\n\nexport interface InteractiveQuestionProps {\n interactive: Interactive;\n goToTimepoint?: (timepointId: string, interactionId: string, visibleAt: number) => void;\n selectedInteractionId?: string;\n maxHeight: number;\n onClickDelete?: (interactionId: string) => void;\n getCorrectness?: (interaction: Interaction) => InteractionCorrectness;\n experimentalInteractiveQuestions?: boolean;\n}\n\nexport function InteractiveQuestions(props: InteractiveQuestionProps): React.ReactElement {\n const {\n interactive,\n goToTimepoint,\n selectedInteractionId,\n maxHeight,\n onClickDelete,\n getCorrectness\n } = props;\n\n const ref = React.useRef<Scrollbars>(null);\n\n function scrollTo(offset: number, elHeight: number): void {\n if (!ref.current)\n return;\n\n const height = ref.current.getClientHeight();\n const scroll = ref.current.getScrollTop();\n const elementFromTop = offset + scroll;\n\n /**\n * Element is above scroll window if it's distance from the top\n * is less than the scroll\n */\n const isAboveScrollWindow = elementFromTop < scroll;\n\n /**\n * Element is beneath scroll window if it's distance from the top\n * plus it's height is greater than the scroll plus the window height\n */\n const isBelowScrollWindow = (elementFromTop + elHeight) > (scroll + height);\n\n /**\n * So we don't scroll if our element is visible\n */\n if (!isAboveScrollWindow && !isBelowScrollWindow)\n return;\n\n /**\n * If our element isn't visible, we want to try scroll so the element is\n * centered in our viewport\n */\n ref.current.scrollTop(elementFromTop - (height / 2) + (elHeight / 2));\n }\n\n const borderClass = goToTimepoint ? 'border rounded' : '';\n\n return (\n <Scrollbars\n autoHeight\n autoHeightMax={maxHeight}\n className={borderClass}\n hideTracksWhenNotNeeded={true}\n ref={ref}\n >\n <div className='px-3 py-2'>\n {interactive.timepoints.map((t, i) => (\n <TimepointComponent\n key={i}\n timepoint={t}\n goToTimepoint={goToTimepoint}\n selectedInteractionId={selectedInteractionId}\n scrollTo={scrollTo}\n onClickDelete={onClickDelete}\n getCorrectness={getCorrectness}\n experimentalInteractiveQuestions={props.experimentalInteractiveQuestions}\n />\n ))\n }\n </div>\n </Scrollbars>\n );\n}\n","// Article name mapped to article ID on support site. Used by `ArticleHelper`\n\nexport enum OnlineSupportArticle {\n AddToPlaylist = '115005679748',\n EditSsoAccounts = '8202508040345',\n\n // LE\n LibraryEditor = '360001974533',\n VideoAccess = '360000153947',\n AddFromOnline = '360011718234',\n UploadToLibraryEditor = '360012069334',\n PBTErrorCodes = '360012421153',\n ManuelReview = '360020004534',\n LibraryReview = '360000163788',\n}\n\nexport enum LiteSupportArticle {\n Integrations = '4407268725529',\n Classrooms = '4405362551833',\n MakeInteractive = '4405370510873',\n EditSsoAccounts = '8202605666073',\n UploadToLibraryEditor = '10672936659865',\n AddFromLite = '10671345281561',\n ManageSsoYearGroups = '14691130889241',\n ContentReview = '18525199576601',\n ContentPermissions = '14692125209497',\n AccessSettings = '27927466562201',\n ContentGuidelines = '24133696186009',\n FoxtelFaq = '24133519542169',\n ViviIntegration = '23826297956377',\n AppleTvIntegration = '25832373739929',\n RssFeed = '32567445635097',\n ManageGroupPermissions = '35407217335705'\n}\n","import React from 'react';\nimport Cropper from 'cropperjs';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { PopupButtons } from 'libs/shared/components/popup/PopupButtons';\nimport { ImageMinDimensions } from 'libs/shared/constants/ImageSizes';\nimport { ImageType } from 'libs/shared/enums/Images';\n\nimport './image-cropper.scss';\n\nconst namespace = 'shared.imageCropper';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst MIME_REGEX = /data:([a-zA-Z0-9]+\\/[a-zA-Z0-9-.+]+).*,.*/;\n\nconst getImageMimeType = (dataUrl: string) => {\n const mime = dataUrl.match(MIME_REGEX);\n\n if (!mime)\n return;\n\n return mime[1];\n};\n\nexport interface SimpleCropperProps {\n src: string;\n alt: string;\n onClickCrop: (dataUrl: string, closePopup: () => void) => void;\n closePopup: () => void;\n popupSize?: 'sm' | 'md' |'lg' | 'xl';\n\n /**\n * If an imageType isn't provide the aspect ratio\n * and min sizes won'd be locked\n */\n imageType?: ImageType;\n}\n\nSimpleCropper.defaultProps = {\n popupSize: 'lg'\n};\n\nexport function SimpleCropper(props: SimpleCropperProps): JSX.Element {\n const [ imageLoaded, setImageLoaded ] = React.useState(false);\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n\n const imageRef = React.useRef<HTMLImageElement>(null);\n const cropperRef = React.useRef<Cropper>(null);\n\n const crop = () => {\n if (!imageLoaded)\n return;\n\n const croppedDataUrl = cropperRef.current.getCroppedCanvas().toDataURL(getImageMimeType(props.src));\n\n setShowSpinner(true);\n props.onClickCrop(croppedDataUrl, props.closePopup);\n };\n\n React.useEffect(() => {\n const image = new Image();\n image.src = props.src;\n\n const viewPortToImageRatio = imageRef.current.offsetWidth / image.width;\n const dimensions = ImageMinDimensions[props.imageType];\n\n const options: Cropper.Options = {\n viewMode: 2,\n autoCropArea: 1, // Number between 0 and 1 that defines the initial cropper area as a percentage of the image.\n ready: () => setImageLoaded(true)\n };\n\n if (dimensions) {\n options.minCropBoxWidth = dimensions.width * viewPortToImageRatio;\n options.minCropBoxHeight = dimensions.height * viewPortToImageRatio;\n options.aspectRatio = dimensions.width / dimensions.height;\n }\n\n cropperRef.current = new Cropper(imageRef.current, options);\n\n return () => { cropperRef.current.destroy(); };\n }, []);\n\n return (\n <Popup\n title={getPhrase('title')}\n closePopup={props.closePopup}\n size={props.popupSize}\n >\n <div>\n <img\n src={props.src}\n alt={props.alt}\n ref={imageRef}\n className='img img-fluid'\n />\n </div>\n\n <PopupButtons>\n <PopupButtons.Cancel onClick={props.closePopup} />\n <PopupButtons.Submit\n onClick={crop}\n text={getPhrase('crop')}\n variant='dark'\n showSpinner={showSpinner}\n />\n </PopupButtons>\n </Popup>\n );\n}","import React from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport { SimpleCropper, SimpleCropperProps } from 'libs/shared/components/image-cropper/SimpleCropper';\n\nexport const CropperHelper = {\n renderCropper(props: Omit<SimpleCropperProps, 'closePopup'>): void {\n const root = createRoot(document.getElementById('dialog-region'));\n\n root.render(\n <SimpleCropper\n {...props}\n closePopup={() => root.unmount()}\n />\n );\n }\n};","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { ShareActivityStatus } from 'libs/shared/enums/ShareActivityStatus';\n\nconst Button = videojs.getComponent('Button');\n\nimport './activity-status-button.scss';\n\ninterface ActivityStatusButtonOptions extends videojs.ComponentOptions {\n activityStatus: ShareActivityStatus;\n clickHandler: () => void;\n}\n\nexport class ActivityStatusButton extends Button {\n public options_: ActivityStatusButtonOptions;\n public controlText_: string;\n\n constructor(player: VideoJsPlayer, options: ActivityStatusButtonOptions) {\n super(player, options);\n\n this.update();\n }\n\n public update(): void {\n if (this.options_.activityStatus === ShareActivityStatus.Complete)\n this.addClass('cv-activity-completed');\n else\n this.removeClass('cv-activity-completed');\n }\n\n public handleClick(...args: any[]) {\n this.options_.activityStatus = this.getToggledActivityStatus();\n\n this.update();\n if (this.options_.clickHandler) {\n this.options_.clickHandler.call(this, args);\n }\n }\n\n public buildCSSClass(): string {\n return 'cv-activity-status-button';\n }\n\n private getToggledActivityStatus(): ShareActivityStatus {\n if (this.options_.activityStatus === ShareActivityStatus.None\n || this.options_.activityStatus === ShareActivityStatus.Incomplete) {\n return ShareActivityStatus.Complete;\n }\n\n if (this.options_.activityStatus === ShareActivityStatus.Complete) {\n return ShareActivityStatus.Incomplete;\n }\n }\n}\n\nActivityStatusButton.prototype.controlText_ = 'Complete';","import videojs from 'video.js';\n\nimport { ShareActivityStatus } from 'libs/shared/enums/ShareActivityStatus';\n\nimport { ActivityStatusButton } from 'projects/player/plugins/activity-status-plugin/components/activity-status-button';\n\nconst Plugin = videojs.getPlugin('plugin');\n\nclass ActivityStatusPlugin extends Plugin {\n private activityStatus: ShareActivityStatus;\n private onToggleStatus: () => void;\n private button: ActivityStatusButton;\n\n public setActivityStatus(activityStatus: ShareActivityStatus, onToggleStatus: () => void): void {\n if (activityStatus === this.activityStatus)\n return;\n\n this.activityStatus = activityStatus;\n this.onToggleStatus = onToggleStatus;\n\n this.player.ready(() => {\n this.renderActivityStatusButton();\n });\n }\n\n // Remove old button and render new button when activity status is different from previous status\n private renderActivityStatusButton(): void {\n if (this.button) {\n this.player.removeChild(this.button);\n }\n\n this.button = new ActivityStatusButton(this.player, {\n activityStatus: this.activityStatus,\n clickHandler: this.onToggleStatus\n });\n\n this.player.addChild(this.button);\n }\n}\n\nvideojs.registerPlugin('activityStatusPlugin', ActivityStatusPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n activityStatusPlugin(): ActivityStatusPlugin;\n }\n}\n","export enum InteractiveMode {\n View,\n Create\n}","import { DialogError } from 'libs/shared/errors/primitives/DialogError';\nimport { DialogOptions } from 'libs/shared/interfaces';\n\nexport class ReconnectionError extends DialogError {\n constructor() {\n super('Could not connect to submit interactive results');\n }\n\n // @ts-ignore\n public get name(): string {\n return 'InternetConnectivityError';\n }\n\n // @ts-ignore\n public get dialogOptions(): DialogOptions {\n return {\n title: 'Connection issues',\n text: 'There seems to be an issue with your internet connection. Refresh the page to try again. ',\n buttons: [{\n text: 'Refresh',\n className: 'btn btn-dark',\n success: true\n }]\n };\n }\n\n public onDone(): void {\n window.location.reload();\n }\n}\n","import { Core } from 'libs/common/core';\n\nimport { SessionHelper } from 'libs/analytics/utils/SessionHelper';\n\nimport { ReconnectionError } from 'projects/player/plugins/interactive-plugin/errors/ReconnectionError';\nimport { InteractionResult } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { AjaxHelper } from 'projects/player/utils/ajax-helper';\n\ninterface SaveActionRequest {\n resultId: string;\n interactionId: string;\n results: InteractionResult[];\n}\n\ninterface StartSessionResponse {\n resultId: string;\n}\n\ninterface StartSessionRequest {\n interactiveId: string;\n metadataId: string;\n userId: string;\n customerId: string;\n shareId: string;\n sessionId?: string;\n anonymous?: boolean;\n}\n\ninterface ResultsServiceOptions extends StartSessionRequest {\n playerApi?: URL;\n}\n\nexport class ResultsService {\n private options: ResultsServiceOptions;\n private resultId: string;\n\n constructor(options: ResultsServiceOptions) {\n this.options = options;\n this.save = this.save.bind(this);\n }\n\n /**\n * @param resultId Allows you to continue an old interactive session\n */\n public start(resultId?: string): void {\n if (resultId)\n this.resultId = resultId;\n\n this.startSession();\n }\n\n private async startSession(): Promise<void> {\n if (this.resultId)\n return;\n\n const {\n interactiveId,\n metadataId,\n userId,\n customerId,\n shareId,\n playerApi\n } = this.options;\n\n const startSessionRequest: StartSessionRequest = {\n interactiveId,\n metadataId,\n userId,\n customerId,\n shareId\n };\n\n if (!userId) {\n startSessionRequest.anonymous = true;\n startSessionRequest.sessionId = SessionHelper.getClientSessionData()?.id;\n }\n\n try {\n const response = await AjaxHelper.post<StartSessionResponse>(\n playerApi + 'interactive/start-session',\n JSON.stringify(startSessionRequest)\n );\n this.resultId = response.resultId;\n } catch {\n Core.ErrorHelper.throw(new ReconnectionError());\n }\n }\n\n public async save(interactionId: string, results: InteractionResult[]): Promise<void> {\n if (!this.resultId)\n await this.startSession();\n\n const saveActionRequest: SaveActionRequest = {\n resultId: this.resultId,\n interactionId,\n results\n };\n\n try {\n await AjaxHelper.post(\n this.options.playerApi + 'interactive/save-actions',\n JSON.stringify(saveActionRequest),\n undefined,\n false\n );\n } catch (err) {\n console.log(err);\n Core.ErrorHelper.throw(new ReconnectionError());\n }\n }\n}\n","import React from 'react';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\n\nimport styles from './interactive-icon-button.scss';\n\ninterface InteractiveIconButtonProps extends React.ButtonHTMLAttributes<HTMLDivElement> {\n svgName: string;\n className?: string;\n onClick: (e: React.MouseEvent) => void;\n}\n\nexport function InteractiveIconButton(\n props: React.PropsWithChildren<InteractiveIconButtonProps>\n): React.ReactElement {\n const { className, svgName, children, ...attributes } = props;\n\n let buttonClassName = `${className} ${styles.iconButton}`;\n\n if (children) {\n buttonClassName += ` ${styles.iconWithText}`;\n } else {\n buttonClassName += ` ${styles.iconOnly}`;\n }\n\n const svg = <SvgContainer svgName={svgName} className={styles.svg} />;\n\n return (\n <DivButton\n className={buttonClassName}\n {...attributes}\n >\n {svg}\n {children}\n </DivButton>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"svg\":\"cDUaE\",\"iconButton\":\"Mr0S0\",\"iconWithText\":\"vHTVo\",\"iconOnly\":\"vIGn0\"};","import React from 'react';\n\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { InteractiveIconButton } from 'projects/player/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button';\n\ninterface AddQuestionButtonProps {\n isCreate: boolean;\n open: boolean;\n showTypeSelector: () => void;\n}\n\nexport function AddQuestionButton(props: AddQuestionButtonProps): React.ReactElement {\n const {\n isCreate,\n open,\n showTypeSelector\n } = props;\n\n if (!isCreate || open)\n return <></>;\n\n return (\n <InteractiveIconButton\n className='btn btn-outline-dark cv-add-question'\n onClick={showTypeSelector}\n svgName={cvSvgLibrary.Plus}\n >\n Add question\n </InteractiveIconButton>\n );\n}\n","// extracted by mini-css-extract-plugin\nexport default {\"colourButton\":\"y6pnq\",\"colourButtonSelected\":\"PAPVX\",\"canvasDrawContainer\":\"__tFu\",\"strokeButtonContainer\":\"D1zMW\",\"strokeButton\":\"J7C_3\",\"selectedButton\":\"aJKor\"};","import React from 'react';\nimport CanvasDraw from 'react-canvas-draw';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { DialogHelper } from 'libs/shared/utils/DialogHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { InteractiveIconButton } from 'projects/player/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button';\n\nimport styles from './illustration-canvas.scss';\n\nenum BrushThickness {\n Small = 2,\n Medium = 4,\n Large = 8\n}\n\nenum BrushColours {\n Black = '#000000',\n Red = '#D9584F',\n Orange = '#F8981D',\n Yellow = '#FFCD52',\n Green = '#5DC786',\n Blue = '#38A2E8',\n Purple = '#7A76E8',\n Grey = '#979797',\n White = '#FFFFFF'\n}\n\ninterface IllustrationCanvasProps {}\n\nexport const IllustrationCanvas = React.forwardRef((\n _: IllustrationCanvasProps,\n ref: React.ForwardedRef<CanvasDraw>\n) => {\n const canvasRef = React.useRef<CanvasDraw>(null);\n React.useImperativeHandle(ref, () => canvasRef.current, [canvasRef.current]);\n\n const canvasContainerRef = React.useRef<HTMLDivElement>(null);\n const [[ canvasWidth, canvasHeight ], setCanvasSize ] = React.useState<number[]>([ 0, 0 ]);\n\n const [ colour, setColour ] = React.useState(BrushColours.Black);\n const [ brushThickness, setBrushThickness ] = React.useState<BrushThickness>(BrushThickness.Small);\n\n const [ eraserChecked, setEraserChecked ] = React.useState(false);\n const [ prevColour, setPrevColour ] = React.useState(BrushColours.Black);\n\n /**\n * This function and the layout effect beneath it are used to \n * resize our canvas to fit the width while maintaining a 16:9 aspect ratio. - Sha\n */\n function calculateCanvasSize(): void {\n if (!canvasContainerRef.current)\n return;\n\n const rect = canvasContainerRef.current.getBoundingClientRect();\n setCanvasSize([ rect.width, rect.width * 0.5625 ]);\n }\n\n React.useLayoutEffect(() => {\n if (!canvasContainerRef.current)\n return;\n\n const resizeObserver = new ResizeObserver(calculateCanvasSize);\n resizeObserver.observe(canvasContainerRef.current);\n\n return () => resizeObserver.disconnect();\n }, [canvasContainerRef.current]);\n\n function onClickEraser(): void {\n if (eraserChecked) {\n setColour(prevColour);\n setEraserChecked(false);\n return;\n }\n\n setPrevColour(colour);\n setColour(BrushColours.White);\n setEraserChecked(true);\n }\n\n function onClickPen(): void {\n if (!eraserChecked) return;\n\n setColour(prevColour);\n setEraserChecked(false);\n }\n\n function onClickColour(bgColour: BrushColours): void {\n setColour(bgColour);\n setPrevColour(colour);\n setEraserChecked(false);\n }\n\n function onClickClear(): void {\n DialogHelper.render(<p>Are you sure you want to discard your drawing?</p>, {\n title: 'Discard your drawing?',\n submitButtonProps: {\n onClick: () => canvasRef.current.clear(),\n variant: 'danger',\n text: 'Discard'\n },\n cancelButtonProps: {\n variant: 'link',\n text: 'Cancel'\n }\n });\n }\n\n return (\n <section>\n <div className='d-flex align-items-start'>\n <div className='d-flex flex-lg-column'>\n <ul className='me-3-lg me-2 list-unstyled'>\n {Object.entries(BrushColours).slice(0, 4).map(([ name, bgColour ], index) => (\n <li key={index}>\n <DivButton\n className={`${styles.colourButton} ${colour === bgColour ? styles.colourButtonSelected : ''} rounded-circle`}\n style={{ backgroundColor: bgColour }}\n onClick={() => onClickColour(bgColour)}\n aria-label={`Select the colour: ${name}`}\n >\n &nbsp;\n </DivButton>\n </li>\n ))}\n </ul>\n <ul className='me-3-lg me-2 list-unstyled'>\n {Object.entries(BrushColours).slice(4).map(([ name, bgColour ], index) => (\n <li key={index}>\n <DivButton\n className={`${styles.colourButton} ${colour === bgColour ? styles.colourButtonSelected : ''} rounded-circle`}\n style={{ backgroundColor: bgColour }}\n onClick={() => onClickColour(bgColour)}\n aria-label={`Select the colour: ${name}`}\n >\n &nbsp;\n </DivButton>\n </li>\n ))}\n </ul>\n </div>\n <div className='flex-grow-1 position-relative' ref={canvasContainerRef}>\n <div className={styles.canvasDrawContainer}>\n {canvasWidth &&\n <CanvasDraw\n canvasHeight={canvasHeight}\n canvasWidth={canvasWidth}\n brushRadius={brushThickness}\n lazyRadius={10}\n hideGrid={true}\n brushColor={colour}\n className='position-absolute top-0 left-0 border'\n ref={canvasRef}\n />\n }\n </div>\n </div>\n <div className='d-flex flex-column align-self-stretch ms-2'>\n <div className='d-flex flex-column gap-2 flex-grow-1'>\n <ul className='d-lg-flex flex-column gap-2 list-unstyled d-none'>\n <InteractiveIconButton\n svgName={cvSvgLibrary.Edit}\n className={`btn btn-outline-dark ${!eraserChecked ? styles.selectedButton : ''}`}\n onClick={onClickPen}\n aria-label='Pen'\n />\n <InteractiveIconButton\n svgName={cvSvgLibrary.Erase}\n className={`btn btn-outline-dark mb-2 ${eraserChecked ? styles.selectedButton : ''}`}\n onClick={onClickEraser}\n aria-label='Eraser'\n />\n </ul>\n <ul className='d-flex flex-column mb-2 list-unstyled'>\n <li className={styles.strokeButtonContainer}>\n <InteractiveIconButton\n svgName={cvSvgLibrary.SmallStroke}\n className={`btn btn-outline-dark ${brushThickness === BrushThickness.Small ? styles.selectedButton : ''} ${styles.strokeButton}`}\n onClick={() => setBrushThickness(BrushThickness.Small)}\n style={{ color: colour !== BrushColours.White ? colour : BrushColours.Black }}\n aria-label='Small stroke'\n />\n </li>\n <li className={styles.strokeButtonContainer}>\n <InteractiveIconButton\n svgName={cvSvgLibrary.MediumStroke}\n className={`btn btn-outline-dark ${brushThickness === BrushThickness.Medium ? styles.selectedButton : ''} ${styles.strokeButton}`}\n onClick={() => setBrushThickness(BrushThickness.Medium)}\n style={{ color: colour !== BrushColours.White ? colour : BrushColours.Black }}\n aria-label='Medium stroke'\n />\n </li>\n <li className={styles.strokeButtonContainer}>\n <InteractiveIconButton\n svgName={cvSvgLibrary.LargeStroke}\n className={`btn btn-outline-dark ${brushThickness === BrushThickness.Large ? styles.selectedButton : ''} ${styles.strokeButton}`}\n onClick={() => setBrushThickness(BrushThickness.Large)}\n style={{ color: colour !== BrushColours.White ? colour : BrushColours.Black }}\n aria-label='Large stroke'\n />\n </li>\n </ul>\n </div>\n <ul className='d-flex flex-column gap-lg-2 list-unstyled'>\n <li>\n <InteractiveIconButton\n svgName={cvSvgLibrary.Undo}\n className='btn btn-outline-dark'\n onClick={(() => canvasRef.current.undo())}\n aria-label='Undo'\n />\n </li>\n\n <li>\n <InteractiveIconButton\n svgName={cvSvgLibrary.Delete}\n onClick={onClickClear}\n className={`btn btn-outline-danger d-lg-block d-none ${styles.myRight}`}\n aria-label='Clear canvas'\n />\n </li>\n </ul>\n </div>\n </div>\n </section>\n );\n});","import React from 'react';\nimport CanvasDraw from 'react-canvas-draw';\nimport SimpleBar from 'simplebar-react';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interaction } from 'libs/shared/interfaces';\nimport { DialogHelper } from 'libs/shared/utils/DialogHelper';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport { IllustrationCanvas } from 'projects/player/plugins/interactive-plugin/components/view-components/illustration/components/illustration-canvas/illustration-canvas';\n\nimport styles from './illustration-panel.scss';\n\ninterface IllustrationPanelProps {\n interaction: Interaction;\n onSave: (dataUrl: string) => void;\n onCancel: () => void;\n}\n\nexport function IllustrationPanel(props: IllustrationPanelProps): JSX.Element {\n const ref = React.useRef<CanvasDraw>(null);\n\n const {\n bgClassName,\n Svg\n } = InteractionTypeHelper.getTypeInfo(props.interaction.typeId);\n\n function onClickSave(): void {\n if (!ref.current)\n return;\n\n props.onSave((ref.current as any).getDataURL('image/png'));\n }\n\n function onClickCancel(): void {\n DialogHelper.render(<p>Are you sure you want to discard your drawing?</p>, {\n title: 'Discard your drawing?',\n submitButtonProps: {\n onClick: props.onCancel,\n variant: 'danger',\n text: 'Discard'\n },\n cancelButtonProps: {\n variant: 'link',\n text: 'Cancel'\n }\n });\n }\n\n return (\n <SimpleBar className='h-100'>\n <section className='d-flex flex-column h-100'>\n <div className='text-center text-body d-flex justify-content-between align-items-center p-2'>\n <div className='d-flex align-items-center'>\n <span className={`${styles.icon} me-3 rounded my-1 text-white align-middle d-inline-block ${bgClassName}`}>\n <Svg />\n </span>\n <span className='text-start flex-grow-1'>\n <h2 className='h6 mb-0'>\n <strong>{props.interaction.name}</strong>\n </h2>\n </span>\n </div>\n <div>\n <DivButton className='btn btn-link' onClick={onClickCancel}>\n Cancel\n </DivButton>\n <DivButton className='btn btn-dark ms-2' onClick={onClickSave}>\n Save\n </DivButton>\n </div>\n </div>\n <div className='cv-timepoint bg-gray-100 flex-grow-1 rounded-bottom'>\n <div className='cv-timepoint-padding h-100'>\n <div className='cv-interactive-question'>\n <div className={`mx-auto ${styles.canvasContainer}`}>\n <IllustrationCanvas ref={ref} />\n </div>\n </div>\n </div>\n </div>\n </section>\n </SimpleBar>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"icon\":\"sTvDl\",\"canvasContainer\":\"kFxi6\"};","import React from 'react';\n\ninterface ViewErrorFeedbackProps {\n error?: string;\n}\n\nexport function ViewErrorFeedback(props: ViewErrorFeedbackProps): React.ReactElement {\n const { error } = props;\n\n if (!props.error)\n return <></>;\n\n return (\n <p className='mt-2 small text-danger'>{error}</p>\n );\n}\n","import React from 'react';\nimport { HtmlPortalNode, InPortal } from 'react-reverse-portal';\n\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { IllustrationPanel } from 'projects/player/plugins/interactive-plugin/components/view-components/illustration/components/illustration-panel/illustration-panel';\nimport { ViewErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback';\nimport { InteractionProps, ResultSubmission, ViewInteractionState, ViewSubmissionOptions } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { AjaxHelper } from 'projects/player/utils/ajax-helper';\n\nconst BASE_64_PREFIX = 'data:image/png;base64,';\n\ninterface IllustrationState extends ViewInteractionState {\n [id: string]: string;\n}\n\ninterface IllustrationInteractionProps extends InteractionProps<IllustrationState> {\n fullWidthPortalNode?: HtmlPortalNode;\n}\n\nexport function IsViewIllustrationValid(state: IllustrationState): string {\n const numberOfKeys = Object.keys(state).filter(k => !!state[k]?.trim()).length;\n\n if (!numberOfKeys)\n return 'Please submit an illustration';\n\n return null;\n}\n\nexport async function SubmitViewIllustration(\n state: IllustrationState,\n interaction: Interaction,\n save: ResultSubmission,\n options: ViewSubmissionOptions\n): Promise<IllustrationState> {\n let image = state[interaction.actionableItems[0].id] || '';\n\n if (image.startsWith(BASE_64_PREFIX)) {\n const base64 = image.replace(BASE_64_PREFIX, '');\n const result = await AjaxHelper.post<HashObject>(`${options.imageApi}v2/thumbnails/base64`, `\"${base64}\"`, { tokenName: 'gateway' });\n image = result.location;\n }\n\n const results = Object.keys(state).map(k => ({\n actionableItemId: k,\n value: image\n }));\n\n await save(interaction.id, results);\n\n /**\n * Returning our state so that we can update our base64 image to an image url.\n */\n return {\n [interaction.actionableItems[0].id]: image\n };\n}\n\nexport function IllustrationInteraction(props: IllustrationInteractionProps): React.ReactElement {\n const { interaction, state, fullWidthPortalNode, setState } = props;\n\n const [ showCanvas, setShowCanvas ] = React.useState(false);\n\n const imageUrl = state[interaction.actionableItems[0].id];\n\n function onSave(dataUrl: string): void {\n setState({ ...state, [interaction.actionableItems[0].id]: dataUrl });\n setShowCanvas(false);\n props.recalculateScroll();\n }\n \n return (\n <div className='cv-interactive-question'>\n <p className='h4 mb-3'>\n {interaction.name}\n </p>\n {imageUrl\n ? <>\n <img className='img-fluid border rounded mb-2 w-75' src={imageUrl} alt='Illustration' />\n {!state.submitted &&\n <DivButton\n className='btn btn-outline-dark'\n onClick={() => setShowCanvas(true)}\n >\n Re-draw my answer\n </DivButton>\n }\n </>\n : <DivButton\n className='btn btn-outline-dark'\n onClick={() => setShowCanvas(true)}\n >\n Draw my answer\n </DivButton>\n }\n <ViewErrorFeedback error={state.error} />\n {showCanvas &&\n <InPortal node={fullWidthPortalNode}>\n <IllustrationPanel\n interaction={interaction}\n onSave={onSave}\n onCancel={() => setShowCanvas(false)}\n />\n </InPortal>\n }\n </div>\n );\n}","import React from 'react';\n\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { ActionableItem, Interaction } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\n\nimport { InteractionProps, ResultSubmission, ViewInteractionState, ViewSubmissionFunction } from 'projects/player/plugins/interactive-plugin//interfaces';\nimport { ViewErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback';\n\nconst LONGEST_WORD_LENGTH = 45;\n\nimport './missing-word-interaction.scss';\n\ninterface MissingWordState extends ViewInteractionState {\n [id: string]: string;\n}\nconst PLACEHOLDER = 'cv-missing-word-';\nconst FONT = '20pt arial';\nfunction getWordWidth(text: string): number {\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n context.font = FONT;\n const metrics = context.measureText(text);\n return metrics.width;\n}\n\nexport function IsMissingWordCorrect(state: MissingWordState, interaction: Interaction): InteractionCorrectness {\n return InteractiveCorrectnessHelper.isMissingWordCorrect(interaction, (id: string) => state[id]);\n}\n\nexport function IsViewMissingWordValid(state: MissingWordState, interaction: Interaction): string {\n const numberOfKeys = Object.keys(state).filter(k => !!state[k]?.trim()).length;\n\n if (!numberOfKeys)\n return 'Please fill in the blanks';\n\n if (numberOfKeys !== interaction.actionableItems.length)\n return 'Please fill in all of the blanks';\n\n return null;\n}\n\nexport const SubmitViewMissingWord: ViewSubmissionFunction =\n (state: MissingWordState, interaction: Interaction, save: ResultSubmission) => {\n return save(interaction.id, Object.keys(state).map(k => ({\n actionableItemId: k,\n value: state[k].toString()\n })));\n };\n\nexport function MissingWordInteraction(props: InteractionProps<MissingWordState>): React.ReactElement {\n const { state, setState, interaction, showFeedback } = props;\n\n const cleanedUp = (interaction.data.sentence as string).replace(/{([^{}]*)}/g, (match: string, val: string) => {\n return `{${PLACEHOLDER}${val}}`;\n });\n\n const items = cleanedUp.split(/{([^{}]*)}/g);\n function onChange(a: ActionableItem, event: React.ChangeEvent<HTMLInputElement>): void {\n event.stopPropagation();\n \n if (!event.target.value) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { [a.id]: removed, ...newState } = state;\n setState(newState, true);\n return;\n }\n\n setState({ [a.id]: event.target.value });\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='mb-2 h4'>\n {items.map((item, index) => {\n if (!item.startsWith(PLACEHOLDER))\n return item;\n\n const order = item.replace(PLACEHOLDER, '');\n const actionableItem = interaction.actionableItems.find(a => a.order.toString() === order);\n\n if (!actionableItem)\n return;\n\n const value = state[actionableItem.id] || '';\n const width = getWordWidth(actionableItem.name);\n\n if (showFeedback) {\n const isCorrect =\n actionableItem.name.toLowerCase().toString() === state[actionableItem.id]?.toLowerCase().toString();\n return (\n <React.Fragment key={index}>\n {!isCorrect && <><del className='text-danger'>{value}</del>&nbsp;</>}\n <span className='text-success'>{actionableItem.name}</span>\n </React.Fragment>\n );\n }\n\n return (\n <span className='cv-missing-word-input-container' key={index}>\n <input\n style={{ width: (width / 16) + 'rem' }}\n onChange={e => onChange(actionableItem, e)}\n value={value}\n maxLength={LONGEST_WORD_LENGTH}\n disabled={!!state.submitted}\n className='cv-missing-word-input'\n autoComplete='off'\n />\n </span>\n );\n })}\n </div>\n <ViewErrorFeedback error={state.error} />\n </div>\n );\n}\n","import { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { Interaction, InteractionTypeId } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\n\nimport { AnnotationInteraction } from 'projects/player/plugins/interactive-plugin/components/view-components/annotation/annotation-interaction';\nimport { IllustrationInteraction, IsViewIllustrationValid, SubmitViewIllustration } from 'projects/player/plugins/interactive-plugin/components/view-components/illustration/illustration-interaction';\nimport { ImageInteraction } from 'projects/player/plugins/interactive-plugin/components/view-components/image/image-interaction';\nimport { IsMissingWordCorrect, IsViewMissingWordValid, MissingWordInteraction, SubmitViewMissingWord } from 'projects/player/plugins/interactive-plugin/components/view-components/missing-word/missing-word-interaction';\nimport { IsMultipleChoiceCorrect, IsViewMultipleChoiceValid, MultipleChoiceInteraction, SubmitViewMultipleChoice } from 'projects/player/plugins/interactive-plugin/components/view-components/multiple-choice/multiple-choice-interaction';\nimport { IsViewShortAnswerValid, ShortAnswerInteraction, ShouldShowShowAnswerFeedback, SubmitViewShortAnswer } from 'projects/player/plugins/interactive-plugin/components/view-components/short-answer/short-answer-interaction';\nimport { IsTrueOrFalseCorrect, IsViewTrueOrFalseValid, SubmitViewTrueOrFalse, TrueOrFalseInteraction } from 'projects/player/plugins/interactive-plugin/components/view-components/true-or-false/true-or-false-interaction';\nimport { InteractionComponent, ViewInteractionState, ViewSubmissionFunction } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ntype ShowFeedbackFunction = (interaction: Interaction) => boolean;\nconst showFeedback = () => true;\nconst dontShowFeedback = () => false;\nconst feedbackLookup: {[typeId: number]: ShowFeedbackFunction} = {\n [InteractionTypeId.Annotation]: dontShowFeedback,\n [InteractionTypeId.Image]: dontShowFeedback,\n [InteractionTypeId.MissingWord]: showFeedback,\n [InteractionTypeId.MultipleChoice]: showFeedback,\n [InteractionTypeId.ShortAnswer]: ShouldShowShowAnswerFeedback,\n [InteractionTypeId.TrueOrFalse]: showFeedback,\n [InteractionTypeId.Illustration]: dontShowFeedback\n};\n\nexport function getShouldShowFeedback(typeId: InteractionTypeId): ShowFeedbackFunction {\n return feedbackLookup[typeId];\n}\n\nconst QuestionLookup: {[typeId: number]: InteractionComponent} = {\n [InteractionTypeId.Annotation]: AnnotationInteraction,\n [InteractionTypeId.Image]: ImageInteraction,\n [InteractionTypeId.MissingWord]: MissingWordInteraction,\n [InteractionTypeId.MultipleChoice]: MultipleChoiceInteraction,\n [InteractionTypeId.ShortAnswer]: ShortAnswerInteraction,\n [InteractionTypeId.TrueOrFalse]: TrueOrFalseInteraction,\n [InteractionTypeId.Illustration]: IllustrationInteraction\n};\n\nexport function getViewComponent(typeId: InteractionTypeId): InteractionComponent {\n return QuestionLookup[typeId];\n}\n\nfunction noValidation(): string {\n return '';\n}\n\ntype ViewValidationFunction = (state: ViewInteractionState, interaction: Interaction) => string;\nconst ValidationLookup: {[typeId: number]: ViewValidationFunction} = {\n [InteractionTypeId.Annotation]: noValidation,\n [InteractionTypeId.Image]: noValidation,\n [InteractionTypeId.MissingWord]: IsViewMissingWordValid,\n [InteractionTypeId.MultipleChoice]: IsViewMultipleChoiceValid,\n [InteractionTypeId.ShortAnswer]: IsViewShortAnswerValid,\n [InteractionTypeId.TrueOrFalse]: IsViewTrueOrFalseValid,\n [InteractionTypeId.Illustration]: IsViewIllustrationValid\n};\n\nexport function getViewValidation(typeId: InteractionTypeId): ViewValidationFunction {\n return ValidationLookup[typeId];\n}\n\nconst SubmissionLookup: {[typeId: number]: ViewSubmissionFunction} = {\n [InteractionTypeId.Annotation]: null,\n [InteractionTypeId.Image]: null,\n [InteractionTypeId.MissingWord]: SubmitViewMissingWord,\n [InteractionTypeId.MultipleChoice]: SubmitViewMultipleChoice,\n [InteractionTypeId.ShortAnswer]: SubmitViewShortAnswer,\n [InteractionTypeId.TrueOrFalse]: SubmitViewTrueOrFalse,\n [InteractionTypeId.Illustration]: SubmitViewIllustration\n};\n\nexport function getViewSubmit(typeId: InteractionTypeId): ViewSubmissionFunction {\n return SubmissionLookup[typeId];\n}\n\ntype IsCorrectFunction = (state: ViewInteractionState, interaction: Interaction) => InteractionCorrectness;\nconst IsCorrectLookup: {[typeId: number]: IsCorrectFunction} = {\n [InteractionTypeId.Annotation]: InteractiveCorrectnessHelper.notApplicable,\n [InteractionTypeId.Image]: InteractiveCorrectnessHelper.notApplicable,\n [InteractionTypeId.MissingWord]: IsMissingWordCorrect,\n [InteractionTypeId.MultipleChoice]: IsMultipleChoiceCorrect,\n [InteractionTypeId.ShortAnswer]: InteractiveCorrectnessHelper.awaitingMarking,\n [InteractionTypeId.TrueOrFalse]: IsTrueOrFalseCorrect,\n [InteractionTypeId.Illustration]: InteractiveCorrectnessHelper.awaitingMarking\n};\nexport function getViewIsCorrect(typeId: InteractionTypeId): IsCorrectFunction {\n return IsCorrectLookup[typeId];\n}\n","import React from 'react';\nimport TextareaAutosize from 'react-textarea-autosize';\n\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { ViewErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback';\nimport { InteractionProps, ResultSubmission, ViewInteractionState, ViewSubmissionFunction } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nconst MAX_LENGTH = 4000;\n\ninterface ShortAnswerState extends ViewInteractionState {\n [id: string]: string;\n}\n\nexport function ShouldShowShowAnswerFeedback(interaction: Interaction): boolean {\n return !!interaction.data.suggestedResponse;\n}\n\nexport function IsViewShortAnswerValid(state: ShortAnswerState, interaction: Interaction): string {\n const numberOfKeys = Object.keys(state).filter(k => !!state[k]?.trim()).length;\n\n if (!numberOfKeys)\n return 'Please provide an answer to the question';\n\n const length = state[interaction.actionableItems[0].id]?.length;\n\n if (length > MAX_LENGTH)\n return `Max answer length is ${MAX_LENGTH} characters`;\n\n return null;\n}\n\nexport const SubmitViewShortAnswer: ViewSubmissionFunction =\n (state: ShortAnswerState, interaction: Interaction, save: ResultSubmission) => {\n return save(interaction.id, Object.keys(state).map(k => ({\n actionableItemId: k,\n value: state[k].toString()\n })));\n };\n\n\nexport function ShortAnswerInteraction(props: InteractionProps<ShortAnswerState>): React.ReactElement {\n const { interaction, state, setState, showFeedback } = props;\n\n function onChange(event: React.ChangeEvent<HTMLTextAreaElement>): void {\n setState({\n ...state,\n [interaction.actionableItems[0].id]: event.target.value\n });\n }\n\n if (showFeedback) {\n return (\n <div className='cv-interactive-question'>\n <p className='h4'>{interaction.name}</p>\n <label className='h4 fw-bold'>My answer</label>\n <p className='h4'>{state[interaction.actionableItems[0].id]}</p>\n {interaction.data.suggestedResponse &&\n <>\n <label className='h4 fw-bold'>Teacher's suggested answer</label>\n <p className='h4'>{interaction.data.suggestedResponse}</p>\n </>\n }\n </div>\n );\n }\n\n return (\n <div className='cv-interactive-question'>\n <p className='h4'>\n {interaction.name}\n </p>\n <TextareaAutosize\n id='short-answer-answer'\n className='form-control mt-2'\n minRows={3}\n value={state[interaction.actionableItems[0].id] || ''}\n onChange={onChange}\n disabled={!!state.submitted}\n />\n <ViewErrorFeedback error={state.error} />\n </div>\n );\n}\n","import React from 'react';\n\nimport { InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nexport function AnnotationInteraction(props: InteractionProps<null>): React.ReactElement {\n const annotation = props.interaction.data.annotation.replace(/<(a)(.*?)>/g, '<$1 target=\"_blank\" $2>');\n\n return (\n <div className='cv-interactive-question'>\n <div className='mb-2 h4' dangerouslySetInnerHTML={{ __html: annotation }}></div>\n </div>\n );\n}\n","import React from 'react';\n\nimport { InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nimport './image-interaction.scss';\n\nexport function ImageInteraction(props: InteractionProps<null>): React.ReactElement {\n const { interaction, recalculateScroll } = props;\n\n const ref = React.useCallback((node: HTMLImageElement) => {\n if (!node) return;\n\n node.onload = () => {\n recalculateScroll();\n };\n }, []);\n\n return (\n <div className='cv-interactive-question cv-image-interactive'>\n <div className='cv-image-container text-center'>\n <img className='img-fluid rounded' src={interaction.data.url} ref={ref} />\n {interaction.data.caption &&\n <>\n <p className='mt-3 h4'>\n {interaction.data.caption}\n </p>\n </>\n }\n </div>\n </div>\n );\n}\n","import React from 'react';\n\nimport { MultipleChoiceInteractionAnswers } from 'libs/shared/components/interaction-answers/multiple-choice/MultipleChoiceInteractionAnswers';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { ActionableItem, Interaction } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport { ViewErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback';\nimport { InteractionProps, ResultSubmission, ViewInteractionState, ViewSubmissionFunction } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nimport './multiple-choice-interaction.scss';\n\ninterface MultipleChoiceState extends ViewInteractionState {\n [id: string]: string;\n}\n\nexport function IsMultipleChoiceCorrect(state: MultipleChoiceState, interaction: Interaction): InteractionCorrectness {\n return InteractiveCorrectnessHelper.isMultipleChoiceCorrect(interaction, (id: string) => state[id]);\n}\n\nexport function IsViewMultipleChoiceValid(state: MultipleChoiceState): string {\n if (!Object.keys(state).length)\n return 'Please choose an answer';\n\n return null;\n}\n\nexport const SubmitViewMultipleChoice: ViewSubmissionFunction =\n (state: MultipleChoiceState, interaction: Interaction, save: ResultSubmission) => {\n return save(interaction.id, Object.keys(state).map(k => {\n const actionableItem = interaction.actionableItems.find(a => a.id?.toString() === k?.toString());\n return {\n actionableItemId: k,\n value: actionableItem?.name\n };\n }));\n };\n\nexport function MultipleChoiceInteraction(props: InteractionProps<MultipleChoiceState>): React.ReactElement {\n const { state, setState, interaction, showFeedback, imageApi, currentUser } = props;\n\n const radio = interaction.actionableItems.filter(a => a.isCorrect).length === 1;\n\n function onChecked(a: ActionableItem, checked: boolean): void {\n if (state.submitted)\n return;\n\n if (radio) {\n setState(checked ? { [a.id]: a.id } : {}, true);\n return;\n }\n\n if (!checked) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { [a.id]: removed, ...newState } = state;\n setState(newState, true);\n return;\n }\n\n setState({ [a.id]: a.id });\n }\n\n return (\n <div className='cv-interactive-question'>\n <p className='h4'>\n {interaction.name}\n </p>\n {!radio &&\n <div className='rounded bg-light-blue p-2 mb-2 text-small'>\n <SvgContainer\n svgName={cvSvgLibrary.Resources}\n className='d-inline-block svg-container sm align-text-bottom me-1'\n />\n <small>\n <strong>Multi-select: </strong>This question has multiple correct answers\n </small>\n </div>\n }\n <MultipleChoiceInteractionAnswers\n interaction={interaction}\n showFeedback={showFeedback}\n onSelectAnswer={onChecked}\n getSelectedAnswer={(id: string) => state[id]}\n imageApi={imageApi.toString()}\n userInitials={UserHelper.getInitials(currentUser.givenName, currentUser.familyName)}\n userAvatar={currentUser.avatar}\n leftHandSidePortalNode={props.leftHandSidePortalNode}\n submitted={!!state.submitted}\n />\n <ViewErrorFeedback error={state.error} />\n </div>\n );\n}\n","import React from 'react';\n\nimport { TrueOrFalseInteractionAnswers } from 'libs/shared/components/interaction-answers/true-or-false/TrueOrFalseInteractionAnswers';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { ActionableItem, Interaction } from 'libs/shared/interfaces';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport { ViewErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/view-components/view-error-feedback/view-error-feedback';\nimport { InteractionProps, ResultSubmission, ViewInteractionState, ViewSubmissionFunction } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ninterface MultipleChoiceState extends ViewInteractionState {\n [id: string]: string;\n}\n\nexport function IsTrueOrFalseCorrect(state: MultipleChoiceState, interaction: Interaction): InteractionCorrectness {\n const items = interaction.actionableItems.filter(a => a.isCorrect);\n const correct = items.every(a => state[a.id] === a.name);\n return correct ? InteractionCorrectness.Correct : InteractionCorrectness.Incorrect;\n}\n\nexport function IsViewTrueOrFalseValid(state: MultipleChoiceState): string {\n if (!Object.keys(state).length)\n return 'Please choose an answer';\n\n return null;\n}\n\nexport const SubmitViewTrueOrFalse: ViewSubmissionFunction =\n (state: MultipleChoiceState, interaction: Interaction, save: ResultSubmission) => {\n return save(interaction.id, Object.keys(state).map(k => ({\n actionableItemId: k,\n value: state[k]\n })));\n };\n\nexport function TrueOrFalseInteraction(props: InteractionProps<MultipleChoiceState>): React.ReactElement {\n const { state, setState, interaction, showFeedback, imageApi, currentUser } = props;\n\n const correctAnswer = interaction.actionableItems.find(i => i.isCorrect);\n\n function onChecked(a: ActionableItem): void {\n if (state.submitted)\n return;\n\n setState({ [a.id]: a.name }, true);\n }\n\n return (\n <div className='cv-interactive-question'>\n <p className='h4'>\n {interaction.name}\n </p>\n <TrueOrFalseInteractionAnswers\n className='justify-content-center'\n interaction={interaction}\n showFeedback={showFeedback}\n onSelectAnswer={onChecked}\n getSelectedAnswer={(id: string) => state[id]}\n imageApi={imageApi.toString()}\n userInitials={UserHelper.getInitials(currentUser.givenName, currentUser.familyName)}\n userAvatar={currentUser.avatar}\n />\n {showFeedback &&\n <div className='text-center px-5 mt-3'>\n <p className='h4'>The answer is <strong>{correctAnswer.name}</strong></p>\n {interaction.data.feedback &&\n <p className='h4'>{interaction.data.feedback}</p>\n }\n </div>\n }\n <ViewErrorFeedback error={state.error} />\n </div>\n );\n}","import React from 'react';\n\nimport { InteractionResponse } from 'libs/shared/components/interaction-response/InteractionResponse';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, InteractionTypeId, Interactive, StudentResults, Timepoint } from 'libs/shared/interfaces';\nimport { getStudentAttempt, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { getViewIsCorrect } from 'projects/player/plugins/interactive-plugin/components/view-components/view-components';\nimport { InteractiveState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nimport styles from './interaction-summary.scss';\n \ninterface InteractionSummaryProps {\n studentResults: StudentResults;\n interaction: Interaction;\n timepoint: Timepoint;\n interactive: Interactive;\n state: InteractiveState;\n goToTimepoint: (timepointId: string, interactionId: string) => void;\n interactionNumber: number;\n imageCdnUrl: string;\n}\n\nexport function InteractionSummary(props: InteractionSummaryProps): React.ReactElement {\n const {\n studentResults,\n interaction,\n timepoint,\n interactive,\n state,\n goToTimepoint,\n interactionNumber,\n imageCdnUrl\n } = props;\n\n const result = getStudentResult(studentResults);\n const studentAttempt = getStudentAttempt(interaction.id, result);\n\n const interactionState = state.interactions[interaction.id];\n const isCorrect = getViewIsCorrect(interaction.typeId);\n const correctness = isCorrect(interactionState || {}, interaction);\n\n const answerable = interaction.typeId !== InteractionTypeId.Annotation\n && interaction.typeId !== InteractionTypeId.Image;\n let showQuestion = answerable;\n\n if (interaction.typeId === InteractionTypeId.MissingWord && studentAttempt)\n showQuestion = false;\n \n const teacherFeedback = interaction.data.suggestedResponse || interaction.data.feedback;\n\n return (\n <li className='mb-3 position-relative'>\n <div\n className='d-flex flex-wrap mb-2 cursor-pointer'\n onClick={() => goToTimepoint(timepoint.id, interaction.id)}\n >\n {interactive.immediateFeedback &&\n <div className={styles.feedback}>\n {(() => {\n if (!studentAttempt)\n return false;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n return <span className='text-secondary fst-italic'>Waiting to be marked</span>;\n\n if (correctness === InteractionCorrectness.Correct)\n return (\n <span className='text-success'>\n Correct&nbsp;\n <SvgContainer className='svg-container align-middle' svgName={cvSvgLibrary.Check}></SvgContainer>\n </span>\n );\n\n if (correctness === InteractionCorrectness.Incorrect)\n return (\n <span className='text-danger'>\n Incorrect&nbsp;\n <SvgContainer className='svg-container align-middle' svgName={cvSvgLibrary.Close}></SvgContainer>\n </span>\n );\n\n return false;\n })()}\n </div>\n }\n <InteractionLabel\n interaction={interaction}\n iconClassName='flex-shrink-0'\n showQuestion={showQuestion}\n showTypeName\n questionClassName='d-block w-100 mt-2'\n questionNumber={interactionNumber}\n />\n </div>\n {answerable && !studentAttempt &&\n <button\n className='btn btn-dark'\n onClick={() => goToTimepoint(timepoint.id, interaction.id)}\n >Answer question</button>}\n {studentAttempt && answerable &&\n <InteractionResponse\n interaction={interaction}\n studentResults={studentResults}\n markedStatus={InteractiveAnswerStatus.PendingReview}\n markInteraction={() => {}}\n imageCdnUrl={imageCdnUrl}\n showFeedback={interactive.immediateFeedback}\n showAvatar\n />\n }\n {interactive.immediateFeedback && studentAttempt && teacherFeedback &&\n <div className='bg-light rounded p-2'>\n <div>\n <strong>\n {interaction.typeId === InteractionTypeId.TrueOrFalse ? 'Teacher\\'s feedback' : 'Teacher\\'s suggested response'}\n </strong>\n </div>\n {teacherFeedback}\n </div>\n }\n </li>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"feedback\":\"O6oD6\"};","import React from 'react';\n\nimport { Interactive } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport styles from './interactions-bar.scss';\n\ninterface InteractionBarProps {\n interactive: Interactive;\n duration: number;\n goToTimepoint: (timepointId: string, interactionId: string) => void;\n}\n\nexport function InteractionsBar(props: InteractionBarProps): React.ReactElement {\n const { interactive, duration } = props;\n\n function onClick(timepointId: string, interactionId: string, event: React.MouseEvent): void {\n event.stopPropagation();\n props.goToTimepoint(timepointId, interactionId);\n }\n\n if (!duration)\n return <></>;\n\n return (\n <>\n {interactive.timepoints.map((t, i) => {\n if (!t.interactions.length)\n return <></>;\n\n const {\n bgClassName\n } = InteractionTypeHelper.getTypeInfo(t.interactions[0].typeId);\n\n const left = ((t.visibleAt / 1000) / duration) * 100;\n\n return (\n <span\n key={i}\n className={`${styles.interaction} ${bgClassName}`}\n style={{\n left: `${left}%`\n }}\n onClick={e => onClick(t.id, t.interactions[0].id, e)}\n />\n );\n })}\n </>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"interaction\":\"pUo8u\"};","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\n\nimport styles from './progress-summary.scss';\n\ninterface ProgressSummaryProps {\n player: VideoJsPlayer;\n duration: number;\n progress?: ProgressEventPair[];\n interactive: Interactive;\n}\n\nexport function ProgressSummary(props: ProgressSummaryProps): React.ReactElement {\n const { duration, progress, player } = props;\n\n const [ , reRender ] = React.useState(progress.length);\n\n const crunched: ProgressEventPair[] = [];\n \n if (progress.length) {\n let last = progress[0];\n crunched.push(last);\n\n progress.forEach((e, i) => {\n if (i === 0) return;\n\n /** \n * If our event gap is less than a second we skip it\n * This is because there' usually a 200-300ms gap in the end histroy if the user pauses\n */\n if ((last.end.time + 1 > e.start.time) && (last.start.time < e.start.time)) {\n last.end = e.end;\n return;\n }\n \n last = e;\n crunched.push(last);\n });\n }\n\n /**\n * Force this view to re-render if any remaining progress is flushed\n * We do this because flushing could be delayed after the video ends.\n */\n React.useEffect(() => {\n const onProgressFlush = () => {\n reRender(progress.length);\n };\n\n player.on('progressflush', onProgressFlush);\n return () => player.off('progressflush', onProgressFlush);\n }, []);\n\n return (\n <>\n {crunched.map((e, i) => {\n const left = e.start.time / duration * 100;\n const right = (1 - e.end.time / duration) * 100;\n\n return (\n <span\n key={i}\n className={styles.progress}\n style={{\n left: `${left}%`,\n right: `${right}%`\n }}\n />\n );\n })}\n </>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"progress\":\"BnKli\"};","import { HashObject } from 'libs/common/react/interfaces';\n\nimport { InteractionState } from '../interfaces';\n\n// When updating this please also update $transition in interactive-style-variables.scss\nexport const SLIDING_TIME = 400;\n\nexport function isNewId(id: string): boolean {\n return !!id?.toString().startsWith('new_');\n}\n\nexport function getFilteredState(state: InteractionState): HashObject {\n /**\n * Filter out state props that aren't considered user data\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { error, hasChanges, submitted, spinner, ...filteredState } = state;\n return filteredState;\n}","import React from 'react';\nimport { Spinner } from 'react-bootstrap';\nimport { HtmlPortalNode, InPortal } from 'react-reverse-portal';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { BaseImage } from 'libs/shared/components/image/BaseImage';\nimport { ImageSize, ImageType } from 'libs/shared/enums/Images';\nimport { Interactive, StudentResults } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { PlayerCurrentUser } from 'projects/player/interfaces/models/PlayerCurrentUser';\nimport { InteractionSummary } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/interaction-summary/interaction-summary';\nimport { InteractionsBar } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/interactions-bar/interactions-bar';\nimport { ProgressSummary } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/progress-summary/progress-summary';\nimport { InteractiveState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\n\nimport { getStudentAttempts } from './getstudentAttempts';\n\nimport styles from './interactive-summary.scss';\n\ninterface InteractiveSummaryProps {\n title: string;\n showSummary: boolean;\n setShowSummary: (show: boolean) => void;\n\n imageCdnUrl: string;\n currentUser: PlayerCurrentUser;\n player: VideoJsPlayer;\n state: InteractiveState;\n progress?: ProgressEventPair[];\n interactive: Interactive;\n portalNode: HtmlPortalNode;\n resultsService?: ResultsService;\n goToTimepoint: (timepointId: string, interactionId: string) => void;\n}\n\nexport function InteractiveSummary(props: InteractiveSummaryProps): React.ReactElement {\n const { showSummary, setShowSummary, state, interactive, player, progress, portalNode } = props;\n\n const barRef = React.useRef<HTMLDivElement>(null);\n const [ submitSpinner, setSubmitSpinner ] = React.useState(false);\n\n function switchToPlayer(): void {\n setShowSummary(false);\n\n player.show();\n player.play();\n }\n \n function goToTimepoint(timepointId: string, interactionId: string): void {\n switchToPlayer();\n props.goToTimepoint(timepointId, interactionId);\n }\n\n function onClickPlayAgainOrContinue(): void {\n switchToPlayer();\n\n if (player.ended())\n player.currentTime(0);\n }\n\n function onClickTime(event: React.MouseEvent): void {\n if (!barRef.current)\n return;\n\n const divRect = barRef.current.getBoundingClientRect();\n const divLeft = event.pageX - divRect.left;\n const divWidth = divRect.width;\n\n const time = (divLeft / divWidth) * duration;\n\n switchToPlayer();\n player.currentTime(time);\n }\n\n function onClickSubmit(): void {\n setSubmitSpinner(true);\n player.gradePassbackPlugin().submit(correctCount / total, !awaitingMarking);\n }\n\n if (!portalNode || !showSummary)\n return <></>;\n\n const {\n correctCount,\n total,\n answered,\n studentAttempts,\n awaitingMarking\n } = getStudentAttempts({ interactive, state });\n\n\n const studentResults: StudentResults = {\n user: {\n name: props.currentUser.givenName,\n surname: props.currentUser.familyName,\n avatar: {\n url: props.currentUser.avatar\n }\n } as any,\n results: [{\n id: interactive.id,\n attempts: studentAttempts\n }]\n };\n\n let interactionNumber = 0;\n const ended = player.ended();\n const duration = player.duration();\n\n return (\n <InPortal node={portalNode}>\n <div className='row pb-3'>\n <div className='col-4 col-xs-12'>\n <BaseImage\n data={player.poster()}\n imageType={ImageType.Thumbnails}\n imageOptions={{ size: ImageSize.Medium }}\n />\n </div>\n <div className='col-8 col-xs-12'>\n <span className='float-end'>\n <IconButton\n svgName={cvSvgLibrary.Play}\n className='btn btn-outline-dark'\n onClick={onClickPlayAgainOrContinue}\n >{ended ? 'Play again' : 'Continue watching'}</IconButton>\n {player.gradePassbackPlugin().enabled &&\n (submitSpinner ?\n <DivButton className='btn btn-dark ms-2' onClick={() => {}}>\n <Spinner as='span' animation='border' role='status' size='sm' />\n </DivButton> :\n <IconButton\n svgName={cvSvgLibrary.Check}\n className='btn btn-dark ms-2'\n onClick={onClickSubmit}\n >Submit</IconButton>\n )\n }\n </span>\n <h1 className='h3'>{props.title}</h1>\n <p></p>\n </div>\n </div>\n <div className='border rounder px-2 mb-3'>\n <div className={`cursor-pointer my-4 ${styles.bar}`} onClick={onClickTime} ref={barRef}>\n <ProgressSummary duration={duration} progress={progress} interactive={interactive} player={player} />\n <InteractionsBar duration={duration} interactive={interactive} goToTimepoint={goToTimepoint} />\n </div>\n </div>\n <h2 className='h4'>My Answers</h2>\n <div className='d-flex justify-content-between'>\n <span>\n {interactive.immediateFeedback &&\n <div>Score: {correctCount}/{total}</div>}\n <div className='mb-3'>\n You have answered&nbsp;\n <strong className={answered !== total ? 'text-danger' : ''}>\n {answered}\n </strong>\n &nbsp;of <strong>{total}</strong> questions\n </div>\n </span>\n </div>\n <div className='row'>\n <div className='col-lg-7 col-12'>\n <ul className='list-unstyled'>\n {interactive.timepoints.reduce((prev, timepoint) => {\n return [ ...prev, ...timepoint.interactions.map(interaction => {\n interactionNumber++;\n return (\n <InteractionSummary\n key={interaction.id}\n studentResults={studentResults}\n interaction={interaction}\n timepoint={timepoint}\n interactive={interactive}\n state={state}\n goToTimepoint={goToTimepoint}\n interactionNumber={interactionNumber}\n imageCdnUrl={props.imageCdnUrl}\n />\n );\n }) ];\n }, [])}\n </ul>\n </div>\n </div>\n </InPortal>\n );\n}","import { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { Interactive, StudentAnswer, StudentAttempt } from 'libs/shared/interfaces';\n\nimport { getViewIsCorrect } from 'projects/player/plugins/interactive-plugin/components/view-components/view-components';\nimport { InteractiveState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { getFilteredState } from 'projects/player/plugins/interactive-plugin/utils/helpers';\n\ninterface GetStudentAttemptOptions {\n interactive: Interactive;\n state: InteractiveState;\n}\n\nexport const getStudentAttempts = (options: GetStudentAttemptOptions) => {\n const {\n interactive,\n state\n } = options;\n\n\n let correctCount = 0;\n let total = 0;\n let answered = 0;\n let awaitingMarking = false;\n \n const studentAttempts: StudentAttempt[] = [];\n\n interactive.timepoints.forEach(t => {\n t.interactions.forEach(i => {\n const interactionState = state.interactions[i.id];\n const isCorrect = getViewIsCorrect(i.typeId);\n const correctness = isCorrect(interactionState || {}, i);\n\n if (correctness === InteractionCorrectness.Correct)\n correctCount++;\n\n if (correctness !== InteractionCorrectness.NotApplicable)\n total++;\n\n if (correctness !== InteractionCorrectness.NotApplicable && interactionState?.submitted)\n answered++;\n\n if (correctness === InteractionCorrectness.AwaitingMarking)\n awaitingMarking = true;\n\n const filteredState = getFilteredState(interactionState || {});\n const answers = Object.keys(filteredState).map(k => {\n return {\n id: k,\n text: filteredState[k]?.toString()\n } as StudentAnswer;\n });\n\n if (!answers.length)\n return;\n\n studentAttempts.push({\n id: i.id,\n answeredAt: 1,\n answers\n });\n });\n });\n\n return {\n correctCount,\n total,\n answered,\n studentAttempts,\n awaitingMarking\n };\n};","// extracted by mini-css-extract-plugin\nexport default {\"bar\":\"gxTA_\"};","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\n\nimport './show-summary-button.scss';\n\ninterface ShowSummaryButtonProps {\n setShowSummary: (show: boolean) => void;\n player: VideoJsPlayer;\n interactive: Interactive;\n resultsService?: ResultsService;\n mobile: boolean;\n}\n\nexport function ShowSummaryButton(props: ShowSummaryButtonProps): React.ReactElement {\n const { player, resultsService, interactive, setShowSummary, mobile } = props;\n\n const [ show, setShow ] = React.useState(false);\n const [ isFinished, setIsFinished ] = React.useState(false);\n\n const hasActivityStatusPlugin = props.player.activePlugins_.activityStatusPlugin;\n const hasFavouritePlugin = props.player.activePlugins_.favouritePlugin;\n\n function onClick(): void {\n setShowSummary(true);\n player.pause();\n player.hide();\n }\n\n function onTimeUpdate(): void {\n const currentTime = player.currentTime();\n const timepoint = interactive.timepoints[interactive.timepoints.length - 1];\n\n if (isFinished) {\n setShow(true);\n return;\n }\n\n if (currentTime > (timepoint.visibleAt / 1000) + 1) {\n setShow(true);\n } else {\n setShow(false);\n }\n }\n\n function onEnded(): void {\n setIsFinished(true);\n }\n\n React.useEffect(() => {\n player.on('ended', onEnded);\n return () => player.off('ended', onEnded);\n }, []);\n\n React.useEffect(() => {\n if (!resultsService || mobile)\n return;\n\n player.on('timeupdate', onTimeUpdate);\n return () => player.off('timeupdate', onTimeUpdate);\n }, [isFinished]);\n\n if (!show)\n return null;\n\n let className = 'btn btn-outline-dark cv-show-summary';\n\n if (hasFavouritePlugin)\n className += ' cv-has-favourite-plugin';\n\n if (hasActivityStatusPlugin)\n className += ' cv-has-activity-status-plugin';\n \n return (\n <DivButton\n className={className}\n onClick={onClick}\n >\n {player.gradePassbackPlugin().enabled ? 'Submit answers' : 'View summary'}\n </DivButton>\n );\n}","import React from 'react';\nimport { HtmlPortalNode } from 'react-reverse-portal';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { PlayerCurrentUser } from 'projects/player/interfaces/models/PlayerCurrentUser';\nimport { InteractiveSummary } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/interactive-summary';\nimport { ShowSummaryButton } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/show-summary-button/show-summary-button';\nimport { InteractiveState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\n\ninterface InteractiveSummaryWrapperProps {\n title: string;\n currentUser: PlayerCurrentUser;\n player: VideoJsPlayer;\n state: InteractiveState;\n progress?: ProgressEventPair[];\n interactive: Interactive;\n portalNode: HtmlPortalNode;\n resultsService: ResultsService;\n imageCdnUrl: string;\n goToTimepoint: (timepointId: string, interactionId: string) => void;\n onShowSummary?: (showing: boolean) => void;\n mobile: boolean;\n}\n\nexport function InteractiveSummaryWrapper(props: InteractiveSummaryWrapperProps): React.ReactElement {\n const { resultsService, player, onShowSummary, mobile } = props;\n\n const [ showSummary, _setShowSummary ] = React.useState(false);\n\n function setShowSummary(showSummary: boolean): void {\n _setShowSummary(showSummary);\n onShowSummary && onShowSummary(showSummary);\n }\n\n function onEnded(): void {\n setShowSummary(true);\n player.hide();\n }\n\n React.useEffect(() => {\n if (!resultsService || mobile)\n return;\n\n player.on('ended', onEnded);\n return () => player.off('ended', onEnded);\n }, []);\n\n React.useEffect(() => {\n // When the summary is shown, exit full screen _if_ the user is in fullscreen\n if (!showSummary || !player.isFullscreen())\n return;\n\n player.exitFullscreen();\n }, [showSummary]);\n\n return (\n <>\n <ShowSummaryButton setShowSummary={setShowSummary} {...props} />\n <InteractiveSummary\n showSummary={showSummary}\n setShowSummary={setShowSummary}\n {...props}\n />\n </>\n );\n}","import React from 'react';\n\nimport { LiteSupportArticle } from 'libs/shared/enums/SupportArticle';\nimport { ArticleHelper } from 'libs/shared/utils/ArticleHelper';\n\nexport function QuestionListEmptyState(): React.ReactElement {\n const article = ArticleHelper.getLiteArticle(LiteSupportArticle.MakeInteractive);\n return (\n <div className='my-5 text-center'>\n <h2 className='h3'>Select an interaction to get started</h2>\n <p className='mb-0'>Choose a point in the video and add a question to interact and engage your students.</p>\n {!!article && (\n <a\n href={article}\n target='_blank'\n className='btn btn-link text-info'\n >\n How do I make interactives?\n </a>\n )}\n </div>\n );\n}","import React from 'react';\nimport { HtmlPortalNode, InPortal } from 'react-reverse-portal';\n\nimport { InteractiveQuestions } from 'libs/shared/components/interactive-questions/InteractiveQuestions';\nimport { Interaction, Interactive } from 'libs/shared/interfaces';\n\nimport { QuestionListEmptyState } from './question-list-empty-state';\n\ninterface QuestionListProps {\n isCreate: boolean;\n interactive: Interactive;\n interaction: Interaction;\n portalNode: HtmlPortalNode;\n goToTimepoint: (timepointId: string, interactionId: string) => void;\n promptDelete: (interactionId: string) => void;\n experimentalInteractiveQuestions: boolean;\n}\n\nexport function QuestionList(props: QuestionListProps): React.ReactElement {\n const {\n isCreate,\n interactive,\n interaction,\n portalNode,\n goToTimepoint,\n promptDelete\n } = props;\n\n if (!portalNode)\n return <></>;\n\n /**\n * If we have perf issues, this is the first place we should look\n * This can probably be optimized to not loop through everything every render\n */\n const interactionCount = interactive.timepoints.reduce((prev, current) => prev + current.interactions.length, 0);\n\n return (\n <InPortal node={portalNode}>\n {(() => {\n if (!interactionCount) {\n if (isCreate)\n return <QuestionListEmptyState />;\n\n return <></>;\n }\n \n return (\n <>\n <h2 className='h4 mt-3'>\n Question List ({interactionCount})\n </h2>\n <InteractiveQuestions\n interactive={interactive}\n maxHeight={300}\n goToTimepoint={goToTimepoint}\n selectedInteractionId={interaction?.id}\n onClickDelete={isCreate ? promptDelete : undefined}\n experimentalInteractiveQuestions={props.experimentalInteractiveQuestions}\n />\n </>\n );\n })()}\n </InPortal>\n );\n}","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { ExperimentalInteractionTypes, Interaction, InteractionTypeId, Timepoint } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport { formatTime } from 'projects/player/utils/formatTime';\n\nimport './create-type-selector.scss';\n\ninterface CreateTypeSelectorProps {\n addInteraction: (typeId: InteractionTypeId) => void;\n cancelTypeSelector: () => void;\n player: VideoJsPlayer;\n timepoint: Timepoint;\n interaction: Interaction;\n open: boolean;\n isCreate: boolean;\n experimentalInteractiveQuestions: boolean;\n}\n\nconst INTERACTION_TYPES = [\n InteractionTypeId.MissingWord,\n InteractionTypeId.MultipleChoice,\n InteractionTypeId.TrueOrFalse,\n InteractionTypeId.ShortAnswer,\n InteractionTypeId.Image,\n InteractionTypeId.Annotation\n];\n\nexport function CreateTypeSelector(props: CreateTypeSelectorProps): React.ReactElement {\n const {\n addInteraction,\n cancelTypeSelector,\n player,\n timepoint,\n open,\n isCreate,\n interaction,\n experimentalInteractiveQuestions\n } = props;\n\n const [ currentTime, setCurrentTime ] = React.useState(formatTime(player.currentTime() || 0));\n\n const interactionTypes = [...INTERACTION_TYPES];\n if (experimentalInteractiveQuestions)\n interactionTypes.push(...(Object.keys(ExperimentalInteractionTypes) as unknown as InteractionTypeId[]));\n\n React.useEffect(() => {\n const onTimeUpdate = () => {\n setCurrentTime(formatTime(player.currentTime()));\n };\n\n player.on('timeupdate', onTimeUpdate);\n return () => player.off('timeupdate', onTimeUpdate);\n }, []);\n\n if (interaction || !isCreate || !open)\n return <></>;\n\n return (\n <div\n className={`d-flex align-items-center justify-content-center h-100\n ${experimentalInteractiveQuestions ? 'cv-experimental-types' : ''}\n `}\n >\n <div className='cv-interactive-type-selector justify-content-center align-items-center'>\n <h2 className='text-center fw-bold w-100 text-body mb-3 cv-add-question-copy'>\n {timepoint ? 'Add another question at:' : 'Add a question at:'} {currentTime}\n </h2>\n <ul\n className={`list-unstyled row g-2\n ${experimentalInteractiveQuestions ? 'row-cols-2' : 'row-cols-3'}`\n }\n >\n {interactionTypes.map((type, index) => {\n const {\n name,\n bgClassName,\n Svg\n } = InteractionTypeHelper.getTypeInfo(type);\n return (\n <li className='col' key={index}>\n <DivButton\n className={`cv-type-selector rounded\n ${experimentalInteractiveQuestions ? ' p-2 w-100 d-flex border justify-content-start align-items-center' : `py-2 w-100 ${bgClassName}`}\n `}\n onClick={() => addInteraction(type)}\n >\n <span\n className={`cv-create-type-icon\n ${experimentalInteractiveQuestions ? `text-shadow rounded ${bgClassName} me-2` : 'mb-1'}\n `}\n >\n <Svg />\n </span>\n <div\n className={`d-flex align-items-center justify-content-center cv-interaction-type-name\n ${experimentalInteractiveQuestions ? 'text-dark' : 'px-1 text-shadow'}\n `}\n >\n {name}\n </div>\n </DivButton>\n </li>\n );\n })}\n </ul>\n {(timepoint || open) &&\n <div className={`text-center w-100 mt-2 ${timepoint ? '' : 'cv-adding-first-cancel'}`}>\n <DivButton className='btn btn-link' onClick={cancelTypeSelector}>\n Cancel\n </DivButton>\n </div>\n }\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { HtmlPortalNode, InPortal } from 'react-reverse-portal';\n\nimport { ActionsDropdown, DropdownActionOptions } from 'libs/shared/components/actions/ActionsDropdown';\nimport { Interaction, Timepoint } from 'libs/shared/interfaces';\n\nimport { QuestionView } from 'projects/player/plugins/interactive-plugin/components/timepoint/timepoint-component';\nimport { isNewId } from 'projects/player/plugins/interactive-plugin/utils/helpers';\n\ninterface InteractionActionsProps {\n timepoint: Timepoint;\n interaction: Interaction;\n promptDelete: (id: string) => void;\n optionsPortalNode: HtmlPortalNode;\n setView: (view: QuestionView) => void;\n}\n\nexport function InteractionActions(props: InteractionActionsProps): React.ReactElement {\n const {\n timepoint,\n interaction,\n promptDelete,\n optionsPortalNode,\n setView\n } = props;\n\n if (!interaction)\n return <></>;\n\n const actions: DropdownActionOptions[] = [];\n\n actions.push({\n label: 'Move time point',\n onClick: () => setView('move')\n });\n\n if (timepoint.interactions.length > 1) {\n const isNew = isNewId(interaction.id);\n actions.push({\n label: 'Re-order questions',\n onClick: () => setView('reorder'),\n className: isNew ? 'disabled' : ''\n });\n }\n\n actions.push({\n label: 'Delete',\n onClick: () => promptDelete(interaction.id),\n className: 'text-danger'\n });\n\n return (\n <InPortal node={optionsPortalNode}>\n {!!interaction &&\n <ActionsDropdown\n actions={actions}\n className='p-0 mt-n2'\n dropdownToggleClassName='p-0'\n />\n }\n </InPortal>\n );\n}","import * as React from 'react';\nimport { Spinner } from 'react-bootstrap';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interaction } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { InteractiveIconButton } from 'projects/player/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button';\nimport { InteractionState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { isNewId } from 'projects/player/plugins/interactive-plugin/utils/helpers';\n\ninterface CreateInteractionButtonsProps {\n interaction: Interaction;\n interactionState: InteractionState;\n onClickContinue: () => void;\n onClickSave: () => void;\n onClickCancel: () => void;\n onClickAddAnother: () => void;\n onClickDiscard: () => void;\n}\n\nexport function CreateInteractionButtons(props: CreateInteractionButtonsProps): React.ReactElement {\n const {\n interaction,\n interactionState,\n onClickContinue,\n onClickSave,\n onClickCancel,\n onClickAddAnother,\n onClickDiscard\n } = props;\n\n const isNew = isNewId(interaction.id);\n const hasChanges = !!interactionState?.hasChanges;\n const showSpinner = !!interactionState?.spinner;\n\n return (\n <div className='cv-timpoint-button-container'>\n {(() => {\n if (isNew) {\n return (\n <DivButton className='btn btn-link' onClick={onClickCancel}>\n Cancel\n </DivButton>\n );\n }\n if (!hasChanges) {\n return (\n <DivButton className='btn btn-link' onClick={onClickAddAnother}>\n Add another question\n </DivButton>\n );\n }\n return (\n <DivButton className='btn btn-link' onClick={onClickDiscard}>\n Discard\n </DivButton>\n );\n })()}\n {(() => {\n if (showSpinner) {\n return (\n <DivButton className='btn btn-dark ms-2 cv-interactive-spinner' onClick={() => {}}>\n <Spinner as='span' animation='border' role='status' size='sm' />\n </DivButton>\n );\n }\n\n if (isNew) {\n if (hasChanges) {\n return (\n <DivButton className='btn btn-dark ms-2' onClick={onClickSave}>\n Save\n </DivButton>\n );\n }\n\n return (\n <DivButton className='btn btn-dark ms-2 disabled' onClick={() => {}}>\n Save\n </DivButton>\n );\n }\n\n if (hasChanges) {\n return (\n <DivButton className='btn btn-dark ms-2' onClick={onClickSave}>\n Save\n </DivButton>\n );\n }\n\n return (\n <InteractiveIconButton\n className='btn btn-dark ms-2'\n onClick={onClickContinue}\n svgName={cvSvgLibrary.Play}\n >\n Continue\n </InteractiveIconButton>\n );\n })()}\n </div>\n );\n}\n","import * as React from 'react';\nimport { Spinner } from 'react-bootstrap';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { InteractionTypeId } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { InteractiveIconButton } from 'projects/player/plugins/interactive-plugin/components/interactive-icon-button/interactive-icon-button';\nimport { getViewSubmit } from 'projects/player/plugins/interactive-plugin/components/view-components/view-components';\nimport { InteractionState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ninterface ViewInteractionButtonsProps {\n typeId: InteractionTypeId,\n interactionState: InteractionState;\n onClickSubmit: () => void;\n onClickSkip: () => void;\n currentIndex: number;\n numberOfInteractions: number;\n changeIndex: (index: number) => void;\n}\n\nexport function ViewInteractionButtons(props: ViewInteractionButtonsProps): React.ReactElement {\n const {\n typeId,\n interactionState,\n onClickSkip,\n numberOfInteractions,\n currentIndex,\n changeIndex\n } = props;\n\n const submitted = !!interactionState?.submitted;\n const hasChanges = !!interactionState?.hasChanges;\n const showSpinner = !!interactionState?.spinner;\n\n const shouldSubmit = !!getViewSubmit(typeId);\n\n const showNext = (currentIndex < (numberOfInteractions - 1));\n function onClickNext(): void {\n if (!showNext)\n return;\n\n changeIndex(currentIndex + 1);\n }\n\n const showPrev = (currentIndex > 0);\n function onClickPrev(): void {\n if (!showPrev)\n return;\n changeIndex(currentIndex - 1);\n }\n\n function onClickSubmit(): void {\n if (!hasChanges)\n return;\n\n props.onClickSubmit();\n }\n\n return (\n <div className='cv-timpoint-button-container flex-wrap'>\n {!submitted && shouldSubmit &&\n <DivButton className='btn btn-link' onClick={onClickSkip}>\n Come back later\n </DivButton>\n }\n {numberOfInteractions > 1 && currentIndex > 0 &&\n <InteractiveIconButton\n className={`btn btn-dark ms-2 ${showPrev ? '' : 'disabled'}`}\n onClick={onClickPrev}\n svgName={cvSvgLibrary.ChevronUp}\n />\n }\n {(() => {\n if (showSpinner) {\n return (\n <DivButton className='btn btn-dark ms-2 cv-interactive-spinner' onClick={() => {}}>\n <Spinner as='span' animation='border' role='status' size='sm' />\n </DivButton>\n );\n }\n\n if (submitted || !shouldSubmit) {\n if (numberOfInteractions === 1 || currentIndex === (numberOfInteractions - 1)) {\n return (\n <InteractiveIconButton\n className='btn btn-dark ms-2'\n onClick={onClickSkip}\n svgName={cvSvgLibrary.Play}\n >\n Continue\n </InteractiveIconButton>\n );\n }\n return (\n <DivButton className={`btn btn-dark ms-2 ${showNext ? '' : 'disabled'}`} onClick={onClickNext}>\n Next\n </DivButton>\n );\n }\n\n return (\n <DivButton className={`btn btn-dark ms-2 ${hasChanges ? '' : 'disabled'}`} onClick={onClickSubmit}>\n Save\n </DivButton>\n );\n })()}\n </div>\n );\n}\n","import React from 'react';\n\nimport { Interaction, Timepoint } from 'libs/shared/interfaces';\n\nimport { CreateInteractionButtons } from 'projects/player/plugins/interactive-plugin/components/create-components/create-interaction-buttons/create-interaction-buttons';\nimport { ViewInteractionButtons } from 'projects/player/plugins/interactive-plugin/components/view-components/view-interaction-buttons/view-iteraction-buttons';\nimport { InteractionState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ninterface InteractionFooterProps {\n isCreate: boolean;\n interaction: Interaction;\n timepoint: Timepoint;\n interactionState: InteractionState;\n currentIndex: number;\n continueInteractive: () => void;\n saveInteraction: () => void;\n cancel: () => void;\n addAnotherQuestion: () => void;\n discardChanges: (after?: () => void) => void;\n submitInteractionAnswer: () => void;\n onClickSkip: () => void;\n changeIndex: (index: number) => void;\n}\n\nexport function InteractionFooter(props: InteractionFooterProps): React.ReactElement {\n const {\n isCreate,\n interaction,\n interactionState,\n continueInteractive,\n saveInteraction,\n cancel,\n addAnotherQuestion,\n discardChanges,\n submitInteractionAnswer,\n onClickSkip,\n changeIndex,\n timepoint,\n currentIndex\n } = props;\n\n return (\n <>\n {isCreate ?\n <CreateInteractionButtons\n interaction={interaction}\n interactionState={interactionState}\n onClickContinue={continueInteractive}\n onClickSave={saveInteraction}\n onClickCancel={cancel}\n onClickAddAnother={addAnotherQuestion}\n onClickDiscard={() => discardChanges()} // Intentional so the event doesn't get passed in\n /> :\n <ViewInteractionButtons\n typeId={interaction.typeId}\n interactionState={interactionState}\n onClickSubmit={submitInteractionAnswer}\n onClickSkip={onClickSkip}\n changeIndex={changeIndex}\n currentIndex={currentIndex}\n numberOfInteractions={timepoint.interactions.length}\n />\n }\n </>\n );\n}","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { InteractionTypeId } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { formatTime } from 'projects/player/utils/formatTime';\n\ninterface CreateInteractionHeadingProps {\n typeId: InteractionTypeId;\n currentIndex: number;\n numberOfInteractions: number;\n changeIndex: (index: number) => void;\n player: VideoJsPlayer;\n}\n\nexport function CreateInteractionHeading(props: CreateInteractionHeadingProps): React.ReactElement {\n const {\n typeId,\n currentIndex,\n numberOfInteractions,\n changeIndex,\n player\n } = props;\n\n const [ currentTime, setCurrentTime ] = React.useState(formatTime(player.currentTime() || 0));\n\n React.useEffect(() => {\n const onTimeUpdate = () => {\n setCurrentTime(formatTime(player.currentTime()));\n };\n\n player.on('timeupdate', onTimeUpdate);\n return () => player.off('timeupdate', onTimeUpdate);\n }, []);\n\n const {\n name,\n bgClassName\n } = InteractionTypeHelper.getTypeInfo(typeId);\n\n const showNext = (currentIndex < (numberOfInteractions - 1));\n function onClickNext(): void {\n if (!showNext)\n return;\n\n changeIndex(currentIndex + 1);\n }\n\n const showPrev = (currentIndex > 0);\n function onClickPrev(): void {\n if (!showPrev)\n return;\n changeIndex(currentIndex - 1);\n }\n\n return (\n <div className={`text-center d-flex justify-content-between align-items-center p-1 ${bgClassName}`}>\n <DivButton\n onClick={onClickPrev}\n className={showPrev ? '' : 'invisible'}\n >\n <SvgContainer\n size={SvgContainerSize.Medium}\n svgName={cvSvgLibrary.ChevronLeft}\n />\n </DivButton>\n <div>\n <h2 className='h6 mb-0'>{name}</h2>\n {(numberOfInteractions > 1) &&\n <div>\n {currentIndex + 1} of {numberOfInteractions} at {currentTime}\n </div>\n }\n </div>\n <DivButton\n onClick={onClickNext}\n className={showNext ? '' : 'invisible'}\n >\n <SvgContainer\n size={SvgContainerSize.Medium}\n svgName={cvSvgLibrary.ChevronRight}\n />\n </DivButton>\n </div>\n );\n}\n","import React from 'react';\n\nimport { ClickDescriptor, EntityType, LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { ImmersiveReader } from 'libs/shared/components/immersive-reader/ImmersiveReader';\nimport { Interaction, InteractionTypeId } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport styles from './interactive-immersive-reader.scss';\n\nconst alphabet = [ 'A', 'B', 'C', 'D' ];\n\ninterface InteractiveImmersiveReaderProps {\n interaction: Interaction;\n className?: string;\n enableImmersiveReader: boolean;\n}\n\nexport function InteractiveImmersiveReader(props: InteractiveImmersiveReaderProps): React.ReactElement {\n if (!props.enableImmersiveReader)\n return <></>;\n\n const { interaction, className } = props;\n\n const { name, typeName } = InteractionTypeHelper.getTypeInfo(interaction.typeId);\n\n let text = '';\n\n switch (interaction.typeId) {\n case InteractionTypeId.Annotation:\n text = interaction.data.annotation;\n break;\n case InteractionTypeId.Image:\n text = interaction.data.caption;\n break;\n case InteractionTypeId.MissingWord:\n text = (interaction.data.sentence as string).replace(/{([^{}]*)}/g, () => {\n return '<u>&nbsp;&nbsp;&nbsp;&nbsp;</u>';\n });\n break;\n case InteractionTypeId.MultipleChoice:\n text = interaction.name;\n interaction.actionableItems.map((a, i) => text += `<br />${alphabet[i]}: ${a.name}`);\n break;\n case InteractionTypeId.ShortAnswer:\n text = interaction.name;\n break;\n case InteractionTypeId.TrueOrFalse:\n text = `True or false: ${interaction.name}`;\n break;\n }\n\n const isHtml = interaction.typeId === InteractionTypeId.Annotation\n || interaction.typeId === InteractionTypeId.MissingWord\n || interaction.typeId === InteractionTypeId.MultipleChoice;\n\n return (\n <ImmersiveReader\n title={name}\n text={text}\n html={isHtml}\n className={`${styles.reader} ${className || ''}`}\n analyticsData={{\n id: interaction.interactiveId,\n type: typeName\n }}\n analyticsOptions={{\n location: LocationContext.InteractivePlayer,\n entity: EntityType.Interactive,\n actionType: UserAction.Click,\n descriptor: ClickDescriptor.LaunchImmersiveReader\n }}\n />\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"reader\":\"Erirh\"};","import React from 'react';\n\nimport { Interaction } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport { InteractiveImmersiveReader } from '../interactive-immersive-reader/interactive-immersive-reader';\n\nimport './view-interaction-heading.scss';\n\ninterface ViewInteractionHeadingProps {\n enableImmersiveReader: boolean;\n interaction: Interaction\n}\n\nexport function ViewInteractionHeading(props: ViewInteractionHeadingProps): React.ReactElement {\n const {\n name,\n prompt,\n bgClassName,\n Svg\n } = InteractionTypeHelper.getTypeInfo(props.interaction.typeId);\n\n return (\n <div className='text-center text-body d-flex justify-content-between align-items-center px-3 pt-3'>\n <div className='d-flex align-items-center'>\n <span className={`cv-interaction-icon rounded my-1 text-white ${bgClassName}`}>\n <Svg />\n </span>\n <span className='text-start flex-grow-1'>\n <div className={`h5 ${prompt ? '' : 'mb-0'}`}>\n <strong>{name}</strong>\n </div>\n {prompt && <div className='h6 mb-0'>{prompt}</div>}\n </span>\n </div>\n <InteractiveImmersiveReader\n interaction={props.interaction}\n className='ms-2'\n enableImmersiveReader={props.enableImmersiveReader}\n />\n </div>\n );\n}\n","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { Interaction, Timepoint } from 'libs/shared/interfaces';\n\nimport { CreateInteractionHeading } from 'projects/player/plugins/interactive-plugin/components/create-components/create-interaction-heading/create-interaction-heading';\nimport { ViewInteractionHeading } from 'projects/player/plugins/interactive-plugin/components/view-components/view-interaction-heading/view-interaction-heading';\nimport { TimepointState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\n\ninterface InteractionHeaderProps {\n isCreate: boolean;\n interaction: Interaction;\n timepointState: TimepointState;\n timepoint: Timepoint;\n player: VideoJsPlayer;\n changeIndex: (index: number) => void;\n enableImmersiveReader: boolean;\n}\n\nexport function InteractionHeader(props: InteractionHeaderProps): React.ReactElement {\n const {\n isCreate,\n interaction,\n player,\n changeIndex,\n timepointState,\n timepoint\n } = props;\n\n if (isCreate) {\n return (\n <CreateInteractionHeading\n typeId={interaction.typeId}\n changeIndex={changeIndex}\n player={player}\n currentIndex={timepointState.interactionIndex}\n numberOfInteractions={timepoint.interactions.length}\n />\n );\n }\n\n return (\n <ViewInteractionHeading\n interaction={interaction}\n enableImmersiveReader={props.enableImmersiveReader}\n />\n );\n}","import React from 'react';\n\ninterface CreateErrorFeedbackProps {\n id?: string;\n error?: string;\n}\n\nexport function CreateErrorFeedback(props: CreateErrorFeedbackProps): React.ReactElement {\n const { error } = props;\n\n if (!props.error)\n return <></>;\n\n return (\n <p\n id={props.id}\n className='mt-2 small text-danger'\n role='status'\n >\n {error}\n </p>\n );\n}\n","import { Interaction, Timepoint } from 'libs/shared/interfaces';\n\nimport { isNewId } from 'projects/player/plugins/interactive-plugin/utils/helpers';\nimport { AjaxHelper, AjaxOptions } from 'projects/player/utils/ajax-helper';\n\nconst endpoints = {\n createInteraction: () => '/api/domain/v1/interactions/bulk',\n updateInteraction: (id: string) => `/api/domain/v1/interactions/bulk/${id}`,\n deleteInteraction: (id: string) => `/api/domain/v1/interactions/${id}`,\n createTimepoint: () => '/api/domain/v1/timepoints',\n deleteTimepoint: (id: string) => `/api/domain/v1/timepoints/${id}`,\n updateTimepoint: (id: string) => `/api/domain/v1/timepoints/${id}`\n};\n\n// Uncomment the token name when we wire this up to gateway api\nconst options: AjaxOptions = {\n // tokenName: 'gateway'\n};\n\nclass InteractiveAjaxSingleton {\n public async saveInteraction(interaction: Interaction): Promise<void> {\n const isNew = isNewId(interaction.id);\n\n const url = isNew ?\n endpoints.createInteraction() :\n endpoints.updateInteraction(interaction.id);\n\n const data: Interaction = {\n name: interaction.name,\n data: interaction.data,\n timepointId: interaction.timepointId,\n interactiveId: interaction.interactiveId,\n typeId: interaction.typeId,\n actionableItems: interaction.actionableItems,\n order: interaction.order\n };\n\n if (!isNew)\n data.id = interaction.id;\n\n const promise = isNew\n ? AjaxHelper.post<Interaction>(url, JSON.stringify(data), options)\n : AjaxHelper.put<Interaction>(url, JSON.stringify(data), options);\n\n const newInteraction = await promise;\n\n if (isNew)\n interaction.id = newInteraction.id;\n }\n\n public async deleteInteraction(id: string): Promise<void> {\n await AjaxHelper.delete(endpoints.deleteInteraction(id), options);\n }\n\n public async saveTimepoint(timepoint: Timepoint): Promise<void> {\n const data = {\n interactiveId: timepoint.interactiveId,\n shouldPause: 1,\n visibleAt: timepoint.visibleAt\n };\n\n const result = await AjaxHelper.post<Timepoint>(endpoints.createTimepoint(), JSON.stringify(data), options);\n\n timepoint.id = result.id;\n }\n\n public async updateTimepoint(timepoint: Timepoint): Promise<void> {\n await AjaxHelper.put<Timepoint>(endpoints.updateTimepoint(timepoint.id), JSON.stringify(timepoint), options);\n }\n\n public async deleteTimepoint(id: string): Promise<void> {\n await AjaxHelper.delete(endpoints.deleteTimepoint(id), options);\n }\n}\n\nexport const InteractiveAjax = new InteractiveAjaxSingleton();\n","import React from 'react';\n\n// Docs: https://github.com/HubSpot/draft-convert#converttohtml\nexport const draftConvertOptions = {\n styleToHTML: (style: any) => {\n if (style === 'SUPERSCRIPT') {\n return {\n start: '<sup>',\n end: '</sup>'\n };\n }\n if (style === 'SUBSCRIPT') {\n return {\n start: '<sub>',\n end: '</sub>'\n };\n }\n },\n entityToHTML: (entity: any, originalText: any) => {\n if (entity.type === 'LINK') {\n return <a href={entity.data.url}>{originalText}</a>;\n }\n return originalText;\n },\n htmlToStyle: (nodeName: any, node: any, currentStyle: any) => {\n if (nodeName === 'sup') {\n return currentStyle.add('SUPERSCRIPT');\n }\n if (nodeName === 'sub') {\n return currentStyle.add('SUBSCRIPT');\n }\n\n return currentStyle;\n },\n htmlToEntity: (nodeName: any, node: any, createEntity: any) => {\n if (nodeName === 'a') {\n return createEntity(\n 'LINK',\n 'MUTABLE',\n { url: node.href }\n );\n }\n }\n};","import React from 'react';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\n\ninterface LinkState {\n link: string;\n selectionText: string;\n}\n\ninterface CreateAnnotationLinkProps {\n onChange: (tool: 'link', text: string, url: string, target: '_blank') => void;\n expanded: boolean;\n onExpandEvent: () => void;\n currentState: LinkState;\n}\n\nexport function CreateAnnotationLink(props: CreateAnnotationLinkProps) {\n const [ url, setUrl ] = React.useState('');\n const [ text, setText ] = React.useState('');\n\n return (\n <div\n aria-haspopup='true'\n aria-expanded={props.expanded}\n aria-label='rdw-color-picker'\n >\n <div\n className='rdw-option-wrapper cv-annotation-toolbar-option cv-annotation-link'\n onClick={props.onExpandEvent}\n >\n &nbsp;\n </div>\n\n {props.expanded && (\n <div className='rdw-link-modal' onClick={e => e.stopPropagation()}>\n <div className='form-group'>\n <label className='cv-interaction-field-label' htmlFor='cv-annotation-url'>URL</label>\n <input\n id='cv-annotation-url'\n className='form-control'\n onChange={e => setUrl(e.target.value)}\n value={url}\n placeholder='Enter URL'\n autoComplete='off'\n />\n </div>\n\n <div className='form-group'>\n <label className='cv-interaction-field-label' htmlFor='cv-annotation-text'>Text</label>\n <input\n id='cv-annotation-text'\n className='form-control'\n onChange={e => setText(e.target.value)}\n value={text}\n placeholder='Enter Text'\n autoComplete='off'\n />\n </div>\n\n <DivButton\n onClick={() => props.onChange('link', text || url, url, '_blank')}\n className='btn btn-dark'\n >\n Add\n </DivButton>\n </div>\n )}\n </div>\n );\n}","import React from 'react';\n\ninterface UploadImageDropzoneProps {\n onDropImage: (files: FileList) => void;\n dragClassName: string;\n}\n\nexport function UploadImageDropzone(props: React.PropsWithChildren<UploadImageDropzoneProps>): JSX.Element {\n const [ isDragging, setIsDragging ] = React.useState(false);\n const [ dragCounter, setDragCounter ] = React.useState(0);\n\n React.useEffect(() => {\n if (dragCounter === 0 && isDragging)\n setIsDragging(false);\n }, [ dragCounter, isDragging, setIsDragging ]);\n\n function onDrag(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n function onDragEnter(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n e.stopPropagation();\n\n setDragCounter(currentVal => currentVal + 1);\n\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0 && !isDragging)\n setIsDragging(true);\n }\n \n function onDragLeave(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n e.stopPropagation();\n\n setDragCounter(currentVal => currentVal - 1);\n }\n\n function onDrop(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n e.stopPropagation();\n\n setIsDragging(false);\n\n if (dragCounter > 0)\n setDragCounter(0);\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n props.onDropImage(e.dataTransfer.files);\n e.dataTransfer.clearData();\n }\n }\n\n return (\n <div\n onDragOver={onDrag}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDrop={onDrop}\n className={isDragging ? props.dragClassName : ''}\n >\n {props.children}\n </div>\n );\n}","import React from 'react';\nimport { OutPortal } from 'react-reverse-portal';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { CreateInteractionState, InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\n\nconst CHAR_REGEX = /[.\\?!,;:\\-''\\(\\)]/g;\n\ninterface Word {\n text: string;\n order: number;\n selected: boolean;\n}\n\ninterface CreateMissingWordState extends CreateInteractionState {\n // No words missing\n fullSentence: string;\n // Words replaced with {1}\n sentence: string;\n // Words replaced with underscores\n preview: string;\n words: Word[];\n}\n\nfunction stripTailChars(word: string): string {\n const chars = word.split('');\n\n while (chars.length && chars[0].match(CHAR_REGEX))\n chars.shift();\n\n while (chars.length && chars[chars.length - 1].match(CHAR_REGEX))\n chars.pop();\n\n return chars.join('');\n}\n\nfunction handleTailChars(startWord: string, intendedWord: string): string {\n const chars = startWord.split('');\n\n const start: string[] = [];\n const end: string[] = [];\n\n while (chars.length && chars[0].match(CHAR_REGEX))\n start.push(chars.shift());\n\n while (chars.length && chars[chars.length - 1].match(CHAR_REGEX))\n end.unshift(chars.pop());\n\n return start.join('') + intendedWord + end.join('');\n}\n\nfunction generatePreview(words: Word[]): string {\n const previewWords = words.map(word => {\n if (!word.selected)\n return word.text;\n\n const wordLength = stripTailChars(word.text).length;\n const underscoreString = new Array(wordLength).fill('_').join('');\n\n return handleTailChars(word.text, underscoreString);\n });\n\n return previewWords.join(' ');\n}\n\nfunction generateSentence(words: Word[]): string {\n return words.map(word => {\n if (!word.selected)\n return word.text;\n\n return handleTailChars(word.text, `{${word.order}}`)?.trim();\n }).join(' ');\n}\n\nfunction generateInitialState(interaction: Interaction): CreateMissingWordState {\n const sentence: string = interaction.data?.sentence || '';\n const placeholderWords = sentence.split(' ').filter(Boolean);\n const words = placeholderWords.map((word, index) => ({\n text: word,\n order: index,\n selected: false\n }));\n\n interaction.actionableItems?.forEach(actionableItem => {\n const { order } = actionableItem;\n\n const reconstructed = handleTailChars(placeholderWords[order], actionableItem.name);\n\n placeholderWords[order] = reconstructed;\n words[order].text = reconstructed;\n words[order].selected = true;\n });\n\n const fullSentence = placeholderWords.join(' ');\n\n return {\n fullSentence,\n sentence,\n // Words replaced with underscores\n preview: interaction.name,\n words\n };\n}\n\nconst MAX_LENGTH = 255;\n\nexport function ValidateMissingWord(state: CreateMissingWordState): string {\n if (!state.sentence?.trim())\n return 'Please provide a sentence';\n \n if (state.sentence?.trim().length > MAX_LENGTH)\n return `Max length is ${MAX_LENGTH} characters`;\n\n if (!state.words.find(word => word.selected))\n return 'Please select a missing word';\n\n return null;\n}\n\nexport async function SubmitMissingWord(state: CreateMissingWordState, interaction: Interaction): Promise<void> {\n interaction.data.sentence = generateSentence(state.words);\n interaction.name = state.preview;\n\n const selectedWords = state.words.filter(word => word.selected);\n\n interaction.actionableItems = selectedWords.map(word => ({\n name: stripTailChars(word.text),\n order: word.order,\n isCorrect: true\n }));\n\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateMissingWord(props: InteractionProps<CreateMissingWordState>): JSX.Element {\n const {\n state = generateInitialState(props.interaction),\n setState,\n optionsPortalNode\n } = props;\n\n const hasSentence = !!state.sentence;\n\n function onChangeSentence(event: React.ChangeEvent<HTMLInputElement>): void {\n const fullSentence = event.target.value;\n\n const words = fullSentence.split(' ')\n .filter(Boolean)\n .map((word, index) => ({\n text: word,\n order: index,\n selected: false\n }));\n\n // Everytime the sentence is changed, all other state is reset.\n setState({\n ...state,\n fullSentence,\n sentence: generateSentence(words),\n preview: generatePreview(words),\n words\n });\n }\n\n function onClickWord(wordIndex: number): void {\n const newWords = state.words.map(word => {\n if (word.order !== wordIndex)\n return word;\n\n return {\n ...word,\n selected: !word.selected\n };\n });\n\n setState({\n ...state,\n words: newWords,\n preview: generatePreview(newWords),\n sentence: generateSentence(newWords)\n });\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='form-group'>\n <div className='d-flex justify-content-between align-items-center'>\n <label className='cv-interaction-field-label' htmlFor='missing-word-sentence'>\n Sentence\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n <input\n id='missing-word-sentence'\n className='form-control'\n placeholder='Enter your sentence here'\n value={state.fullSentence || ''}\n onChange={onChangeSentence}\n autoComplete='off'\n />\n </div>\n\n {hasSentence && (\n <>\n <div className='form-group'>\n <label className='cv-interaction-field-label'>Select the missing word(s)</label>\n <ul className='list-unstyled d-flex flex-wrap mx-n1 mb-n1'>\n {state.words.map((word, i) => {\n const withOutTailChars = stripTailChars(word.text)?.trim();\n\n if (!withOutTailChars)\n return <React.Fragment key={`${i}-${word.text}`} />;\n\n return (\n <li key={`${i}-${word.text}`}>\n <DivButton\n className={`rounded border p-2 mx-1 mb-1 cursor-pointer ${word.selected ? 'bg-dark text-white' : 'bg-white'}`}\n onClick={() => onClickWord(i)}\n >\n {stripTailChars(word.text)}\n </DivButton>\n </li>\n );\n })}\n </ul>\n </div>\n\n <div>\n <label className='cv-interaction-field-label'>Preview</label>\n <p>{state.preview}</p>\n </div>\n </>\n )}\n <CreateErrorFeedback error={state.error} />\n </div>\n );\n}\n","import React from 'react';\n\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\ninterface FeedbackTooltipProps {\n tooltipText: string;\n}\n\nexport function FeedbackTooltip(props: FeedbackTooltipProps): JSX.Element {\n return (\n <Tooltip title={props.tooltipText} spanHack spanHackClassName='d-inline-block'>\n <SvgContainer svgName={cvSvgLibrary.Info} />\n </Tooltip>\n );\n}\n","import React from 'react';\n\nexport function UploadImageIcon(): JSX.Element {\n return (\n <svg viewBox='0 0 43 38' className='cv-upload-image-icon'>\n <g transform='translate(-1193.000000, -185.000000)'>\n <g transform='translate(1183.000000, 173.000000)'>\n <path d='M49.875,12.9166667 C51.3247475,12.9166667 52.5,14.0732644 52.5,15.5 L52.5,46.5 C52.5,47.9267356 51.3247475,49.0833333 49.875,49.0833333 L13.125,49.0833333 C11.6752525,49.0833333 10.5,47.9267356 10.5,46.5 L10.5,15.5 C10.5,14.0732644 11.6752525,12.9166667 13.125,12.9166667 L49.875,12.9166667 Z M49.875,15.5 L13.125,15.5 L13.125,46.5 L49.875,46.5 L49.875,15.5 Z M35.5085905,22.5470241 L45.7260956,38.0470241 C46.1206004,38.6454897 45.9474325,39.445375 45.3393142,39.8336178 C44.731196,40.2218607 43.9184093,40.0514415 43.5239044,39.4529759 L34.3641741,25.5576247 L29.9489593,31.7425222 C29.4803332,32.3989804 28.5233602,32.4806343 27.9469223,31.9133463 L26.3920049,30.38311 L19.425,39.525 C18.9900758,40.0956942 18.167399,40.211354 17.5875,39.7833333 C17.007601,39.3553127 16.8900758,38.5456942 17.325,37.975 L25.2,27.6416667 C25.6792326,27.0128323 26.6132966,26.9475041 27.1780777,27.5033204 L28.6987913,28.9998957 L33.3335357,22.5074778 C33.8680838,21.758675 35.0025121,21.7793009 35.5085905,22.5470241 Z M21,19.375 C23.1746212,19.375 24.9375,21.1098966 24.9375,23.25 C24.9375,25.3901034 23.1746212,27.125 21,27.125 C18.8253788,27.125 17.0625,25.3901034 17.0625,23.25 C17.0625,21.1098966 18.8253788,19.375 21,19.375 Z M21,21.9583333 C20.2751263,21.9583333 19.6875,22.5366322 19.6875,23.25 C19.6875,23.9633678 20.2751263,24.5416667 21,24.5416667 C21.7248737,24.5416667 22.3125,23.9633678 22.3125,23.25 C22.3125,22.5366322 21.7248737,21.9583333 21,21.9583333 Z' id='Combined-Shape'></path>\n </g>\n </g>\n </svg>\n );\n}","import React from 'react';\n\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { ImageType } from 'libs/shared/enums/Images';\nimport { CropperHelper } from 'libs/shared/utils/CropperHelper';\nimport { ImageSelectHelper } from 'libs/shared/utils/ImageSelectHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { UploadImageDropzone } from 'projects/player/plugins/interactive-plugin/components/create-components/create-image/upload-image-dropzone';\nimport { UploadImageIcon } from 'projects/player/plugins/interactive-plugin/components/create-components/create-image/upload-image-icon';\nimport { AjaxHelper } from 'projects/player/utils/ajax-helper';\n\nimport { MultipleChoiceAnswer } from './create-multiple-choice';\n\ninterface MultipleChoiceAnswerProps {\n answer: MultipleChoiceAnswer;\n onChange: (answer: MultipleChoiceAnswer) => void;\n isTrueOrFalse: boolean;\n imageApi: URL;\n}\n\nexport function MultipleChoiceAnswer(props: MultipleChoiceAnswerProps): JSX.Element {\n const labelRef = React.useRef(null);\n const imageInputRef = React.useRef(null);\n\n function onToggleCheckbox(): void {\n props.onChange({\n ...props.answer,\n isCorrect: !props.answer.isCorrect\n });\n }\n\n function onChangeName(e: React.ChangeEvent<HTMLInputElement>): void {\n props.onChange({\n ...props.answer,\n name: e.target.value\n });\n }\n\n function onImageSelect(files: FileList): void {\n if (props.isTrueOrFalse)\n return;\n\n if (!files || !files[0])\n return;\n\n ImageSelectHelper.onFileSelect(ImageType.None, files, image => {\n CropperHelper.renderCropper({\n src: image.src,\n alt: '',\n onClickCrop\n });\n });\n }\n\n function onClickCrop(imageUrl: string, closePopup: () => void): void {\n const base64 = imageUrl.split(',')[1];\n AjaxHelper.post<HashObject>(`${props.imageApi}v2/thumbnails/base64`, `\"${base64}\"`, { tokenName: 'gateway' })\n .then(res => {\n props.onChange({\n ...props.answer,\n data: {\n imageUrl: res.location\n }\n });\n\n closePopup();\n })\n .catch(() => alert('Something went wrong while trying to upload image. Please try again.'));\n }\n\n\n function onClickRemove(): void {\n props.onChange({\n ...props.answer,\n data: undefined\n });\n }\n\n return (\n <UploadImageDropzone onDropImage={onImageSelect} dragClassName='cv-multiple-choice-upload-mask'>\n <div className='p-2 my-1 w-100 bg-white d-flex align-items-center rounded cv-multiple-choice-answer'>\n <div\n className={`form-check`}\n onKeyDown={(e: React.KeyboardEvent) => e.key === 'Enter' && onToggleCheckbox()}\n >\n <input\n id={`multiple-choice--${props.answer.order}`}\n type={props.isTrueOrFalse ? 'radio' : 'checkbox'}\n className='form-check-input me-2'\n name='multiple-choice-answer'\n checked={props.answer.isCorrect}\n onChange={onToggleCheckbox}\n disabled={!props.answer.name && !props.answer.data?.imageUrl}\n aria-label={`Correct answer ${props.answer.order}`}\n />\n <label ref={labelRef} htmlFor={`multiple-choice--${props.answer.order}`} className='cursor-pointer form-check-label'></label>\n </div>\n\n {props.isTrueOrFalse\n ? <label\n className='mb-0'\n htmlFor={`multiple-choice--${props.answer.order}`}>{props.answer.name}</label>\n : <input\n placeholder='Answer'\n onChange={onChangeName}\n value={props.answer.name}\n className='border-0 outline-none w-100 me-2'\n autoComplete='off'\n />\n }\n {!props.isTrueOrFalse &&\n <>\n <input\n type='file'\n className='file-select d-none'\n multiple={false}\n accept='image/jpg,image/jpeg,image/png'\n ref={imageInputRef}\n onChange={e => onImageSelect(e.target.files)}\n />\n \n {props.answer.data?.imageUrl ?\n // Keys are important to reset the hover on the tooltip when an image is added - Sha\n <Tooltip key='1' title='Remove image' spanHack spanHackClassName='mt-n2 mb-n2 me-n2'>\n <DivButton\n type='button'\n className='cv-multiple-choice-create-image rounded-end bg-gray-400'\n style={{ backgroundImage: `url(${props.answer.data.imageUrl})` }}\n onClick={onClickRemove}\n >\n <span className='cv-multiple-choice-remove-image'>\n <SvgContainer svgName={cvSvgLibrary.Delete} />\n </span>\n </DivButton>\n </Tooltip> :\n <Tooltip key='2' title='Upload an image' spanHack>\n <DivButton\n type='button'\n className='svg-container'\n onClick={() => {\n imageInputRef.current.value = null;\n imageInputRef.current.click(null);\n }}\n >\n <UploadImageIcon />\n </DivButton>\n </Tooltip>\n }\n </>\n }\n </div>\n </UploadImageDropzone>\n );\n}\n","import React from 'react';\nimport { OutPortal } from 'react-reverse-portal';\nimport TextareaAutosize from 'react-textarea-autosize';\n\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { FeedbackTooltip } from 'libs/shared/components/feedback-tooltip/FeedbackTooltip';\nimport { useDisableVideoDragDrop } from 'libs/shared/hooks/UseVideoDragDropState';\nimport { Interaction, InteractionTypeId } from 'libs/shared/interfaces';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { CreateInteractionState, InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\n\nimport { MultipleChoiceAnswer } from './multiple-choice-answer';\n\nimport './create-multiple-choice.scss';\n\nconst MIN_ANSWERS = 2;\nconst MAX_ANSWERS = 4;\n\nexport interface MultipleChoiceAnswer {\n order: number;\n name: string;\n isCorrect: boolean;\n data?: {\n imageUrl: string;\n };\n}\n\ninterface CreateMultipleChoiceState extends CreateInteractionState {\n question: string;\n answers: MultipleChoiceAnswer[]\n feedback?: string;\n}\n\nfunction getInitialState(interaction: Interaction): CreateMultipleChoiceState {\n const isTrueOrFalse = interaction.typeId === InteractionTypeId.TrueOrFalse;\n\n let answers = interaction.actionableItems?.map(a => ({\n order: a.order,\n name: a.name,\n isCorrect: a.isCorrect,\n data: a.data ? {\n imageUrl: a.data.imageUrl\n } : null\n }));\n\n if (!answers?.length) {\n answers = [{\n order: 0,\n name: isTrueOrFalse ? 'True' : '',\n isCorrect: false,\n data: null\n }, {\n order: 1,\n name: isTrueOrFalse ? 'False' : '',\n isCorrect: false,\n data: null\n }];\n } else if (!isTrueOrFalse && answers?.length < MAX_ANSWERS) {\n answers.push({\n order: answers.length,\n name: '',\n isCorrect: false,\n data: null\n });\n }\n\n return {\n question: interaction.name || '',\n answers,\n feedback: interaction.data.feedback || ''\n };\n}\n\nconst MAX_ANSWER_LENGTH = 255;\nconst MAX_QUESTION_LENGTH = 500;\n\nexport function ValidateMultipleChoice(state: CreateMultipleChoiceState): string {\n if (!state.question?.trim())\n return 'Please provide a question';\n\n if (state.question?.trim().length > MAX_QUESTION_LENGTH) {\n return `Max question length is ${MAX_QUESTION_LENGTH} characters`;\n }\n\n if (!state.answers.find(a => a.isCorrect))\n return 'Please select the correct answer';\n\n if (state.answers.find(a => a.name?.length > MAX_ANSWER_LENGTH))\n return `Max answer length is ${MAX_ANSWER_LENGTH} characters`;\n\n const validAnswers = state.answers.filter(a => !!a.name?.trim() || !!a.data?.imageUrl);\n if (validAnswers.length < 2)\n return 'Please provide at least two answers';\n\n const textAnswers = state.answers.filter(a => !!a.name?.trim());\n if (textAnswers.length && textAnswers.length !== validAnswers.length)\n return 'Please add text to every question or none of the questions.';\n\n let hasDuplicates = false;\n const answerDuplicateTracker: HashObject = {};\n\n textAnswers.forEach(a => {\n if (hasDuplicates)\n return;\n\n if (!answerDuplicateTracker[a.name]) {\n answerDuplicateTracker[a.name] = true;\n return;\n }\n\n hasDuplicates = true;\n });\n\n if (hasDuplicates)\n return 'There are duplicates in your answers';\n\n const imageCount = validAnswers.filter(a => a.data?.imageUrl).length;\n if (imageCount && imageCount < validAnswers.length)\n return 'Please add an image to all answers';\n\n return null;\n}\n\nexport async function SubmitMultipleChoice(state: CreateMultipleChoiceState, interaction: Interaction): Promise<void> {\n interaction.name = state.question?.trim();\n interaction.actionableItems = state.answers.filter(a => !!a.name?.trim() || !!a.data?.imageUrl);\n\n if (state.feedback)\n interaction.data.feedback = state.feedback;\n\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateMultipleChoice(props: InteractionProps<CreateMultipleChoiceState>): JSX.Element {\n const {\n state = getInitialState(props.interaction),\n setState,\n interaction,\n optionsPortalNode,\n showFeedback\n } = props;\n\n const isTrueOrFalse = interaction.typeId === InteractionTypeId.TrueOrFalse;\n\n useDisableVideoDragDrop();\n\n function onChangeQuestion(event: React.ChangeEvent<HTMLInputElement>): void {\n setState({\n ...state,\n question: event.target.value\n });\n }\n\n function onUpdateAnswer(answer: MultipleChoiceAnswer): void {\n let updatedAnswers = state.answers.map(a => {\n if (a.order !== answer.order)\n return {\n ...a,\n isCorrect: isTrueOrFalse ? false : a.isCorrect\n };\n\n return answer;\n });\n\n /**\n * Handle the updated answer being deleted.\n */\n if (updatedAnswers.find(a => !a.name && !a.data?.imageUrl))\n updatedAnswers = removeDeletedAnswer(updatedAnswers);\n\n /**\n * If we haven't reached the max number of answers,\n * and all current answers fields have been filled out,\n * we add a new answer field.\n */\n if (!isTrueOrFalse && updatedAnswers.length < MAX_ANSWERS) {\n if (!updatedAnswers.find(a => !a.name && !a.data?.imageUrl)) {\n const lastAnswer = ArrayHelper.last(updatedAnswers);\n\n updatedAnswers.push({\n name: '',\n order: lastAnswer.order + 1,\n isCorrect: false,\n data: undefined\n });\n }\n }\n\n setState({\n ...state,\n answers: updatedAnswers\n });\n }\n\n function removeDeletedAnswer(answers: MultipleChoiceAnswer[]): MultipleChoiceAnswer[] {\n const deletedAnswer = answers.find(a => !a.name && !a.data?.imageUrl);\n\n /**\n * If we exceeded the minimum answers,\n * we want to delete one of the fields.\n */\n if (answers.length > MIN_ANSWERS) {\n return answers\n .filter(a => a.order !== deletedAnswer.order)\n .map((a, index) => ({\n ...a,\n order: index\n }));\n }\n\n /**\n * If we have not exceeded the minimum answers,\n * we want to keep the same number of fields,\n * but ensure the deleted answer is not ticked\n * as a correct answer.\n */\n return answers.map(a => {\n if (a.order !== deletedAnswer.order)\n return a;\n\n return {\n ...a,\n isCorrect: false\n };\n });\n }\n\n function onChangeFeedback(event: React.ChangeEvent<HTMLTextAreaElement>): void {\n setState({\n ...state,\n feedback: event.target.value\n });\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='form-group'>\n <div className='d-flex justify-content-between align-items-center'>\n <label className='cv-interaction-field-label' htmlFor='multiple-choice-question'>\n Question\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n <input\n id='multiple-choice-question'\n className='form-control'\n placeholder='Enter your question here'\n value={state.question}\n onChange={onChangeQuestion}\n autoComplete='off'\n />\n {!state.question && <CreateErrorFeedback error={state.error} />}\n </div>\n\n <div className='form-group'>\n <label className='cv-interaction-field-label' htmlFor='multiple-choice-answer'>\n {isTrueOrFalse ? <>Answer</> : <>Answers</>}\n </label>\n\n <ul className='list-unstyled'>\n {state.answers.map(answer => (\n <li key={answer.order}>\n <MultipleChoiceAnswer\n answer={answer}\n onChange={onUpdateAnswer}\n isTrueOrFalse={isTrueOrFalse}\n imageApi={props.imageApi}\n />\n </li>\n ))}\n </ul>\n\n {state.question && <CreateErrorFeedback error={state.error} />}\n </div>\n\n {showFeedback && isTrueOrFalse &&\n <div className='form-group mb-0'>\n <label\n className='cv-interaction-field-label d-flex justify-content-between align-items-end'\n htmlFor='true-or-false-feedback'\n >\n <span>\n Feedback\n &nbsp;\n <small className='text-secondary'>(optional)</small>\n </span>\n <FeedbackTooltip tooltipText='Provide answer feedback for your students' />\n </label>\n <TextareaAutosize\n id='true-or-false-feedback'\n className='form-control'\n minRows={2}\n value={state.feedback || ''}\n onChange={onChangeFeedback}\n placeholder='Give feedback for this question'\n />\n </div>\n }\n </div>\n );\n}\n","import React from 'react';\nimport { OutPortal } from 'react-reverse-portal';\nimport TextareaAutosize from 'react-textarea-autosize';\n\nimport { FeedbackTooltip } from 'libs/shared/components/feedback-tooltip/FeedbackTooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { CreateInteractionState, InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\n\ninterface CreateShortAnswerState extends CreateInteractionState {\n question: string;\n suggestedResponse?: string;\n}\n\nfunction generateInitialState(interaction: Interaction): CreateShortAnswerState {\n return { question: interaction.name, suggestedResponse: interaction.data.suggestedResponse || '' };\n}\n\nconst MAX_LENGTH = 255;\nconst MAX_SUGGESTED_RESPONSE_LENGTH = 4000;\n\nconst NO_QUESTION = 'Please provide a question';\nconst MAX_QUESTION_LENGTH = `Max question length is ${MAX_LENGTH} characters`;\nconst MAX_ANSWER_LENGTH = `Max answer length is ${MAX_SUGGESTED_RESPONSE_LENGTH} characters`;\n\nenum ERROR_TYPE {\n QUESTION,\n ANSWER\n}\n\nexport function ValidateShortAnswer(state: CreateShortAnswerState): string {\n if (!state.question?.trim())\n return NO_QUESTION;\n\n if (state.question?.trim().length > MAX_LENGTH)\n return MAX_QUESTION_LENGTH;\n\n if (state.suggestedResponse?.trim().length > MAX_SUGGESTED_RESPONSE_LENGTH)\n return MAX_ANSWER_LENGTH;\n\n return null;\n}\n\nexport async function SubmitShortAnswer(state: CreateShortAnswerState, interaction: Interaction): Promise<void> {\n interaction.name = state.question?.trim();\n interaction.data.suggestedResponse = state.suggestedResponse?.trim();\n\n // Unfortunately the API requires at least 1 actionable item\n // even though short answer don't use them\n interaction.actionableItems = [{ name: 'Answer' }];\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateShortAnswer(props: InteractionProps<CreateShortAnswerState>): React.ReactElement {\n const {\n state = generateInitialState(props.interaction),\n setState,\n interaction,\n optionsPortalNode,\n showFeedback\n } = props;\n\n function onChangeQuestion(event: React.ChangeEvent<HTMLInputElement>): void {\n setState({\n ...state,\n question: event.target.value\n });\n }\n\n function onChangeSuggestedResponse(event: React.ChangeEvent<HTMLTextAreaElement>): void {\n setState({\n ...state,\n suggestedResponse: event.target.value\n });\n }\n\n function getErrorType() {\n switch (state.error) {\n case NO_QUESTION:\n case MAX_QUESTION_LENGTH:\n return ERROR_TYPE.QUESTION;\n case MAX_ANSWER_LENGTH:\n return ERROR_TYPE.ANSWER;\n }\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='form-group'>\n <div className='d-flex justify-content-between align-items-center'>\n <label className='cv-interaction-field-label' htmlFor='short-answer-question'>\n Question\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n <input\n id='short-answer-question'\n className='form-control'\n onChange={onChangeQuestion}\n value={state.question || interaction.data.text || ''}\n placeholder='Enter your question here'\n autoComplete='off'\n aria-errormessage='question-error'\n />\n {getErrorType() === ERROR_TYPE.QUESTION && <CreateErrorFeedback id='question-error' error={state.error} />}\n </div>\n\n {showFeedback &&\n <div className='form-group'>\n <label\n className='cv-interaction-field-label d-flex justify-content-between align-items-end'\n htmlFor='short-answer-suggested-response'\n >\n <span>\n Suggested Response\n &nbsp;\n <small className='text-secondary'>(optional)</small>\n </span>\n <FeedbackTooltip tooltipText='Provide a suggested response for your students' />\n </label>\n <TextareaAutosize\n id='short-answer-suggested-response'\n className='form-control'\n minRows={2}\n value={state.suggestedResponse || ''}\n onChange={onChangeSuggestedResponse}\n placeholder='Give a suggested response for this question'\n aria-errormessage='answer-error'\n />\n {getErrorType() === ERROR_TYPE.ANSWER && <CreateErrorFeedback id='answer-error' error={state.error} />}\n </div>\n }\n </div>\n );\n}\n","import { Interaction, InteractionTypeId } from 'libs/shared/interfaces';\n\nimport { CreateAnnotation, SubmitAnnotation, ValidateAnnotation } from 'projects/player/plugins/interactive-plugin/components/create-components/create-annotation/create-annotation';\nimport { CreateIllustration, SubmitIllustration, ValidateIllustration } from 'projects/player/plugins/interactive-plugin/components/create-components/create-illustration/create-illustration';\nimport { CreateImage, SubmitImage, ValidateImage } from 'projects/player/plugins/interactive-plugin/components/create-components/create-image/create-image';\nimport { CreateMissingWord, SubmitMissingWord, ValidateMissingWord } from 'projects/player/plugins/interactive-plugin/components/create-components/create-missing-word/create-missing-word';\nimport { CreateMultipleChoice, SubmitMultipleChoice, ValidateMultipleChoice } from 'projects/player/plugins/interactive-plugin/components/create-components/create-multiple-choice/create-multiple-choice';\nimport { CreateShortAnswer, SubmitShortAnswer, ValidateShortAnswer } from 'projects/player/plugins/interactive-plugin/components/create-components/create-short-answer/create-short-answer';\nimport { CreateInteractionState, CreateSubmissionFunction, InteractionComponent } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nconst QuestionLookup: {[typeId: number]: InteractionComponent} = {\n [InteractionTypeId.Annotation]: CreateAnnotation,\n [InteractionTypeId.Image]: CreateImage,\n [InteractionTypeId.MissingWord]: CreateMissingWord,\n [InteractionTypeId.MultipleChoice]: CreateMultipleChoice,\n [InteractionTypeId.ShortAnswer]: CreateShortAnswer,\n [InteractionTypeId.TrueOrFalse]: CreateMultipleChoice,\n [InteractionTypeId.Illustration]: CreateIllustration\n};\n\nexport function getCreateComponent(typeId: InteractionTypeId): InteractionComponent {\n return QuestionLookup[typeId];\n}\n\ntype CreateValidationFunction = (state: CreateInteractionState, interaction: Interaction) => string;\nconst ValidationLookup: {[typeId: number]: CreateValidationFunction} = {\n [InteractionTypeId.Annotation]: ValidateAnnotation,\n [InteractionTypeId.Image]: ValidateImage,\n [InteractionTypeId.MissingWord]: ValidateMissingWord,\n [InteractionTypeId.MultipleChoice]: ValidateMultipleChoice,\n [InteractionTypeId.ShortAnswer]: ValidateShortAnswer,\n [InteractionTypeId.TrueOrFalse]: ValidateMultipleChoice,\n [InteractionTypeId.Illustration]: ValidateIllustration\n};\n\nexport function getCreateValidation(typeId: InteractionTypeId): CreateValidationFunction {\n return ValidationLookup[typeId];\n}\n\nconst SubmissionLookup: {[typeId: number]: CreateSubmissionFunction} = {\n [InteractionTypeId.Annotation]: SubmitAnnotation,\n [InteractionTypeId.Image]: SubmitImage,\n [InteractionTypeId.MissingWord]: SubmitMissingWord,\n [InteractionTypeId.MultipleChoice]: SubmitMultipleChoice,\n [InteractionTypeId.ShortAnswer]: SubmitShortAnswer,\n [InteractionTypeId.TrueOrFalse]: SubmitMultipleChoice,\n [InteractionTypeId.Illustration]: SubmitIllustration\n};\n\nexport function getCreateSubmit(typeId: InteractionTypeId): CreateSubmissionFunction {\n return SubmissionLookup[typeId];\n}\n","import React from 'react';\nimport { Editor } from 'react-draft-wysiwyg';\nimport { OutPortal } from 'react-reverse-portal';\nimport { convertFromHTML, convertToHTML } from 'draft-convert';\nimport { EditorState } from 'draft-js';\n\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { CreateInteractionState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\n\nimport { draftConvertOptions } from './create-annotation-helpers';\nimport { CreateAnnotationLink } from './create-annotation-link';\n\nimport './create-annotation.scss';\n\nconst MAX_LENGTH = 3500;\n\ninterface CreateAnnotationState extends CreateInteractionState {\n annotation: string;\n}\n\nfunction removeHtmlTags(str: string) {\n return str.replace(/<[^>]*>/g, '');\n}\n\nfunction generateInitialState(interaction: Interaction): CreateAnnotationState {\n return { annotation: interaction.data?.annotation || '' };\n}\n\nexport function ValidateAnnotation(state: CreateAnnotationState): string {\n if (!state.annotation?.trim())\n return 'Please provide an annotation';\n\n const strippedAnnotation = removeHtmlTags(state.annotation?.trim());\n\n if (strippedAnnotation.length > MAX_LENGTH) {\n return `Max length is ${MAX_LENGTH} characters`;\n }\n\n return null;\n}\n\nexport async function SubmitAnnotation(state: CreateAnnotationState, interaction: Interaction): Promise<void> {\n interaction.name = 'Annotation';\n interaction.data.annotation = state.annotation?.trim();\n\n // Unfortunately the API requires at least 1 actionable item\n // even though annotations don't use them\n interaction.actionableItems = [{ name: 'Answer' }];\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateAnnotation(props: InteractionProps<CreateAnnotationState>): React.ReactElement {\n const {\n state = generateInitialState(props.interaction),\n setState,\n interaction,\n optionsPortalNode\n } = props;\n\n function getEditorInitialState(): EditorState {\n const html = interaction.data.annotation;\n\n // Check if the user is editing a pre-existing interaction\n if (html) {\n const content = convertFromHTML(draftConvertOptions)(html);\n return EditorState.createWithContent(content);\n }\n\n return EditorState.createEmpty();\n }\n\n const [ editorState, setEditorState ] = React.useState(getEditorInitialState());\n const [ editorRef, setEditorRef ] = React.useState(null);\n\n function onChangeAnnotation(editorState: EditorState): void {\n setEditorState(editorState);\n\n const contentState = editorState.getCurrentContent();\n\n if (!contentState.hasText()) {\n setState({\n ...state,\n annotation: ''\n });\n return;\n }\n\n const html = convertToHTML(draftConvertOptions)(contentState);\n\n setState({\n ...state,\n annotation: html\n });\n }\n\n /**\n * Draft's logic around when to hide the placeholder is somewhat broken,\n * in that the placeholder still displays if you add nothing but an empty\n * list. This fixes that issue.\n * Link: https://github.com/facebook/draft-js/issues/1205#issuecomment-358025861\n */\n function shouldHidePlaceholder(): boolean {\n if (!editorState)\n return false;\n\n const contentState = editorState.getCurrentContent();\n return contentState.hasText() || contentState.getBlockMap().first().getType() !== 'unstyled';\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='form-group'>\n <div className='d-flex justify-content-between align-items-center'>\n <label className='cv-interaction-field-label' onClick={() => editorRef?.focusEditor()}>\n Annotation\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n\n {/* Docs: https://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp */}\n <div className={`cv-annotation ${shouldHidePlaceholder() ? 'Editor--hide-placeholder' : ''}`}>\n {editorState && (\n <Editor\n editorState={editorState}\n onEditorStateChange={onChangeAnnotation}\n toolbarClassName='cv-annotation-toolbar'\n editorClassName='form-control cv-annotation-editor'\n ref={setEditorRef}\n placeholder='Enter your annotation here'\n spellCheck\n toolbar={{\n options: [ 'inline', 'list', 'link' ],\n inline: {\n options: [ 'bold', 'italic', 'underline', 'superscript', 'subscript' ],\n // Icons are applied with classnames as Draft doesn't accept SVGs for icons\n bold: { className: 'cv-annotation-toolbar-option cv-annotation-bold', icon: '' },\n italic: { className: 'cv-annotation-toolbar-option cv-annotation-italic', icon: '' },\n underline: { className: 'cv-annotation-toolbar-option cv-annotation-underline', icon: '' },\n superscript: { className: 'cv-annotation-toolbar-option cv-annotation-superscript', icon: '' },\n subscript: { className: 'cv-annotation-toolbar-option cv-annotation-subscript', icon: '' }\n },\n list: {\n options: [ 'unordered', 'ordered' ],\n unordered: { className: 'cv-annotation-toolbar-option cv-annotation-bullet-list', icon: '' },\n ordered: { className: 'cv-annotation-toolbar-option cv-annotation-number-list', icon: '' }\n },\n link: {\n component: CreateAnnotationLink,\n options: ['link']\n }\n }}\n />\n )}\n <CreateErrorFeedback error={state.error} />\n </div>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { OutPortal } from 'react-reverse-portal';\n\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { ImageType } from 'libs/shared/enums/Images';\nimport { useDisableVideoDragDrop } from 'libs/shared/hooks/UseVideoDragDropState';\nimport { Interaction } from 'libs/shared/interfaces';\nimport { CropperHelper } from 'libs/shared/utils/CropperHelper';\nimport { ImageSelectHelper } from 'libs/shared/utils/ImageSelectHelper';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { CreateInteractionState, InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\nimport { AjaxHelper } from 'projects/player/utils/ajax-helper';\n\nimport { UploadImageDropzone } from './upload-image-dropzone';\n\nimport './create-image.scss';\n\ninterface CreateImageState extends CreateInteractionState {\n url: string;\n caption?: string;\n}\n\nfunction generateInitialState(interaction: Interaction): CreateImageState {\n return { url: interaction.data?.url || '', caption: interaction.data.caption };\n}\n\nexport function ValidateImage(state: CreateImageState): string {\n if (!state.url)\n return 'Please upload an image';\n\n return null;\n}\n\nexport async function SubmitImage(state: CreateImageState, interaction: Interaction): Promise<void> {\n interaction.data.url = state.url;\n interaction.name = state.caption?.trim() || 'Image';\n interaction.data.caption = state.caption?.trim();\n\n // Unfortunately the API requires at least 1 actionable item\n // even though images don't use them\n interaction.actionableItems = [{ name: 'Answer' }];\n\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateImage(props: InteractionProps<CreateImageState>): React.ReactElement {\n const {\n state = generateInitialState(props.interaction),\n setState,\n interaction,\n optionsPortalNode\n } = props;\n\n useDisableVideoDragDrop();\n\n const imageInputRef = React.useRef(null);\n\n function onChangeCaption(event: React.ChangeEvent<HTMLTextAreaElement>): void {\n setState({\n ...state,\n caption: event.target.value\n });\n }\n\n function onImageSelect(files: FileList): void {\n if (!files || !files[0])\n return;\n\n ImageSelectHelper.onFileSelect(ImageType.None, files, image => {\n CropperHelper.renderCropper({\n src: image.src,\n alt: '',\n onClickCrop\n });\n });\n }\n\n function onClickCrop(imageUrl: string, closePopup: () => void): void {\n const base64 = imageUrl.split(',')[1];\n AjaxHelper.post<HashObject>(`${props.imageApi}v2/thumbnails/base64`, `\"${base64}\"`, { tokenName: 'gateway' })\n .then(res => {\n setState({\n ...state,\n url: res.location\n });\n\n closePopup();\n })\n .catch(() => alert('Something went wrong while trying to upload image. Please try again.'));\n }\n\n function onClickRemoveImage(): void {\n setState({\n ...state,\n url: ''\n });\n }\n\n return (\n <div className='cv-interactive-question'>\n <div className='form-group'>\n <div className='d-flex justify-content-between align-items-center mb-2'>\n <label className='cv-interaction-field-label'>\n Image\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n {state.url\n ? (\n <div className='text-center'>\n <div className='cv-uploaded-image-container'>\n <img className='img img-fluid rounded' src={state.url} alt={state.caption} />\n <DivButton\n className='cv-remove-uploaded-image d-flex justify-content-center align-items-center'\n onClick={onClickRemoveImage}\n >\n <div className='btn btn-link text-light'>\n Remove\n </div>\n </DivButton>\n </div>\n </div>\n ) : (\n <UploadImageDropzone onDropImage={onImageSelect} dragClassName='cv-image-upload-mask'>\n <div className='cv-image-interaction-upload-container bg-white rounded py-3 text-center'>\n <div className='cv-upload-scenery-image mx-auto' />\n <p className='mb-0'>Drag and drop an image file or</p>\n <DivButton\n type='button'\n className='text-underline d-inline-block'\n onClick={() => {\n imageInputRef.current.value = null;\n imageInputRef.current.click(null);\n }}\n >\n upload from your device\n </DivButton>\n <input\n type='file'\n className='file-select d-none'\n multiple={false}\n accept='image/jpg,image/jpeg,image/png'\n ref={imageInputRef}\n onChange={e => onImageSelect(e.target.files)}\n />\n </div>\n </UploadImageDropzone>\n )\n }\n <CreateErrorFeedback error={state.error} />\n </div>\n\n <div className='form-group'>\n <label className='cv-interaction-field-label' htmlFor='image-caption'>\n Caption\n &nbsp;\n <small className='text-secondary'>(optional)</small>\n </label>\n <textarea\n id='image-caption'\n className='form-control'\n placeholder='Caption your image'\n value={state.caption || interaction.data.caption || ''}\n onChange={onChangeCaption}\n rows={2}\n >\n </textarea>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { InPortal, OutPortal } from 'react-reverse-portal';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { CreateErrorFeedback } from 'projects/player/plugins/interactive-plugin/components/create-components/create-error-feedback/create-error-feedback';\nimport { IllustrationPanel } from 'projects/player/plugins/interactive-plugin/components/view-components/illustration/components/illustration-panel/illustration-panel';\nimport { CreateInteractionState, InteractionProps } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\n\ninterface CreateIllustrationState extends CreateInteractionState {\n question: string;\n}\n\nfunction generateInitialState(interaction: Interaction): CreateIllustrationState {\n return { question: interaction.name };\n}\n\nexport function ValidateIllustration(state: CreateIllustrationState): string {\n if (!state.question?.trim())\n return 'Please provide a question';\n\n return null;\n}\n\nexport async function SubmitIllustration(state: CreateIllustrationState, interaction: Interaction): Promise<void> {\n interaction.name = state.question?.trim();\n\n // Unfortunately the API requires at least 1 actionable item\n // even though illustrations don't use them\n interaction.actionableItems = [{ name: 'Answer' }];\n await InteractiveAjax.saveInteraction(interaction);\n}\n\nexport function CreateIllustration(props: InteractionProps<CreateIllustrationState>): React.ReactElement {\n const [ demoDataUrl, setDemoDataUrl ] = React.useState<string>();\n const [ showCanvas, setShowCanvas ] = React.useState(false);\n\n const {\n state = generateInitialState(props.interaction),\n setState,\n optionsPortalNode\n } = props;\n\n function onChangeQuestion(event: React.ChangeEvent<HTMLInputElement>): void {\n setState({\n ...state,\n question: event.target.value\n });\n }\n\n return (\n <div className='cv-interactive-question'>\n <fieldset className='form-group'>\n <div className='d-flex justify-content-between align-items-center'>\n <label className='cv-interaction-field-label' htmlFor='illustration-question'>\n Prompt\n </label>\n <OutPortal node={optionsPortalNode}></OutPortal>\n </div>\n <input\n id='illustration-question'\n className='form-control'\n onChange={onChangeQuestion}\n value={state.question || ''}\n placeholder='Enter your prompt here'\n autoComplete='off'\n aria-invalid={!!state.error}\n aria-errormessage='illustrationQuestionError'\n />\n <CreateErrorFeedback id='illustrationQuestionError' error={state.error} />\n </fieldset>\n <div className='alert text-dark bg-light-blue px-2 rounded-3'>\n Students attempting this question will be prompted to draw their answer.&nbsp;\n <DivButton\n onClick={() => setShowCanvas(true)}\n className='btn-link text-underline d-inline'\n >\n Preview how students will answer.\n </DivButton>\n </div>\n {showCanvas &&\n <InPortal node={props.fullWidthPortalNode}>\n <IllustrationPanel\n interaction={{\n ...props.interaction,\n name: state.question\n }}\n onSave={dataUrl => {\n setDemoDataUrl(dataUrl);\n setShowCanvas(false);\n }}\n onCancel={() => setShowCanvas(false)}\n />\n </InPortal>\n }\n {demoDataUrl &&\n <img\n className='img-fluid border rounded mt-2 w-50 d-block'\n src={demoDataUrl}\n alt='Illustration you just created.'\n />\n }\n </div>\n );\n}\n","import React from 'react';\nimport { Spinner } from 'react-bootstrap';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { Timepoint } from 'libs/shared/interfaces';\n\nimport { formatTime } from 'projects/player/utils/formatTime';\n\nimport './move-timepoint.scss';\n\nconst ENTER_KEYCODE = 13;\nconst LEFT_ARROW_KEYCODE = 37;\nconst RIGHT_ARROW_KEYCODE = 39;\n\n/**\n * For performance reasons I'm keeping these\n * values outside of react state\n * - Sha\n */\nlet interval: number = null;\nlet count = 0;\nlet multiplier = 1;\n\ninterface MoveTimepointProps {\n updateTimepointTime: (time: number) => void\n timepoint: Timepoint;\n saveTimepoint: () => void;\n back: () => void;\n clearTimepointTimeState: (reset?: boolean) => void;\n}\n\nexport function MoveTimepoint(props: MoveTimepointProps): React.ReactElement {\n const { timepoint, updateTimepointTime, saveTimepoint, back, clearTimepointTimeState } = props;\n\n const [ time, setTime ] = React.useState(formatTime(timepoint.visibleAt / 1000));\n const [ spinner, setSpinner ] = React.useState(false);\n\n function move(direction: number): void {\n updateTimepointTime(direction * multiplier);\n\n setTime(formatTime(timepoint.visibleAt / 1000));\n \n count++;\n\n /**\n * No science behind this ramp up\n * I just played around with it and picked\n * something that felt good\n */\n if (count === 2) {\n multiplier = 5;\n } else if (count === 4) {\n multiplier = 20;\n } else if (count === 6) {\n multiplier = 60;\n } else if (count === 8)\n multiplier = 120;\n\n if (interval)\n return;\n\n interval = window.setInterval(() => move(direction), 200);\n window.addEventListener('mouseup', stop);\n }\n\n function clear(): void {\n window.removeEventListener('mouseup', stop);\n window.clearInterval(interval);\n interval = null;\n }\n\n function stop(): void {\n clear();\n count = 0;\n multiplier = 1;\n }\n\n async function onClickSave(): Promise<void> {\n setSpinner(true);\n await saveTimepoint();\n back();\n }\n\n function onClickCancel(): void {\n clearTimepointTimeState(true);\n back();\n }\n\n React.useEffect(() => {\n return stop;\n }, []);\n\n return (\n <>\n <div className='cv-timepoint flex-grow-1'>\n <div className='cv-timepoint-padding'>\n <div className='cv-interactive-question'>\n <label htmlFor='move-time-point' className='cv-interaction-field-label mb-0'>\n Move time point\n </label>\n <div className='text-center mt-3'>\n <DivButton\n className='cv-left-arrow d-inline-block cursor-pointer'\n onClick={() => {}}\n onMouseDown={() => move(-1)}\n onKeyDown={(e: React.KeyboardEvent) => {\n e.stopPropagation();\n if (e.keyCode === ENTER_KEYCODE && count === 0)\n move(-1);\n }}\n onKeyUp={stop}\n />\n <input\n id='move-time-point'\n className={`form-control text-center d-inline-block cv-move-timepoint-input`}\n value={time}\n onChange={() => { /* As we are setting value, onChange is required */ }}\n onKeyDown={(e: React.KeyboardEvent) => {\n e.stopPropagation();\n if (e.keyCode === LEFT_ARROW_KEYCODE && count === 0)\n move(-1);\n\n if (e.keyCode === RIGHT_ARROW_KEYCODE && count === 0)\n move(1);\n }}\n onKeyUp={stop}\n />\n <DivButton\n className='cv-right-arrow d-inline-block cursor-pointer'\n onClick={() => {}}\n onMouseDown={() => move(1)}\n onKeyDown={(e: React.KeyboardEvent) => {\n e.stopPropagation();\n if (e.keyCode === ENTER_KEYCODE && count === 0)\n move(1);\n }}\n onKeyUp={stop}\n />\n </div>\n </div>\n </div>\n </div>\n <div className='cv-timpoint-button-container'>\n <DivButton className='btn btn-link' onClick={onClickCancel}>\n Cancel\n </DivButton>\n {spinner ?\n <DivButton className='btn btn-dark ms-2 cv-interactive-spinner' onClick={() => {}}>\n <Spinner as='span' animation='border' role='status' size='sm' />\n </DivButton> :\n <DivButton className='btn btn-dark' onClick={onClickSave}>\n Save\n </DivButton>\n }\n </div>\n </>\n );\n}","import React from 'react';\nimport { Spinner } from 'react-bootstrap';\nimport { DragEndEvent } from '@dnd-kit/core';\n\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { DivButton } from 'libs/shared/components/div-button/DivButton';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { SortableContainerWrapper } from 'libs/shared/components/sortable/SortableContainerWrapper';\nimport { PropsWithSortableItemProps, SortableItemWrapper } from 'libs/shared/components/sortable/SortableItemWrapper';\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { useGrabCursorProps } from 'libs/shared/hooks/UseGrabCursorProps';\nimport { Interaction } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './reorder-interactions.scss';\n\n/**\n * CBF writing my own\n * this is from https://stackoverflow.com/questions/5306680/move-an-array-element-from-one-array-position-to-another\n */\nfunction moveItems(items: any[], oldIndex: number, newIndex: number): any[] {\n while (oldIndex < 0) {\n oldIndex += items.length;\n }\n while (newIndex < 0) {\n newIndex += items.length;\n }\n if (newIndex >= items.length) {\n let k = newIndex - items.length + 1;\n while (k--) {\n items.push(undefined);\n }\n }\n items.splice(newIndex, 0, items.splice(oldIndex, 1)[0]);\n return items;\n}\n\ninterface SortableItemProps {\n interaction: Interaction;\n}\n\nconst SortableItem = (props: SortableItemProps) => {\n const { interaction } = props;\n\n const { bgClassName } = InteractionTypeHelper.getTypeInfo(interaction.typeId);\n\n const Item = React.forwardRef((\n props: PropsWithSortableItemProps<HashObject>,\n ref: React.LegacyRef<HTMLDivElement>\n ) => (\n <div className='py-2 text-start' {...props.dragAttributes} {...props.dragListeners} ref={ref} style={props.style}>\n <span className={styles.dragIcon}>\n <SvgContainer\n size={SvgContainerSize.Small}\n svgName={cvSvgLibrary.Handle}\n />\n </span>\n <InteractionLabel\n interaction={interaction}\n iconClassName={`${styles.type} ${bgClassName}`}\n questionClassName={`${styles.name} clamp-1`}\n />\n </div>\n ));\n\n return (\n <SortableItemWrapper id={interaction.id} childComponent={Item} childProps={{}} />\n );\n};\n\ninterface SortableInteractionListProps {\n interactions: Interaction[];\n onSortEnd: (event: DragEndEvent) => void;\n}\n\nconst SortableInteractionList = (props: SortableInteractionListProps) => {\n const { interactions } = props;\n\n const grabCursorProps = useGrabCursorProps();\n\n return (\n <SortableContainerWrapper\n ids={interactions.map(i => i.id)}\n getDragOverlay={id => (\n <SortableItem\n key={id}\n interaction={interactions.find(i => i.id === id)}\n />\n )}\n onSortEnd={props.onSortEnd}\n >\n <div\n tabIndex={0}\n {...grabCursorProps}\n >\n {interactions.map(interaction => (\n <SortableItem\n key={interaction.id}\n interaction={interaction}\n />\n ))}\n </div>\n </SortableContainerWrapper>\n );\n};\n\ninterface ReorderInteractionsProps {\n interactions: Interaction[];\n back: () => void;\n reOrderQuestions: (interactions: Interaction[]) => void;\n}\n\nexport function ReorderInteractions(props: ReorderInteractionsProps): React.ReactElement {\n const [ spinner, setSpinner ] = React.useState(false);\n const [ items, setItems ] = React.useState([...props.interactions]);\n const [ hasChanges, setHasChanges ] = React.useState(false);\n\n function onSortEnd({ active, over }: DragEndEvent): void {\n const oldIndex = items.findIndex(v => v.id.toString() === active.id.toString());\n const newIndex = items.findIndex(v => v.id.toString() === over.id.toString());\n\n if (oldIndex === newIndex)\n return;\n\n setItems([...moveItems(items, oldIndex, newIndex)]);\n setHasChanges(true);\n }\n\n function onClickCancel(): void {\n setItems([...props.interactions]);\n setHasChanges(false);\n props.back();\n }\n\n async function onClickSave(): Promise<void> {\n if (!hasChanges)\n return;\n\n setSpinner(true);\n await props.reOrderQuestions(items);\n setSpinner(false);\n props.back();\n }\n\n return (\n <>\n <div className='cv-timepoint flex-grow-1'>\n <div className='cv-timepoint-padding'>\n <div className='cv-interactive-question'>\n <label className='cv-interaction-field-label mb-0'>\n Re-order questions\n </label>\n <div className='text-center mt-3'>\n <SortableInteractionList\n onSortEnd={onSortEnd}\n interactions={items}\n />\n </div>\n </div>\n </div>\n </div>\n <div className='cv-timpoint-button-container'>\n <DivButton className='btn btn-link' onClick={onClickCancel}>\n Cancel\n </DivButton>\n {spinner ?\n <DivButton className='btn btn-dark ms-2 cv-interactive-spinner' onClick={() => {}}>\n <Spinner as='span' animation='border' role='status' size='sm' />\n </DivButton> :\n <DivButton className={`btn btn-dark ${hasChanges ? '' : 'disabled'}`} onClick={onClickSave}>\n Save\n </DivButton>\n }\n </div>\n </>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"type\":\"GSE1a\",\"dragIcon\":\"fB8W8\",\"name\":\"qKMzc\",\"dragging\":\"jGy0h\"};","import React from 'react';\n\n/**\n * This is a bit of a dumpster fire but it's the only sane solution\n * I could find for implementing proper cursors while using \n * react-sortable-hoc\n * https://github.com/clauderic/react-sortable-hoc/issues/328\n */\nexport const useGrabCursorProps = () => {\n const ref = React.useRef<HTMLDivElement>(null);\n const style = { cursor: 'grab' };\n\n function onMouseDown(): void {\n document.body.style.cursor = 'grabbing';\n document.addEventListener('mouseup', onMouseUp);\n\n if (ref.current)\n ref.current.style.cursor = 'grabbing';\n }\n\n function onMouseUp(): void {\n document.body.style.cursor = '';\n document.removeEventListener('mouseup', onMouseUp);\n\n if (ref.current)\n ref.current.style.cursor = 'grab';\n }\n\n return {\n ref,\n style,\n onMouseDown,\n onMouseUp\n };\n};","import React from 'react';\nimport { createHtmlPortalNode, HtmlPortalNode } from 'react-reverse-portal';\nimport SimpleBar from 'simplebar-react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { Interaction, InteractionTypeId, Timepoint } from 'libs/shared/interfaces';\n\nimport { PlayerCurrentUser } from 'projects/player/interfaces/models/PlayerCurrentUser';\nimport { CreateTypeSelector } from 'projects/player/plugins/interactive-plugin/components/create-components/create-type-selector/create-type-selector';\nimport { InteractionActions } from 'projects/player/plugins/interactive-plugin/components/interaction-actions/interaction-actions';\nimport { InteractionFooter } from 'projects/player/plugins/interactive-plugin/components/interaction-footer/interaction-footer';\nimport { InteractionHeader } from 'projects/player/plugins/interactive-plugin/components/interaction-header/interaction-header';\nimport { InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractionState, TimepointState } from 'projects/player/plugins/interactive-plugin/interfaces/InteractiveState';\nimport { getInteractionComponent } from 'projects/player/plugins/interactive-plugin/utils/getInteractionComponents';\nimport { SLIDING_TIME } from 'projects/player/plugins/interactive-plugin/utils/helpers';\n\nimport { MoveTimepoint } from '../move-timepoint/move-timepoint';\nimport { ReorderInteractions } from '../reorder-interactions/reorder-interactions';\n\nimport './timepoint-component.scss';\n\nexport type QuestionView = 'question' | 'move' | 'reorder';\n\nexport interface TimepointProps {\n /* Used in this component */\n isCreate: boolean;\n interaction: Interaction;\n mode: InteractiveMode;\n immediateFeedback: boolean;\n interactionState: InteractionState;\n userUpdateInteractionState: (value: InteractionState) => void;\n submitInteractionAnswer: () => void;\n saveInteraction: () => void;\n shouldFocus?: boolean;\n delayFocus?: boolean;\n \n /* Drilled to children */\n currentUser?: PlayerCurrentUser;\n timepoint: Timepoint;\n timepointState: TimepointState;\n imageApi: URL;\n player: VideoJsPlayer;\n open: boolean;\n currentIndex: number;\n enableImmersiveReader: boolean;\n addInteraction: (typeId: InteractionTypeId) => void;\n cancelTypeSelector: () => void;\n changeIndex: (index: number) => void;\n continueInteractive: () => void;\n cancel: () => void;\n addAnotherQuestion: () => void;\n discardChanges: (after?: () => void) => void;\n skip: () => void;\n promptDelete: (id: string) => void;\n updateTimepointTime: (time: number) => void;\n saveTimepoint: () => void;\n clearTimepointTimeState: (reset?: boolean) => void;\n reOrderQuestions: (interactions: Interaction[]) => void;\n leftHandSidePortalNode?: HtmlPortalNode;\n fullWidthPortalNode?: HtmlPortalNode;\n experimentalInteractiveQuestions: boolean;\n}\n\nexport function TimepointComponent(props: TimepointProps): React.ReactElement {\n const {\n isCreate,\n interaction,\n mode,\n immediateFeedback,\n interactionState,\n shouldFocus,\n delayFocus,\n open,\n timepoint,\n\n userUpdateInteractionState,\n submitInteractionAnswer,\n saveInteraction,\n skip\n } = props;\n\n /**\n * Set's users focus inside the question for A11y\n */\n const focusRef = React.useRef<HTMLDivElement>(null);\n const ref = React.useRef(null);\n\n const focusTimeoutRef = React.useRef<number>(0);\n\n const isXlDown = useMediaQuery(MediaQueryStrings.XLDown);\n const isSlidingOver = !isCreate || isXlDown;\n\n function recalculateScroll(): void {\n (ref.current as any).recalculate();\n }\n\n function shouldFocusCheck(): boolean {\n if (!focusRef.current) return false;\n if (!shouldFocus) return false;\n if (!open) return false;\n return true;\n }\n\n function focus(): void {\n if (!focusRef.current)\n return;\n\n focusRef.current.focus();\n setHasFocused(true);\n }\n\n /**\n * Because of how we store our state at the top of the interactives\n * it's possible our effect runs again after a state update\n * so we ensure we can only focus once\n */\n const [ hasFocused, setHasFocused ] = React.useState(false);\n React.useEffect(() => {\n if (!shouldFocusCheck()) return;\n if (hasFocused) return;\n\n if (!delayFocus || !isSlidingOver) {\n focus();\n return;\n }\n \n focusTimeoutRef.current = window.setTimeout(() => {\n focusTimeoutRef.current = 0;\n\n if (!shouldFocusCheck()) return;\n focus();\n }, SLIDING_TIME);\n }, [ focusRef.current, hasFocused ]);\n\n function onSubmit(event: React.FormEvent): void {\n event.preventDefault();\n\n if (isCreate) {\n saveInteraction();\n return;\n }\n\n submitInteractionAnswer();\n }\n\n function onClickSkip(): void {\n if (focusTimeoutRef.current)\n window.clearTimeout(focusTimeoutRef.current);\n\n skip();\n }\n\n const [ view, setView ] = React.useState<QuestionView>('question');\n\n const optionsPortalNode = React.useMemo(() => createHtmlPortalNode(), []);\n\n const Question = interaction ? getInteractionComponent(interaction.typeId, mode) : null;\n\n let showFeedback = immediateFeedback;\n\n if (!isCreate)\n showFeedback = showFeedback && interactionState?.submitted;\n\n return (\n <>\n <InteractionActions\n optionsPortalNode={optionsPortalNode}\n setView={setView}\n {...props}\n />\n <SimpleBar className='h-100' ref={ref}>\n <CreateTypeSelector {...props} />\n {!!interaction &&\n <div className='d-flex flex-column h-100'>\n <InteractionHeader {...props} />\n {view === 'question' &&\n <>\n <form className='cv-timepoint flex-grow-1' tabIndex={-1} onSubmit={onSubmit}>\n <div className='cv-timepoint-padding h-100'>\n <div ref={focusRef} tabIndex={0} />\n <Question\n state={interactionState}\n setState={userUpdateInteractionState}\n recalculateScroll={recalculateScroll}\n showFeedback={showFeedback}\n optionsPortalNode={optionsPortalNode}\n {...props}\n />\n </div>\n </form>\n <InteractionFooter onClickSkip={onClickSkip} {...props} />\n </>\n }\n {view === 'move' &&\n <MoveTimepoint back={() => setView('question')} {...props}/>\n }\n\n {view === 'reorder' &&\n <ReorderInteractions back={() => setView('question')} interactions={timepoint.interactions} {...props} />\n }\n </div>\n }\n </SimpleBar>\n </>\n );\n}\n","import { InteractionTypeId } from 'libs/shared/interfaces';\n\nimport { getCreateComponent } from 'projects/player/plugins/interactive-plugin/components/create-components/create-components';\nimport { getViewComponent } from 'projects/player/plugins/interactive-plugin/components/view-components/view-components';\nimport { InteractionComponent, InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nexport function getInteractionComponent(typeId: InteractionTypeId, mode: InteractiveMode): InteractionComponent {\n if (mode === InteractiveMode.Create)\n return getCreateComponent(typeId);\n\n if (mode === InteractiveMode.View)\n return getViewComponent(typeId);\n\n throw new Error(`Cannot find components for the mode ${mode}`);\n}\n","import React from 'react';\nimport { createHtmlPortalNode, OutPortal } from 'react-reverse-portal';\n\nimport { Interaction } from 'libs/shared/interfaces';\n\nimport { TimepointComponent, TimepointProps } from 'projects/player/plugins/interactive-plugin/components/timepoint/timepoint-component';\nimport { InteractionState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\nimport './sliding-timepoints.scss';\n\ninterface SlidingTimepointProps extends Omit<TimepointProps, 'currentIndex'> {\n nextInteraction: Interaction;\n nextInteractionState: InteractionState;\n delayFocus: boolean;\n}\n\nexport function SlidingTimepoint(props: SlidingTimepointProps): React.ReactElement {\n const {\n open,\n nextInteraction,\n nextInteractionState,\n timepointState,\n interaction,\n delayFocus,\n experimentalInteractiveQuestions\n } = props;\n\n const leftHandSidePortalNode = React.useMemo(() => createHtmlPortalNode({\n attributes: { class: 'cv-interactive-lhs' }\n }), []);\n const fullWidthPortalNode = React.useMemo(() => createHtmlPortalNode({\n attributes: { class: 'cv-interactive-full' }\n }), []);\n\n const transitionPrev = nextInteraction && timepointState.nextInteractionIndex < timepointState.interactionIndex;\n const transitionNext = nextInteraction && timepointState.nextInteractionIndex > timepointState.interactionIndex;\n const slideOutUp = transitionNext && timepointState.slideIn;\n const slideOutDown = transitionPrev && timepointState.slideIn;\n\n const showExtraPanels = open && !transitionPrev && !transitionNext;\n\n return (\n <>\n <div className={`cv-interactive-full-container ${showExtraPanels ? '' : 'cv-closed-full'}`}>\n <OutPortal node={fullWidthPortalNode} />\n </div>\n <div className={`cv-interactive-lhs-container ${showExtraPanels ? '' : 'cv-closed-lhs'}`}>\n <OutPortal node={leftHandSidePortalNode} />\n </div>\n <div className={`cv-interactive ${open ? 'cv-open' : ''}`}>\n {transitionPrev &&\n <div className={`cv-prev-interaction ${timepointState.slideIn ? 'cv-slide-in' : ''}`}>\n <TimepointComponent\n {...props}\n currentIndex={timepointState.nextInteractionIndex}\n interaction={nextInteraction}\n interactionState={nextInteractionState}\n />\n </div>\n }\n <div className={`\n cv-main-slide\n ${slideOutUp ? 'cv-slide-out-up' : ''}\n ${slideOutDown ? 'cv-slide-out-down' : ''}\n ${nextInteraction ? 'cv-transitioning' : ''}\n `}>\n <TimepointComponent\n key={interaction?.id}\n {...props}\n currentIndex={timepointState.interactionIndex}\n shouldFocus={interaction && !transitionPrev && !transitionNext}\n delayFocus={delayFocus}\n leftHandSidePortalNode={leftHandSidePortalNode}\n fullWidthPortalNode={fullWidthPortalNode}\n experimentalInteractiveQuestions={experimentalInteractiveQuestions}\n />\n </div>\n {transitionNext &&\n <div className={`cv-next-interaction ${timepointState.slideIn ? 'cv-slide-in' : ''}`}>\n <TimepointComponent\n {...props}\n currentIndex={timepointState.nextInteractionIndex}\n interaction={nextInteraction}\n interactionState={nextInteractionState}\n />\n </div>\n }\n </div>\n </>\n );\n}","import { InteractionState, InteractiveState, LatestSession, TimepointState } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ninterface InteractionAction {\n type: 'interaction';\n id: string;\n value: InteractionState;\n}\n\ninterface TimepointAction {\n type: 'timepoint';\n id: string;\n value: TimepointState;\n}\n\nconst initialState: InteractiveState = {\n interactions: {},\n timepoints: {}\n};\n\nexport function getInitialState(latestSession: LatestSession): InteractiveState {\n if (!latestSession)\n return initialState;\n\n return {\n timepoints: {},\n interactions: latestSession.actions.reduce((prev: {[key: string]: InteractionState}, current) => {\n prev[current.interactionId] = {\n ...prev[current.interactionId],\n [current.actionableItemId]: current.data,\n submitted: true\n };\n return prev;\n }, {})\n };\n}\n\nexport function interactiveReducer(\n state: InteractiveState,\n action: InteractionAction | TimepointAction\n): InteractiveState {\n if (action.type === 'interaction') {\n return {\n timepoints: state.timepoints,\n interactions: {\n ...state.interactions,\n [action.id]: action.value\n }\n };\n }\n\n\n if (action.type === 'timepoint') {\n return {\n interactions: state.interactions,\n timepoints: {\n ...state.timepoints,\n [action.id]: action.value\n }\n };\n }\n}","import React from 'react';\n\nimport { Timepoint } from 'libs/shared/interfaces';\n\nimport { InteractionState, InteractiveMode, LatestSession, TimepointState } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { getInitialState, interactiveReducer } from 'projects/player/plugins/interactive-plugin/utils/InteractiveReducer';\n\nconst initialTimepointState: TimepointState = {\n interactionIndex: 0\n};\n\ninterface UseInteractiveStateProps {\n mode: InteractiveMode;\n timepoint: Timepoint;\n latestSession?: LatestSession;\n}\n\n/**\n * This should only be used inside of useStateManager\n */\nexport const useInteractiveState = (props: UseInteractiveStateProps) => {\n const {\n mode,\n timepoint,\n latestSession\n } = props;\n\n const isCreate = mode === InteractiveMode.Create;\n\n const [ state, dispatch ] = React.useReducer(interactiveReducer, null, () => getInitialState(latestSession));\n\n const timepointState = getTimepointState(timepoint?.id);\n\n const interaction = timepoint?.interactions[timepointState.interactionIndex];\n const nextInteraction = typeof timepointState.nextInteractionIndex === 'number' ?\n timepoint?.interactions[timepointState.nextInteractionIndex] :\n null;\n\n const interactionState = getInteractionState(interaction?.id);\n const nextInteractionState = getInteractionState(nextInteraction?.id);\n\n function getTimepointState(id: string): TimepointState {\n if (!id) return initialTimepointState;\n\n return state.timepoints[id] || initialTimepointState;\n }\n\n function getInteractionState(id: string): InteractionState {\n if (!id) return {};\n\n const localInteractionState = state.interactions[id];\n\n /**\n * We only want an empty state object for viewing\n * interactives, otherwise the create component\n * is responsible for setting up the initial state\n */\n if (!localInteractionState && !isCreate)\n return {};\n\n return localInteractionState;\n }\n\n function updateTimepointState(id: string, value: TimepointState): void {\n const oldState = getTimepointState(id);\n dispatch({\n type: 'timepoint',\n id,\n value: {\n ...oldState,\n ...value\n }\n });\n }\n\n function updateInteractionState(id: string, value: InteractionState, clear?: boolean): void {\n const oldState = getInteractionState(id);\n dispatch({\n type: 'interaction',\n id,\n value: {\n ...(clear ? {} : oldState),\n ...value\n }\n });\n }\n\n function clearTimepointState(id: string): void {\n dispatch({ type: 'timepoint', id, value: undefined });\n }\n\n function clearInteractionState(id: string): void {\n dispatch({ type: 'interaction', id, value: undefined });\n }\n\n /**\n * This is used by the interaction components to update\n * their state, we set hasChanges to true so we know if the user\n * has interacted with the component\n * and we clear the any error they would have seen from submitting\n */\n function userUpdateInteractionState(value: InteractionState, clear?: boolean): void {\n updateInteractionState(interaction.id, {\n ...value,\n hasChanges: true,\n error: null\n }, clear);\n }\n\n return {\n state,\n\n interaction,\n interactionState,\n timepointState,\n\n nextInteraction,\n nextInteractionState,\n\n getTimepointState,\n getInteractionState,\n updateTimepointState,\n updateInteractionState,\n clearTimepointState,\n clearInteractionState,\n userUpdateInteractionState\n };\n};","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { EntityType, HashObject, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { Interaction, InteractionTypeId, Interactive, Timepoint } from 'libs/shared/interfaces';\nimport { DialogHelper } from 'libs/shared/utils/DialogHelper';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport { getCreateSubmit, getCreateValidation } from 'projects/player/plugins/interactive-plugin/components/create-components/create-components';\nimport { getShouldShowFeedback, getViewSubmit, getViewValidation } from 'projects/player/plugins/interactive-plugin/components/view-components/view-components';\nimport { InteractionState, InteractiveMode, LatestSession } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { getFilteredState, isNewId, SLIDING_TIME } from 'projects/player/plugins/interactive-plugin/utils/helpers';\nimport { InteractiveAjax } from 'projects/player/plugins/interactive-plugin/utils/interactive-ajax';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { AnalyticsService } from 'projects/player/services/analytics-service';\n\nimport { useInteractiveState } from './useInteractiveState';\n\nlet timepointHasChanges = false;\n\ninterface UseStateManagerProps {\n mode: InteractiveMode;\n timepoint: Timepoint;\n interactive: Interactive;\n player: VideoJsPlayer;\n resultsService?: ResultsService;\n latestSession?: LatestSession;\n analyticsService?: AnalyticsService;\n imageApi: URL;\n\n // Track\n setOpen: (open: boolean) => void;\n addCue: (timepointId: string) => void;\n updateCue: (oldTimepointId: string, timepointId: string) => void;\n removeCue: (visibleAt: number) => void;\n continueInteractive: () => void;\n moveTimepoint: (newTime: number) => void;\n}\n\nexport const useStateManager = (props: UseStateManagerProps) => {\n const {\n interactive, timepoint, player, mode, resultsService, latestSession, analyticsService, imageApi, ...trackManager\n } = props;\n\n const {\n state, interaction, interactionState, timepointState, nextInteraction, nextInteractionState, ...interactiveState\n } = useInteractiveState({ mode, timepoint, latestSession });\n\n const isCreate = mode === InteractiveMode.Create;\n\n function _findInteractionAndTimepoint(\n interactionId: string\n ): { localInteraction: Interaction, localTimepoint: Timepoint } {\n let i = 0;\n while (i < interactive.timepoints.length) {\n const localTimepoint = interactive.timepoints[i];\n\n let j = 0;\n while (j < localTimepoint.interactions.length) {\n const localInteraction = localTimepoint.interactions[j];\n\n if (localInteraction.id === interactionId)\n return { localTimepoint, localInteraction };\n\n j++;\n }\n\n i++;\n }\n return {\n localInteraction: null,\n localTimepoint: null\n };\n }\n\n function _findTimepoint(timepointId: string): Timepoint {\n let i = 0;\n while (i < interactive.timepoints.length) {\n const localTimepoint = interactive.timepoints[i];\n\n if (localTimepoint.id === timepointId)\n return localTimepoint;\n i++;\n }\n return null;\n }\n\n function _getInteractionAnalyticsData(interactionData: Interaction): HashObject {\n const type = InteractionTypeHelper.getTypeInfo(interactionData.typeId);\n return {\n id: isNewId(interactionData.id) ? undefined : interactionData.id,\n typeId: interactionData.typeId,\n type: type.typeName,\n interactiveId: interactive.id,\n timepointId: isNewId(interactionData.timepointId) ? undefined : interactionData.timepointId,\n order: interactionData.order\n };\n }\n\n function goToTimepoint(timepointId: string, interactionId: string): void {\n const localTimepoint = _findTimepoint(timepointId);\n\n const localInteraction = localTimepoint.interactions.find(i => {\n return i.id.toString() === interactionId.toString();\n });\n\n player.currentTime(localTimepoint.visibleAt / 1000);\n interactiveState.updateTimepointState(localTimepoint.id, {\n interactionIndex: localTimepoint.interactions.indexOf(localInteraction)\n });\n }\n\n async function deleteInteraction(interactionId: string): Promise<void> {\n const { localInteraction, localTimepoint } = _findInteractionAndTimepoint(interactionId);\n\n if (!localInteraction || !localTimepoint)\n throw new Error(`Could not find the interaction and timepoint for the interactionId ${interactionId}`);\n\n const data = _getInteractionAnalyticsData(localInteraction);\n if (!isNewId(localInteraction.id)) {\n await InteractiveAjax.deleteInteraction(localInteraction.id);\n \n analyticsService?.logUserAction(data, {\n actionType: UserAction.Delete,\n entity: EntityType.Interaction,\n workflowPhase: WorkflowPhase.Complete\n });\n } else {\n analyticsService?.logUserAction(data, {\n actionType: UserAction.Create,\n entity: EntityType.Interaction,\n workflowPhase: WorkflowPhase.Discard\n });\n }\n\n // Remove interaction from timepoint\n const interactionIndex = localTimepoint.interactions.findIndex(i => i.id === localInteraction.id);\n localTimepoint.interactions.splice(interactionIndex, 1);\n\n // Delete interaction state\n interactiveState.clearInteractionState(localInteraction.id);\n\n // Decrese the interactionIndex\n const timepointState = interactiveState.getTimepointState(localTimepoint.id);\n\n /**\n * If we removed an interaction ahead of the current one, we need to\n * drop the index 1\n */\n if (interactionIndex < timepointState.interactionIndex) {\n interactiveState.updateTimepointState(localTimepoint.id, {\n interactionIndex: timepointState.interactionIndex - 1\n });\n }\n\n /**\n * If we have any more interactions we don't want to delete the\n * timepoint\n */\n if (localTimepoint.interactions.length > 0)\n return;\n\n if (!isNewId(localTimepoint.id)) {\n await InteractiveAjax.deleteTimepoint(localTimepoint.id);\n }\n\n // Remove timepoint from interactive\n const timepointIndex = interactive.timepoints.findIndex(t => t.id === localTimepoint.id);\n interactive.timepoints.splice(timepointIndex, 1);\n\n trackManager.removeCue(localTimepoint.visibleAt / 1000);\n\n // Delete timepoint state\n interactiveState.clearTimepointState(localTimepoint.id);\n }\n\n function discardChanges(afterDiscard?: () => void): void {\n if (!interaction) {\n afterDiscard && afterDiscard();\n return;\n }\n\n const isNew = isNewId(interaction.id);\n\n if (!isNew && !interactionState?.hasChanges && !timepointState?.hasChanges) {\n afterDiscard && afterDiscard();\n return;\n }\n\n const success = () => {\n if (timepointState?.hasChanges)\n clearTimepointTimeState(true);\n\n if (isNew) {\n deleteInteraction(interaction.id);\n return;\n }\n\n interactiveState.clearInteractionState(interaction.id);\n };\n\n DialogHelper.render(<p>Do you want to discard your changes?</p>, {\n title: 'Unsaved changes',\n submitButtonProps: {\n onClick: () => {\n success();\n afterDiscard && afterDiscard();\n },\n variant: 'danger',\n text: 'Discard'\n },\n cancelButtonProps: {\n variant: 'link',\n text: 'Cancel'\n }\n });\n }\n\n function changeIndex(interactionIndex: number, prompt: boolean = true): void {\n if (isCreate) {\n discardChanges(() => {\n interactiveState.updateTimepointState(timepoint.id, { interactionIndex });\n });\n return;\n }\n\n const afterDiscard = () => {\n interactiveState.updateTimepointState(timepoint.id, { nextInteractionIndex: interactionIndex });\n\n /**\n * Allow react to render the next interaction\n * before we update the state trigger the slide animation\n */\n window.requestAnimationFrame(() => {\n interactiveState.updateTimepointState(timepoint.id, { nextInteractionIndex: interactionIndex, slideIn: true });\n\n window.setTimeout(() => {\n interactiveState.updateTimepointState(timepoint.id, {\n interactionIndex: interactionIndex,\n nextInteractionIndex: null,\n slideIn: null\n });\n }, SLIDING_TIME); // Tied to the animation number in sliding-timepoint.scss\n });\n };\n\n if (prompt)\n discardChanges(afterDiscard);\n else\n afterDiscard();\n }\n\n function skip(): void {\n if ((timepointState.interactionIndex + 1) >= timepoint.interactions.length) {\n trackManager.continueInteractive();\n return;\n }\n changeIndex(timepointState.interactionIndex + 1, false);\n }\n\n function addInteraction(typeId: InteractionTypeId): void {\n player.pause();\n\n const timepointId = timepoint?.id || `new_${Math.round(Math.random() * Number.MAX_SAFE_INTEGER)}`;\n\n const newInteraction: Interaction = {\n id: `new_${Math.round(Math.random() * Number.MAX_SAFE_INTEGER)}`,\n timepointId,\n typeId: typeId,\n order: timepoint?.interactions?.length || 0,\n interactiveId: interactive.id,\n data: {}\n };\n\n const data = _getInteractionAnalyticsData(newInteraction);\n analyticsService?.logUserAction(data, {\n actionType: UserAction.Create,\n entity: EntityType.Interaction,\n workflowPhase: WorkflowPhase.Start\n });\n\n if (timepoint) {\n timepoint.interactions.push(newInteraction);\n\n /**\n * Atm I don't have another nice way to re-render this component\n * with the new data\n */\n changeIndex(timepointState.interactionIndex);\n return;\n }\n\n const currentTime = player.currentTime();\n\n if (!interactive.timepoints)\n interactive.timepoints = [];\n\n interactive.timepoints.push({\n id: timepointId,\n visibleAt: currentTime * 1000,\n interactiveId: interactive.id,\n shouldPause: 1,\n interactions: [newInteraction]\n });\n\n sortTimepoints();\n\n trackManager.addCue(timepointId);\n }\n\n function sortTimepoints(): void {\n interactive.timepoints.sort((a, b) => {\n if (a.visibleAt > b.visibleAt)\n return 1;\n\n if (b.visibleAt > a.visibleAt)\n return -1;\n\n return 0;\n });\n }\n\n async function saveInteraction(): Promise<void> {\n if (!isCreate)\n throw new Error('Should not be calling onClickSave while viewing an interactive');\n\n const validate = getCreateValidation(interaction.typeId);\n const error = validate(interactiveState.getInteractionState(interaction.id), interaction);\n\n if (error) {\n interactiveState.updateInteractionState(interaction.id, { error });\n return;\n }\n\n interactiveState.updateInteractionState(interaction.id, { spinner: true });\n\n if (isNewId(timepoint.id)) {\n /**\n * It's not explicit here but saveTimepoint\n * will update the timepoint objects id\n * Not the most elegant but it works - Sha\n */\n const oldTimepointId = timepoint.id;\n await InteractiveAjax.saveTimepoint(timepoint);\n\n trackManager.updateCue(oldTimepointId, timepoint.id);\n interactiveState.clearTimepointState(oldTimepointId);\n\n if (timepointState?.hasChanges) {\n sortTimepoints();\n clearTimepointTimeState();\n }\n }\n\n interaction.timepointId = timepoint.id;\n \n /**\n * It's not explicit here but submit\n * will update the interaction objects id\n * Not the most elegant but it works - Sha\n */\n const oldInteractionId = interaction.id;\n const submit = getCreateSubmit(interaction.typeId);\n await submit(interactiveState.getInteractionState(interaction.id), interaction);\n interactiveState.clearInteractionState(oldInteractionId);\n\n const isNewInteractionId = isNewId(oldInteractionId);\n const data = _getInteractionAnalyticsData(interaction);\n analyticsService?.logUserAction(data, {\n actionType: isNewInteractionId ? UserAction.Create : UserAction.Edit,\n entity: EntityType.Interaction,\n workflowPhase: isNewInteractionId ? WorkflowPhase.Complete : WorkflowPhase.Save\n });\n }\n\n async function submitInteractionAnswer(): Promise<void> {\n if (mode !== InteractiveMode.View)\n throw new Error('Should not be calling onClickSubmit while creating an interactive');\n\n if (interactionState.submitted) {\n if (timepointState.interactionIndex >= timepoint.interactions.length) {\n trackManager.continueInteractive();\n return;\n }\n changeIndex(timepointState.interactionIndex + 1);\n return;\n }\n \n const filteredState = getFilteredState(interactionState);\n\n const validate = getViewValidation(interaction.typeId);\n const errorText = validate(filteredState, interaction);\n\n if (errorText) {\n interactiveState.updateInteractionState(interaction.id, { error: errorText });\n return;\n }\n\n let submissionResult: InteractionState = {};\n if (resultsService && interactionState.hasChanges) {\n const submit = getViewSubmit(interaction.typeId);\n\n interactiveState.updateInteractionState(interaction.id, { spinner: true });\n\n if (submit) {\n submissionResult = await submit(filteredState, interaction, resultsService.save, { imageApi }) || {};\n\n const data = _getInteractionAnalyticsData(interaction);\n analyticsService?.logUserAction(data, {\n actionType: UserAction.Submit,\n entity: EntityType.Interaction\n });\n }\n }\n\n interactiveState.updateInteractionState(interaction.id, {\n ...submissionResult,\n submitted: true,\n error: null,\n hasChanges: false,\n spinner: false\n });\n\n if (!interactive.immediateFeedback) {\n skip();\n return;\n }\n\n const showFeedbackFunction = getShouldShowFeedback(interaction.typeId);\n const showFeedback = showFeedbackFunction(interaction);\n\n if (!showFeedback)\n skip();\n }\n\n async function saveTimepoint(): Promise<void> {\n /**\n * Don't need to save anything if it's a new timepoint\n */\n if (isNewId(timepoint.id))\n return;\n\n await InteractiveAjax.updateTimepoint(timepoint);\n sortTimepoints();\n clearTimepointTimeState();\n }\n\n async function cancel(): Promise<void> {\n if (interactionState?.hasChanges) {\n discardChanges();\n return;\n }\n\n await deleteInteraction(interaction.id);\n trackManager.setOpen(true);\n }\n\n function addAnotherQuestion(): void {\n changeIndex(timepoint.interactions.length);\n }\n\n function showTypeSelector(): void {\n player.pause();\n trackManager.setOpen(true);\n if (timepoint)\n addAnotherQuestion();\n }\n\n function cancelTypeSelector(): void {\n if (timepoint) {\n changeIndex(timepointState.interactionIndex - 1);\n return;\n }\n trackManager.setOpen(false);\n player.play();\n }\n\n function promptDelete(interactionId: string): void {\n const { localInteraction } = _findInteractionAndTimepoint(interactionId);\n const data = _getInteractionAnalyticsData(localInteraction);\n analyticsService?.logUserAction(data, {\n actionType: UserAction.Delete,\n entity: EntityType.Interaction,\n workflowPhase: WorkflowPhase.Start\n });\n\n DialogHelper.render(<p>Are you sure you want to delete this question?</p>, {\n title: 'Delete question',\n submitButtonProps: {\n onClick: () => deleteInteraction(interactionId),\n variant: 'danger',\n text: 'Delete question'\n },\n cancelButtonProps: {\n variant: 'link',\n text: 'Cancel'\n }\n });\n }\n\n function adjustForCollisions(time: number): number {\n let newTime = timepoint.visibleAt + (time * 1000);\n const increment = time > 0;\n\n for (let i = 0; i < interactive.timepoints.length; i++) {\n const t = interactive.timepoints[i];\n\n if (newTime < t.visibleAt - 1000 || newTime > t.visibleAt + 1000)\n continue;\n\n /**\n * If we get here it means there's a time collision\n * so we move the newTime to the start or end of our timepoint\n * and then restart out loop\n */\n if (increment)\n newTime = t.visibleAt + 1001;\n else\n newTime = t.visibleAt - 1001;\n i = 0;\n }\n return newTime;\n }\n\n /**\n * If we start seeing lag with the moving time point UI\n * This guy is probably the cause - Sha\n */\n function updateTimepointTime(time: number): void {\n const duration = player.duration();\n const newTime = adjustForCollisions(time);\n\n if ((newTime / 1000) > duration)\n return;\n\n if (newTime < 0)\n return;\n\n const originalVisibleAt = timepoint.visibleAt;\n\n if (!timepointHasChanges) {\n /**\n * I really hate to do this, but because this function gets called\n * many times before React.useReducer will actually update and return\n * I need a more immediate method\n */\n timepointHasChanges = true;\n interactiveState.updateTimepointState(timepoint.id, {\n originalVisibleAt,\n hasChanges: true\n });\n }\n\n trackManager.moveTimepoint(newTime);\n }\n\n function clearTimepointTimeState(reset?: boolean): void {\n if (!timepointState?.hasChanges)\n return;\n\n if (reset)\n trackManager.moveTimepoint(timepointState.originalVisibleAt);\n\n interactiveState.updateTimepointState(timepoint.id, {\n hasChanges: undefined,\n originalVisibleAt: undefined\n });\n timepointHasChanges = false;\n }\n\n async function reOrderQuestions(interactions: Interaction[]): Promise<void> {\n for (let i = 0; i < interactions.length; i++) {\n await InteractiveAjax.saveInteraction({\n ...interactions[i],\n order: i\n });\n }\n \n /**\n * The user needs to get taken back to the same interaction\n * but the interactionIndex will refer to a different interaction\n * so we need to update it\n */\n const currentInteraction = timepoint.interactions[timepointState.interactionIndex];\n timepoint.interactions = interactions;\n interactiveState.updateTimepointState(timepoint.id, {\n interactionIndex: interactions.indexOf(currentInteraction)\n });\n }\n\n return {\n state,\n interaction,\n interactionState,\n timepointState,\n nextInteraction,\n nextInteractionState,\n\n // functions\n skip,\n cancel,\n addAnotherQuestion,\n goToTimepoint,\n discardChanges,\n changeIndex,\n promptDelete,\n showTypeSelector,\n cancelTypeSelector,\n deleteInteraction,\n saveInteraction,\n addInteraction,\n submitInteractionAnswer,\n userUpdateInteractionState: interactiveState.userUpdateInteractionState,\n updateTimepointTime,\n saveTimepoint,\n clearTimepointTimeState,\n reOrderQuestions\n };\n};","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { Interactive, Timepoint } from 'libs/shared/interfaces';\n\nimport { InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces';\n\ninterface useInteractiveOptions {\n player: VideoJsPlayer;\n track: TextTrack;\n interactive: Interactive;\n mode: InteractiveMode;\n clipOffset?: number;\n}\n\nexport const useInteractiveTrack = (options: useInteractiveOptions) => {\n const { player, track, interactive, clipOffset } = options;\n\n const [ open, _setOpen ] = React.useState(false);\n\n /**\n * Stored the previous open state so that we know if our panel is sliding in or not.\n */\n const [ wasOpen, setWasOpen ] = React.useState(false);\n\n const [ timepoint, setTimepoint ] = React.useState<Timepoint>(null);\n\n React.useEffect(() => {\n track.addEventListener('cuechange', onCueChange);\n return () => track.removeEventListener('cuechange', onCueChange);\n });\n\n function getClipOffset(time: number): number {\n if (!clipOffset)\n return time;\n\n return time + clipOffset;\n }\n\n function setOpen(val: boolean): void {\n if (!val)\n setWasOpen(false);\n else\n setWasOpen(open);\n \n _setOpen(val);\n }\n\n function onCueChange(): void {\n const activeCues = track.activeCues;\n\n if (!activeCues.length) {\n setOpen(false);\n setTimepoint(null);\n return;\n }\n\n const currentTimepoint = interactive.timepoints.find(t => {\n return t.id.toString() === (activeCues[0] as any).text.toString();\n });\n\n if (!currentTimepoint) {\n setOpen(false);\n setTimepoint(null);\n return;\n }\n\n if (currentTimepoint.shouldPause) {\n if (!player.seeking()) {\n player.pause();\n } else {\n player.one('play', () => player.pause());\n }\n }\n\n setOpen(true);\n setTimepoint(currentTimepoint);\n }\n\n function continueInteractive(): void {\n setOpen(false);\n player.play();\n }\n\n function findCue(timepointId: string): TextTrackCue {\n for (let i = 0; i < track.cues.length; i++) {\n const cue = track.cues[i] as any;\n\n if (cue.text.toString() === timepointId.toString())\n return cue;\n }\n }\n\n function updateCue(oldTimepointId: string, timepointId: string): void {\n const cue = findCue(oldTimepointId) as any;\n cue.text = timepointId.toString();\n cue.originalCue_.text = timepointId.toString();\n }\n\n function addCue(timepointId: string): void {\n const currentTime = player.currentTime();\n\n (track as any).addCue({\n startTime: getClipOffset(currentTime) - 0.001,\n endTime: getClipOffset(currentTime + 1),\n text: timepointId\n });\n\n /**\n * Lets the InteractiveBarItems component know it needs\n * to re-render\n */\n (track as any).trigger('cv:cuechange');\n\n /**\n * If the player is paused the cuechange won't fire till the player starts playing again\n * so we force trigger it here\n */\n if (player.paused())\n (track as any).trigger('cuechange');\n }\n\n function removeCue(visibleAt: number): void {\n visibleAt = getClipOffset(visibleAt);\n\n let i = 0;\n while (i < track.cues.length) {\n const cue = track.cues[i];\n\n if (cue.startTime <= visibleAt && cue.endTime >= visibleAt) {\n track.removeCue(cue);\n (track as any).trigger('cv:cuechange');\n (track as any).trigger('cuechange');\n break;\n }\n\n i++;\n }\n }\n\n function moveTimepoint(newTime: number): void {\n const cue = findCue(timepoint.id);\n\n if (!cue)\n return;\n\n const timeInSeconds = newTime / 1000;\n\n cue.startTime = getClipOffset(timeInSeconds);\n cue.endTime = getClipOffset(timeInSeconds + 1);\n \n /**\n * Set time to the middle of the timepoint\n */\n (player as any).currentTime(timeInSeconds + 0.5, true);\n\n timepoint.visibleAt = newTime;\n\n (track as any).trigger('cv:cuechange');\n }\n\n return {\n open,\n setOpen,\n wasOpen,\n timepoint,\n continueInteractive,\n updateCue,\n addCue,\n removeCue,\n moveTimepoint,\n getClipOffset\n };\n};\n","import React from 'react';\nimport { HtmlPortalNode, InPortal } from 'react-reverse-portal';\n\nimport { ActionOptions, Actions } from 'libs/shared/components/actions/Actions';\nimport { CurationStatus } from 'libs/shared/enums/CurationStatus';\nimport { Clip, Interactive, Video } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nfunction hasInteractions(interactive: Interactive): boolean {\n let interactions = 0;\n\n interactive?.timepoints?.forEach(t => t.interactions?.forEach(() => interactions++));\n\n return interactions > 0;\n}\n\ninterface InteractiveActionsProps {\n interactive: Interactive;\n portalNode: HtmlPortalNode;\n onClickCopy?: () => void;\n onClickEditDetails?: () => void;\n onClickPublish?: () => void;\n onClickDelete?: () => void;\n parentVideo?: Video | Clip;\n}\n\nexport function InteractiveActions(props: InteractiveActionsProps): React.ReactElement {\n const isParentPublished = (!props.parentVideo || props.parentVideo?.status === CurationStatus.Published);\n const canPublish = hasInteractions(props.interactive) && isParentPublished;\n\n const actions: ActionOptions[] = [];\n\n if (props.onClickEditDetails) {\n actions.push({\n label: 'Edit details',\n svgName: cvSvgLibrary.Edit,\n button: true,\n className: 'btn btn-outline-dark',\n onClick: props.onClickEditDetails\n });\n }\n\n if (props.onClickPublish) {\n actions.push({\n label: 'Publish',\n button: true,\n className: `btn btn-dark ms-2${canPublish ? '' : ' disabled'}`,\n disabled: !canPublish,\n tooltip: canPublish\n ? ''\n : isParentPublished\n ? 'Interactives cannot be published without questions'\n : 'Parent video must be published before interactives can be published',\n onClick: onClickPublish\n });\n }\n\n if (props.onClickCopy) {\n actions.push({\n label: 'Copy interactive',\n button: false,\n onClick: props.onClickCopy\n });\n }\n\n if (props.onClickDelete) {\n actions.push({\n label: 'Delete interactive',\n button: false,\n onClick: props.onClickDelete,\n className: 'text-danger'\n });\n }\n\n function onClickPublish(): void {\n if (!canPublish)\n return;\n\n props.onClickPublish && props.onClickPublish();\n }\n\n if (!actions.length)\n return <></>;\n\n return (\n <InPortal node={props.portalNode}>\n <Actions actions={actions} actionsDropdownClassName='btn btn-outline-dark ms-2' />\n </InPortal>\n );\n}","import React from 'react';\nimport { HtmlPortalNode } from 'react-reverse-portal';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Clip, Interactive, Video } from 'libs/shared/interfaces';\n\nimport { PlayerCurrentUser } from 'projects/player/interfaces/models/PlayerCurrentUser';\nimport { AddQuestionButton } from 'projects/player/plugins/interactive-plugin/components/add-question-button/add-question-button';\nimport { InteractiveSummaryWrapper } from 'projects/player/plugins/interactive-plugin/components/interactive-summary/InteractiveSummaryWrapper';\nimport { QuestionList } from 'projects/player/plugins/interactive-plugin/components/question-list/question-list';\nimport { SlidingTimepoint } from 'projects/player/plugins/interactive-plugin/components/sliding-timepoint/sliding-timepoints';\nimport { useStateManager } from 'projects/player/plugins/interactive-plugin/hooks//useStateManager';\nimport { useInteractiveTrack } from 'projects/player/plugins/interactive-plugin/hooks/useInteractiveTrack';\nimport { useLockPlayer } from 'projects/player/plugins/interactive-plugin/hooks/useLockPlayer';\nimport { LatestSession } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces/InteractiveMode';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\nimport { getReactComponent } from 'projects/player/react/react-component';\nimport { AnalyticsService } from 'projects/player/services/analytics-service';\n\nimport { InteractiveActions } from '../interactive-actions/interactive-actions';\n\nimport './interactive-component.scss';\n\ninterface InteractiveProps {\n title: string;\n currentUser?: PlayerCurrentUser;\n player: VideoJsPlayer;\n track: TextTrack;\n mode: InteractiveMode;\n interactive: Interactive;\n imageApi: URL;\n resultsService?: ResultsService;\n progress?: ProgressEventPair[];\n actionsPortalNode?: HtmlPortalNode;\n questionListPortalNode?: HtmlPortalNode;\n parentVideo?: Video | Clip;\n summaryPortalNode?: HtmlPortalNode;\n latestSession?: LatestSession;\n clipOffset?: number;\n analyticsService?: AnalyticsService;\n enableImmersiveReader: boolean;\n mobile: boolean;\n experimentalInteractiveQuestions?: boolean;\n onClickCopy?: () => void;\n onShowSummary?: (showing: boolean) => void;\n onClickEditDetails?: () => void;\n onClickPublish?: () => void;\n onClickDelete?: () => void;\n}\n\nfunction InteractiveComponent(props: InteractiveProps): React.ReactElement {\n const {\n title,\n player,\n track,\n mode,\n interactive,\n imageApi,\n actionsPortalNode,\n questionListPortalNode,\n summaryPortalNode,\n resultsService,\n currentUser,\n progress,\n latestSession,\n clipOffset,\n analyticsService,\n enableImmersiveReader,\n mobile,\n parentVideo,\n experimentalInteractiveQuestions\n } = props;\n\n /**\n * useInteractiveTrack is responsible for returning \n * the active timepoint whenever the player gets to one\n * as well as providing functions to keep the track\n * up to date, these functions are use in useStateManager\n */\n const {\n open, timepoint, wasOpen, ...trackManager\n } = useInteractiveTrack({ player, track, interactive, mode, clipOffset });\n\n /**\n * All state manipulation and communication with the server\n * resides in useStateManager\n */\n const {\n interaction, interactionState, nextInteraction, nextInteractionState, timepointState, state, ...stateManager\n } = useStateManager({\n mode, interactive, timepoint, player, resultsService, latestSession, analyticsService, imageApi, ...trackManager\n });\n\n /**\n * Prevents navigation, both in the player and with appLinks\n */\n useLockPlayer({\n mode,\n player,\n timepoint,\n interaction,\n discardChanges: stateManager.discardChanges,\n interactionState,\n timepointState\n });\n\n const isCreate = mode === InteractiveMode.Create;\n\n const viewState = {\n mode,\n open,\n isCreate,\n interaction,\n nextInteraction,\n timepoint,\n interactive,\n interactionState,\n nextInteractionState,\n timepointState,\n player\n };\n\n return (\n <>\n {!!actionsPortalNode &&\n <InteractiveActions\n interactive={interactive}\n onClickEditDetails={props.onClickEditDetails}\n onClickPublish={props.onClickPublish}\n onClickDelete={props.onClickDelete}\n onClickCopy={props.onClickCopy}\n portalNode={actionsPortalNode}\n parentVideo={parentVideo}\n />\n }\n <AddQuestionButton {...viewState} {...stateManager} />\n <SlidingTimepoint\n imageApi={imageApi}\n currentUser={currentUser}\n immediateFeedback={interactive.immediateFeedback}\n delayFocus={!wasOpen} // We only want to delay our focus call if the player wasn't previously open\n enableImmersiveReader={enableImmersiveReader}\n experimentalInteractiveQuestions={experimentalInteractiveQuestions}\n {...viewState}\n {...stateManager}\n {...trackManager}\n />\n <InteractiveSummaryWrapper\n title={title}\n currentUser={currentUser}\n state={state}\n portalNode={summaryPortalNode}\n progress={progress}\n resultsService={resultsService}\n imageCdnUrl={imageApi.toString()}\n onShowSummary={props.onShowSummary}\n mobile={mobile}\n {...viewState}\n {...stateManager}\n />\n <QuestionList\n portalNode={questionListPortalNode}\n experimentalInteractiveQuestions={experimentalInteractiveQuestions}\n {...viewState}\n {...stateManager}\n />\n </>\n );\n}\n\nvideojs.registerComponent(\n 'Interactive',\n getReactComponent((player: VideoJsPlayer, options: InteractiveProps) =>\n <InteractiveComponent player={player} {...options} />)\n);\n","import React from 'react';\nimport { VideoJsPlayer } from 'video.js';\n\nimport { useNavLock } from 'libs/shared/hooks/useNavLock';\nimport { Interaction, Timepoint } from 'libs/shared/interfaces';\n\nimport { InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { InteractionState, TimepointState } from 'projects/player/plugins/interactive-plugin/interfaces/InteractiveState';\nimport { isNewId } from 'projects/player/plugins/interactive-plugin/utils/helpers';\n\ninterface UseLockNavProps {\n mode: InteractiveMode;\n player: VideoJsPlayer;\n timepoint: Timepoint;\n interaction: Interaction;\n interactionState: InteractionState;\n timepointState: TimepointState;\n discardChanges: (after?: () => void) => void;\n}\n\nexport function useLockPlayer(props: UseLockNavProps): void {\n const {\n mode,\n player,\n timepoint,\n interaction,\n discardChanges,\n interactionState,\n timepointState\n } = props;\n\n const navLock = useNavLock();\n\n const isCreate = mode === InteractiveMode.Create;\n\n React.useEffect(() => {\n if (!isCreate)\n return;\n\n const isNew = isNewId(interaction?.id);\n\n if (isNew || interactionState?.hasChanges || timepointState?.hasChanges) {\n navLock.lock({\n id: 'interactive',\n title: 'Are you sure you want to leave?',\n text: 'Your interactive still has unsaved changes'\n });\n \n player.lock((success: () => void) => {\n discardChanges(success);\n });\n return;\n }\n\n player.unlock();\n navLock.unlock('interactive');\n\n // if something updates state or an interaction is added\n }, [ interaction, interactionState?.hasChanges, timepoint?.interactions?.length, timepointState?.hasChanges ]);\n}","import React from 'react';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { PopupButtons } from 'libs/shared/components/popup/PopupButtons';\n\nimport { getReactComponent } from 'projects/player/react/react-component';\n\nimport styles from './continue-session.scss';\n\ninterface ContinueSessionProps {\n player: VideoJsPlayer;\n continue: (sameSession: boolean) => void;\n}\n\nexport function ContinueSession(props: ContinueSessionProps): React.ReactElement {\n const { player } = props;\n\n function closePopup() {\n const component = player.getChild('ContinueSession');\n player.removeChild(component);\n component.dispose();\n }\n\n function continueSession(): void {\n props.continue(true);\n closePopup();\n }\n\n function startAgain(): void {\n props.continue(false);\n closePopup();\n }\n\n return (\n <Popup\n title='Continue interactive?'\n closePopup={continueSession}\n dialogClassName={styles.continueSessionPopup}\n >\n <p>\n It looks like you've already started this interactive.\n Would you like to continue your attempt or start a new one?\n </p>\n <PopupButtons className={styles.popupButtons}>\n <PopupButtons.Cancel text='Start again' onClick={startAgain} />\n <PopupButtons.Submit variant='dark' text='Continue' onClick={continueSession} />\n </PopupButtons>\n </Popup>\n );\n}\n\nvideojs.registerComponent(\n 'ContinueSession',\n getReactComponent((player: VideoJsPlayer, options: ContinueSessionProps) =>\n <ContinueSession player={player} {...options} />)\n);","// extracted by mini-css-extract-plugin\nexport default {\"continueSessionPopup\":\"VVqKz\",\"popupButtons\":\"kw8gW\"};","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { HashObject } from 'libs/common/react/interfaces';\n\nconst Plugin = videojs.getPlugin('plugin');\n\nclass GradePassbackPlugin extends Plugin {\n public enabled: boolean = false;\n\n constructor(player: VideoJsPlayer) {\n super(player);\n\n this.player.ready(() => this.initialize());\n }\n\n private initialize(): void {\n this.onReceiveMessage = this.onReceiveMessage.bind(this);\n window.addEventListener('message', this.onReceiveMessage, false);\n window.parent.postMessage(JSON.stringify({ type: 'cv-app-loaded' }), '*');\n }\n\n public dispose(): void {\n window.removeEventListener('message', this.onReceiveMessage);\n }\n\n private onReceiveMessage(event: MessageEvent): void {\n let data: HashObject = {};\n\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n if (data.type !== 'enable-grade-passback')\n return;\n\n this.enabled = true;\n window.removeEventListener('message', this.onReceiveMessage);\n }\n\n public submit(score: number, fullyGraded: boolean): void {\n const message = {\n type: 'cv-lms-submit-score',\n data: { score, fullyGraded }\n };\n window.parent.postMessage(JSON.stringify(message), '*');\n }\n}\n\nvideojs.registerPlugin('gradePassbackPlugin', GradePassbackPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n gradePassbackPlugin(): GradePassbackPlugin;\n }\n}","import { HtmlPortalNode } from 'react-reverse-portal';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { EntityType, InteractiveSessionDescriptor, UserAction } from 'libs/analytics/interfaces';\n\nimport { Clip, Interactive, Video } from 'libs/shared/interfaces';\n\nimport { PlayerCurrentUser } from 'projects/player/interfaces/models/PlayerCurrentUser';\nimport { InteractiveBarItems } from 'projects/player/plugins/interactive-plugin/components/seek-bar/interactive-bar-items';\nimport { InteractiveMode, LatestSession } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\nimport { AnalyticsService } from 'projects/player/services/analytics-service';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nimport './interactive-plugin-styles.scss';\n\nimport 'projects/player/plugins/interactive-plugin/components/interactive/interactive-component';\nimport 'projects/player/plugins/interactive-plugin/components/continue-session/continue-session';\nimport './grade-passback-plugin';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface InteractivePluginOptions {\n title: string;\n currentUser?: PlayerCurrentUser;\n interactive: Interactive;\n mode?: InteractiveMode;\n imageApi?: URL;\n resultsService?: ResultsService;\n actionsPortalNode?: HtmlPortalNode;\n questionListPortalNode?: HtmlPortalNode;\n summaryPortalNode?: HtmlPortalNode;\n parentVideo?: Video | Clip;\n progress?: ProgressEventPair[]\n latestSession?: LatestSession;\n clipOffset?: number;\n analyticsService?: AnalyticsService;\n enableImmersiveReader: boolean;\n mobile: boolean;\n experimentalInteractiveQuestions: boolean;\n onClickCopy?: () => void;\n onShowSummary?: (showing: boolean) => void;\n onClickEditDetails?: () => void;\n onClickPublish?: () => void;\n onClickDelete?: () => void;\n}\n\nclass InteractivePlugin extends Plugin {\n private options: InteractivePluginOptions;\n private continueSession: boolean = false;\n\n constructor(player: VideoJsPlayer, options: InteractivePluginOptions) {\n super(player);\n\n this.options = options;\n\n player.ready(() => this.initialize());\n }\n\n private initialize(): void {\n // Needs to be called before calling useTrack because onTrackLoaded will add the popup\n this.player.gradePassbackPlugin();\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n TrackHelper.useMetadataTrack(this.player, 'interactive', this.onTrackLoaded.bind(this));\n\n this.player.addClass('cv-interactive-plugin');\n\n if (this.options.resultsService && !this.options.latestSession) {\n this.startSession = this.startSession.bind(this);\n this.player.one('play', this.startSession);\n this.on('dispose', () => {\n this.player.off('play', this.startSession);\n });\n }\n }\n\n private startSession(): void {\n let resultId = this.options.latestSession?.resultId;\n\n if (!this.continueSession)\n resultId = null;\n\n this.options.resultsService.start(resultId);\n }\n\n private onTrackLoaded(track: TextTrack): void {\n if (!this.options.resultsService || !this.options.latestSession) {\n this.addChildren(track);\n return;\n }\n\n this.player.addChild('ContinueSession', {\n continue: (sameSession: boolean) => {\n this.options.analyticsService?.logUserAction({}, {\n actionType: UserAction.Click,\n entity: EntityType.Interactive,\n descriptor: sameSession ?\n InteractiveSessionDescriptor.ContinueSession :\n InteractiveSessionDescriptor.NewSession\n });\n\n this.continueSession = sameSession;\n this.startSession();\n this.addChildren(track);\n\n if (!this.continueSession)\n this.player.currentTime(0);\n\n this.player.play();\n }\n });\n }\n\n /**\n * Because the clip plugin requires the start and end time to be set to 4 significant digits\n * we also need to do it here so that our track offsets are accurate.\n */\n private getClipOffset(): number | null {\n if (!this.options.clipOffset)\n return null;\n\n return parseFloat(this.options.clipOffset.toPrecision(4));\n }\n\n private addChildren(track: TextTrack): void {\n this.player.addChild('Interactive', {\n ...this.options,\n track,\n clipOffset: this.getClipOffset(),\n mode: this.options.mode || InteractiveMode.View,\n latestSession: this.continueSession && this.options.latestSession\n });\n\n // 🌶 inject the interactive bar items into the seek bar\n const seekBar = this.player.controlBar.getChild('progressControl').getChild('SeekBar');\n\n seekBar.addChild(new InteractiveBarItems(this.player, {\n interactive: this.options.interactive,\n track\n }));\n }\n}\n\nvideojs.registerPlugin('viewInteractivePlugin', InteractivePlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n viewInteractivePlugin(options?: InteractivePluginOptions): InteractivePlugin;\n }\n}","/* eslint simple-import-sort/imports: 0 */\n\n/**\n * NOTICE: DO NOT CHANGE THE ORDER OF OUR IMPORTS.\n * IF YOU LINTED THIS FILE DISCARD YOUR CHANGES - SHA\n */\n\nimport { HtmlPortalNode } from 'react-reverse-portal';\nimport { ClipData } from 'projects/player/interfaces/models/ClipData';\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\nimport { InteractiveMode } from 'projects/player/plugins/interactive-plugin/interfaces';\nimport { ResultsService } from 'projects/player/plugins/interactive-plugin/utils/ResultsService';\nimport { ProgressEventPair } from 'projects/player/plugins/progress-reporter-plugin/interfaces/ProgressEvent';\nimport { AnalyticsPlayerType } from 'projects/player/services/analytics-service';\nimport { AjaxHelper } from 'projects/player/utils/ajax-helper';\nimport { InteractiveTrackHelper } from 'projects/player/utils/interactive-track-helper';\nimport { VideoJsPlayerOptions } from 'video.js';\n\nimport { DevError } from 'libs/common/backbone/errors/DevError';\nimport { Core } from 'libs/common/core';\n\nimport { HashObject } from 'libs/analytics/interfaces';\n\nimport { ShareActivityStatus } from 'libs/shared/enums/ShareActivityStatus';\nimport { Clip, CurrentUser, ExperimentalInteractionTypes, Interactive, Video } from 'libs/shared/interfaces';\n\nimport { BasePlayer, BasePlayerOptions } from './base-player';\n\nimport 'projects/player/plugins/clip-plugin/clip-plugin';\nimport 'projects/player/plugins/activity-status-plugin/activity-status-plugin';\nimport 'projects/player/plugins/interactive-plugin/interactive-plugin';\nimport 'projects/player/plugins/prevent-scrubbing-plugin/prevent-scrubbing-plugin';\n\ntype CollectResultsOptionalOptions = {\n collectResults?: false;\n shareId?: string;\n currentUser?: CurrentUser;\n publicName?: string;\n profileId?: string;\n};\n\ntype CollectResultsRequiredOptions = {\n collectResults: true;\n shareId: string;\n currentUser: CurrentUser;\n};\n\nexport type InteractivePlayerOptions = {\n mode?: InteractiveMode;\n imageApi?: URL;\n authToken?: string;\n actionsPortalNode?: HtmlPortalNode;\n questionListPortalNode?: HtmlPortalNode;\n summaryPortalNode?: HtmlPortalNode;\n furthestVisitedTime?: number;\n onShowSummary?: (showing: boolean) => void;\n onClickEditDetails?: () => void;\n onClickPublish?: () => void;\n onClickDelete?: () => void;\n onClickCopy?: () => void;\n enableImmersiveReader?: boolean;\n parentVideo?: Video | Clip;\n experimentalInteractiveQuestions?: boolean;\n} & (CollectResultsOptionalOptions | CollectResultsRequiredOptions) & BasePlayerOptions;\n\nexport class InteractivePlayer extends BasePlayer {\n protected options: InteractivePlayerOptions;\n private track: TextTrack;\n private resultsService: ResultsService;\n private totalProgress: ProgressEventPair[] = [];\n\n constructor(id: string | Element, options: InteractivePlayerOptions) {\n super(id, options);\n\n AjaxHelper.setToken('gateway', this.options.authToken);\n\n if (this.options.mode === InteractiveMode.Create)\n this.player.addClass('cv-create-interactives');\n }\n\n public togglePreviewPreventScrubbing(): void {\n const plugin = this.player.preventScrubbingPlugin();\n\n if (plugin) {\n plugin.togglePreview(!plugin.isPreviewing);\n }\n }\n\n protected getPlayerOptions(): VideoJsPlayerOptions {\n const options = super.getPlayerOptions();\n\n options.setMaxHeight = false;\n\n /**\n * We want to lock the interactive player into a 16:9 ratio when it's not embedded\n * Unfortunately the UI for it isn't designed to handle other ratios.\n */\n if (!this.options.embed)\n options.aspectRatio = '16:9';\n\n /**\n * Setting this option to true will make the player take up the full window space\n * on iPhone when the fullscreen button is pressed (instead of going into the native\n * fullscreen experience). This is necessary because the native fullscreen experience\n * on iPhone only plays videos - meaning iPhone users cannot attempt the interactive in\n * the native fullscreen experience.\n * \n * Find out more about this option here: https://videojs.com/guides/options/#preferfullwindow\n */\n options.preferFullWindow = true;\n\n return options;\n }\n\n protected onFlushProgress(events: ProgressEventPair[]): void {\n super.onFlushProgress(events);\n\n if (this.options.mode !== InteractiveMode.Create)\n this.totalProgress.push(...events);\n }\n\n protected async additionalSetup(playbackObject: PlaybackObject): Promise<void> {\n super.additionalSetup(playbackObject);\n\n this.setupClipPlugin(playbackObject);\n this.setupPreventScrubbingPlugin(playbackObject);\n }\n\n protected setupAnalyticsDependentPlugins(playbackObject: PlaybackObject): void {\n super.setupAnalyticsDependentPlugins(playbackObject);\n\n this.setupViewInteractivePlugin(playbackObject);\n }\n\n protected handleAutoplay(playbackObject: PlaybackObject): void {\n const showContinueSession = (\n this.options.collectResults &&\n this.options.currentUser &&\n this.options.shareId &&\n playbackObject.additionalData?.latestSession\n );\n\n if (showContinueSession) {\n if (this.options.autoplay)\n this.showSplash();\n return;\n }\n\n super.handleAutoplay(playbackObject);\n }\n\n private setupPreventScrubbingPlugin(playbackObject: PlaybackObject): void {\n if (!playbackObject.additionalData?.interactive)\n return;\n\n const interactive = playbackObject.additionalData.interactive as Interactive;\n const isPreviewOrEditing = this.options.mode === InteractiveMode.Create || !this.options.collectResults;\n\n this.player.preventScrubbingPlugin({\n isEnabled: !isPreviewOrEditing && interactive.preventScrubbing,\n furthestVisitedTime: this.options.furthestVisitedTime ?? 0\n });\n }\n \n private setupClipPlugin(playbackObject: PlaybackObject): void {\n if (!playbackObject?.additionalData?.clipData)\n return;\n\n const clipData = playbackObject.additionalData.clipData as ClipData;\n this.player.clipPlugin({\n startTime: clipData.startTime,\n endTime: clipData.endTime\n });\n }\n\n private filterNewQuestionTypes(interactive: Interactive): Interactive {\n return {\n ...interactive,\n timepoints: interactive.timepoints?.map(t => {\n return {\n ...t,\n interactions: t.interactions?.filter(i => !ExperimentalInteractionTypes[i.typeId])\n };\n }).filter(t => !!t.interactions?.length)\n };\n }\n\n private validateCollectResultsOptions(): void {\n if (!this.options.shareId)\n Core.ErrorHelper.throw(\n new DevError('Must provide a shareId in order to collect interactive results')\n );\n }\n\n private setupViewInteractivePlugin(playbackObject: PlaybackObject): void {\n this.track = InteractiveTrackHelper.getInteractiveTrack(this.player, playbackObject);\n\n let interactive = playbackObject.additionalData.interactive as Interactive;\n\n if (!this.options.experimentalInteractiveQuestions)\n interactive = this.filterNewQuestionTypes(interactive);\n\n const clipOffset = playbackObject.additionalData.clipData?.startTime;\n\n if (this.options.collectResults) {\n this.validateCollectResultsOptions();\n\n this.resultsService = new ResultsService({\n interactiveId: interactive.id,\n metadataId: playbackObject.mediaId,\n userId: this.options.currentUser?.id,\n customerId: this.options.currentUser?.customerId,\n playerApi: this.options.playerApi,\n shareId: this.options.shareId\n });\n }\n\n this.player.viewInteractivePlugin({\n interactive,\n title: playbackObject.title,\n mode: this.options.mode,\n imageApi: this.options.imageApi,\n resultsService: this.resultsService,\n actionsPortalNode: this.options.actionsPortalNode,\n questionListPortalNode: this.options.questionListPortalNode,\n summaryPortalNode: this.options.summaryPortalNode,\n currentUser: this.options.currentUser,\n latestSession: playbackObject.additionalData.latestSession,\n progress: this.totalProgress,\n parentVideo: this.options.parentVideo,\n clipOffset,\n analyticsService: this.analyticsService,\n enableImmersiveReader: this.options.enableImmersiveReader,\n onShowSummary: this.options.onShowSummary,\n onClickCopy: this.options.onClickCopy,\n onClickEditDetails: this.options.onClickEditDetails,\n onClickPublish: this.options.onClickPublish,\n onClickDelete: this.options.onClickDelete,\n mobile: this.options.mobile,\n experimentalInteractiveQuestions: this.options.experimentalInteractiveQuestions\n });\n }\n\n protected getAdditionalAnalyticsData(playbackObject: PlaybackObject): HashObject {\n if (!playbackObject.additionalData?.clipData?.clipId)\n return {};\n \n return {\n clip: {\n id: playbackObject.additionalData?.clipData?.clipId\n }\n };\n }\n\n protected getSeekBarOptions(): any {\n return {\n ignoreChapters: true\n };\n }\n\n protected getAnalyticsPlayerType(): AnalyticsPlayerType {\n return 'interactive-player';\n }\n\n public setActivityStatus(status: ShareActivityStatus, onToggle: () => void): void {\n const plugin = this.player.activityStatusPlugin();\n plugin.setActivityStatus(status, onToggle);\n }\n}\n","import React from 'react';\n\nimport { InteractivePlayer, InteractivePlayerOptions } from 'projects/player/players/interactive-player';\nimport { getProxy } from 'projects/player/utils/getProxy';\n\ninterface ClickViewInteractivePlayerProps {\n onReady?: (player: InteractivePlayer) => void;\n className?: string;\n}\n\nexport function ClickViewInteractivePlayer(\n props: InteractivePlayerOptions & ClickViewInteractivePlayerProps\n): React.ReactElement {\n const { onReady, className, ...options } = props;\n\n const ref = React.useRef(null);\n\n React.useEffect(() => {\n const player = new InteractivePlayer(ref.current, options);\n\n if (onReady) {\n player.ready(() => {\n onReady(getProxy(player));\n });\n }\n\n return () => {\n window.requestAnimationFrame(() => player.dispose());\n };\n }, []);\n\n return (\n <>\n <div ref={ref} className={className}></div>\n <div id='popup-region' />\n </>\n );\n}\n","import { BasePlayer } from 'projects/player/players/base-player';\n\nexport function getProxy<T extends BasePlayer>(player: T) {\n return new Proxy(player, {\n get(target: T, p: string, receiver: any) {\n /**\n * We still allow removing event listeners if the player is diposed\n */\n if (p !== 'off' && target.isDisposed())\n return;\n\n return Reflect.get(target, p, receiver);\n }\n });\n}"],"names":["namespace","Correctness","props","interaction","getCorrectness","InteractionCorrectness","className","SvgContainer","size","S","svgName","Text","phrase","InteractionComponent","visibleAt","selectedInteractionId","goToTimepoint","scrollTo","isFirstInteraction","selected","id","toString","ref","current","el","rect","getBoundingClientRect","offset","top","offsetParent","height","cursor","DivButton","onClick","DurationHelper","InteractionLabel","showTypeName","typeNameClassName","questionClassName","onClickDelete","event","stopPropagation","TimepointComponent","timepoint","interactionId","interactions","map","i","experimentalInteractiveQuestions","typeId","key","InteractiveQuestions","interactive","maxHeight","elHeight","getClientHeight","scroll","getScrollTop","elementFromTop","scrollTop","borderClass","autoHeight","autoHeightMax","hideTracksWhenNotNeeded","timepoints","t","OnlineSupportArticle","LiteSupportArticle","getPhrase","LanguageService","MIME_REGEX","SimpleCropper","imageLoaded","setImageLoaded","showSpinner","setShowSpinner","imageRef","cropperRef","image","Image","src","viewPortToImageRatio","offsetWidth","width","dimensions","imageType","options","viewMode","autoCropArea","ready","minCropBoxWidth","minCropBoxHeight","aspectRatio","destroy","Popup","title","closePopup","popupSize","alt","PopupButtons","croppedDataUrl","getCroppedCanvas","toDataURL","dataUrl","mime","match","getImageMimeType","onClickCrop","text","variant","defaultProps","CropperHelper","renderCropper","root","document","getElementById","render","unmount","ActivityStatusButton","player","update","this","options_","activityStatus","ShareActivityStatus","addClass","removeClass","getToggledActivityStatus","clickHandler","args","call","prototype","controlText_","ActivityStatusPlugin","onToggleStatus","renderActivityStatusButton","button","removeChild","addChild","InteractiveMode","ReconnectionError","buttons","success","window","location","reload","ResultsService","save","bind","resultId","startSession","interactiveId","metadataId","userId","customerId","shareId","playerApi","startSessionRequest","anonymous","sessionId","SessionHelper","JSON","stringify","response","results","saveActionRequest","undefined","console","log","InteractiveIconButton","children","attributes","buttonClassName","svg","AddQuestionButton","isCreate","open","showTypeSelector","BrushThickness","BrushColours","IllustrationCanvas","_","canvasRef","canvasContainerRef","canvasWidth","canvasHeight","setCanvasSize","Black","colour","setColour","Small","brushThickness","setBrushThickness","eraserChecked","setEraserChecked","prevColour","setPrevColour","calculateCanvasSize","onClickColour","bgColour","resizeObserver","ResizeObserver","observe","disconnect","Object","entries","slice","index","name","style","backgroundColor","brushRadius","lazyRadius","hideGrid","brushColor","White","color","Medium","Large","undo","DialogHelper","submitButtonProps","clear","cancelButtonProps","IllustrationPanel","InteractionTypeHelper","bgClassName","Svg","onCancel","onSave","getDataURL","ViewErrorFeedback","error","BASE_64_PREFIX","PLACEHOLDER","showFeedback","dontShowFeedback","feedbackLookup","data","suggestedResponse","getShouldShowFeedback","QuestionLookup","annotation","replace","dangerouslySetInnerHTML","__html","recalculateScroll","node","onload","url","caption","state","setState","items","sentence","val","split","item","startsWith","order","actionableItem","actionableItems","find","a","context","value","createElement","getContext","font","measureText","isCorrect","toLowerCase","onChange","e","target","newState","maxLength","disabled","submitted","autoComplete","imageApi","currentUser","radio","filter","length","MultipleChoiceInteractionAnswers","onSelectAnswer","checked","getSelectedAnswer","userInitials","UserHelper","givenName","familyName","userAvatar","avatar","leftHandSidePortalNode","minRows","correctAnswer","TrueOrFalseInteractionAnswers","feedback","fullWidthPortalNode","showCanvas","setShowCanvas","imageUrl","noValidation","ValidationLookup","numberOfKeys","keys","k","trim","SubmissionLookup","actionableItemId","base64","tokenName","result","getViewSubmit","IsCorrectLookup","InteractiveCorrectnessHelper","every","getViewIsCorrect","InteractionSummary","studentResults","interactionNumber","imageCdnUrl","studentAttempt","interactionState","correctness","answerable","showQuestion","teacherFeedback","immediateFeedback","iconClassName","questionNumber","InteractionResponse","markedStatus","InteractiveAnswerStatus","markInteraction","showAvatar","InteractionsBar","duration","left","timepointId","ProgressSummary","progress","reRender","crunched","last","push","forEach","end","time","start","onProgressFlush","on","off","right","isNewId","getFilteredState","hasChanges","spinner","InteractiveSummary","showSummary","setShowSummary","portalNode","barRef","submitSpinner","setSubmitSpinner","switchToPlayer","show","play","correctCount","total","answered","awaitingMarking","studentAttempts","filteredState","answers","answeredAt","getStudentAttempts","user","surname","attempts","ended","BaseImage","poster","imageOptions","IconButton","currentTime","gradePassbackPlugin","enabled","Spinner","as","animation","role","submit","divRect","pageX","reduce","prev","ShowSummaryButton","resultsService","mobile","setShow","isFinished","setIsFinished","hasActivityStatusPlugin","activePlugins_","activityStatusPlugin","hasFavouritePlugin","favouritePlugin","onTimeUpdate","onEnded","pause","hide","InteractiveSummaryWrapper","onShowSummary","_setShowSummary","isFullscreen","exitFullscreen","QuestionListEmptyState","article","ArticleHelper","href","QuestionList","promptDelete","interactionCount","INTERACTION_TYPES","CreateTypeSelector","addInteraction","cancelTypeSelector","formatTime","setCurrentTime","interactionTypes","type","InteractionActions","optionsPortalNode","setView","actions","label","isNew","ActionsDropdown","dropdownToggleClassName","CreateInteractionButtons","onClickContinue","onClickSave","onClickCancel","onClickAddAnother","onClickDiscard","ViewInteractionButtons","onClickSkip","numberOfInteractions","currentIndex","changeIndex","shouldSubmit","showNext","showPrev","onClickSubmit","InteractionFooter","continueInteractive","saveInteraction","cancel","addAnotherQuestion","discardChanges","submitInteractionAnswer","CreateInteractionHeading","alphabet","InteractiveImmersiveReader","enableImmersiveReader","typeName","isHtml","ImmersiveReader","html","analyticsData","analyticsOptions","entity","actionType","descriptor","ViewInteractionHeading","prompt","InteractionHeader","timepointState","interactionIndex","CreateErrorFeedback","endpoints","InteractiveAjax","promise","newInteraction","shouldPause","draftConvertOptions","styleToHTML","entityToHTML","originalText","htmlToStyle","nodeName","currentStyle","add","htmlToEntity","createEntity","CreateAnnotationLink","setUrl","setText","expanded","onExpandEvent","htmlFor","placeholder","UploadImageDropzone","isDragging","setIsDragging","dragCounter","setDragCounter","onDragOver","preventDefault","onDragEnter","currentVal","dataTransfer","onDragLeave","onDrop","files","onDropImage","clearData","dragClassName","CHAR_REGEX","stripTailChars","word","chars","shift","pop","join","handleTailChars","startWord","intendedWord","unshift","generatePreview","words","wordLength","underscoreString","Array","fill","generateSentence","FeedbackTooltip","Tooltip","tooltipText","spanHack","spanHackClassName","UploadImageIcon","viewBox","transform","d","MultipleChoiceAnswer","labelRef","imageInputRef","onToggleCheckbox","answer","onImageSelect","isTrueOrFalse","ImageSelectHelper","then","res","alert","onKeyDown","multiple","accept","backgroundImage","click","ValidateMultipleChoice","question","validAnswers","textAnswers","hasDuplicates","answerDuplicateTracker","imageCount","SubmitMultipleChoice","CreateMultipleChoice","getInitialState","onUpdateAnswer","deletedAnswer","updatedAnswers","lastAnswer","ArrayHelper","ERROR_TYPE","NO_QUESTION","generateInitialState","content","EditorState","getEditorInitialState","editorState","setEditorState","editorRef","setEditorRef","focusEditor","contentState","getCurrentContent","hasText","getBlockMap","first","getType","shouldHidePlaceholder","Editor","onEditorStateChange","toolbarClassName","editorClassName","spellCheck","toolbar","inline","bold","icon","italic","underline","superscript","subscript","list","unordered","ordered","link","component","rows","placeholderWords","Boolean","reconstructed","fullSentence","preview","hasSentence","wordIndex","newWords","getErrorType","QUESTION","ANSWER","demoDataUrl","setDemoDataUrl","selectedWords","getCreateSubmit","interval","count","multiplier","MoveTimepoint","updateTimepointTime","saveTimepoint","back","clearTimepointTimeState","setTime","setSpinner","move","direction","setInterval","addEventListener","stop","removeEventListener","clearInterval","onMouseDown","keyCode","onKeyUp","SortableItem","Item","dragAttributes","dragListeners","SortableItemWrapper","childComponent","childProps","SortableInteractionList","grabCursorProps","onMouseUp","body","useGrabCursorProps","SortableContainerWrapper","ids","getDragOverlay","onSortEnd","tabIndex","ReorderInteractions","setItems","setHasChanges","active","over","oldIndex","findIndex","v","newIndex","splice","moveItems","reOrderQuestions","mode","shouldFocus","delayFocus","userUpdateInteractionState","skip","focusRef","focusTimeoutRef","isXlDown","isSlidingOver","shouldFocusCheck","focus","setHasFocused","hasFocused","setTimeout","view","Question","getCreateComponent","getViewComponent","Error","getInteractionComponent","onSubmit","recalculate","clearTimeout","SlidingTimepoint","nextInteraction","nextInteractionState","class","transitionPrev","nextInteractionIndex","transitionNext","slideOutUp","slideIn","slideOutDown","showExtraPanels","initialState","interactiveReducer","action","initialTimepointState","useInteractiveState","latestSession","dispatch","getTimepointState","getInteractionState","localInteractionState","updateInteractionState","oldState","updateTimepointState","clearTimepointState","clearInteractionState","timepointHasChanges","InteractiveActions","isParentPublished","parentVideo","status","CurationStatus","canPublish","hasInteractions","onClickEditDetails","onClickPublish","tooltip","onClickCopy","Actions","actionsDropdownClassName","InteractiveComponent","track","actionsPortalNode","questionListPortalNode","summaryPortalNode","clipOffset","analyticsService","_setOpen","wasOpen","setWasOpen","setTimepoint","getClipOffset","setOpen","onCueChange","activeCues","currentTimepoint","seeking","one","findCue","cues","cue","updateCue","oldTimepointId","originalCue_","addCue","startTime","endTime","trigger","paused","removeCue","moveTimepoint","newTime","timeInSeconds","useInteractiveTrack","trackManager","interactiveState","_findInteractionAndTimepoint","localTimepoint","j","localInteraction","_getInteractionAnalyticsData","interactionData","deleteInteraction","logUserAction","workflowPhase","deleteTimepoint","timepointIndex","afterDiscard","requestAnimationFrame","sortTimepoints","sort","b","reset","originalVisibleAt","_findTimepoint","indexOf","validate","oldInteractionId","isNewInteractionId","Math","round","random","Number","MAX_SAFE_INTEGER","errorText","submissionResult","showFeedbackFunction","increment","adjustForCollisions","updateTimepoint","currentInteraction","useStateManager","stateManager","navLock","useNavLock","lock","unlock","useLockPlayer","viewState","ContinueSession","getChild","dispose","continueSession","dialogClassName","GradePassbackPlugin","initialize","onReceiveMessage","parent","postMessage","parse","score","fullyGraded","message","InteractivePlugin","onTrackLoaded","continue","sameSession","addChildren","parseFloat","toPrecision","controlBar","InteractivePlayer","totalProgress","authToken","plugin","preventScrubbingPlugin","togglePreview","isPreviewing","setMaxHeight","embed","preferFullWindow","events","playbackObject","additionalSetup","setupClipPlugin","setupPreventScrubbingPlugin","setupViewInteractivePlugin","collectResults","additionalData","autoplay","showSplash","isPreviewOrEditing","isEnabled","preventScrubbing","furthestVisitedTime","clipData","clipPlugin","DevError","filterNewQuestionTypes","validateCollectResultsOptions","mediaId","viewInteractivePlugin","clipId","clip","ignoreChapters","onToggle","setActivityStatus","ClickViewInteractivePlayer","onReady","getProxy","Proxy","get","p","receiver","isDisposed","Reflect"],"sourceRoot":""}