@clickview/lite 0.70.1-dev.0 → 0.70.1-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/bundles.json +1 -1
  2. package/dist/css/{2018-lite-4aa02cdb17.chunk.css → 581-lite-a1cdc302ab.chunk.css} +3 -1
  3. package/dist/css/{2614-lite-0503112afe.chunk.css → 6156-lite-1b21a4e130.chunk.css} +3 -2
  4. package/dist/languages/en.json +1 -1
  5. package/dist/scripts/2154-6da16cef10-lite.chunk.js +2 -0
  6. package/dist/scripts/2154-6da16cef10-lite.chunk.js.map +1 -0
  7. package/dist/scripts/{2952-4f5abfce6d-lite.chunk.js → 2952-c5ec8f135e-lite.chunk.js} +2 -2
  8. package/dist/scripts/2952-c5ec8f135e-lite.chunk.js.map +1 -0
  9. package/dist/scripts/4377-001a8ee263-lite.chunk.js +2 -0
  10. package/dist/scripts/4377-001a8ee263-lite.chunk.js.map +1 -0
  11. package/dist/scripts/549-2d591052e3-lite.chunk.js +2 -0
  12. package/dist/scripts/549-2d591052e3-lite.chunk.js.map +1 -0
  13. package/dist/scripts/5721-2141ed4fb6-lite.chunk.js +2 -0
  14. package/dist/scripts/5721-2141ed4fb6-lite.chunk.js.map +1 -0
  15. package/dist/scripts/5797-f84ce545b9-lite.chunk.js +2 -0
  16. package/dist/scripts/5797-f84ce545b9-lite.chunk.js.map +1 -0
  17. package/dist/scripts/581-6e9a9afba8-lite.chunk.js +2 -0
  18. package/dist/scripts/{2018-693740d206-lite.chunk.js.map → 581-6e9a9afba8-lite.chunk.js.map} +1 -1
  19. package/dist/scripts/5829-5b395badf2-lite.chunk.js +3 -0
  20. package/dist/scripts/5829-5b395badf2-lite.chunk.js.map +1 -0
  21. package/dist/scripts/6046-5652117548-lite.chunk.js +2 -0
  22. package/dist/scripts/6046-5652117548-lite.chunk.js.map +1 -0
  23. package/dist/scripts/6156-d9a351e53f-lite.chunk.js +2 -0
  24. package/dist/scripts/{2614-bc2fef6ae0-lite.chunk.js.map → 6156-d9a351e53f-lite.chunk.js.map} +1 -1
  25. package/dist/scripts/6629-910e316a83-lite.chunk.js +3 -0
  26. package/dist/scripts/6629-910e316a83-lite.chunk.js.map +1 -0
  27. package/dist/scripts/7428-6dd787bc07-lite.chunk.js +2 -0
  28. package/dist/scripts/7428-6dd787bc07-lite.chunk.js.map +1 -0
  29. package/dist/scripts/7757-9b72774917-lite.chunk.js +2 -0
  30. package/dist/scripts/{7757-e4d91d7fac-lite.chunk.js.map → 7757-9b72774917-lite.chunk.js.map} +1 -1
  31. package/dist/scripts/8191-ff27deee6c-lite.chunk.js +2 -0
  32. package/dist/scripts/8191-ff27deee6c-lite.chunk.js.map +1 -0
  33. package/dist/scripts/{bundle-f9b9be2d02.min.js → bundle-4b10174000.min.js} +3 -3
  34. package/dist/scripts/{bundle-f9b9be2d02.min.js.map → bundle-4b10174000.min.js.map} +1 -1
  35. package/package.json +1 -1
  36. package/dist/scripts/1386-3be201d425-lite.chunk.js +0 -2
  37. package/dist/scripts/1386-3be201d425-lite.chunk.js.map +0 -1
  38. package/dist/scripts/2018-693740d206-lite.chunk.js +0 -2
  39. package/dist/scripts/2614-bc2fef6ae0-lite.chunk.js +0 -2
  40. package/dist/scripts/2952-4f5abfce6d-lite.chunk.js.map +0 -1
  41. package/dist/scripts/4377-f6e641f39a-lite.chunk.js +0 -2
  42. package/dist/scripts/4377-f6e641f39a-lite.chunk.js.map +0 -1
  43. package/dist/scripts/52-9d13c36f9b-lite.chunk.js +0 -2
  44. package/dist/scripts/52-9d13c36f9b-lite.chunk.js.map +0 -1
  45. package/dist/scripts/549-f06f2dab2b-lite.chunk.js +0 -2
  46. package/dist/scripts/549-f06f2dab2b-lite.chunk.js.map +0 -1
  47. package/dist/scripts/5721-bfd734f968-lite.chunk.js +0 -2
  48. package/dist/scripts/5721-bfd734f968-lite.chunk.js.map +0 -1
  49. package/dist/scripts/5797-04d8a61b80-lite.chunk.js +0 -2
  50. package/dist/scripts/5797-04d8a61b80-lite.chunk.js.map +0 -1
  51. package/dist/scripts/5829-82562ea6c2-lite.chunk.js +0 -3
  52. package/dist/scripts/5829-82562ea6c2-lite.chunk.js.map +0 -1
  53. package/dist/scripts/6046-339bc1b2e1-lite.chunk.js +0 -2
  54. package/dist/scripts/6046-339bc1b2e1-lite.chunk.js.map +0 -1
  55. package/dist/scripts/6629-55dc1fdb80-lite.chunk.js +0 -3
  56. package/dist/scripts/6629-55dc1fdb80-lite.chunk.js.map +0 -1
  57. package/dist/scripts/7757-e4d91d7fac-lite.chunk.js +0 -2
  58. package/dist/scripts/8191-d5f68d2463-lite.chunk.js +0 -2
  59. package/dist/scripts/8191-d5f68d2463-lite.chunk.js.map +0 -1
  60. /package/dist/css/{52-lite-e2d7497beb.chunk.css → 7428-lite-e2d7497beb.chunk.css} +0 -0
  61. /package/dist/scripts/{5829-82562ea6c2-lite.chunk.js.LICENSE.txt → 5829-5b395badf2-lite.chunk.js.LICENSE.txt} +0 -0
  62. /package/dist/scripts/{6629-55dc1fdb80-lite.chunk.js.LICENSE.txt → 6629-910e316a83-lite.chunk.js.LICENSE.txt} +0 -0
  63. /package/dist/scripts/{bundle-f9b9be2d02.min.js.LICENSE.txt → bundle-4b10174000.min.js.LICENSE.txt} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripts/7428-6dd787bc07-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/common/src/react/hooks/UsePolling.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseAnonSessions.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseEngagementUsers.ts","file:///app/packages/libs/shared/src/apps/share/components/shared-object-image/shared-object-image.scss","file:///app/packages/libs/shared/src/apps/share/components/shared-object-image/SharedObjectImage.tsx","file:///app/packages/libs/shared/src/components/thumbnails/collection/title/collection-thumbnail-title.scss","file:///app/packages/libs/shared/src/components/thumbnails/collection/title/CollectionThumbnailTitle.tsx","file:///app/packages/libs/shared/src/components/thumbnails/collection/collection-thumbnail.scss","file:///app/packages/libs/shared/src/components/thumbnails/collection/CollectionThumbnail.tsx","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/flight-requests/VideoViewRequests.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/projects/lite/src/apps/insights/components/share-options/ShareOptions.tsx","file:///app/packages/projects/lite/src/apps/insights/views/share-options/ShareOptionsView.tsx","file:///app/packages/projects/lite/src/apps/share-v2/components/ShareAvatar.tsx","file:///app/packages/projects/lite/src/apps/share-v2/enums/SharePrivacy.ts","file:///app/packages/projects/lite/src/apps/share-v2/enums/ShareType.ts","file:///app/packages/projects/lite/src/apps/share-v2/flight-requests/ShareRequests.ts","file:///app/packages/projects/lite/src/apps/share-v2/utils/ShareLinkHelper.ts","file:///app/node_modules/copy-to-clipboard/index.js","file:///app/node_modules/react-copy-to-clipboard/lib/Component.js","file:///app/node_modules/react-copy-to-clipboard/lib/index.js","file:///app/node_modules/toggle-selection/index.js"],"sourcesContent":["import * as React from 'react';\n\nimport { FunctionHelper } from 'libs/common/backbone/utils/FunctionHelper';\n\nconst DEFAULT_POLLING_INTERVAL = 5000; // 5 seconds.\n\n/**\n * Hook to fire a callback at a set interval.\n * @param callback \n * @param pollingInterval \n * \n * Returns a function to clear the timeout.\n */\nexport function usePolling(callback: () => void, pollingInterval: number = DEFAULT_POLLING_INTERVAL): () => void {\n const [ pollingTrigger, setPollingTrigger ] = React.useState(false);\n\n const timeoutRef = React.useRef<number>(null);\n\n const poll = () => {\n setPollingTrigger(t => !t);\n\n timeoutRef.current = window.setTimeout(poll, pollingInterval);\n };\n\n React.useEffect(() => {\n timeoutRef.current = window.setTimeout(poll, pollingInterval);\n }, []);\n\n React.useEffect(() => {\n if (FunctionHelper.isFunction(callback))\n callback();\n }, [pollingTrigger]);\n\n return () => window.clearTimeout(timeoutRef.current);\n}","import { usePolling } from 'libs/common/react/hooks/UsePolling';\nimport { Flight } from 'libs/common/react/index';\n\nimport { ShareRequests } from 'libs/shared/apps/share/flight-requests/ShareRequests';\n\nexport interface AnonSession {\n sessionId: string;\n sessionName: string;\n}\n\nexport interface AnonSessions extends Record<string, AnonSession> {}\n\nexport function useAnonSessions(shareId: string): AnonSessions {\n const fetch = Flight.useGetFetch();\n const anonSessionsRequest = shareId && ShareRequests.getAnonSessions(shareId);\n const anonSessionsResponse = Flight.useBasicFetch<AnonSession[]>(anonSessionsRequest);\n\n usePolling(() => fetch(anonSessionsRequest), 5000);\n\n if (!anonSessionsResponse.data?.length)\n return {};\n\n return anonSessionsResponse.data.reduce((prev, current) => ({ ...prev, [current.sessionId]: current }), {});\n}","import { Flight } from 'libs/common/react/index';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { User } from 'libs/shared/interfaces';\n\nexport function useChunkedUsersResponse(usersIds: string[]) {\n const userIdChunks = ArrayHelper.chunk<string>(usersIds ?? [], 25);\n const usersResponse = Flight.useBasicFetchAll<User[]>(userIdChunks.map(chunk => UserRequests.getById(chunk)));\n const users = ArrayHelper.flatten<User>(usersResponse.data);\n return { users, isLoading: !usersResponse.hasCompleted, usersResponse };\n}","// extracted by mini-css-extract-plugin\nexport default {\"thumbnailFallbackSvg\":\"D4JFs\",\"posterFallbackSvg\":\"bjUWl\",\"coverFallbackSvg\":\"kdLpt\",\"thumbnailContainer\":\"d3CKN\",\"insightsMask\":\"KM76U\",\"requireMarking\":\"peLH7\",\"badge\":\"mVu0E\",\"bar\":\"zO3MS\",\"a\":\"K1jW5\",\"expandBar\":\"YITJl\",\"b\":\"tCpLF\",\"c\":\"lC0cq\"};","import React from 'react';\n\nimport { Core } from 'libs/common/core';\n\nimport { LocationContext, UserAction } from 'libs/analytics/interfaces';\n\nimport { ShareViewHelper } from 'libs/shared/apps/share/views/share/ShareViewHelper';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { BaseImage } from 'libs/shared/components/image/BaseImage';\nimport { ImageFallback, ImageFallbackType } from 'libs/shared/components/image/ImageFallback';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { CollectionThumbnail } from 'libs/shared/components/thumbnails/collection/CollectionThumbnail';\nimport { VideoThumbnail } from 'libs/shared/components/thumbnails/video/VideoThumbnail';\nimport { BG_COLOUR_CLASS_NAMES } from 'libs/shared/constants/ColourClassNames';\nimport { ImageSize, ImageType } from 'libs/shared/enums/Images';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { ThumbnailTextPosition } from 'libs/shared/enums/ThumbnailTextPosition';\nimport { BaseObject, Image, Playlist, Series } from 'libs/shared/interfaces';\nimport { getBgColorClass } from 'libs/shared/utils/getBgColorClass';\nimport { ImageHelper, ImageOptions } from 'libs/shared/utils/ImageHelper';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nimport styles from './shared-object-image.scss';\n\nconst namespace = 'shared.sharedObjectImage';\n\nconst BASE_IMAGE_CLASS_NAME = 'rounded overflow-hidden';\n\ninterface ImageProps {\n image: Image;\n imageType: ImageType;\n imageClassName?: string;\n imageFallbackComponent: JSX.Element;\n}\n\nfunction getImageProps(object: BaseObject): ImageProps {\n const image = ImageHelper.getDisplayImageFromObject(object);\n\n if (VideoHelper.isVideoType(object))\n return {\n image,\n imageType: ImageType.Thumbnails,\n imageClassName: BASE_IMAGE_CLASS_NAME,\n imageFallbackComponent: <ImageFallback type={ImageFallbackType.Video} />\n };\n\n switch (object.typeId) {\n case MasterType.Series:\n return {\n image,\n imageType: ImageType.TallPosters,\n imageClassName: BASE_IMAGE_CLASS_NAME,\n imageFallbackComponent:\n <ImageFallback type={ImageFallbackType.Series} svgContainerClassName={styles.posterFallbackSvg} />\n };\n\n case MasterType.Playlist:\n return {\n image,\n imageType: ImageType.Covers,\n imageClassName: !image?.url\n ? `${BASE_IMAGE_CLASS_NAME} ${getBgColorClass(object.name, BG_COLOUR_CLASS_NAMES)}`\n : BASE_IMAGE_CLASS_NAME,\n imageFallbackComponent: (\n <ImageFallback\n type={ImageFallbackType.Playlist}\n svgContainerClassName={image?.url ? styles.coverFallbackSvg : 'd-none'}\n extraClasses={!image?.url && 'bg-transparent'}\n />\n )\n };\n }\n}\n\nfunction InsightsMask() {\n return (\n <div className={`d-flex pointer-events-none position-absolute bottom-0 start-0 h-100 w-100 z-1 justify-content-center align-items-center`}>\n <div className='position-absolute bg-dark bg-gradient opacity-50 w-100 h-100 z-0 rounded-3'></div>\n <div className='d-flex align-items-end gap-2 h-50 z-1'>\n <div className='d-flex align-items-end h-50'>\n <div className={`${styles.bar} ${styles.a} rounded shadow`}></div>\n </div>\n <div className='d-flex align-items-end h-75'>\n <div className={`${styles.bar} ${styles.b} rounded shadow`}></div>\n </div>\n <div className='d-flex align-items-end h-100'>\n <div className={`${styles.bar} ${styles.c} rounded shadow`}></div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction getImageRatio(object: BaseObject): ImageFallbackType {\n if (VideoHelper.isVideoType(object))\n return 16 / 9;\n\n if (object.typeId === MasterType.Playlist)\n return 1;\n\n if (object.typeId === MasterType.Series)\n return 9 / 16;\n}\n\nSharedObjectImage.defaultProps = {\n imageOptions: { size: ImageSize.Small }\n};\n\ninterface SharedObjectImageProps {\n object: BaseObject;\n locationContext: LocationContext;\n appLink?: Core.AppLink;\n showVideoMetadata?: boolean;\n fixedHeight?: boolean;\n requireMarking?: number;\n imageOptions?: ImageOptions;\n showInsightsMask?: boolean;\n showCollectionMask?: boolean;\n showVideoCount?: boolean;\n thumbnailSize?: 'sm' | 'md';\n}\n\nexport function SharedObjectImage(props: SharedObjectImageProps): JSX.Element {\n const ref = React.useCallback((el: HTMLDivElement) => {\n if (!el || !props.fixedHeight)\n return;\n\n el.style.width = `${el.offsetHeight * getImageRatio(props.object)}px`;\n }, []);\n\n const useVideoThumbnail = VideoHelper.isVideoType(props.object);\n\n const {\n image,\n imageType,\n imageClassName,\n imageFallbackComponent\n } = getImageProps(props.object);\n\n const metadataFlags = !props.showVideoMetadata ? {\n hideDuration: true,\n hideMask: true,\n hideRating: true,\n hideVideoTypeBadge: true\n } : {};\n\n return (\n <div className='d-flex align-items-center justify-content-center w-100 h-100'>\n <div ref={ref} className={props.fixedHeight ? 'h-100' : 'w-100'}>\n {useVideoThumbnail &&\n <div className={`${styles.thumbnailContainer} position-relative`}>\n {props.showInsightsMask && <InsightsMask />}\n <AppLink appLink={props.appLink}>\n <VideoThumbnail\n video={props.object}\n size={props.thumbnailSize}\n imageOptions={props.imageOptions}\n textPosition={ThumbnailTextPosition.Independent}\n type='cosmetic'\n {...metadataFlags}\n />\n </AppLink>\n {!!props.requireMarking && (\n <div className={`${props.showInsightsMask && styles.requireMarking} position-absolute bottom-0 end-0 z-1 m-2`}>\n <div className={`${styles.badge} d-flex align-items-center bg-light-ultramarine text-ultramarine fw-semibold rounded-pill w-fit mt-1 px-2`}>\n <Text namespace={namespace} phrase='requireMarking' options={{ smartCount: props.requireMarking }} />\n </div>\n </div>\n )}\n </div>\n }\n {!useVideoThumbnail &&\n <>\n {'videos' in (props.object as Playlist | Series) ? (\n <CollectionThumbnail\n collection={props.object}\n imageOptions={props.imageOptions}\n appLink={props.appLink}\n analyticsData={{\n id: props.object.id,\n name: props.object.name\n }}\n analyticsOptions={{\n entity: ShareViewHelper.getAnalyticsEntity(props.object.type),\n actionType: UserAction.Click,\n location: props.locationContext\n }}\n showMask={props.showCollectionMask}\n showVideoCount={props.showVideoCount}\n />\n ) : (\n <BaseImage\n data={image?.url}\n imageType={imageType}\n imageOptions={props.imageOptions}\n appLink={props.appLink}\n className={imageClassName}\n analyticsData={{\n id: props.object.id,\n name: props.object.name\n }}\n analyticsOptions={{\n entity: ShareViewHelper.getAnalyticsEntity(props.object.type),\n actionType: UserAction.Click,\n location: props.locationContext\n }}\n >\n {imageFallbackComponent}\n </BaseImage>\n )}\n </>\n }\n </div>\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"thumbnailTitle\":\"OsWjL\"};","import React from 'react';\n\nimport { Core } from 'libs/common/core';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\n\nimport styles from './collection-thumbnail-title.scss';\n\ninterface BaseCollectionThumbnailTitleProps {\n title: string;\n}\n\nfunction BaseCollectionThumbnailTitle(props: BaseCollectionThumbnailTitleProps): JSX.Element {\n return (\n <h3 title={props.title} className='h6'>{props.title}</h3>\n );\n}\n\ninterface CollectionThumbnailTitleProps extends BaseCollectionThumbnailTitleProps {\n appLink: Core.AppLink;\n}\n\nexport function CollectionThumbnailTitle(props: CollectionThumbnailTitleProps) {\n if (!props.appLink) {\n return (\n <BaseCollectionThumbnailTitle {...props} />\n );\n }\n \n return (\n <AppLink appLink={props.appLink} className={`${styles.thumbnailTitle}`}>\n <BaseCollectionThumbnailTitle {...props} />\n </AppLink>\n );\n}\n","// extracted by mini-css-extract-plugin\nexport default {\"badge\":\"M4zat\",\"mask\":\"r0Ztg\",\"thumbnailContainer\":\"uD9dz\"};","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { AnalyticsOptions, EntityType, UserAction } from 'libs/analytics/interfaces';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { CollectionThumbnailTitle } from 'libs/shared/components/thumbnails/collection/title/CollectionThumbnailTitle';\nimport { VideoThumbnail } from 'libs/shared/components/thumbnails/video/VideoThumbnail';\nimport { TitleSubText } from 'libs/shared/components/title-sub-text/TitleSubText';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { ThumbnailTextPosition } from 'libs/shared/enums/ThumbnailTextPosition';\nimport { Playlist, Series } from 'libs/shared/interfaces';\nimport { ImageOptions } from 'libs/shared/utils/ImageHelper';\nimport { MasterTypeHelper } from 'libs/shared/utils/MasterTypeHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './collection-thumbnail.scss';\n\nconst namespace = 'shared.collectionThumbnail';\n\ntype SupportedContentType = Playlist | Series;\n\ninterface CollectionThumbnailProps {\n appLink?: Core.AppLink\n collection: SupportedContentType;\n imageOptions?: ImageOptions;\n analyticsData?: HashObject;\n analyticsOptions?: AnalyticsOptions;\n showMask?: boolean;\n showVideoCount?: boolean;\n title?: string;\n titleAppLink?: Core.AppLink;\n subText?: string;\n subTextAppLink?: Core.AppLink;\n hoverText?: string;\n}\n\nexport function CollectionThumbnail(props: CollectionThumbnailProps) {\n function getFirstVideo() {\n let collectionVideos = props.collection?.videos;\n\n if (!collectionVideos)\n return;\n\n if (!collectionVideos.count && props.collection.typeId === MasterType.Playlist) {\n const playlist = props.collection as Playlist;\n\n if (playlist.clips.count)\n collectionVideos = playlist.clips;\n\n if (playlist.interactives.count)\n collectionVideos = playlist.interactives;\n }\n\n return ArrayHelper.first(collectionVideos.data);\n }\n\n function getVideoCount() {\n let totalCount = 0;\n\n if (props.collection.videos && props.collection.videos.count) {\n totalCount += props.collection.videos.count;\n }\n\n if (props.collection.typeId === MasterType.Playlist) {\n const playlist = props.collection as Playlist;\n\n if (playlist.interactives?.count)\n totalCount += playlist.interactives.count;\n\n if (playlist.clips?.count)\n totalCount += playlist.clips.count;\n }\n\n return totalCount;\n }\n\n function getEntityType(collection: SupportedContentType) {\n if (MasterTypeHelper.isType<Playlist>(collection, MasterType.Playlist)) {\n return EntityType.Playlist;\n }\n\n if (MasterTypeHelper.isType<Series>(collection, MasterType.Series)) {\n return EntityType.Series;\n }\n }\n\n const firstVideo = getFirstVideo();\n const videoCount = getVideoCount();\n const showTexts = props.title?.length || props.subText?.length;\n\n const analyticsData = {\n id: props.collection.id.toString(),\n name: props.collection.name,\n\n ...props.analyticsData\n };\n\n const analyticsOptions = {\n actionType: UserAction.Click,\n entity: getEntityType(props.collection),\n \n ...props.analyticsOptions\n };\n\n return (\n <div>\n <div className={`position-relative ${styles.thumbnailContainer} z-1`}>\n <AppLink\n appLink={props.appLink}\n analyticsData={analyticsData}\n analyticsOptions={analyticsOptions}\n preventFocus\n >\n {props.showMask &&\n <div className={`${styles.mask} position-absolute w-100 h-100 rounded-3 bg-dark bg-gradient z-1 bg-opacity-50 pointer-events-none`}>\n <div className={`${styles.badge} d-flex align-items-center w-fit flex-grow-0 bg-dark rounded-pill ps-1 m-2`}>\n <SvgContainer svgName={cvSvgLibrary.Play} className='svg-container text-white' />\n <p className='d-inline fw-medium text-white mb-0'>\n {props.hoverText?.length ?\n <span>{props.hoverText}</span> :\n <Text namespace={namespace} phrase='playAll' />\n }\n </p>\n </div>\n </div>\n }\n\n {firstVideo &&\n <VideoThumbnail\n video={firstVideo}\n imageOptions={props.imageOptions}\n textPosition={ThumbnailTextPosition.Independent}\n type='cosmetic'\n hideMask\n hideRating\n hideDuration\n hideVideoTypeBadge\n />\n }\n\n {!firstVideo &&\n <div className='ratio ratio-16x9 bg-light rounded-3'>\n <div className='d-flex justify-content-center align-items-center'>\n <SvgContainer svgName={cvSvgLibrary.Play} className='w-33 opacity-25 text-gray-400' />\n </div>\n </div>\n }\n\n {props.showVideoCount &&\n <div className={`${styles.badge} d-flex align-items-center w-fit bg-dark bg-opacity-75 rounded-pill position-absolute bottom-0 end-0 ps-1 m-2`}>\n <SvgContainer svgName={cvSvgLibrary.Series} className='svg-container text-white me-1' />\n <p className='d-inline fw-semibold text-white mb-0'>\n <Text namespace={namespace} phrase='videos' options={{ count: videoCount, smartCount: videoCount }} />\n </p>\n </div>\n }\n </AppLink>\n\n </div>\n \n {showTexts &&\n <div className='mt-2 d-flex flex-column'>\n {props.subText &&\n <TitleSubText title={props.subText} appLink={props.subTextAppLink}>\n {props.subText}\n </TitleSubText>\n }\n {props.title &&\n <CollectionThumbnailTitle\n title={props.collection.name}\n appLink={props.titleAppLink}\n />\n }\n </div>\n }\n </div>\n );\n}","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { AnalyticsRequestFilter, Engagement } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\nexport const VideoViewRequests = {\n individualEngagement(\n objectId: string,\n filter: AnalyticsRequestFilter,\n sharerId?: string,\n includeAnonViews?: boolean\n ): Flight.Request {\n const queryParams: HashObject = {\n objectId,\n ...filter\n };\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n\n if (includeAnonViews)\n queryParams.includeAnonViews = true;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/heat-map', queryParams),\n key: getAnalyticsRequestKey(`engagement:${objectId}:${includeAnonViews}`, filter, sharerId),\n formatData: (data: any) => {\n return {\n ...data,\n data: data.data?.map((d: any) => ({\n ...d,\n heatMap: d.heatMap ?? []\n }))\n };\n },\n normalize: false\n };\n },\n \n aggregateEngagement(\n objectId: string,\n filter: AnalyticsRequestFilter,\n sharerId?: string,\n includeAnonViews?: boolean\n ): Flight.Request {\n const queryParams: HashObject = {\n objectId,\n ...filter\n };\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n \n if (includeAnonViews)\n queryParams.includeAnonViews = true;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/heat-map/aggregations', queryParams),\n key: getAnalyticsRequestKey(`aggregate:engagement:${objectId}:${includeAnonViews}`, filter, sharerId),\n formatData: (data: Engagement) => {\n return {\n ...data,\n heatMap: data.heatMap ?? []\n };\n },\n normalize: false\n };\n },\n \n views(\n filter: AnalyticsRequestFilter,\n objectId?: string,\n sharerId?: string,\n includeAnonViews?: boolean\n ): Flight.Request {\n const queryParams: HashObject = {\n ...filter,\n timeOffset: DateHelper.getTimezoneOffset()\n };\n\n if (objectId)\n queryParams.objectId = objectId;\n\n if (sharerId)\n queryParams.sharerId = sharerId;\n \n if (includeAnonViews)\n queryParams.includeAnonViews = true;\n\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/video-views', queryParams),\n key: getAnalyticsRequestKey(`video:views:${objectId}:${includeAnonViews}`, filter, sharerId),\n normalize: false\n };\n }\n};","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import React from 'react';\nimport { CopyToClipboard } from 'react-copy-to-clipboard';\n\nimport { AppLinkHelper } from 'libs/common/backbone/core';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { SharedObjectImage } from 'libs/shared/apps/share/components/shared-object-image/SharedObjectImage';\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { ImageSize } from 'libs/shared/enums/Images';\nimport { BaseObject, Classroom } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\nimport { VideoAppLinkHelper } from 'shared/utils/VideoAppLinkHelper';\n\nimport { ShareAvatar } from 'apps/share-v2/components/ShareAvatar';\nimport { Pincode } from 'apps/share-v2/interfaces/Pincode';\nimport { ShareLink } from 'apps/share-v2/interfaces/ShareLink';\n\ninterface ShareOptionsProps {\n sharedObject?: BaseObject;\n shareLink?: ShareLink;\n pinCode?: Pincode;\n classroom?: Classroom;\n}\n\nexport function ShareOptions(props: ShareOptionsProps) {\n function onExpandCode() {\n console.log('Expanding code..');\n }\n\n const qrCodeValue = props.shareLink?.link?.shortenedUrl ?? '';\n const videoAppLink = VideoAppLinkHelper.getAppLink(props.sharedObject);\n const url = AppLinkHelper.getHref(videoAppLink);\n \n return (\n <div>\n <h3>Share information</h3>\n <div className='mb-4 bg-light-blue p-3 rounded-3'>\n <div className='d-flex gap-3'>\n { props.sharedObject && (\n <div style={{ minWidth: 220 }} className='d-flex flex-column'>\n <SharedObjectImage\n object={props.sharedObject}\n showVideoMetadata\n locationContext={LocationContext.Insights}\n imageOptions={{ size: ImageSize.Medium }}\n showCollectionMask\n showVideoCount\n appLink={videoAppLink}\n />\n </div>\n )}\n <div className='d-flex flex-column justify-content-between'>\n <div className='d-flex align-items-center'>\n <a href={url} className='cursor-pointer h6 mb-0 d-inline me-2'>{props.sharedObject?.name}</a>\n <IconButton\n svgName={cvSvgLibrary.NewWindow}\n appLink={videoAppLink}\n svgSize={SvgContainerSize.Small}\n className='d-inline-block'\n customSize\n />\n </div>\n {props.shareLink && <ShareAvatar shareLink={props.shareLink} classroomName={props.classroom?.name} />}\n <div className='d-flex gap-2'>\n <IconButton\n svgName={cvSvgLibrary.Share}\n className='btn btn-outline-dark'\n appLink={{\n application: AppChannels.SHARE_V2,\n action: Actions.ShareV2.LINK,\n args: [props.sharedObject?.id],\n params: {\n entityType: props.sharedObject?.type,\n shareId: props.shareLink?.shareId\n }\n }}\n >\n Share a link or embed\n </IconButton>\n <IconButton\n svgName={cvSvgLibrary.Download}\n className='btn btn-outline-dark'\n appLink={{\n application: AppChannels.INSIGHTS,\n action: Actions.Insights.QR_CODE,\n params: {\n value: qrCodeValue\n }\n }}\n >\n QR code\n </IconButton>\n </div>\n </div>\n\n <div className='flex-grow-1' />\n\n {props.pinCode && (\n <div className='border p-3 rounded-3 d-flex flex-column align-items-center bg-white'>\n <p>Go to <a href='https://staging.clickview.net/pin' target='_blank' className='text-info'>staging.clickview.net/pin</a> and enter PIN:</p>\n <div className='d-flex align-items-center'>\n <h4 className='mb-0 pb-0 me-1'>{props.pinCode?.code}</h4>\n <CopyToClipboard text={props.pinCode?.code}>\n <IconButton\n svgName={cvSvgLibrary.Copy}\n className='btn'\n />\n </CopyToClipboard>\n <IconButton\n svgName={cvSvgLibrary.NewWindow}\n onClick={onExpandCode}\n className='btn'\n />\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}","import React from 'react';\n\nimport { usePolling } from 'libs/common/react/hooks/UsePolling';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\nimport { Flight } from 'libs/common/react/index';\n\nimport { EngagementTable } from 'libs/shared/apps/analytics/components/engagement-table/EngagementTable';\nimport { useAnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { useChunkedUsersResponse } from 'libs/shared/apps/analytics/hooks/UseEngagementUsers';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { getAudienceParams } from 'libs/shared/apps/analytics/utils/AudienceUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { getFilterParamsKey } from 'libs/shared/apps/analytics/utils/FilterParamUtils';\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { PlaylistRequests } from 'libs/shared/flight-requests/PlaylistRequests';\nimport { SeriesRequests } from 'libs/shared/flight-requests/SeriesRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoViewRequests } from 'libs/shared/flight-requests/VideoViewRequests';\nimport { useFetchAll } from 'libs/shared/hooks/UseFetchAll';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { AnalyticsRequestFilter, Classroom, Config, CurrentUser, Engagement, IndividualEngagementResponse, Playlist, Series, User, VideoTypes } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nimport { ViewModelKeys } from 'shared/constants/LiteViewModels';\n\nimport { ClassroomRequests } from 'apps/classrooms/flight-requests/ClassroomRequests';\nimport { ShareOptions } from 'apps/insights/components/share-options/ShareOptions';\nimport { InsightsHeader } from 'apps/my-shares/components/insights-header/InsightsHeader';\nimport { getInsightsClipTabs, getInsightsInteractiveTabs, getInsightsPlaylistTabs, getInsightsSeriesTabs, getInsightsVideoTabs } from 'apps/my-shares/utils/InsightsAppLinkUtils';\nimport { ShareType } from 'apps/share-v2/enums/ShareType';\nimport { ShareRequests } from 'apps/share-v2/flight-requests/ShareRequests';\nimport { Pincode } from 'apps/share-v2/interfaces/Pincode';\nimport { ShareLink } from 'apps/share-v2/interfaces/ShareLink';\nimport { ShareLinkHelper } from 'apps/share-v2/utils/ShareLinkHelper';\n\ninterface ShareOptionsViewProps {\n objectId: string;\n typeId: MasterType;\n shareId?: string;\n}\n\nexport function ShareOptionsView(props: ShareOptionsViewProps) {\n const [anonymiseUsers] = useViewModel<boolean>(ViewModelKeys.ANONYMISE_USERS);\n\n const fetch = Flight.useGetFetch();\n\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n const shareLink = Flight.useBasicFetch<ShareLink>(props.shareId && ShareRequests.getShareLink(props.shareId));\n const pinCode = Flight.useBasicFetch<Pincode>(props.shareId && ShareRequests.getPincodeByShareId(props.shareId));\n const classRoomId = ShareLinkHelper.getClassroomId(shareLink.data);\n const classroom = Flight.useBasicFetch<Classroom>(classRoomId && ClassroomRequests.getClassroom(classRoomId));\n\n const { hasShareFlowV2, publicInteractiveAttempts } = useSettings(null);\n const { hasPermissions } = usePermissions();\n\n const isVideo = () => [ MasterType.Video, MasterType.Clip, MasterType.Interactive ].includes(props.typeId);\n const isSeries = () => props.typeId === MasterType.Series;\n const isPlaylist = () => props.typeId === MasterType.Playlist;\n\n const videoRequest = isVideo() && VideoHelper.getVideoRequest(props.objectId, props.typeId);\n const video = Flight.useBasicFetch<VideoTypes>(videoRequest);\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const seriesRequest = isSeries() && SeriesRequests.series(props.objectId);\n const series = Flight.useBasicFetch<Series>(seriesRequest);\n\n const playlistRequest = isPlaylist() && PlaylistRequests.getPlaylist(props.objectId);\n const playlist = Flight.useBasicFetch<Playlist>(playlistRequest);\n\n const audienceAppLinkParams = AnalyticsFilterHelper.getAudienceAppLinkParams();\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n const params = {\n ...audienceAppLinkParams,\n ...dateRangeAppLinkParams,\n shareId: props.shareId\n };\n\n const requestFilter: AnalyticsRequestFilter = {\n ...getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams),\n ...getAudienceParams(audienceAppLinkParams)\n };\n\n const engagementRequest = currentUser.data &&\n VideoViewRequests.individualEngagement(\n props.objectId,\n requestFilter,\n currentUser.data?.id,\n publicInteractiveAttempts\n );\n const individualEngagement = Flight.useBasicFetch<IndividualEngagementResponse>(engagementRequest);\n usePolling(() => fetch(engagementRequest), 5000);\n\n const userIds = individualEngagement.data?.data?.map(d => d.userId).filter(Boolean) || [];\n \n const { users, isLoading } = useChunkedUsersResponse(userIds);\n const anonSessions = useAnonSessions(props.shareId);\n\n const fakeEngagement = useGetFakeEngagement(currentUser.data, shareLink.data, individualEngagement.data);\n\n useLockContentWidth();\n useSetPageMetadata({ title: video.data?.name ?? series.data?.name ?? playlist.data?.name });\n useHandleObjectError([ video, series, playlist ]);\n\n const tableDataLoaded = !!individualEngagement.data && (!userIds.length || !isLoading);\n const tableRowsWillBeEmpty = !fakeEngagement.length;\n const showTableEmptyState = !tableDataLoaded || tableRowsWillBeEmpty;\n\n console.log({\n individualEngagementLength: individualEngagement.data?.data.length,\n userIdsLength: userIds.length,\n anonSessionsLength: Object.keys(anonSessions).length,\n fakeEngagementLength: fakeEngagement.length\n });\n\n function getInsightsTabs() {\n if (props.typeId === MasterType.Interactive)\n return getInsightsInteractiveTabs(props.objectId, 'shareOptions', params, hasShareFlowV2);\n\n if (props.typeId === MasterType.Clip)\n return getInsightsClipTabs(props.objectId, 'shareOptions', params, hasShareFlowV2);\n\n if (props.typeId === MasterType.Video)\n return getInsightsVideoTabs(props.objectId, 'shareOptions', params, hasShareFlowV2);\n\n if (props.typeId === MasterType.Series)\n return getInsightsSeriesTabs(props.objectId, 'shareOptions', params);\n\n if (props.typeId === MasterType.Playlist)\n return getInsightsPlaylistTabs(props.objectId, 'shareOptions', params);\n }\n\n\n return (\n <div className='px-3'>\n <InsightsHeader\n video={video.data ?? series.data ?? playlist.data}\n dateRangeAppLinkParams={dateRangeAppLinkParams}\n tabs={getInsightsTabs()}\n hasAnalytics={hasPermissions(PermissionName.ViewCustomerAnalytics)}\n analyticsWebUrl={config.data?.analyticsWebUrl}\n hasShareFlowV2={hasShareFlowV2}\n shareId={props.shareId}\n />\n <ShareOptions\n sharedObject={video.data ?? series.data ?? playlist.data}\n shareLink={shareLink.data}\n pinCode={pinCode.data}\n classroom={classroom.data}\n />\n <div className='d-flex align-items-center mt-5'>\n <h3 className='p-0 m-0'>{shareLink.data?.type === ShareType.Classroom ? 'All recipients' : 'Students who have viewed this video'}</h3>\n {shareLink.data?.type === ShareType.Classroom && (\n <IconButton\n svgName={cvSvgLibrary.Plus}\n onClick={() => console.log('Add new student..')}\n className='btn btn-outline-dark ms-auto'\n >\n Add new student\n </IconButton>\n )}\n </div>\n <div className='col-12 mt-2 mb-5'>\n <EngagementTable\n key={getFilterParamsKey({ ...audienceAppLinkParams, ...dateRangeAppLinkParams })}\n engagement={fakeEngagement}\n users={users ?? []}\n imageCdnUrl={config.data?.imageCdnUrl}\n anonymiseUsers={anonymiseUsers}\n border\n anonSessions={anonSessions}\n hideWhenEmpty={false}\n theme={{\n header: showTableEmptyState ? 'border-0' : 'border-bottom',\n table: showTableEmptyState ? 'bg-white rounded px-0 rounded-bottom-0' : 'bg-white rounded px-0'\n }}\n />\n {showTableEmptyState && (\n <div style={{ minHeight: 400 }} className='border border-top-0 rounded-1 rounded-top-0 pt-5 pb-5 text-center'>\n <h4>Waiting for students to view...</h4>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction useGetFakeEngagement(\n currentUser: CurrentUser,\n shareLink: ShareLink,\n individualEngagement: IndividualEngagementResponse\n) {\n const fetch = Flight.useGetFetch();\n\n const classroomId = shareLink?.recipients?.[0]?.recipientTypeId === MasterType.Classroom &&\n shareLink.recipients[0].recipientId;\n\n const getClassroomRequest = (cursor: string) => classroomId\n && ClassroomRequests.getClassroomStudents(classroomId, cursor);\n const clasroomStudents = useFetchAll<User>(\n getClassroomRequest,\n cursor => fetch(getClassroomRequest(cursor))\n );\n\n const engagementMap = individualEngagement?.data?.reduce<Record<string, Engagement>>((prev, next) =>\n ({ ...prev, [next.userId]: next }), {}) ?? {};\n \n const fakeEngagement = clasroomStudents.items?.length ?\n clasroomStudents.items.map<Engagement>(user => {\n const engagement = engagementMap[user.id];\n\n if (engagement)\n return null;\n\n return {\n customerId: currentUser?.customerId,\n engagementRate: 0,\n heatMap: [],\n userId: user.id,\n videoDuration: 500,\n viewCount: 0,\n videoId: null,\n userIds: [],\n sessionId: null,\n sessionIds: [],\n user\n };\n }).filter(e => !!e)\n : [];\n\n return [ ...individualEngagement?.data ?? [], ...fakeEngagement ];\n}","import React from 'react';\n\nimport { IconCircle } from 'libs/shared/components/icon-circle/IconCircle';\nimport { SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { SharePrivacy } from '../enums/SharePrivacy';\nimport { ShareType } from '../enums/ShareType';\nimport { ShareLink } from '../interfaces/ShareLink';\n\ninterface ShareAvatarProps {\n shareLink: Partial<ShareLink>;\n classroomName?: string;\n hideSubtitle?: boolean;\n svgSize?: SvgContainerSize;\n svgWrapperClassName?: string;\n}\n\nexport function ShareAvatar(props: ShareAvatarProps): JSX.Element {\n return (\n <div className='d-flex align-items-center'>\n <div className='d-flex align-items-center justify-content-center'>\n <div>\n <IconCircle\n svgName={icons[props.shareLink.type]}\n variant={iconColours[props.shareLink.type]}\n textVariant='white'\n svgWrapperClassName={props.svgWrapperClassName ?? 'p-1'}\n svgSize={props.svgSize ?? SvgContainerSize.Standard}\n />\n </div>\n <div className='d-flex flex-column ms-2'>\n <label className='m-0'>{getTitle(props)}</label>\n {!props.hideSubtitle && <span className='text-secondary'>{getSubtitle(props)}</span>}\n </div>\n </div>\n </div>\n );\n}\n\nconst icons = {\n [ShareType.Open]: cvSvgLibrary.School,\n [ShareType.Link]: cvSvgLibrary.Link,\n [ShareType.Classroom]: cvSvgLibrary.Classrooms,\n [ShareType.Live]: cvSvgLibrary.Play\n};\n\nconst iconColours = {\n [ShareType.Open]: 'blue',\n [ShareType.Link]: 'black',\n [ShareType.Classroom]: 'teal',\n [ShareType.Live]: 'purple'\n};\n\nconst titles = {\n [ShareType.Open]: 'Open classroom',\n [ShareType.Link]: 'Link',\n [ShareType.Classroom]: 'Classroom',\n [ShareType.Live]: 'Live'\n};\n\nfunction pluralize(count: number, singular: string, plural: string) {\n return count === 1 ? singular : plural;\n}\n\nfunction getTitle({ shareLink, classroomName }: ShareAvatarProps) {\n if (shareLink.type === ShareType.Classroom && classroomName)\n return classroomName;\n\n return titles[shareLink.type];\n}\n\nfunction getSubtitle({ shareLink }: ShareAvatarProps) {\n if (shareLink.type === ShareType.Classroom) {\n const groupCount = shareLink.recipients?.filter(r => r.recipientTypeId === MasterType.ClassroomGroup).length ?? 0;\n const studentCount = shareLink.recipients?.filter(r => r.recipientTypeId === MasterType.User).length ?? 0;\n\n if (groupCount && studentCount)\n return `${groupCount} ${pluralize(groupCount, 'group', 'groups')}, ${studentCount} ${pluralize(studentCount, 'student', 'students')} can view`;\n\n if (groupCount)\n return `${groupCount} ${pluralize(groupCount, 'group', 'groups')} can view`;\n\n if (studentCount)\n return `${studentCount} ${pluralize(studentCount, 'student', 'students')} can view`;\n\n return `All students in classroom can view`;\n }\n\n if (shareLink.type === ShareType.Open)\n return 'Students watch using a PIN code';\n\n if (shareLink.type === ShareType.Link) {\n if ([ SharePrivacy.JustMySchool, SharePrivacy.Protected ].includes(shareLink.privacy))\n return 'Respect ratings and restrictions';\n\n if (shareLink.privacy === SharePrivacy.JustMySchoolOverrideRestriction)\n return 'Anyone in your school can view';\n\n if (shareLink.privacy === SharePrivacy.ProtectedOverrideRestriction)\n return 'Anyone signed into ClickView can view';\n\n if (shareLink.privacy === SharePrivacy.Public)\n return 'Anyone with a link can view';\n\n if (shareLink.privacy === SharePrivacy.PinCode)\n return 'Anyone with a PIN code can view';\n }\n\n if (shareLink.type === ShareType.Live)\n return 'Live now';\n\n return 'Anyone signed into ClickView can view';\n}","export enum SharePrivacy {\n Public = 'Public',\n PinCode = 'PinCode',\n PasswordProtected = 'PasswordProtected',\n ProtectedOverrideRestriction = 'ProtectedOverrideRestriction',\n JustMySchoolOverrideRestriction = 'JustMySchoolOverrideRestriction',\n Protected = 'Protected',\n JustMySchool = 'JustMySchool',\n Direct = 'Direct'\n}","export enum ShareType {\n Link = 'Link',\n Classroom = 'Classroom',\n Open = 'Open',\n Live = 'Live'\n}","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\n\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { BasePaginatedCollection } from 'libs/shared/interfaces';\n\nimport { CreateShareLinkRequest } from 'apps/share-v2/interfaces/CreateShareLinkRequest';\nimport { ShareLink } from 'apps/share-v2/interfaces/ShareLink';\n\nconst normalizeOptions: Flight.NormalizeOptions = {\n namespace: 'share-v2'\n};\n\nexport interface GetSentSharesParams {\n cursor?: string;\n limit?: number;\n objectTypeId?: MasterType | MasterType[];\n recipientUserId?: string | string[];\n recipientGroupId?: string | string[];\n start?: string;\n end?: string;\n scopeId?: string;\n}\n\nexport const ShareRequests = {\n createShareLink(\n data: CreateShareLinkRequest,\n success?: (shareLink: ShareLink) => void,\n error?: () => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: '/api/share/v2/shares',\n key: 'create:share-v2:link',\n type: HttpVerbs.POST,\n data,\n normalizeOptions,\n invalidationKeys: [\n `share:link:object:${data.objectId}`,\n `privacy:${data.objectId}`,\n 'sent:shares',\n 'get:share-v2:shares:object'\n ],\n success,\n error,\n always\n };\n },\n\n getShareLink(\n shareId: string,\n success?: (shareLink: ShareLink) => void,\n error?: () => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/share/v2/shares/${shareId}`,\n key: `get:share-v2:link:${shareId}`,\n type: HttpVerbs.GET,\n normalizeOptions,\n success,\n error,\n always\n };\n },\n\n getSharesByObjectId(\n objectId: string | number,\n success?: (shares: ShareLink[]) => void,\n error?: () => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/share/v2/shares/objects/${objectId}`,\n key: `get:share-v2:shares:object:${objectId}`,\n type: HttpVerbs.GET,\n normalizeOptions,\n success,\n error,\n always\n };\n },\n\n getSentShares(\n params: GetSentSharesParams = {},\n success?: (response: BasePaginatedCollection<ShareLink>[]) => void,\n error?: () => void,\n always?: () => void\n ): Flight.Request {\n const adaptedParams = {\n scopeId: params.scopeId,\n limit: params.limit || 25,\n offset: parseInt(params.cursor) || 0\n };\n\n const key = Object.values(adaptedParams).join(':');\n\n return {\n url: UrlHelper.urlBuilder('/api/share/v2/shares/sent', adaptedParams),\n key: `sent:shares-v2:${key}`,\n formatData: (response: ShareLink[]) => {\n return {\n data: response,\n count: response.length,\n pagination: {\n cursors: {\n next: adaptedParams.offset + response.length\n }\n }\n };\n },\n type: HttpVerbs.GET,\n normalize: false,\n success,\n error,\n always\n };\n },\n\n createPincode(shareId: string): Flight.Request {\n return {\n url: `/api/share/v2/shares/${shareId}/pincode`,\n key: 'create:share-v2:pincode',\n type: HttpVerbs.POST\n };\n },\n\n getPincode(code: string): Flight.Request {\n return {\n url: `/api/share/v2/shares/pincode?code=${code}`,\n key: `get:share-v2:pincode:${code}`\n };\n },\n\n getPincodeByShareId(shareId: string): Flight.Request {\n return {\n url: `/api/share/v2/shares/${shareId}/pincode`,\n key: `get:share-v2:${shareId}:pincode`\n };\n }\n};","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { ShareLinkStatus } from 'libs/shared/enums/ShareLinkStatus';\nimport { BaseObject, YearGroup } from 'libs/shared/interfaces';\nimport { RestrictionHelper } from 'libs/shared/utils/RestrictionHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nimport { SharePrivacy } from '../enums/SharePrivacy';\nimport { ShareType } from '../enums/ShareType';\nimport { ShareLink } from '../interfaces/ShareLink';\n\nconst namespace = 'share.shareLinkInfo';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface GetIconAndTextOptions {\n linkExpireDate: string;\n isPasswordProtected: boolean;\n privacy: SharePrivacy;\n status: ShareLinkStatus;\n entityTypeId: MasterType;\n hasStudentExp: boolean;\n entity: BaseObject;\n yearGroups: YearGroup[];\n}\n\n\nexport const ShareLinkHelper = {\n getPrivateIconAndText: (options: GetIconAndTextOptions) => {\n const { entityTypeId, privacy, hasStudentExp, entity, yearGroups } = options;\n \n if (entityTypeId === MasterType.Topic || entityTypeId === MasterType.Series)\n return { icon: cvSvgLibrary.VisibleOn, text: getPhrase(hasStudentExp ? 'justMySchoolTeachers' : 'justMySchoolDescription') };\n \n /**\n * This is mainly for typescript, privacy will be an array for playlists\n * but that is handled above\n */\n if (Array.isArray(privacy))\n return;\n \n switch (privacy) {\n case SharePrivacy.Public:\n return { icon: cvSvgLibrary.VisibleOn, text: getPhrase('publicDescription') };\n case SharePrivacy.ProtectedOverrideRestriction:\n return { icon: cvSvgLibrary.VisibleOn, text: getPhrase('clickViewOnly') };\n case SharePrivacy.Protected:\n return {\n icon: cvSvgLibrary.Lock,\n text: ShareLinkHelper.getRespectRatingText(entity, yearGroups, hasStudentExp)\n };\n case SharePrivacy.JustMySchoolOverrideRestriction:\n return { icon: cvSvgLibrary.Lock, text: getPhrase(hasStudentExp ? 'justMySchoolTeachers' : 'justMySchoolDescription') };\n case SharePrivacy.JustMySchool:\n return {\n icon: cvSvgLibrary.Lock,\n text: ShareLinkHelper.getRespectRatingText(entity, yearGroups, hasStudentExp)\n };\n case SharePrivacy.PinCode:\n case SharePrivacy.PasswordProtected:\n return { icon: cvSvgLibrary.Lock, text: getPhrase('privateDescription') };\n default:\n return {};\n }\n },\n\n getIconAndText: (options: GetIconAndTextOptions) => {\n const { linkExpireDate, isPasswordProtected, status } = options;\n if (!linkExpireDate && !isPasswordProtected)\n return ShareLinkHelper.getPrivateIconAndText(options);\n \n if (!linkExpireDate)\n return { icon: cvSvgLibrary.Lock, text: getPhrase('password') };\n \n const isToday = DateHelper.isToday(linkExpireDate);\n const dayDifference = DateHelper.diffBetween(linkExpireDate, new Date(), 'day');\n \n if (!isPasswordProtected) {\n let text = isToday\n ? getPhrase('expiryToday')\n : getPhrase('expiry', { days: dayDifference });\n \n if (status === ShareLinkStatus.Expired)\n text = getPhrase('expired');\n \n return { icon: cvSvgLibrary.Timer, text };\n }\n \n let text = isToday\n ? getPhrase('passwordExpiryToday')\n : getPhrase('passwordExpiry', { days: dayDifference });\n \n if (status === ShareLinkStatus.Expired)\n text = getPhrase('passwordExpired');\n \n return { icon: cvSvgLibrary.Lock, text };\n },\n\n getRespectRatingText(video: BaseObject, yearGroups: YearGroup[], hasStudentExp: boolean) {\n if (!video || !yearGroups)\n return null;\n \n if (hasStudentExp)\n return getPhrase('justMySchoolTeachers');\n \n if (!VideoHelper.isVideoType(video))\n return getPhrase('collectionRating');\n \n const restriction = RestrictionHelper.getWeightedRestriction(video._restrictions?.value);\n \n /**\n * Restrictions without a year level are teacher restricitons, which means only admins can see it.\n */\n if (restriction && !restriction.yearGroup)\n return getPhrase('onlyAdmins');\n \n const rating = VideoHelper.getRating(video);\n \n let maxYearGroup: YearGroup;\n let minAllowedYearGroup: YearGroup;\n \n for (const yearGroup of yearGroups) {\n /**\n * If our year level is our new highest so far, save it\n */\n if (!maxYearGroup || yearGroup.value > maxYearGroup.value)\n maxYearGroup = yearGroup;\n \n /**\n * If the restriction is higher than this year level, skip it.\n */\n if (restriction && yearGroup.value <= restriction.yearGroup)\n continue;\n \n /**\n * If therating is higher than this year level's rating value, skip it.\n */\n if (rating && yearGroup.rating.value < rating.value)\n continue;\n \n /**\n * If our year level is the new lowest so far, save it\n */\n if (!minAllowedYearGroup || yearGroup.value < minAllowedYearGroup.value)\n minAllowedYearGroup = yearGroup;\n }\n \n /**\n * If no year levels are allowed, then it's staff only.\n */\n if (!minAllowedYearGroup)\n return getPhrase('onlyStaff');\n \n \n /**\n * If there's only one year level, and it's allowed, then we can just\n * say that everyone in your school can access it.\n */\n if (yearGroups.length === 1)\n return getPhrase('clickViewOnly');\n \n /**\n * We differentiate the copy if it's the highest year level or not. \n * Basically if we need to say \"X and above\" or not.\n */\n if (minAllowedYearGroup.value === maxYearGroup.value)\n return getPhrase('maxYearGroup', { yearGroup: maxYearGroup.name });\n \n return getPhrase('yearGroupRange', { yearGroup: minAllowedYearGroup.name });\n },\n\n getClassroomId(shareLink: ShareLink | undefined): string {\n if (!shareLink)\n return '';\n\n if (shareLink.type !== ShareType.Classroom)\n return '';\n\n const classroom = shareLink.recipients?.find(r => r.recipientTypeId === MasterType.Classroom);\n\n if (classroom)\n return classroom.recipientId.toString();\n\n const recipientWithScope = shareLink.recipients?.find(r => r.scopeId);\n\n return recipientWithScope?.scopeId.toString() || '';\n }\n};","\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n \"text/plain\": \"Text\",\n \"text/html\": \"Url\",\n \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\") + \"+C\";\n return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n var debug,\n message,\n reselectPrevious,\n range,\n selection,\n mark,\n success = false;\n if (!options) {\n options = {};\n }\n debug = options.debug || false;\n try {\n reselectPrevious = deselectCurrent();\n\n range = document.createRange();\n selection = document.getSelection();\n\n mark = document.createElement(\"span\");\n mark.textContent = text;\n // avoid screen readers from reading out loud the text\n mark.ariaHidden = \"true\"\n // reset user styles for span element\n mark.style.all = \"unset\";\n // prevents scrolling to the end of the page\n mark.style.position = \"fixed\";\n mark.style.top = 0;\n mark.style.clip = \"rect(0, 0, 0, 0)\";\n // used to preserve spaces and line breaks\n mark.style.whiteSpace = \"pre\";\n // do not inherit user-select (it may be `none`)\n mark.style.webkitUserSelect = \"text\";\n mark.style.MozUserSelect = \"text\";\n mark.style.msUserSelect = \"text\";\n mark.style.userSelect = \"text\";\n mark.addEventListener(\"copy\", function(e) {\n e.stopPropagation();\n if (options.format) {\n e.preventDefault();\n if (typeof e.clipboardData === \"undefined\") { // IE 11\n debug && console.warn(\"unable to use e.clipboardData\");\n debug && console.warn(\"trying IE specific stuff\");\n window.clipboardData.clearData();\n var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n window.clipboardData.setData(format, text);\n } else { // all other browsers\n e.clipboardData.clearData();\n e.clipboardData.setData(options.format, text);\n }\n }\n if (options.onCopy) {\n e.preventDefault();\n options.onCopy(e.clipboardData);\n }\n });\n\n document.body.appendChild(mark);\n\n range.selectNodeContents(mark);\n selection.addRange(range);\n\n var successful = document.execCommand(\"copy\");\n if (!successful) {\n throw new Error(\"copy command was unsuccessful\");\n }\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using execCommand: \", err);\n debug && console.warn(\"trying IE specific stuff\");\n try {\n window.clipboardData.setData(options.format || \"text\", text);\n options.onCopy && options.onCopy(window.clipboardData);\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using clipboardData: \", err);\n debug && console.error(\"falling back to prompt\");\n message = format(\"message\" in options ? options.message : defaultMessage);\n window.prompt(message, text);\n }\n } finally {\n if (selection) {\n if (typeof selection.removeRange == \"function\") {\n selection.removeRange(range);\n } else {\n selection.removeAllRanges();\n }\n }\n\n if (mark) {\n document.body.removeChild(mark);\n }\n reselectPrevious();\n }\n\n return success;\n}\n\nmodule.exports = copy;\n","\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.CopyToClipboard = void 0;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _copyToClipboard = _interopRequireDefault(require(\"copy-to-clipboard\"));\n\nvar _excluded = [\"text\", \"onCopy\", \"options\", \"children\"];\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, \"prototype\", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nvar CopyToClipboard = /*#__PURE__*/function (_React$PureComponent) {\n _inherits(CopyToClipboard, _React$PureComponent);\n\n var _super = _createSuper(CopyToClipboard);\n\n function CopyToClipboard() {\n var _this;\n\n _classCallCheck(this, CopyToClipboard);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"onClick\", function (event) {\n var _this$props = _this.props,\n text = _this$props.text,\n onCopy = _this$props.onCopy,\n children = _this$props.children,\n options = _this$props.options;\n\n var elem = _react[\"default\"].Children.only(children);\n\n var result = (0, _copyToClipboard[\"default\"])(text, options);\n\n if (onCopy) {\n onCopy(text, result);\n } // Bypass onClick if it was present\n\n\n if (elem && elem.props && typeof elem.props.onClick === 'function') {\n elem.props.onClick(event);\n }\n });\n\n return _this;\n }\n\n _createClass(CopyToClipboard, [{\n key: \"render\",\n value: function render() {\n var _this$props2 = this.props,\n _text = _this$props2.text,\n _onCopy = _this$props2.onCopy,\n _options = _this$props2.options,\n children = _this$props2.children,\n props = _objectWithoutProperties(_this$props2, _excluded);\n\n var elem = _react[\"default\"].Children.only(children);\n\n return /*#__PURE__*/_react[\"default\"].cloneElement(elem, _objectSpread(_objectSpread({}, props), {}, {\n onClick: this.onClick\n }));\n }\n }]);\n\n return CopyToClipboard;\n}(_react[\"default\"].PureComponent);\n\nexports.CopyToClipboard = CopyToClipboard;\n\n_defineProperty(CopyToClipboard, \"defaultProps\", {\n onCopy: undefined,\n options: undefined\n});","\"use strict\";\n\nvar _require = require('./Component'),\n CopyToClipboard = _require.CopyToClipboard;\n\nCopyToClipboard.CopyToClipboard = CopyToClipboard;\nmodule.exports = CopyToClipboard;","\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n"],"names":["DEFAULT_POLLING_INTERVAL","usePolling","callback","pollingInterval","pollingTrigger","setPollingTrigger","timeoutRef","t","current","window","setTimeout","clearTimeout","useAnonSessions","shareId","fetch","anonSessionsRequest","anonSessionsResponse","data","length","reduce","prev","sessionId","useChunkedUsersResponse","usersIds","userIdChunks","usersResponse","map","chunk","users","isLoading","hasCompleted","namespace","BASE_IMAGE_CLASS_NAME","InsightsMask","className","SharedObjectImage","props","ref","el","object","fixedHeight","style","width","offsetHeight","VideoHelper","typeId","MasterType","useVideoThumbnail","image","ImageHelper","imageType","imageClassName","imageFallbackComponent","ImageFallback","type","svgContainerClassName","url","getBgColorClass","name","extraClasses","getImageProps","metadataFlags","showVideoMetadata","hideDuration","hideMask","hideRating","hideVideoTypeBadge","showInsightsMask","AppLink","appLink","VideoThumbnail","video","size","thumbnailSize","imageOptions","textPosition","ThumbnailTextPosition","requireMarking","Text","phrase","options","smartCount","CollectionThumbnail","collection","analyticsData","id","analyticsOptions","entity","ShareViewHelper","actionType","location","locationContext","showMask","showCollectionMask","showVideoCount","BaseImage","defaultProps","BaseCollectionThumbnailTitle","title","CollectionThumbnailTitle","firstVideo","collectionVideos","videos","count","playlist","clips","interactives","ArrayHelper","getFirstVideo","videoCount","totalCount","getVideoCount","showTexts","subText","toString","MasterTypeHelper","preventFocus","SvgContainer","svgName","hoverText","TitleSubText","subTextAppLink","titleAppLink","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","VideoViewRequests","individualEngagement","objectId","filter","sharerId","includeAnonViews","queryParams","key","formatData","d","heatMap","normalize","aggregateEngagement","views","timeOffset","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","Array","isArray","useEffect","forEach","ShareOptions","qrCodeValue","shareLink","link","shortenedUrl","videoAppLink","VideoAppLinkHelper","sharedObject","minWidth","href","IconButton","svgSize","S","customSize","ShareAvatar","classroomName","classroom","application","action","args","params","entityType","value","pinCode","target","code","CopyToClipboard","text","onClick","console","log","ShareOptionsView","anonymiseUsers","config","ConfigRequests","ShareRequests","classRoomId","ShareLinkHelper","ClassroomRequests","useSettings","hasShareFlowV2","publicInteractiveAttempts","hasPermissions","usePermissions","videoRequest","includes","currentUser","UserRequests","seriesRequest","SeriesRequests","series","playlistRequest","PlaylistRequests","audienceAppLinkParams","dateRangeAppLinkParams","requestFilter","engagementRequest","userIds","userId","Boolean","anonSessions","fakeEngagement","classroomId","recipients","recipientTypeId","recipientId","getClassroomRequest","cursor","clasroomStudents","engagementMap","next","items","user","customerId","engagementRate","videoDuration","viewCount","videoId","sessionIds","e","useGetFakeEngagement","useLockContentWidth","useSetPageMetadata","tableDataLoaded","tableRowsWillBeEmpty","showTableEmptyState","individualEngagementLength","userIdsLength","anonSessionsLength","Object","keys","fakeEngagementLength","InsightsHeader","tabs","hasAnalytics","PermissionName","analyticsWebUrl","ShareType","EngagementTable","engagement","imageCdnUrl","border","hideWhenEmpty","theme","header","table","minHeight","icons","variant","iconColours","textVariant","svgWrapperClassName","titles","hideSubtitle","groupCount","r","studentCount","pluralize","getSubtitle","singular","plural","SharePrivacy","normalizeOptions","createShareLink","success","error","always","invalidationKeys","getShareLink","getSharesByObjectId","getSentShares","adaptedParams","scopeId","limit","offset","parseInt","values","response","pagination","cursors","createPincode","getPincode","getPincodeByShareId","getPhrase","getPrivateIconAndText","entityTypeId","hasStudentExp","yearGroups","icon","getRespectRatingText","getIconAndText","linkExpireDate","isPasswordProtected","isToday","dayDifference","Date","days","restriction","_restrictions","yearGroup","maxYearGroup","minAllowedYearGroup","getClassroomId","find","recipientWithScope","deselectCurrent","clipboardToIE11Formatting","module","exports","debug","message","reselectPrevious","range","selection","mark","document","createRange","getSelection","createElement","textContent","ariaHidden","all","position","top","clip","whiteSpace","webkitUserSelect","MozUserSelect","msUserSelect","userSelect","addEventListener","stopPropagation","format","preventDefault","clipboardData","warn","clearData","setData","onCopy","body","appendChild","selectNodeContents","addRange","execCommand","Error","err","copyKey","test","navigator","userAgent","replace","prompt","removeRange","removeAllRanges","removeChild","_typeof","Symbol","iterator","constructor","prototype","defineProperty","_react","_interopRequireDefault","_copyToClipboard","_excluded","__esModule","ownKeys","enumerableOnly","getOwnPropertySymbols","symbols","sym","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","i","arguments","source","_defineProperty","getOwnPropertyDescriptors","defineProperties","_defineProperties","descriptor","configurable","writable","_setPrototypeOf","o","p","setPrototypeOf","__proto__","_assertThisInitialized","self","ReferenceError","_getPrototypeOf","getPrototypeOf","_React$PureComponent","subClass","superClass","TypeError","create","_inherits","Constructor","protoProps","Derived","hasNativeReflectConstruct","_super","Reflect","construct","sham","Proxy","valueOf","call","_isNativeReflectConstruct","result","Super","NewTarget","this","_possibleConstructorReturn","_this","instance","_classCallCheck","_len","_key","concat","event","_this$props","children","elem","Children","only","_this$props2","excluded","sourceKeys","indexOf","_objectWithoutPropertiesLoose","sourceSymbolKeys","propertyIsEnumerable","_objectWithoutProperties","cloneElement","PureComponent","undefined","rangeCount","active","activeElement","ranges","getRangeAt","tagName","toUpperCase","blur","focus"],"sourceRoot":""}
@@ -0,0 +1,2 @@
1
+ "use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[7757],{70376:(e,t,n)=>{n.d(t,{W:()=>o});var r=n(32735),a=n(91967);function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var s=5e3;function o(e){var t,n,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s,u=(t=r.useState(!1),n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,s,o=[],u=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(o.push(r.value),o.length!==t);u=!0);}catch(e){l=!0,a=e}finally{try{if(!u&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(l)throw a}}return o}}(t,n)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),l=u[0],c=u[1],d=r.useRef(null),m=function(){c((function(e){return!e})),d.current=window.setTimeout(m,o)};return r.useEffect((function(){d.current=window.setTimeout(m,o)}),[]),r.useEffect((function(){a.q.isFunction(e)&&e()}),[l]),function(){return window.clearTimeout(d.current)}}},5255:(e,t,n)=>{n.d(t,{Y:()=>o});var r=n(70376),a=n(20354),i=n(30439);function s(e){return s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s(e)}function o(e){var t,n=a.a.useGetFetch(),o=e&&i.o.getAnonSessions(e),u=a.a.useBasicFetch(o);return(0,r.W)((function(){return n(o)}),5e3),(null===(t=u.data)||void 0===t?void 0:t.length)?u.data.reduce((function(e,t){return Object.assign(Object.assign({},e),(n={},r=t.sessionId,a=t,(r=function(e){var t=function(e){if("object"!=s(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=s(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==s(t)?t:t+""}(r))in n?Object.defineProperty(n,r,{value:a,enumerable:!0,configurable:!0,writable:!0}):n[r]=a,n));var n,r,a}),{}):{}}},41196:(e,t,n)=>{n.d(t,{W:()=>o});var r=n(20354),a=n(71553),i=n(20768),s=n(31949);function o(e,t,n){var o,u=r.a.useBasicFetch(s.N.currentUser()),l=r.a.useBasicFetch(!!e&&i.b.interactiveMetadata(e)),c=r.a.useBasicFetch(!!(null===(o=l.data)||void 0===o?void 0:o.interactiveId)&&i.b.interactive(l.data.interactiveId)),d=!!u.data&&!!c.data&&!!t;return r.a.useBasicFetch(d&&a.I.interactiveResultSet(l.data.interactiveId,l.data.id,u.data,t,n))}},26025:(e,t,n)=>{n.d(t,{B:()=>i});var r=n(1048),a=n(75795),i={getAudienceAppLinkParams:function(){var e=a.O.getCurrentRoute().appLink,t=r.t.isObject(e.params)?e.params:{},n=t.users,i=t.classrooms,s=t.classroomGroups,o=function(e){var n=t[e];if(n)return Array.isArray(n)?n:[n]},u={};return n&&(u.users=o("users")),i&&(u.classrooms=o("classrooms")),s&&(u.classroomGroups=o("classroomGroups")),u},getDateRangeAppLinkParams:function(){var e=a.O.getCurrentRoute().appLink,t=r.t.isObject(e.params)?e.params:{},n=t.from,i=t.to,s=t.rangeName,o={};return n&&(o.from=n),i&&(o.to=i),s&&(o.rangeName=s),o}}},26136:(e,t,n)=>{n.d(t,{B2:()=>o,DV:()=>l,jP:()=>u});var r=n(76198),a=n(23481),i=n(64818),s=a.T.encloseNamespace("shared.analyticsUtils");function o(e,t){return e?t?(0,r._8)((n="sessionId"in e?e.sessionName:e.id,a=+"".concat(n).concat(Math.floor((new Date).getMinutes()/5)),{dictionaries:[r.O9,r.yd],separator:" ",length:2,style:"capital",seed:a})):"sessionId"in e?e.sessionName:i.l.getFullName(e):"";var n,a}function u(e,t){var n={sessionId:e,sessionName:s("anonymousUser")};return e&&t&&t[e]||n}function l(e,t){return e.user?e.user:u(e.sessionId,t)}},40003:(e,t,n)=>{n.d(t,{Hb:()=>o,wO:()=>l});var r=n(23481),a=n(110),i=(n(57266),r.T.encloseNamespace("shared.analyticsUtils"));function s(e){var t=a.O.convertDateToUTC(e);return a.O.format(t,"YYYY-MM-DDTHH:mm:ss")}function o(){var e=new Date(2021,0,1),t=(new Date).getFullYear(),n=t===e.getFullYear();return[{name:i("today"),startDate:new Date,endDate:new Date},{name:i("thisMonth"),startDate:new Date(t,(new Date).getMonth(),1),endDate:new Date},{name:i("lastThreeMonths"),startDate:new Date(t,(new Date).getMonth()-2,1),endDate:new Date},{name:i("lastSixMonths"),startDate:new Date(t,(new Date).getMonth()-5,1),endDate:new Date},{name:i("thisYear"),startDate:new Date(t,0,1),endDate:new Date},{name:i("lastYear"),startDate:new Date(t-1,0,1),endDate:new Date(t,0,0),disabled:n,tooltip:n?i("lastYearDisabled"):""},{name:i("allTime"),startDate:a.O.subtract(new Date,5,"years"),endDate:new Date,default:!0}]}function u(e){return a.O.format(e,"YYYY-MM-DD")}function l(e,t){var n=function(e){return s(a.O.startOf(e,"day"))},r=function(e){return s(a.O.endOf(e,"day"))},i=function(e,t){if(t)return e.find((function(e){return e.name===t}))}(e,t.rangeName);if(i)return{start:n(u(i.startDate)),end:r(u(i.endDate))};if(t.from&&t.to)return{start:n(t.from),end:r(t.to)};var o=e.find((function(e){return!!e.default}));return{start:n(u(o.startDate)),end:r(u(o.endDate))}}},43503:(e,t,n)=>{n.r(t),n.d(t,{InteractiveStudentResultsView:()=>A});var r=n(32735),a=n(23481),i=n(20354),s=n(2948),o=n(5255),u=n(41196),l=n(9193),c=n(26025),d=n(26136),m=n(40003),f=n(3218),v=n(9111),b=n(38143),y=n(39151),p=n(20768),g=n(26304),w=n(91286),h=n(93322);function k(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var S=a.T.encloseNamespace("shared.interactiveStudentResults");function A(e){var t,n,a,A,D,I,E=(D=(0,s.D)(b.g.ANONYMISE_USERS),I=1,function(e){if(Array.isArray(e))return e}(D)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,s,o=[],u=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(o.push(r.value),o.length!==t);u=!0);}catch(e){l=!0,a=e}finally{try{if(!u&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(l)throw a}}return o}}(D,I)||function(e,t){if(e){if("string"==typeof e)return k(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?k(e,t):void 0}}(D,I)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0];(0,h.F)();var O=i.a.useBasicFetch(p.b.interactiveMetadata(e.interactiveId)),C=i.a.useBasicFetch((null===(t=O.data)||void 0===t?void 0:t.interactiveId)&&p.b.interactive(O.data.interactiveId)),R=c.B.getDateRangeAppLinkParams(),M=(0,u.W)(e.interactiveId,(0,m.wO)((0,m.Hb)(),R)),N=i.a.useBasicFetch(y.L.config()),j=(0,o.Y)(e.shareId);(0,w.v)([O,M]),(0,g.b)(O);var T=(0,l.D)(null===(n=C.data)||void 0===n?void 0:n.id,null===(a=O.data)||void 0===a?void 0:a.id,e.closePopup),F=T.markedAnswers,U=T.addMarkedAnswers,B=T.submitMarkedAnswers,Y=null===(A=M.data)||void 0===A?void 0:A.students.find((function(t){var n,r,a,i,s;return e.userId?(null===(r=null===(n=t.user)||void 0===n?void 0:n.id)||void 0===r?void 0:r.toString())===(null===(a=e.userId)||void 0===a?void 0:a.toString()):!!e.sessionId&&(null===(i=t.sessionId)||void 0===i?void 0:i.toString())===(null===(s=e.sessionId)||void 0===s?void 0:s.toString())})),H=Y?S("heading",{studentName:(0,d.B2)((0,d.DV)(Y,j),E)}):"",P=!!C.data&&!!M.data&&!!N.data;return r.createElement(v.G,{title:H,showLoadingSpinner:!P,closePopup:e.closePopup,size:"lg"},P&&r.createElement(f.R,{interactive:C.data,studentResults:Y,markedAnswers:F,addMarkedAnswers:U,submitMarkedAnswers:B,imageCdnUrl:N.data.imageCdnUrl,selectedInteractionId:e.interactionId,onClickClose:e.closePopup,anonymiseUsers:E,reportsStyling:e.reportsStyling,anonSessions:j}))}},3218:(e,t,n)=>{n.d(t,{R:()=>S});var r=n(32735),a=n(69087),i=n(26136),s=n(39157),o=n(69186),u=n(86572),l=n(28972),c=n(83140),d=n(80845),m=n(23481),f=n(2102),v=n(36532),b=m.T.encloseNamespace("interactives.studentResponseList");function y(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-end pt-3"},r.createElement("div",null,!e.showSubmitButtonSpinner&&r.createElement("button",{className:"btn btn-link",onClick:e.onClickClose},b("close")),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(v.u,{id:"submitAnswers",title:b("demoOnly"),spanHack:!0,spanHackClassName:"d-inline-flex"},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},b("submitAnswers"))):r.createElement(f.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},b("submitAnswers")))))}var p=m.T.encloseNamespace("interactives.studentResponseList");function g(e){var t=Object.keys(e.markedAnswers).length;return r.createElement("div",{className:"d-flex justify-content-between pb-3"},r.createElement("div",{className:"d-flex"},!!e.summary.unanswered&&r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},p("unanswered")),e.summary.unanswered),r.createElement("div",{className:"bg-light rounded p-2 me-2"},r.createElement("strong",{className:"me-2"},p("score")),e.summary.awaitingMarking?r.createElement("em",null,p("pending")):"".concat(Math.round(100*e.summary.percentCorrect),"%"))),!!e.interactionsToMark.length&&r.createElement(r.Fragment,null,e.isDemo?r.createElement(v.u,{id:"submitAnswers",title:p("demoOnly"),spanHack:!0},r.createElement("button",{className:"btn btn-outline-dark pointer-events-none",disabled:!t},p("submitAnswers"))):r.createElement(f.m,{variant:"outline-dark",onClick:e.onClickSubmit,disabled:!t,showSpinner:e.showSubmitButtonSpinner},p("submitAnswers"))))}const w={awaitingMarking:"MvGb5"};function h(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,s,o=[],u=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(o.push(r.value),o.length!==t);u=!0);}catch(e){l=!0,a=e}finally{try{if(!u&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(l)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return k(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?k(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function k(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function S(e){var t,n,m,f,v=h(r.useState(!1),2),b=v[0],p=v[1],k=(t=r.useRef(null),n=h(r.useState(!1),2),m=n[0],f=n[1],r.useEffect((function(){t.current&&!m&&(f(!0),requestAnimationFrame((function(){return t.current.scrollIntoView({behavior:"smooth",block:"center"})})))}),[t.current,m]),t),S=(0,s.Rt)(e.interactive,e.studentResults),A=(0,d.Q)(e.interactive),D=function(e,t){return e.filter((function(e){return c.A.isInteractionCorrect(e,(0,d.j_)(t))===l.w.AwaitingMarking}))}(A,e.studentResults);function I(){p(!0),e.submitMarkedAnswers()}return r.createElement(r.Fragment,null,r.createElement(g,{summary:S,interactionsToMark:D,markedAnswers:e.markedAnswers,onClickSubmit:I,showSubmitButtonSpinner:b,isDemo:e.isDemo}),r.createElement("ul",{className:"list-unstyled"},A.map((function(t,n){var l,c=t.id.toString()===(null===(l=e.selectedInteractionId)||void 0===l?void 0:l.toString()),d=D.some((function(e){return e.id===t.id})),m=(0,i.B2)((0,i.DV)(e.studentResults,e.anonSessions),e.anonymiseUsers),f="p-2 mb-3 rounded";return c&&(f+=" border-2 border-info shadow"),f+=d?" ".concat(w.awaitingMarking):" border",r.createElement("li",{key:n,className:f,ref:c?k:null},r.createElement("div",{className:"d-flex mb-2"},r.createElement(u.y,{interaction:t,iconClassName:"flex-shrink-0"})),e.reportsStyling?r.createElement(o.O,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,className:"bg-light ps-2",showFeedback:!0,reportsStyling:!0,responseComponentClass:"mx-n2"}):r.createElement(a.d,{interaction:t,studentResults:e.studentResults,markedStatus:(0,s.HI)(t.id,e.studentResults,e.markedAnswers),markInteraction:e.addMarkedAnswers,imageCdnUrl:e.imageCdnUrl,anonymisedUserName:m,showFeedback:!0}))}))),r.createElement(y,{interactionsToMark:D,markedAnswers:e.markedAnswers,onClickSubmit:I,onClickClose:e.onClickClose,showSubmitButtonSpinner:b,isDemo:e.isDemo}))}},94892:(e,t,n)=>{n.d(t,{T:()=>a,i:()=>r});var r={HIGH:.75,MODERATE:.5},a={HIGH:.7,MODERATE:.7}},94644:(e,t,n)=>{n.d(t,{r:()=>c});var r=n(50242),a=n(81886),i=n(67058),s=n(14553),o=n(49267),u=n(49075),l={notFound:i.d,forbidden:{rating:s.q,yearLevel:s.q,region:o.a,privacy:s.q},badRequest:u._,internalServerError:u._};function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(e){var i;i="number"==typeof e?e:e.status;var s=Object.assign(Object.assign({},l),t);i&&a.Q.Ry.isStatusCodeError(i)&&(i!==r.o.InternalServer?i!==r.o.NotFound?i!==r.o.Forbidden?n.badRequest||a.Q.Ry.throw(new s.badRequest):n.forbidden||a.Q.Ry.throw(new s.forbidden.privacy):n.notFound||a.Q.Ry.throw(new s.notFound):n.internalServerError||a.Q.Ry.throw(new u._))}}},91286:(e,t,n)=>{n.d(t,{v:()=>s});var r=n(32735),a=n(94644);function i(e){return e.map((function(e){return e.statusCode})).join(":")}function s(e,t,n){var s=Array.isArray(e)?e:[e];(0,r.useEffect)((function(){s.forEach((function(e){(0,a.r)(e.statusCode,t,n)}))}),[i(s),t,n])}},62875:(e,t,n)=>{function r(e,t,n){var r="".concat(e,":").concat(t.start,":").concat(t.end),a=Array.isArray(t.userId)?t.userId.sort().join(":"):t.userId,i=Array.isArray(t.groupId)?t.groupId.sort().join(":"):t.groupId;return a&&(r+=":".concat(a)),i&&(r+=":".concat(i)),n&&(r+=":".concat(n)),r}n.d(t,{H:()=>r})},57266:(e,t,n)=>{n.d(t,{e:()=>s});var r=n(81886),a=n(1048),i=n(75795),s={updateParams:function(e,t){var n=i.O.getCurrentRoute().appLink,s="string"==typeof n.params?r.Q.Ab.DeserializeQueryParams(n.params):n.params;t.keysToRemove&&(s=a.t.omit(s,t.keysToRemove));var o=(null==t?void 0:t.merge)?Object.assign(Object.assign({},s),e):e,u=Object.assign(Object.assign({},n),{params:o});a.t.isEqual(n,u)||r.Q.C$.trigger(u,a.t.omit(t,["merge","keysToRemove"]))}}}}]);
2
+ //# sourceMappingURL=7757-9b72774917-lite.chunk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts/7757-e4d91d7fac-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/shared/src/apps/analytics/hooks/UseAnonSessions.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnalyticsFilterUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/interactive-student-results/InteractiveStudentResultsView.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListFooter.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListHeader.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/student-response-list.scss","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseList.tsx","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/utils/AnalyticsRequestUtils.ts","file:///app/packages/libs/shared/src/utils/AppRouteHelper.ts"],"sourcesContent":["import { Flight } from 'libs/common/react/index';\n\nimport { ShareRequests } from 'libs/shared/apps/share/flight-requests/ShareRequests';\n\nexport interface AnonSession {\n sessionId: string;\n sessionName: string;\n}\n\nexport interface AnonSessions extends Record<string, AnonSession> {}\n\nexport function useAnonSessions(shareId: string): AnonSessions {\n const anonSessions = Flight.useBasicFetch<AnonSession[]>(shareId && ShareRequests.getAnonSessions(shareId));\n\n if (!anonSessions.data?.length)\n return {};\n\n return anonSessions.data.reduce((prev, current) => ({ ...prev, [current.sessionId]: current }), {});\n}","import { Flight } from 'libs/common/flight';\n\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { AnalyticsRequestFilter, CurrentUser, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nexport function useFetchInteractiveResults(\n interactiveMetadataId: string,\n requestFilter: AnalyticsRequestFilter,\n includePublicResults?: boolean\n): Flight.Response<InteractiveResultSet> {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(!!interactiveMetadataId &&\n InteractiveRequests.interactiveMetadata(interactiveMetadataId));\n\n const interactive = Flight.useBasicFetch<Interactive>(!!interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const shouldFetchResults = !!currentUser.data && !!interactive.data && (!!requestFilter);\n\n return Flight.useBasicFetch<InteractiveResultSet>(shouldFetchResults &&\n InteractiveResultsRequests.interactiveResultSet(\n interactiveMetadata.data.interactiveId,\n interactiveMetadata.data.id,\n currentUser.data,\n requestFilter,\n includePublicResults\n ));\n}","import { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nexport const AnalyticsFilterHelper = {\n getAudienceAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { users, classrooms, classroomGroups } = params;\n\n const getParam = (key: keyof AudienceQueryParams) => {\n const param = params[key];\n\n if (!param)\n return;\n\n return Array.isArray(param) ? param : [param];\n };\n\n const audienceFilters: AudienceQueryParams = {};\n\n if (users)\n audienceFilters.users = getParam('users');\n\n if (classrooms)\n audienceFilters.classrooms = getParam('classrooms');\n\n if (classroomGroups)\n audienceFilters.classroomGroups = getParam('classroomGroups');\n\n return audienceFilters;\n },\n getDateRangeAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { from, to, rangeName } = params;\n\n const dateRangeFilters: DateRangeQueryParams = {};\n\n if (from)\n dateRangeFilters.from = from;\n\n if (to)\n dateRangeFilters.to = to;\n\n if (rangeName)\n dateRangeFilters.rangeName = rangeName;\n\n return dateRangeFilters;\n }\n};","import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { AnonSession, AnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { UserOrAnonSession } from 'libs/shared/apps/analytics/interfaces/UserOrAnonSession';\nimport { StudentResults } from 'libs/shared/interfaces';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: UserOrAnonSession, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'sessionId' in user ? user.sessionName : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('sessionId' in user ? user.sessionName : user.id));\n}\n\nexport function getAnonSession(sessionId: string, anonSessions: AnonSessions): AnonSession {\n const fallback = {\n sessionId: sessionId,\n sessionName: getPhrase('anonymousUser')\n };\n\n if (!sessionId || !anonSessions)\n return fallback;\n\n const anonSession = anonSessions[sessionId];\n\n if (anonSession)\n return anonSession;\n\n return fallback;\n}\n\nexport function getUserOrAnonSession(result: StudentResults, anonSessions: AnonSessions): UserOrAnonSession {\n if (result.user)\n return result.user;\n\n return getAnonSession(result.sessionId, anonSessions);\n}\n","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresets: DateRange[]): DateRange {\n return dateRangePresets.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastTwelveMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 11, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = {\n startDate,\n endDate,\n name: initialDateRangeValid\n ? rangeName || 'custom'\n : ''\n };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { useAnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { useMarkAnswers } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { anonymiseUserName, getUserOrAnonSession } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { StudentResponseList } from 'libs/shared/apps/student-response-list/StudentResponseList';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { Config, Interactive, InteractiveMetadata } from 'libs/shared/interfaces';\nimport { PopupViewProps } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.interactiveStudentResults';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InteractiveStudentResultsViewProps extends PopupViewProps {\n userId: string;\n interactiveId: string;\n interactionId?: string;\n reportsStyling?: boolean;\n sessionId?: string;\n shareId?: string;\n}\n\nexport function InteractiveStudentResultsView(props: InteractiveStudentResultsViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n useLockContentWidth();\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n\n const results = useFetchInteractiveResults(\n props.interactiveId,\n getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams)\n );\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const anonSessions = useAnonSessions(props.shareId);\n\n useHandleObjectError([ interactiveMetadata, results ]);\n useCannotConsumeError(interactiveMetadata);\n\n const { markedAnswers, addMarkedAnswers, submitMarkedAnswers } = useMarkAnswers(\n interactive.data?.id,\n interactiveMetadata.data?.id,\n props.closePopup\n );\n\n const studentResults = results.data?.students.find(s => {\n if (props.userId)\n return s.user?.id?.toString() === props.userId?.toString();\n\n if (props.sessionId)\n return s.sessionId?.toString() === props.sessionId?.toString();\n\n return false;\n });\n\n const popupTitle = studentResults\n ? getPhrase('heading', { studentName: anonymiseUserName(getUserOrAnonSession(studentResults, anonSessions), anonymiseUsers) })\n : '';\n const dataLoaded = !!interactive.data && !!results.data && !!config.data;\n\n return (\n <Popup\n title={popupTitle}\n showLoadingSpinner={!dataLoaded}\n closePopup={props.closePopup}\n size='lg'\n >\n {dataLoaded &&\n <StudentResponseList\n interactive={interactive.data}\n studentResults={studentResults}\n markedAnswers={markedAnswers}\n addMarkedAnswers={addMarkedAnswers}\n submitMarkedAnswers={submitMarkedAnswers}\n imageCdnUrl={config.data.imageCdnUrl}\n selectedInteractionId={props.interactionId}\n onClickClose={props.closePopup}\n anonymiseUsers={anonymiseUsers}\n reportsStyling={props.reportsStyling}\n anonSessions={anonSessions}\n />\n }\n </Popup>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListFooterProps {\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n onClickClose: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListFooter(props: StudentResponseListFooterProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-end pt-3'>\n <div>\n {!props.showSubmitButtonSpinner &&\n <button className='btn btn-link' onClick={props.onClickClose}>\n {getPhrase('close')}\n </button>\n }\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip\n id='submitAnswers'\n title={getPhrase('demoOnly')}\n spanHack\n spanHackClassName='d-inline-flex'\n >\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n </div>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListHeaderProps {\n summary: ResultsSummary;\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListHeader(props: StudentResponseListHeaderProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-between pb-3'>\n <div className='d-flex'>\n {!!props.summary.unanswered &&\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('unanswered')}</strong>\n {props.summary.unanswered}\n </div>\n }\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('score')}</strong>\n {props.summary.awaitingMarking\n ? <em>{getPhrase('pending')}</em>\n : `${Math.round(props.summary.percentCorrect * 100)}%`\n }\n </div>\n </div>\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip id='submitAnswers' title={getPhrase('demoOnly')} spanHack>\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"awaitingMarking\":\"MvGb5\"};","import React from 'react';\n\nimport { InteractionResponseItem } from 'libs/shared/apps/analytics/components/questions-list/interaction-response-item/InteractionResponseItem';\nimport { AnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { anonymiseUserName, getUserOrAnonSession } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getMarkedStatus, getStudentResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { InteractionResponse } from 'libs/shared/components/interaction-response/InteractionResponse';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, Interactive, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\nimport { StudentResponseListFooter } from './StudentResponseListFooter';\nimport { StudentResponseListHeader } from './StudentResponseListHeader';\n\nimport styles from './student-response-list.scss';\n\nfunction getInteractionsToMark(\n interactions: Interaction[],\n studentResults: StudentResults\n): Interaction[] {\n return interactions.filter(i => {\n return InteractiveCorrectnessHelper.isInteractionCorrect(\n i,\n getStudentResult(studentResults)\n ) === InteractionCorrectness.AwaitingMarking;\n });\n}\n\n// eslint-disable-next-line rulesdir/require-view-title\nfunction useScrollSelectedInteractionIntoView(): React.MutableRefObject<HTMLLIElement> {\n const ref = React.useRef<HTMLLIElement>(null);\n const [ scrolled, setScrolled ] = React.useState(false);\n\n // Only scroll once\n React.useEffect(() => {\n if (!ref.current || scrolled)\n return;\n\n setScrolled(true);\n requestAnimationFrame(() => ref.current.scrollIntoView({ behavior: 'smooth', block: 'center' }));\n }, [ ref.current, scrolled ]);\n\n return ref;\n}\n\ninterface StudentResponseListProps {\n interactive: Interactive;\n markedAnswers: MarkedAnswerHash;\n studentResults: StudentResults;\n addMarkedAnswers: (answer: StudentAnswer[], status: InteractiveAnswerStatus) => void;\n submitMarkedAnswers: () => void;\n onClickClose: () => void;\n imageCdnUrl: string;\n selectedInteractionId?: string;\n anonymiseUsers: boolean;\n reportsStyling?: boolean;\n isDemo?: boolean;\n anonSessions?: AnonSessions;\n}\n\nexport function StudentResponseList(props: StudentResponseListProps): JSX.Element {\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n const selectedInteractionRef = useScrollSelectedInteractionIntoView();\n\n const summary = getStudentResultsSummary(props.interactive, props.studentResults);\n const interactions = getInteractions(props.interactive);\n const questionsToMark = getInteractionsToMark(interactions, props.studentResults);\n\n function onClickSubmit(): void {\n setShowSpinner(true);\n props.submitMarkedAnswers();\n }\n\n return (\n <>\n <StudentResponseListHeader\n summary={summary}\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n <ul className='list-unstyled'>\n {interactions.map((interaction, idx) => {\n const isSelected = interaction.id.toString() === props.selectedInteractionId?.toString();\n const markingRequired = questionsToMark.some(q => q.id === interaction.id);\n const anonymisedUserName = anonymiseUserName(\n getUserOrAnonSession(props.studentResults, props.anonSessions),\n props.anonymiseUsers\n );\n\n let className = 'p-2 mb-3 rounded';\n\n if (isSelected)\n className += ' border-2 border-info shadow';\n\n if (markingRequired)\n className += ` ${styles.awaitingMarking}`;\n else\n className += ' border';\n\n return (\n <li key={idx} className={className} ref={isSelected ? selectedInteractionRef : null}>\n <div className='d-flex mb-2'>\n <InteractionLabel\n interaction={interaction}\n iconClassName='flex-shrink-0'\n />\n </div>\n {props.reportsStyling ? (\n <InteractionResponse\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n className='bg-light ps-2'\n showFeedback\n reportsStyling\n responseComponentClass='mx-n2'\n />\n ) : (\n <InteractionResponseItem\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n showFeedback\n />\n )}\n </li>\n );\n })}\n </ul>\n <StudentResponseListFooter\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n onClickClose={props.onClickClose}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n </>\n );\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nexport function getAnalyticsRequestKey(baseKey: string, filter: AnalyticsRequestFilter, sharerId?: string): string {\n let key = `${baseKey}:${filter.start}:${filter.end}`;\n\n const userIdKey = Array.isArray(filter.userId) ? filter.userId.sort().join(':') : filter.userId;\n const groupIdKey = Array.isArray(filter.groupId) ? filter.groupId.sort().join(':') : filter.groupId;\n\n if (userIdKey)\n key += `:${userIdKey}`;\n\n if (groupIdKey)\n key += `:${groupIdKey}`;\n\n if (sharerId)\n key += `:${sharerId}`;\n\n return key;\n}","import { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { ContextService } from 'libs/shared/services/ContextService';\n\ninterface UpdateParamsOptions extends Core.AppLinkOptions {\n merge?: boolean;\n keysToRemove?: string[]\n}\n\nexport const AppRouteHelper = {\n /**\n * Utility to update the params on the current appRoute.\n * \n * This is built on top of ContextService rather than build into AppLink\n * as we will generally only want to update params on appRoutes, not appLinks.\n */\n updateParams(params: HashObject, options?: UpdateParamsOptions): void {\n const { appLink } = ContextService.getCurrentRoute();\n\n let currentParams = typeof(appLink.params) === 'string'\n ? Core.LocationUtils.DeserializeQueryParams(appLink.params)\n : appLink.params as HashObject;\n\n if (options.keysToRemove)\n currentParams = ObjectHelper.omit(currentParams, options.keysToRemove);\n\n const updatedParams = options?.merge\n ? { ...currentParams, ...params }\n : params;\n\n const updatedAppLink = {\n ...appLink,\n params: updatedParams\n };\n\n /**\n * This prevents us pointlessly re-triggering if we're already on the right applink.\n */\n if (ObjectHelper.isEqual(appLink, updatedAppLink))\n return;\n \n Core.AppLinkHelper.trigger(updatedAppLink, ObjectHelper.omit(options, [ 'merge', 'keysToRemove' ]));\n }\n};"],"names":["useAnonSessions","shareId","anonSessions","data","length","reduce","prev","current","sessionId","useFetchInteractiveResults","interactiveMetadataId","requestFilter","includePublicResults","currentUser","interactiveMetadata","interactive","interactiveId","shouldFetchResults","I","id","AnalyticsFilterHelper","getAudienceAppLinkParams","appLink","params","users","classrooms","classroomGroups","getParam","key","param","Array","isArray","audienceFilters","getDateRangeAppLinkParams","from","to","rangeName","dateRangeFilters","getPhrase","anonymiseUserName","user","shouldAnonymise","sessionName","seed","Math","floor","Date","getMinutes","dictionaries","separator","style","getAnonSession","fallback","getUserOrAnonSession","result","convertDateToUtcDateTimeString","date","utc","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","name","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getStartEndParams","dateRangePresetss","filterParams","getStartDate","getEndDate","presetRange","find","p","getPresetRangeByName","start","end","defaultRange","range","InteractiveStudentResultsView","props","anonymiseUsers","dateRangeAppLinkParams","results","config","closePopup","markedAnswers","addMarkedAnswers","submitMarkedAnswers","studentResults","students","s","userId","toString","popupTitle","studentName","dataLoaded","title","showLoadingSpinner","size","imageCdnUrl","selectedInteractionId","interactionId","onClickClose","reportsStyling","LanguageService","StudentResponseListFooter","numMarkedAnswers","Object","keys","className","showSubmitButtonSpinner","onClick","interactionsToMark","isDemo","Tooltip","spanHack","spanHackClassName","SpinnerButton","variant","onClickSubmit","showSpinner","StudentResponseListHeader","summary","unanswered","awaitingMarking","round","percentCorrect","StudentResponseList","ref","scrolled","setScrolled","setShowSpinner","selectedInteractionRef","requestAnimationFrame","scrollIntoView","behavior","block","interactions","questionsToMark","filter","i","InteractiveCorrectnessHelper","InteractionCorrectness","getInteractionsToMark","map","interaction","idx","isSelected","markingRequired","some","q","anonymisedUserName","InteractionLabel","iconClassName","InteractionResponse","markedStatus","markInteraction","showFeedback","responseComponentClass","InteractionResponseItem","ScoreThresholdDefaults","HIGH","MODERATE","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","useEffect","forEach","getAnalyticsRequestKey","baseKey","sharerId","userIdKey","sort","groupIdKey","groupId","AppRouteHelper","updateParams","options","currentParams","keysToRemove","updatedParams","merge","updatedAppLink"],"sourceRoot":""}
1
+ {"version":3,"file":"scripts/7757-9b72774917-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/common/src/react/hooks/UsePolling.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseAnonSessions.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnalyticsFilterUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/interactive-student-results/InteractiveStudentResultsView.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListFooter.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseListHeader.tsx","file:///app/packages/libs/shared/src/apps/student-response-list/student-response-list.scss","file:///app/packages/libs/shared/src/apps/student-response-list/StudentResponseList.tsx","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/utils/AnalyticsRequestUtils.ts","file:///app/packages/libs/shared/src/utils/AppRouteHelper.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { FunctionHelper } from 'libs/common/backbone/utils/FunctionHelper';\n\nconst DEFAULT_POLLING_INTERVAL = 5000; // 5 seconds.\n\n/**\n * Hook to fire a callback at a set interval.\n * @param callback \n * @param pollingInterval \n * \n * Returns a function to clear the timeout.\n */\nexport function usePolling(callback: () => void, pollingInterval: number = DEFAULT_POLLING_INTERVAL): () => void {\n const [ pollingTrigger, setPollingTrigger ] = React.useState(false);\n\n const timeoutRef = React.useRef<number>(null);\n\n const poll = () => {\n setPollingTrigger(t => !t);\n\n timeoutRef.current = window.setTimeout(poll, pollingInterval);\n };\n\n React.useEffect(() => {\n timeoutRef.current = window.setTimeout(poll, pollingInterval);\n }, []);\n\n React.useEffect(() => {\n if (FunctionHelper.isFunction(callback))\n callback();\n }, [pollingTrigger]);\n\n return () => window.clearTimeout(timeoutRef.current);\n}","import { usePolling } from 'libs/common/react/hooks/UsePolling';\nimport { Flight } from 'libs/common/react/index';\n\nimport { ShareRequests } from 'libs/shared/apps/share/flight-requests/ShareRequests';\n\nexport interface AnonSession {\n sessionId: string;\n sessionName: string;\n}\n\nexport interface AnonSessions extends Record<string, AnonSession> {}\n\nexport function useAnonSessions(shareId: string): AnonSessions {\n const fetch = Flight.useGetFetch();\n const anonSessionsRequest = shareId && ShareRequests.getAnonSessions(shareId);\n const anonSessionsResponse = Flight.useBasicFetch<AnonSession[]>(anonSessionsRequest);\n\n usePolling(() => fetch(anonSessionsRequest), 5000);\n\n if (!anonSessionsResponse.data?.length)\n return {};\n\n return anonSessionsResponse.data.reduce((prev, current) => ({ ...prev, [current.sessionId]: current }), {});\n}","import { Flight } from 'libs/common/flight';\n\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { AnalyticsRequestFilter, CurrentUser, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nexport function useFetchInteractiveResults(\n interactiveMetadataId: string,\n requestFilter: AnalyticsRequestFilter,\n includePublicResults?: boolean\n): Flight.Response<InteractiveResultSet> {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(!!interactiveMetadataId &&\n InteractiveRequests.interactiveMetadata(interactiveMetadataId));\n\n const interactive = Flight.useBasicFetch<Interactive>(!!interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const shouldFetchResults = !!currentUser.data && !!interactive.data && (!!requestFilter);\n\n return Flight.useBasicFetch<InteractiveResultSet>(shouldFetchResults &&\n InteractiveResultsRequests.interactiveResultSet(\n interactiveMetadata.data.interactiveId,\n interactiveMetadata.data.id,\n currentUser.data,\n requestFilter,\n includePublicResults\n ));\n}","import { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nexport const AnalyticsFilterHelper = {\n getAudienceAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { users, classrooms, classroomGroups } = params;\n\n const getParam = (key: keyof AudienceQueryParams) => {\n const param = params[key];\n\n if (!param)\n return;\n\n return Array.isArray(param) ? param : [param];\n };\n\n const audienceFilters: AudienceQueryParams = {};\n\n if (users)\n audienceFilters.users = getParam('users');\n\n if (classrooms)\n audienceFilters.classrooms = getParam('classrooms');\n\n if (classroomGroups)\n audienceFilters.classroomGroups = getParam('classroomGroups');\n\n return audienceFilters;\n },\n getDateRangeAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { from, to, rangeName } = params;\n\n const dateRangeFilters: DateRangeQueryParams = {};\n\n if (from)\n dateRangeFilters.from = from;\n\n if (to)\n dateRangeFilters.to = to;\n\n if (rangeName)\n dateRangeFilters.rangeName = rangeName;\n\n return dateRangeFilters;\n }\n};","import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { AnonSession, AnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { UserOrAnonSession } from 'libs/shared/apps/analytics/interfaces/UserOrAnonSession';\nimport { StudentResults } from 'libs/shared/interfaces';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: UserOrAnonSession, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'sessionId' in user ? user.sessionName : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('sessionId' in user ? user.sessionName : user.id));\n}\n\nexport function getAnonSession(sessionId: string, anonSessions: AnonSessions): AnonSession {\n const fallback = {\n sessionId: sessionId,\n sessionName: getPhrase('anonymousUser')\n };\n\n if (!sessionId || !anonSessions)\n return fallback;\n\n const anonSession = anonSessions[sessionId];\n\n if (anonSession)\n return anonSession;\n\n return fallback;\n}\n\nexport function getUserOrAnonSession(result: StudentResults, anonSessions: AnonSessions): UserOrAnonSession {\n if (result.user)\n return result.user;\n\n return getAnonSession(result.sessionId, anonSessions);\n}\n","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresets: DateRange[]): DateRange {\n return dateRangePresets.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastTwelveMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 11, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = {\n startDate,\n endDate,\n name: initialDateRangeValid\n ? rangeName || 'custom'\n : ''\n };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\n\nimport { useAnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { useMarkAnswers } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { anonymiseUserName, getUserOrAnonSession } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { StudentResponseList } from 'libs/shared/apps/student-response-list/StudentResponseList';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { Config, Interactive, InteractiveMetadata } from 'libs/shared/interfaces';\nimport { PopupViewProps } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.interactiveStudentResults';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InteractiveStudentResultsViewProps extends PopupViewProps {\n userId: string;\n interactiveId: string;\n interactionId?: string;\n reportsStyling?: boolean;\n sessionId?: string;\n shareId?: string;\n}\n\nexport function InteractiveStudentResultsView(props: InteractiveStudentResultsViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n useLockContentWidth();\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n\n const results = useFetchInteractiveResults(\n props.interactiveId,\n getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams)\n );\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const anonSessions = useAnonSessions(props.shareId);\n\n useHandleObjectError([ interactiveMetadata, results ]);\n useCannotConsumeError(interactiveMetadata);\n\n const { markedAnswers, addMarkedAnswers, submitMarkedAnswers } = useMarkAnswers(\n interactive.data?.id,\n interactiveMetadata.data?.id,\n props.closePopup\n );\n\n const studentResults = results.data?.students.find(s => {\n if (props.userId)\n return s.user?.id?.toString() === props.userId?.toString();\n\n if (props.sessionId)\n return s.sessionId?.toString() === props.sessionId?.toString();\n\n return false;\n });\n\n const popupTitle = studentResults\n ? getPhrase('heading', { studentName: anonymiseUserName(getUserOrAnonSession(studentResults, anonSessions), anonymiseUsers) })\n : '';\n const dataLoaded = !!interactive.data && !!results.data && !!config.data;\n\n return (\n <Popup\n title={popupTitle}\n showLoadingSpinner={!dataLoaded}\n closePopup={props.closePopup}\n size='lg'\n >\n {dataLoaded &&\n <StudentResponseList\n interactive={interactive.data}\n studentResults={studentResults}\n markedAnswers={markedAnswers}\n addMarkedAnswers={addMarkedAnswers}\n submitMarkedAnswers={submitMarkedAnswers}\n imageCdnUrl={config.data.imageCdnUrl}\n selectedInteractionId={props.interactionId}\n onClickClose={props.closePopup}\n anonymiseUsers={anonymiseUsers}\n reportsStyling={props.reportsStyling}\n anonSessions={anonSessions}\n />\n }\n </Popup>\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListFooterProps {\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n onClickClose: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListFooter(props: StudentResponseListFooterProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-end pt-3'>\n <div>\n {!props.showSubmitButtonSpinner &&\n <button className='btn btn-link' onClick={props.onClickClose}>\n {getPhrase('close')}\n </button>\n }\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip\n id='submitAnswers'\n title={getPhrase('demoOnly')}\n spanHack\n spanHackClassName='d-inline-flex'\n >\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n </div>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { ResultsSummary } from 'libs/shared/apps/analytics/interfaces/ResultsSummary';\nimport { SpinnerButton } from 'libs/shared/components/spinner-button/SpinnerButton';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { Interaction } from 'libs/shared/interfaces';\n\nconst namespace = 'interactives.studentResponseList';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface StudentResponseListHeaderProps {\n summary: ResultsSummary;\n interactionsToMark: Interaction[];\n markedAnswers: MarkedAnswerHash;\n onClickSubmit: () => void;\n showSubmitButtonSpinner: boolean;\n isDemo?: boolean;\n}\n\nexport function StudentResponseListHeader(props: StudentResponseListHeaderProps): JSX.Element {\n const numMarkedAnswers = Object.keys(props.markedAnswers).length;\n\n return (\n <div className='d-flex justify-content-between pb-3'>\n <div className='d-flex'>\n {!!props.summary.unanswered &&\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('unanswered')}</strong>\n {props.summary.unanswered}\n </div>\n }\n <div className='bg-light rounded p-2 me-2'>\n <strong className='me-2'>{getPhrase('score')}</strong>\n {props.summary.awaitingMarking\n ? <em>{getPhrase('pending')}</em>\n : `${Math.round(props.summary.percentCorrect * 100)}%`\n }\n </div>\n </div>\n {!!props.interactionsToMark.length && (\n <>\n {props.isDemo ? (\n <Tooltip id='submitAnswers' title={getPhrase('demoOnly')} spanHack>\n <button\n className='btn btn-outline-dark pointer-events-none'\n disabled={!numMarkedAnswers}\n >\n {getPhrase('submitAnswers')}\n </button>\n </Tooltip>\n ) : (\n <SpinnerButton\n variant='outline-dark'\n onClick={props.onClickSubmit}\n disabled={!numMarkedAnswers}\n showSpinner={props.showSubmitButtonSpinner}\n >\n {getPhrase('submitAnswers')}\n </SpinnerButton>\n )}\n </>\n )}\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"awaitingMarking\":\"MvGb5\"};","import React from 'react';\n\nimport { InteractionResponseItem } from 'libs/shared/apps/analytics/components/questions-list/interaction-response-item/InteractionResponseItem';\nimport { AnonSessions } from 'libs/shared/apps/analytics/hooks/UseAnonSessions';\nimport { MarkedAnswerHash } from 'libs/shared/apps/analytics/hooks/UseMarkAnswers';\nimport { anonymiseUserName, getUserOrAnonSession } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { getMarkedStatus, getStudentResultsSummary } from 'libs/shared/apps/analytics/utils/InteractiveUtils';\nimport { InteractionResponse } from 'libs/shared/components/interaction-response/InteractionResponse';\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveAnswerStatus } from 'libs/shared/enums/InteractiveAnswerStatus';\nimport { Interaction, Interactive, StudentAnswer, StudentResults } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\n\nimport { StudentResponseListFooter } from './StudentResponseListFooter';\nimport { StudentResponseListHeader } from './StudentResponseListHeader';\n\nimport styles from './student-response-list.scss';\n\nfunction getInteractionsToMark(\n interactions: Interaction[],\n studentResults: StudentResults\n): Interaction[] {\n return interactions.filter(i => {\n return InteractiveCorrectnessHelper.isInteractionCorrect(\n i,\n getStudentResult(studentResults)\n ) === InteractionCorrectness.AwaitingMarking;\n });\n}\n\n// eslint-disable-next-line rulesdir/require-view-title\nfunction useScrollSelectedInteractionIntoView(): React.MutableRefObject<HTMLLIElement> {\n const ref = React.useRef<HTMLLIElement>(null);\n const [ scrolled, setScrolled ] = React.useState(false);\n\n // Only scroll once\n React.useEffect(() => {\n if (!ref.current || scrolled)\n return;\n\n setScrolled(true);\n requestAnimationFrame(() => ref.current.scrollIntoView({ behavior: 'smooth', block: 'center' }));\n }, [ ref.current, scrolled ]);\n\n return ref;\n}\n\ninterface StudentResponseListProps {\n interactive: Interactive;\n markedAnswers: MarkedAnswerHash;\n studentResults: StudentResults;\n addMarkedAnswers: (answer: StudentAnswer[], status: InteractiveAnswerStatus) => void;\n submitMarkedAnswers: () => void;\n onClickClose: () => void;\n imageCdnUrl: string;\n selectedInteractionId?: string;\n anonymiseUsers: boolean;\n reportsStyling?: boolean;\n isDemo?: boolean;\n anonSessions?: AnonSessions;\n}\n\nexport function StudentResponseList(props: StudentResponseListProps): JSX.Element {\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n const selectedInteractionRef = useScrollSelectedInteractionIntoView();\n\n const summary = getStudentResultsSummary(props.interactive, props.studentResults);\n const interactions = getInteractions(props.interactive);\n const questionsToMark = getInteractionsToMark(interactions, props.studentResults);\n\n function onClickSubmit(): void {\n setShowSpinner(true);\n props.submitMarkedAnswers();\n }\n\n return (\n <>\n <StudentResponseListHeader\n summary={summary}\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n <ul className='list-unstyled'>\n {interactions.map((interaction, idx) => {\n const isSelected = interaction.id.toString() === props.selectedInteractionId?.toString();\n const markingRequired = questionsToMark.some(q => q.id === interaction.id);\n const anonymisedUserName = anonymiseUserName(\n getUserOrAnonSession(props.studentResults, props.anonSessions),\n props.anonymiseUsers\n );\n\n let className = 'p-2 mb-3 rounded';\n\n if (isSelected)\n className += ' border-2 border-info shadow';\n\n if (markingRequired)\n className += ` ${styles.awaitingMarking}`;\n else\n className += ' border';\n\n return (\n <li key={idx} className={className} ref={isSelected ? selectedInteractionRef : null}>\n <div className='d-flex mb-2'>\n <InteractionLabel\n interaction={interaction}\n iconClassName='flex-shrink-0'\n />\n </div>\n {props.reportsStyling ? (\n <InteractionResponse\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n className='bg-light ps-2'\n showFeedback\n reportsStyling\n responseComponentClass='mx-n2'\n />\n ) : (\n <InteractionResponseItem\n interaction={interaction}\n studentResults={props.studentResults}\n markedStatus={getMarkedStatus(interaction.id, props.studentResults, props.markedAnswers)}\n markInteraction={props.addMarkedAnswers}\n imageCdnUrl={props.imageCdnUrl}\n anonymisedUserName={anonymisedUserName}\n showFeedback\n />\n )}\n </li>\n );\n })}\n </ul>\n <StudentResponseListFooter\n interactionsToMark={questionsToMark}\n markedAnswers={props.markedAnswers}\n onClickSubmit={onClickSubmit}\n onClickClose={props.onClickClose}\n showSubmitButtonSpinner={showSpinner}\n isDemo={props.isDemo}\n />\n </>\n );\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nexport function getAnalyticsRequestKey(baseKey: string, filter: AnalyticsRequestFilter, sharerId?: string): string {\n let key = `${baseKey}:${filter.start}:${filter.end}`;\n\n const userIdKey = Array.isArray(filter.userId) ? filter.userId.sort().join(':') : filter.userId;\n const groupIdKey = Array.isArray(filter.groupId) ? filter.groupId.sort().join(':') : filter.groupId;\n\n if (userIdKey)\n key += `:${userIdKey}`;\n\n if (groupIdKey)\n key += `:${groupIdKey}`;\n\n if (sharerId)\n key += `:${sharerId}`;\n\n return key;\n}","import { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { ContextService } from 'libs/shared/services/ContextService';\n\ninterface UpdateParamsOptions extends Core.AppLinkOptions {\n merge?: boolean;\n keysToRemove?: string[]\n}\n\nexport const AppRouteHelper = {\n /**\n * Utility to update the params on the current appRoute.\n * \n * This is built on top of ContextService rather than build into AppLink\n * as we will generally only want to update params on appRoutes, not appLinks.\n */\n updateParams(params: HashObject, options?: UpdateParamsOptions): void {\n const { appLink } = ContextService.getCurrentRoute();\n\n let currentParams = typeof(appLink.params) === 'string'\n ? Core.LocationUtils.DeserializeQueryParams(appLink.params)\n : appLink.params as HashObject;\n\n if (options.keysToRemove)\n currentParams = ObjectHelper.omit(currentParams, options.keysToRemove);\n\n const updatedParams = options?.merge\n ? { ...currentParams, ...params }\n : params;\n\n const updatedAppLink = {\n ...appLink,\n params: updatedParams\n };\n\n /**\n * This prevents us pointlessly re-triggering if we're already on the right applink.\n */\n if (ObjectHelper.isEqual(appLink, updatedAppLink))\n return;\n \n Core.AppLinkHelper.trigger(updatedAppLink, ObjectHelper.omit(options, [ 'merge', 'keysToRemove' ]));\n }\n};"],"names":["DEFAULT_POLLING_INTERVAL","usePolling","callback","pollingInterval","pollingTrigger","setPollingTrigger","timeoutRef","t","current","window","setTimeout","clearTimeout","useAnonSessions","shareId","fetch","anonSessionsRequest","anonSessionsResponse","data","length","reduce","prev","sessionId","useFetchInteractiveResults","interactiveMetadataId","requestFilter","includePublicResults","currentUser","interactiveMetadata","interactive","interactiveId","shouldFetchResults","I","id","AnalyticsFilterHelper","getAudienceAppLinkParams","appLink","params","users","classrooms","classroomGroups","getParam","key","param","Array","isArray","audienceFilters","getDateRangeAppLinkParams","from","to","rangeName","dateRangeFilters","getPhrase","anonymiseUserName","user","shouldAnonymise","sessionName","seed","Math","floor","Date","getMinutes","dictionaries","separator","style","getAnonSession","anonSessions","fallback","getUserOrAnonSession","result","convertDateToUtcDateTimeString","date","utc","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","name","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getStartEndParams","dateRangePresetss","filterParams","getStartDate","getEndDate","presetRange","find","p","getPresetRangeByName","start","end","defaultRange","range","InteractiveStudentResultsView","props","anonymiseUsers","dateRangeAppLinkParams","results","config","closePopup","markedAnswers","addMarkedAnswers","submitMarkedAnswers","studentResults","students","s","userId","toString","popupTitle","studentName","dataLoaded","title","showLoadingSpinner","size","imageCdnUrl","selectedInteractionId","interactionId","onClickClose","reportsStyling","LanguageService","StudentResponseListFooter","numMarkedAnswers","Object","keys","className","showSubmitButtonSpinner","onClick","interactionsToMark","isDemo","Tooltip","spanHack","spanHackClassName","SpinnerButton","variant","onClickSubmit","showSpinner","StudentResponseListHeader","summary","unanswered","awaitingMarking","round","percentCorrect","StudentResponseList","ref","scrolled","setScrolled","setShowSpinner","selectedInteractionRef","requestAnimationFrame","scrollIntoView","behavior","block","interactions","questionsToMark","filter","i","InteractiveCorrectnessHelper","InteractionCorrectness","getInteractionsToMark","map","interaction","idx","isSelected","markingRequired","some","q","anonymisedUserName","InteractionLabel","iconClassName","InteractionResponse","markedStatus","markInteraction","showFeedback","responseComponentClass","InteractionResponseItem","ScoreThresholdDefaults","HIGH","MODERATE","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","useEffect","forEach","getAnalyticsRequestKey","baseKey","sharerId","userIdKey","sort","groupIdKey","groupId","AppRouteHelper","updateParams","options","currentParams","keysToRemove","updatedParams","merge","updatedAppLink"],"sourceRoot":""}