@clickview/lite 0.104.0-rc.6 → 0.104.0
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.
- package/dist/.vite/manifest.json +807 -806
- package/dist/bundles.json +1 -1
- package/dist/en.json +1 -1
- package/dist/scripts/{Dnz8CbEu.chunk.js → -QIG2ZHc.chunk.js} +3 -3
- package/dist/scripts/{Dnz8CbEu.chunk.js.map → -QIG2ZHc.chunk.js.map} +1 -1
- package/dist/scripts/{CEv1_bDW.chunk.js → -brFp4w1.chunk.js} +2 -2
- package/dist/scripts/{CEv1_bDW.chunk.js.map → -brFp4w1.chunk.js.map} +1 -1
- package/dist/scripts/{CX6c7KRp2.chunk.js → 0mx04bmJ2.chunk.js} +2 -2
- package/dist/scripts/{CX6c7KRp2.chunk.js.map → 0mx04bmJ2.chunk.js.map} +1 -1
- package/dist/scripts/{CMHxOVI7.chunk.js → 41LJfkjO.chunk.js} +2 -2
- package/dist/scripts/{CMHxOVI7.chunk.js.map → 41LJfkjO.chunk.js.map} +1 -1
- package/dist/scripts/{BBWnpWNB2.chunk.js → 7uvJMXC12.chunk.js} +2 -2
- package/dist/scripts/{BBWnpWNB2.chunk.js.map → 7uvJMXC12.chunk.js.map} +1 -1
- package/dist/scripts/{CaCm4N_d2.chunk.js → B-HfRX562.chunk.js} +2 -2
- package/dist/scripts/{CaCm4N_d2.chunk.js.map → B-HfRX562.chunk.js.map} +1 -1
- package/dist/scripts/{D9wxi5or2.chunk.js → B2_RD6Px2.chunk.js} +2 -2
- package/dist/scripts/{D9wxi5or2.chunk.js.map → B2_RD6Px2.chunk.js.map} +1 -1
- package/dist/scripts/{DSPMbDdF.chunk.js → B3_lC6bW.chunk.js} +2 -2
- package/dist/scripts/{DSPMbDdF.chunk.js.map → B3_lC6bW.chunk.js.map} +1 -1
- package/dist/scripts/{8JGe5Ug_2.chunk.js → B5GEXNkP2.chunk.js} +2 -2
- package/dist/scripts/{8JGe5Ug_2.chunk.js.map → B5GEXNkP2.chunk.js.map} +1 -1
- package/dist/scripts/{0Fek4oFk.chunk.js → BLE8DLAY.chunk.js} +2 -2
- package/dist/scripts/{0Fek4oFk.chunk.js.map → BLE8DLAY.chunk.js.map} +1 -1
- package/dist/scripts/{BgPye7Nd2.chunk.js → BRt-Kdnn2.chunk.js} +2 -2
- package/dist/scripts/{BgPye7Nd2.chunk.js.map → BRt-Kdnn2.chunk.js.map} +1 -1
- package/dist/scripts/BTWmC6pW.chunk.js +5 -0
- package/dist/scripts/BTWmC6pW.chunk.js.map +1 -0
- package/dist/scripts/{D3ncynN72.chunk.js → BVBpDZoT2.chunk.js} +3 -3
- package/dist/scripts/{D3ncynN72.chunk.js.map → BVBpDZoT2.chunk.js.map} +1 -1
- package/dist/scripts/{5PKjjI4Y.chunk.js → BapoiGsj.chunk.js} +2 -2
- package/dist/scripts/{5PKjjI4Y.chunk.js.map → BapoiGsj.chunk.js.map} +1 -1
- package/dist/scripts/{CNfmLVE82.chunk.js → Bc1JT5Y-2.chunk.js} +2 -2
- package/dist/scripts/{CNfmLVE82.chunk.js.map → Bc1JT5Y-2.chunk.js.map} +1 -1
- package/dist/scripts/{cDv6zuhh.chunk.js → BhE5KhcC.chunk.js} +2 -2
- package/dist/scripts/{cDv6zuhh.chunk.js.map → BhE5KhcC.chunk.js.map} +1 -1
- package/dist/scripts/{Bzk4AwVx2.chunk.js → BncgzKKQ2.chunk.js} +2 -2
- package/dist/scripts/{Bzk4AwVx2.chunk.js.map → BncgzKKQ2.chunk.js.map} +1 -1
- package/dist/scripts/{CV-fOLNI2.chunk.js → Bpf3Tyy12.chunk.js} +2 -2
- package/dist/scripts/{CV-fOLNI2.chunk.js.map → Bpf3Tyy12.chunk.js.map} +1 -1
- package/dist/scripts/{DPZnaz74.chunk.js → C1OiUBQI.chunk.js} +2 -2
- package/dist/scripts/{DPZnaz74.chunk.js.map → C1OiUBQI.chunk.js.map} +1 -1
- package/dist/scripts/{B1TqilLB.chunk.js → C6z8ii6C.chunk.js} +2 -2
- package/dist/scripts/{B1TqilLB.chunk.js.map → C6z8ii6C.chunk.js.map} +1 -1
- package/dist/scripts/{fMgBORUX.chunk.js → C8x-QH43.chunk.js} +2 -2
- package/dist/scripts/{fMgBORUX.chunk.js.map → C8x-QH43.chunk.js.map} +1 -1
- package/dist/scripts/{BiWUSyJr.chunk.js → CAkqvKfy.chunk.js} +2 -2
- package/dist/scripts/{BiWUSyJr.chunk.js.map → CAkqvKfy.chunk.js.map} +1 -1
- package/dist/scripts/{CjOMeOwb2.chunk.js → CGv0OFnc2.chunk.js} +2 -2
- package/dist/scripts/{CjOMeOwb2.chunk.js.map → CGv0OFnc2.chunk.js.map} +1 -1
- package/dist/scripts/{B82m7K0U.chunk.js → CJGWbJ4m.chunk.js} +2 -2
- package/dist/scripts/{B82m7K0U.chunk.js.map → CJGWbJ4m.chunk.js.map} +1 -1
- package/dist/scripts/{D-iyHqNw2.chunk.js → CLvImDXv2.chunk.js} +3 -3
- package/dist/scripts/{D-iyHqNw2.chunk.js.map → CLvImDXv2.chunk.js.map} +1 -1
- package/dist/scripts/{Cqq1N9xw.chunk.js → CM8248d7.chunk.js} +2 -2
- package/dist/scripts/{Cqq1N9xw.chunk.js.map → CM8248d7.chunk.js.map} +1 -1
- package/dist/scripts/Cr6TXzQQ2.chunk.js.map +1 -1
- package/dist/scripts/{B_TE5XUR2.chunk.js → CvilnM0u2.chunk.js} +2 -2
- package/dist/scripts/{B_TE5XUR2.chunk.js.map → CvilnM0u2.chunk.js.map} +1 -1
- package/dist/scripts/{AEOAlemi.chunk.js → Cwocc8uV.chunk.js} +2 -2
- package/dist/scripts/{AEOAlemi.chunk.js.map → Cwocc8uV.chunk.js.map} +1 -1
- package/dist/scripts/{Bld7iWR52.chunk.js → D-pn0sNx2.chunk.js} +2 -2
- package/dist/scripts/{Bld7iWR52.chunk.js.map → D-pn0sNx2.chunk.js.map} +1 -1
- package/dist/scripts/{Cyit3dMk.chunk.js → D78QEASE.chunk.js} +2 -2
- package/dist/scripts/{Cyit3dMk.chunk.js.map → D78QEASE.chunk.js.map} +1 -1
- package/dist/scripts/{Dtag-27K.chunk.js → DER8311r.chunk.js} +2 -2
- package/dist/scripts/{Dtag-27K.chunk.js.map → DER8311r.chunk.js.map} +1 -1
- package/dist/scripts/{CAD-W-lP.chunk.js → DFFJpTVB.chunk.js} +2 -2
- package/dist/scripts/{CAD-W-lP.chunk.js.map → DFFJpTVB.chunk.js.map} +1 -1
- package/dist/scripts/{CmnbQiBA.chunk.js → DSZaceCq.chunk.js} +2 -2
- package/dist/scripts/{CmnbQiBA.chunk.js.map → DSZaceCq.chunk.js.map} +1 -1
- package/dist/scripts/{CfNYFxJl2.chunk.js → D_1m0b_a2.chunk.js} +2 -2
- package/dist/scripts/{CfNYFxJl2.chunk.js.map → D_1m0b_a2.chunk.js.map} +1 -1
- package/dist/scripts/{-KvTbeQV.chunk.js → DhcRnxkp.chunk.js} +2 -2
- package/dist/scripts/{-KvTbeQV.chunk.js.map → DhcRnxkp.chunk.js.map} +1 -1
- package/dist/scripts/{DKDWcWxk.chunk.js → Dqn0sInF.chunk.js} +2 -2
- package/dist/scripts/{DKDWcWxk.chunk.js.map → Dqn0sInF.chunk.js.map} +1 -1
- package/dist/scripts/{DICsRDM42.chunk.js → Dz8KlJhf2.chunk.js} +2 -2
- package/dist/scripts/{DICsRDM42.chunk.js.map → Dz8KlJhf2.chunk.js.map} +1 -1
- package/dist/scripts/{D0b_r0MV.chunk.js → KjTtF4IH.chunk.js} +2 -2
- package/dist/scripts/{D0b_r0MV.chunk.js.map → KjTtF4IH.chunk.js.map} +1 -1
- package/dist/scripts/{CAs2Sere2.chunk.js → MW7W80HY2.chunk.js} +2 -2
- package/dist/scripts/{CAs2Sere2.chunk.js.map → MW7W80HY2.chunk.js.map} +1 -1
- package/dist/scripts/{CwFYdvvA.chunk.js → Okf3Hn0s.chunk.js} +2 -2
- package/dist/scripts/{CwFYdvvA.chunk.js.map → Okf3Hn0s.chunk.js.map} +1 -1
- package/dist/scripts/{Dt5731Ay.chunk.js → _lqYS5Jx.chunk.js} +2 -2
- package/dist/scripts/{Dt5731Ay.chunk.js.map → _lqYS5Jx.chunk.js.map} +1 -1
- package/dist/scripts/{app-DxHnJ6f2.js → app-H3wSQ-PR.js} +4 -4
- package/dist/scripts/{app-DxHnJ6f2.js.map → app-H3wSQ-PR.js.map} +1 -1
- package/dist/scripts/{Bkp6sdnZ2.chunk.js → dVOiGqhu2.chunk.js} +2 -2
- package/dist/scripts/{Bkp6sdnZ2.chunk.js.map → dVOiGqhu2.chunk.js.map} +1 -1
- package/dist/scripts/{B3AhKFfz.chunk.js → ftYw2FVB.chunk.js} +2 -2
- package/dist/scripts/{B3AhKFfz.chunk.js.map → ftYw2FVB.chunk.js.map} +1 -1
- package/dist/scripts/{DyE6EUDb.chunk.js → kjRiUKIL.chunk.js} +2 -2
- package/dist/scripts/{DyE6EUDb.chunk.js.map → kjRiUKIL.chunk.js.map} +1 -1
- package/dist/scripts/{B3y60nT5.chunk.js → pDWQ8Uj5.chunk.js} +2 -2
- package/dist/scripts/{B3y60nT5.chunk.js.map → pDWQ8Uj5.chunk.js.map} +1 -1
- package/dist/scripts/{BCqRKj1E2.chunk.js → s6NJOjzU2.chunk.js} +2 -2
- package/dist/scripts/{BCqRKj1E2.chunk.js.map → s6NJOjzU2.chunk.js.map} +1 -1
- package/package.json +1 -1
- package/dist/scripts/DCT6XY8t.chunk.js +0 -5
- package/dist/scripts/DCT6XY8t.chunk.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"-KvTbeQV.chunk.js","names":[],"sources":["../../../../libs/shared/src/apps/analytics/components/engagement-table/engagement-table.module.scss","../../../../libs/shared/src/apps/analytics/components/engagement-table/EngagementTableUtils.tsx","../../../../libs/shared/src/apps/analytics/components/engagement-table/EngagementTable.tsx","../../../../libs/shared/src/components/percentage-indicator/PartialPercentageIndicator.tsx","../../../../libs/shared/src/apps/analytics/components/insights/amount-watched/InsightAmountWatched.tsx","../../../../libs/shared/src/apps/analytics/utils/ChartColourUtils.ts","../../../../libs/shared/src/apps/analytics/utils/SharedUserActivityPieChartUtils.ts","../../../../libs/shared/src/apps/analytics/components/insights/total-views/InsightTotalViews.tsx","../../src/apps/my-shares/components/insights-heatmap/partial-loading/partial-insights-heatmap.module.scss","../../src/apps/my-shares/components/insights-heatmap/partial-loading/PartialInsightsHeatmap.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay-menu-item/engagement-overlay-menu-item.ts","../../../player/src/plugins/engagement-overlay-plugin/components/timepoint-interactions/timepoint-interactions.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay-chart-options.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay.ts","../../../player/src/plugins/engagement-overlay-plugin/engagement-overlay-plugin.ts","../../../player/src/plugins/interactive-plugin/interactive-seek-bar-plugin.ts","../../../player/src/players/reports/reports-player.ts","../../../player/src/react/ReportsPlayer.tsx","../../src/apps/my-shares/components/video-engagement-overlay/video-engagement-overlay.module.scss","../../src/apps/my-shares/components/video-engagement-overlay/VideoEngagementOverlay.tsx","../../src/apps/my-shares/components/insights-heatmap/insights-heatmap.module.scss","../../src/apps/my-shares/components/insights-heatmap/InsightsHeatmap.tsx"],"sourcesContent":[":local {\n .heatMap {\n height: 1rem;\n }\n\n // use avatar width\n .avatarContainer {\n width: 2rem;\n height: 2rem;\n }\n\n .cogIcon {\n cursor: pointer;\n color: $gray-900;\n line-height: 1;\n }\n}","import React from 'react';\nimport { Column, ColumnInstance, Row } from 'react-table';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EngagementHeatMap } from 'libs/shared/apps/analytics/components/engagement-heat-map/EngagementHeatMap';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { EngagementAvatar } from 'libs/shared/components/engagement-avatar/EngagementAvatar';\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { CogSvg } from 'libs/shared/images/svg/objects/CogSvg';\nimport { Engagement, EngagementType } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport styles from './engagement-table.module.scss';\n\nconst namespace = 'shared.engagementTable';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst EMPTY_ENGAGEMENT: Partial<Engagement> = {\n heatMap: [],\n engagementRate: 0,\n viewCount: 0\n};\n\ninterface CellWrapperProps {\n className?: string;\n}\n\nfunction CellWrapper(props: React.PropsWithChildren<CellWrapperProps>): JSX.Element {\n return (\n <div className={`${props.className ?? ''}`}>\n {props.children}\n </div>\n );\n}\n\ninterface HeaderCellProps {\n column: ColumnInstance<EngagementTableData>;\n phraseKey: string;\n}\n\nfunction HeaderCell(props: HeaderCellProps): JSX.Element {\n return (\n <CellWrapper className={`d-inline-block ${props.column.isSorted ? 'fw-bold' : ''}`}>\n {getPhrase(props.phraseKey)}\n </CellWrapper>\n );\n}\n\nexport interface EngagementTableData extends Engagement {\n user: AnonUser;\n}\n\nfunction getMaxHeatMapValue(engagement: Engagement[]): number {\n let max = 0;\n\n engagement.forEach(e => {\n const localMax = Math.max(...e.heatMap);\n\n if (localMax > max)\n max = localMax;\n });\n\n return max;\n}\n\n/**\n * Resolves the engagement type, inferring 'anon' for legacy data\n * where type is not set but userId is null.\n */\nfunction resolveEngagementType(engagement: Engagement): EngagementType | undefined {\n if (engagement.type) return engagement.type;\n if (engagement.userId === null || engagement.userId === undefined) return 'anon';\n return undefined;\n}\n\nfunction getEngagementTypeLabel(type: EngagementType): string | null {\n switch (type) {\n case 'student-reach':\n return getPhrase('classroomViews');\n case 'anon':\n return getPhrase('anonymous');\n default:\n return null;\n }\n}\n\nfunction getUsersName(user: AnonUser, anonymiseUsers: boolean, type?: EngagementType) {\n if (type) {\n const label = getEngagementTypeLabel(type);\n if (label && !user?.name) return { name: label, surname: '' };\n }\n\n const fullName = anonymiseUserName(user, anonymiseUsers);\n const nameParts = fullName.split(' ').filter(n => !!n);\n\n return {\n name: nameParts[0],\n surname: nameParts.slice(1).join(' ')\n };\n}\n\ninterface EngagementColumnProps {\n engagement: Engagement[];\n imageCdnUrl: string;\n anonymiseUsers: boolean;\n showSeparateNameColumns?: boolean;\n classroomViewsAppLink?: Core.AppLink;\n classroomViewsTooltip?: string;\n}\n\nexport function useGetColumns(props: EngagementColumnProps): Column<EngagementTableData>[] {\n return React.useMemo(() => {\n const maxHeatMapValue = getMaxHeatMapValue(props.engagement);\n\n const nameColumns: Column<EngagementTableData>[] = props.showSeparateNameColumns ? [\n {\n id: 'firstName',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='firstName' />,\n accessor: 'user',\n width: 63,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const { name: nameA } = getUsersName(rowA.values.firstName, props.anonymiseUsers, typeA);\n const { name: nameB } = getUsersName(rowB.values.firstName, props.anonymiseUsers, typeB);\n return nameA > nameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const effectiveType = resolveEngagementType(original);\n const { name, surname } = getUsersName(value, props.anonymiseUsers, effectiveType);\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className={styles.avatarContainer}>\n <EngagementAvatar\n type={effectiveType}\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(name, surname)}\n imageUrl={!props.anonymiseUsers && !effectiveType && value?.avatar?.url}\n anonymiseUsers={props.anonymiseUsers}\n />\n </span>\n <span className='ms-2 clamp-1'>\n {name}\n </span>\n {effectiveType === 'student-reach' && props.classroomViewsAppLink &&\n <IconButton\n customSize\n svg={CogSvg}\n svgSize={SvgContainerSize.Standard}\n appLink={props.classroomViewsAppLink}\n className={styles.cogIcon}\n tooltip={props.classroomViewsTooltip}\n tooltipTrigger={['hover']}\n ariaLabel={props.classroomViewsTooltip}\n />\n }\n </CellWrapper>\n );\n }\n },\n {\n id: 'surname',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='surname' />,\n accessor: 'user',\n width: 68,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const { surname: surnameA } = getUsersName(rowA.values.surname, props.anonymiseUsers, typeA);\n const { surname: surnameB } = getUsersName(rowB.values.surname, props.anonymiseUsers, typeB);\n return surnameA > surnameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const { surname } = getUsersName(value, props.anonymiseUsers, resolveEngagementType(original));\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className='clamp-1'>\n {surname || ''}\n </span>\n </CellWrapper>\n );\n }\n }\n ] : [\n {\n id: 'name',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='name' />,\n accessor: 'user',\n width: 22,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const nameA = typeA ?\n getEngagementTypeLabel(typeA) :\n anonymiseUserName(rowA.values.user, props.anonymiseUsers);\n const nameB = typeB ?\n getEngagementTypeLabel(typeB) :\n anonymiseUserName(rowB.values.user, props.anonymiseUsers);\n\n return nameA > nameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const effectiveType = resolveEngagementType(original);\n const { name, surname } = getUsersName(value, props.anonymiseUsers, effectiveType);\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className={styles.avatarContainer}>\n <EngagementAvatar\n type={effectiveType}\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(name, surname)}\n imageUrl={!props.anonymiseUsers && !effectiveType && value?.avatar?.url}\n anonymiseUsers={props.anonymiseUsers}\n />\n </span>\n <span className='ms-2 clamp-1 me-1'>\n {name} {surname}\n </span>\n {effectiveType === 'student-reach' && props.classroomViewsAppLink &&\n <IconButton\n customSize\n svg={CogSvg}\n svgSize={SvgContainerSize.Standard}\n appLink={props.classroomViewsAppLink}\n className={styles.cogIcon}\n tooltip={props.classroomViewsTooltip}\n tooltipTrigger={['hover']}\n ariaLabel={props.classroomViewsTooltip}\n />\n }\n </CellWrapper>\n );\n }\n }\n ];\n\n return [\n ...nameColumns,\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='views' />,\n accessor: 'viewCount',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 47 : 15,\n sortType: 'basic',\n sortDescFirst: true,\n Cell: ({ value }) => (\n <CellWrapper className='d-flex align-items-center h-100'>\n <div>{value}</div>\n </CellWrapper>\n )\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='engagement' />,\n accessor: 'engagementRate',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 79 : 20,\n sortDescFirst: true,\n Cell: ({ value }) => (\n <CellWrapper className='w-33'>\n <PercentageIndicator\n percentage={value}\n layout={PercentageIndicatorLayout.LabelBefore}\n />\n </CellWrapper>\n )\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='heatMap' />,\n accessor: 'heatMap',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 230 : 48,\n disableSortBy: true,\n Cell: ({ row: { original } }) => (\n <CellWrapper className='d-flex align-items-center h-100'>\n <EngagementHeatMap\n engagement={original}\n max={maxHeatMapValue}\n className={`${styles.heatMap} flex-grow-1`}\n />\n </CellWrapper>\n )\n }\n ];\n }, [ props.anonymiseUsers, props.showSeparateNameColumns ]);\n}\n\nexport function useGetTableData(\n engagement: Engagement[],\n users: AnonUser[],\n classroomStudents?: AnonUser[]\n): EngagementTableData[] {\n return React.useMemo(() => {\n const data: EngagementTableData[] = [];\n\n const userIdSet = new Set<string>();\n engagement?.forEach(e => {\n const user = users?.find(u => {\n if (u.id && u.id === e.userId) {\n userIdSet.add(u.id);\n return true;\n }\n\n if (u.sessionId && u.sessionId === e.sessionId)\n return true;\n\n return false;\n });\n\n data.push({ ...e, user });\n });\n\n if (classroomStudents?.length) {\n const students = classroomStudents\n .filter(s => !userIdSet.has(s.id))\n .map(user => ({ ...EMPTY_ENGAGEMENT, userId: user.id, user } as EngagementTableData));\n data.push(...students);\n }\n\n return data;\n }, [ engagement, users, classroomStudents ]);\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { Table, TableTheme } from 'libs/shared/components/table/Table';\nimport { Engagement } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\n\nimport { useGetColumns, useGetTableData } from './EngagementTableUtils';\n\nconst theme: TableTheme = {\n table: 'bg-white rounded px-0',\n header: 'border-bottom',\n headerCell: 'm-3',\n cell: 'mx-3 my-2'\n};\n\ninterface EngagementTableProps {\n engagement: Engagement[];\n imageCdnUrl: string;\n users?: AnonUser[];\n classroomStudents?: AnonUser[];\n anonymiseUsers: boolean;\n border?: boolean;\n enableSort?: boolean;\n showSeparateNameColumns?: boolean;\n classroomViewsAppLink?: Core.AppLink;\n classroomViewsTooltip?: string;\n}\n\nexport function EngagementTable(props: EngagementTableProps): JSX.Element {\n const columns = useGetColumns({\n engagement: props.engagement,\n imageCdnUrl: props.imageCdnUrl,\n anonymiseUsers: props.anonymiseUsers,\n showSeparateNameColumns: props.showSeparateNameColumns,\n classroomViewsAppLink: props.classroomViewsAppLink,\n classroomViewsTooltip: props.classroomViewsTooltip\n });\n\n const data = useGetTableData(props.engagement, props.users, props.classroomStudents);\n\n if (!data.length)\n return <></>;\n\n return (\n <Table\n columns={columns}\n data={data}\n theme={{\n ...theme,\n table: props.border ? `${theme.table} border` : theme.table\n }}\n enableSort={props.enableSort}\n />\n );\n}\n","import React from 'react';\n\nimport { PercentageIndicator, PercentageIndicatorLayout } from './PercentageIndicator';\n\ninterface PartialPercentageIndicatorProps {\n layout: PercentageIndicatorLayout;\n className?: string;\n}\n\nexport function PartialPercentageIndicator(props: PartialPercentageIndicatorProps): JSX.Element {\n return (\n <PercentageIndicator\n layout={props.layout}\n className={props.className}\n percentage={0}\n customLabel='--%'\n />\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { getEngagementRate } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { PartialPercentageIndicator } from 'libs/shared/components/percentage-indicator/PartialPercentageIndicator';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { TimerSvg } from 'libs/shared/images/svg/status/TimerSvg';\nimport { Engagement } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.insightAmountWatched';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightAmountWatchedProps {\n engagement: Engagement[];\n}\n\nexport function InsightAmountWatched(props: InsightAmountWatchedProps) {\n const engagementRate = getEngagementRate(props.engagement);\n const percentage = Math.round(engagementRate * 100);\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svg={TimerSvg}\n svgClassName='bg-light-green text-green'\n >\n <div className='d-flex flex-column align-items-center my-auto gap-2'>\n {!!props.engagement &&\n <>\n <PercentageIndicator\n percentage={engagementRate}\n layout={PercentageIndicatorLayout.LabelInside}\n />\n <p className='text-center'>\n {typeof engagementRate === 'number' ?\n <Text namespace={namespace} phrase='everyoneWatched' options={{ percentage }} /> :\n <Text namespace={namespace} phrase='notWatched' />\n }\n </p>\n </>\n }\n {!props.engagement &&\n <>\n <PartialPercentageIndicator layout={PercentageIndicatorLayout.LabelInside} />\n </>\n }\n </div>\n </InsightCard>\n );\n}\n","const CHART_COLOURS = [\n '#FF9300', // Pizazz\n '#38A2E8', // Picton Blue\n '#7A76E8', // Portage\n '#B679C7', // East Side\n '#F7847B', // Froly\n '#D9584F', // Red (Not in the Primary palette)\n '#FFCD52', // Yellow (Not in the Primary Palette)\n '#5DC786', // Emerald\n '#40BCC3', // Perolous\n '#40C2BB' // Puerto rico\n];\n\nexport function mixinSeriesColours<T>(data: T[]): T[] {\n return data.map((d, idx) => ({\n ...d,\n color: CHART_COLOURS[idx % CHART_COLOURS.length]\n }));\n}\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { HashObject } from 'libs/analytics/interfaces';\n\nimport { BaseAnalyticsEventResponse, GroupedAnalyticsCount } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { UnionEventResponse } from 'libs/shared/apps/analytics/interfaces/UnionEvent';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { mixinSeriesColours } from 'libs/shared/apps/analytics/utils/ChartColourUtils';\n\ntype EventResponseGroupByAttributes = keyof Pick<VideoViewEventResponse, 'contentTypeCount'> |\n keyof Pick<BaseAnalyticsEventResponse, 'userTypeCount' | 'yearGroupCount'>;\n\nexport function groupEvents(\n events: UnionEventResponse,\n groupBy: EventResponseGroupByAttributes,\n groupsToOmit?: string[],\n getSeriesName?: (group: string) => string\n): Highcharts.PointOptionsObject[] {\n const groups: HashObject<number> = {};\n\n const eventCounts = events[groupBy as keyof UnionEventResponse] as GroupedAnalyticsCount[];\n\n eventCounts?.forEach(ev => {\n const name = ev.name || 'Unknown';\n\n if (!name || groupsToOmit?.includes(name.toLowerCase()))\n return;\n\n groups[name] = groups[name] ?? 0;\n groups[name] += ev.count;\n });\n\n return mixinSeriesColours(ArrayHelper.sortBy(Object.keys(groups).map(group => ({\n name: getSeriesName ? getSeriesName(group) : group,\n y: groups[group],\n type: 'pie'\n })), 'name'));\n}\n\nexport function sortByYearGroup(data: Highcharts.PointOptionsObject[]) {\n const staffIndex = data.findIndex(group => group.name === 'Staff');\n\n // Move Staff to last index\n if (staffIndex > -1) {\n const [staffObject] = data.splice(staffIndex, 1);\n\n data.push(staffObject);\n }\n return data.sort((a, b) => {\n const numA = parseInt((a.name as string).match(/\\d+/)?.[0]);\n const numB = parseInt((b.name as string).match(/\\d+/)?.[0]);\n return numA - numB;\n });\n}\n\nexport function getTotalEventCount(data?: Highcharts.PointOptionsObject[]): number | null {\n return data?.reduce((a, b) => a + b.y, 0) ?? null;\n}\n","import React from 'react';\nimport Highcharts from 'highcharts';\nimport { HighchartsReact } from 'highcharts-react-official';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { CHART_FONT_STYLES } from 'libs/shared/apps/analytics/constants/ChartStyles';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { getTotalEventCount, groupEvents, sortByYearGroup } from 'libs/shared/apps/analytics/utils/SharedUserActivityPieChartUtils';\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { VisibleOnSvg } from 'libs/shared/images/svg/actions/VisibleOnSvg';\n\nconst namespace = 'shared.insightTotalViews';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction mapUserTypeToChartLabel(type: string): string {\n if (type === 'Unknown')\n return getPhrase('anon');\n return type;\n}\n\nconst STATIC_CHART_OPTIONS: Highcharts.Options = {\n title: {\n text: null\n },\n credits: {\n enabled: false\n },\n chart: {\n backgroundColor: 'transparent',\n spacing: [ 0, 0, 0, 0 ]\n },\n legend: {\n itemStyle: CHART_FONT_STYLES,\n itemDistance: 8\n },\n plotOptions: {\n pie: {\n allowPointSelect: true,\n cursor: 'pointer',\n dataLabels: {\n enabled: false\n },\n showInLegend: true,\n borderWidth: 1,\n borderColor: '#ffffff',\n borderRadius: 0,\n size: '80%'\n }\n }\n};\n\ninterface InsightTotalViewsProps {\n events: VideoViewEventResponse;\n emptyStateImage: string;\n hideStaffResults: boolean;\n}\n\nexport function InsightTotalViews(props: InsightTotalViewsProps) {\n const grouped = groupEvents(\n props.events,\n 'yearGroupCount',\n props.hideStaffResults ? ['staff'] : [],\n mapUserTypeToChartLabel\n );\n const chartData = sortByYearGroup(grouped);\n const totalViews = getTotalEventCount(chartData);\n\n function getChartOptions(\n data: Highcharts.PointOptionsObject[]\n ): Highcharts.Options {\n return {\n ...STATIC_CHART_OPTIONS,\n series: [{\n type: 'pie',\n name: getPhrase('title'),\n data\n }]\n };\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n // Replace with ultra marine + light colour\n svgClassName='bg-light-blue text-blue'\n // Add visibility icon \n svg={VisibleOnSvg}\n >\n {chartData?.length ? (\n <>\n <p className='mb-0'><Text namespace={namespace} phrase='totalViews' options={{ totalViews }} /></p>\n\n <div className='d-flex justify-content-center h-75'>\n <HighchartsReact\n highcharts={Highcharts}\n options={getChartOptions(chartData)}\n containerProps={{\n className: `w-100`\n }}\n />\n </div>\n </>\n ) : (\n <EmptyState className='pt-0 my-auto'>\n <EmptyState.Image src={props.emptyStateImage} className='w-75 h-auto'></EmptyState.Image>\n <EmptyState.Heading className='h4'><Text namespace={namespace} phrase='noViews' /></EmptyState.Heading>\n <EmptyState.Info className='w-100'><Text namespace={namespace} phrase='notWatched' /></EmptyState.Info>\n </EmptyState>\n )}\n </InsightCard>\n );\n}\n",":local {\n .partialInsights {\n height: 21.5rem;\n }\n\n .videoContainer {\n width: 44%;\n }\n}","import React from 'react';\n\nimport styles from './partial-insights-heatmap.module.scss';\n\nexport function PartialInsightsHeatmap() {\n return (\n <div>\n <div className='row g-3 mb-3'>\n <div className='col'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n <div className='col'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n <div className={styles.videoContainer}>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n </div>\n\n <div className='row g-3 mb-5'>\n <div className='col-12'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n </div>\n </div>\n );\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface EngagementOverlayMenuItemOptions extends videojs.MenuItemOptions {\n overlayVisible: boolean;\n}\n\nexport class EngagementOverlayMenuItem extends MenuItem {\n private toggleEl: Element;\n private overlayVisible: boolean;\n\n /**\n * Because we want to bind our listener in createEl\n * and createEl runs in super. We store if we've bounud\n * our handler, so we only call bind once and \n * the call to removeEventListener will still work\n */\n private handlerBound: boolean;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayMenuItemOptions) {\n super(player, options);\n\n this.overlayVisible = options.overlayVisible;\n this.toggle(this.overlayVisible);\n }\n\n public handleToggle(): void {\n this.toggle(!this.overlayVisible);\n }\n\n private toggle(state: boolean): void {\n state ? this.toggleOn() : this.toggleOff();\n }\n\n private toggleOn(): void {\n videojs.dom.addClass(this.toggleEl, 'on');\n this.overlayVisible = true;\n this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible);\n this.player().addClass('cv-reports-player-overlay-visible');\n }\n\n private toggleOff(): void {\n videojs.dom.removeClass(this.toggleEl, 'on');\n this.overlayVisible = false;\n this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible);\n this.player().removeClass('cv-reports-player-overlay-visible');\n }\n\n /**\n * Because we extend MenuItem which will close the menu by default\n * we need to halt the event propogation here\n */\n public handleClick(event: videojs.EventTarget.Event): void {\n event.stopImmediatePropagation();\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): HTMLLIElement {\n /**\n * Bind our event listener only once\n * see the comment where handlerBound is defined\n */\n if (!this.handlerBound) {\n this.handleToggle = this.handleToggle.bind(this);\n this.handlerBound = true;\n }\n\n if (this.toggleEl)\n this.toggleEl.removeEventListener('click', this.handleToggle);\n\n this.toggleEl = videojs.dom.createEl('div', {\n className: `custom-toggle custom-toggle-info toggle-option float-end`,\n innerHTML: '<span class=\"handle\"></span></div>'\n });\n this.toggleEl.addEventListener('click', this.handleToggle);\n\n const innerHTML = `\n <span class=\"vjs-menu-item-text\">Heat Map</span>\n <span class=\"cv-toggle-container\"></span>`;\n\n const el = super.createEl(tagName, {\n className: 'vjs-menu-item cv-cog-menu-item',\n innerHTML\n }, attributes);\n\n /**\n * Indexing into the child this way is only safe to do because\n * we know that the el only has two children\n */\n el.children[1].appendChild(this.toggleEl);\n\n return el;\n }\n}\n\nvideojs.registerComponent('EngagementOverlayMenuItem', EngagementOverlayMenuItem);\n","import React from 'react';\n\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { Interactive } from 'libs/shared/interfaces';\n\nconst MAX_INTERACTIONS_TO_SHOW = 3;\n\ninterface TimepointInteractionsProps {\n interactive: Interactive;\n time: number;\n}\n\nexport function TimepointInteractions(props: TimepointInteractionsProps): JSX.Element {\n const timepoint = props.interactive.timepoints.find(t => {\n const timepointTime = t.visibleAt / 1000;\n \n return Math.floor(props.time) === Math.floor(timepointTime)\n || Math.ceil(props.time) === Math.ceil(timepointTime);\n });\n\n if (!timepoint?.interactions?.length)\n return <></>;\n\n const interactions = timepoint.interactions.length > MAX_INTERACTIONS_TO_SHOW ?\n timepoint.interactions.slice(0, MAX_INTERACTIONS_TO_SHOW - 1) :\n timepoint.interactions;\n\n const hiddenInteractions = timepoint.interactions.length - interactions.length;\n\n return (\n <div className='d-flex justify-content-end ms-2'>\n {interactions.map((i, idx) => (\n <InteractionLabel\n key={idx}\n interaction={i}\n showQuestion={false}\n iconClassName='ms-1'\n />\n ))}\n {!!hiddenInteractions &&\n <div\n className={'interaction-type-icon d-flex justify-content-center' +\n ' align-items-center border border-dark text-body ms-1'}\n >\n {`+${hiddenInteractions}`}\n </div>\n }\n </div>\n );\n}\n","import React from 'react';\nimport { renderToStaticMarkup } from 'react-dom/server';\nimport Highcharts from 'highcharts';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { TimepointInteractions } from 'projects/player/plugins/engagement-overlay-plugin/components/timepoint-interactions/timepoint-interactions';\nimport { formatTime } from 'projects/player/utils/formatTime';\n\nexport const STATIC_CHART_OPTIONS: Highcharts.Options = {\n title: {\n text: null\n },\n xAxis: {\n visible: false,\n minPadding: 0,\n maxPadding: 0\n },\n legend: {\n enabled: false\n },\n credits: {\n enabled: false\n },\n defs: {\n gradient: ({\n tagName: 'linearGradient',\n id: 'area-gradient',\n x1: 0,\n y1: 1,\n x2: 0,\n y2: 0,\n children: [\n ({\n tagName: 'stop',\n offset: 0\n } as Highcharts.ASTNode),\n ({\n tagName: 'stop',\n offset: 1\n } as Highcharts.ASTNode)\n ]\n } as Highcharts.ASTNode)\n }\n};\n\nexport function getChartOptions(width: number, height: number): Highcharts.ChartOptions {\n return {\n styledMode: true,\n spacing: [ 15, 0, 0, 0 ],\n width,\n height\n };\n}\n\nexport function getYAxisChartOptions(heatMap: number[]): Highcharts.YAxisOptions {\n const maxValue = Math.max(...heatMap);\n\n return {\n /**\n * To prevent max values from being cut off, we pad them relative to the chart scale.\n */\n max: maxValue * 1.05,\n min: 0,\n minPadding: 0,\n maxPadding: 0,\n allowDecimals: true,\n startOnTick: false,\n endOnTick: false,\n visible: false\n };\n}\n\nexport function getTooltipOptions(interactive?: Interactive): Highcharts.TooltipOptions {\n return {\n formatter: function () {\n const timepointInteractionsHtml = interactive ?\n getTimepointInteractionsHtml(interactive, this.x) :\n '';\n\n return (\n '<div class=\"cv-engagement-tooltip bg-white rounded\">' +\n '<div class=\"d-flex justify-content-between\">' +\n `<strong>${formatTime(this.x)}</strong>` +\n `${timepointInteractionsHtml}` +\n '</div>' +\n '<div class=\"d-flex justify-content-between rounded bg-light cv-view-count-container\">' +\n `<strong>Views</strong> <span class=\"cv-view-count\">${this.y}</span>` +\n '</div>' +\n '</div>'\n );\n },\n positioner: function (\n labelWidth: number,\n labelHeight: number,\n point: Highcharts.TooltipPositionerPointObject\n ) {\n const minX = 0;\n const maxX = this.chart.plotWidth - labelWidth;\n const x = point.plotX - labelWidth / 2;\n \n return {\n // Clamp x between min and max\n x: Math.min(Math.max(x, minX), maxX),\n y: this.chart.plotTop\n };\n },\n useHTML: true,\n padding: 0\n };\n}\n\nexport function getPlotOptions(moveTimepointIndicator: (x: number | null) => void): Highcharts.PlotOptions {\n return {\n area: {\n point: {\n events: {\n mouseOver: function () {\n moveTimepointIndicator(this.x);\n },\n mouseOut: function () {\n moveTimepointIndicator(null);\n }\n }\n }\n },\n series: {\n marker: {\n enabled: false\n }\n }\n };\n}\n\nfunction getTimepointInteractionsHtml(interactive: Interactive, time: number): string {\n return renderToStaticMarkup(\n <TimepointInteractions time={time} interactive={interactive} />\n );\n}\n","import Highcharts from 'highcharts';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport {\n getChartOptions,\n getPlotOptions,\n getTooltipOptions,\n getYAxisChartOptions,\n STATIC_CHART_OPTIONS\n} from './engagement-overlay-chart-options';\n\nimport './engagement-overlay.scss';\n\nconst Component = videojs.getComponent('Component');\n\nHighcharts.AST.allowedTags.push('g');\nHighcharts.AST.allowedAttributes.push('viewBox', 'transform');\n\ninterface ChartDimensions {\n width: number;\n height: number;\n}\n\ninterface EngagementOverlayOptions extends videojs.ComponentOptions {\n heatMap: number[];\n interactive?: Interactive;\n onTimepointHover?: (time: number | null) => void;\n}\n\nexport class EngagementOverlay extends Component {\n public options_: EngagementOverlayOptions;\n private chart: Highcharts.Chart;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayOptions) {\n super(player, options);\n\n this.initialize();\n this.bindListeners();\n }\n\n public initialize(): void {\n this.player().ready(() => this.buildChart());\n }\n\n public buildCSSClass(): string {\n return 'cv-engagement-overlay';\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const innerHTML = '<div class=\"cv-engagement-chart\"></div>' +\n '<div class=\"cv-engagement-timepoint-indicator\"></div>';\n\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass(),\n innerHTML\n }, attributes);\n }\n\n public toggleChart(show: boolean): void {\n if (show)\n this.buildChart();\n else\n this.destroyChart();\n }\n\n private bindListeners(): void {\n this.handleClick = this.handleClick.bind(this);\n this.resizeChart = this.resizeChart.bind(this);\n\n this.player().on('playerresize', this.resizeChart);\n\n this.on(this.el(), 'mouseup', this.handleClick);\n\n this.player().on('dispose', () => {\n this.player().off('playerresize', this.resizeChart);\n\n this.off(this.el(), 'mouseup', this.handleClick);\n });\n }\n\n private handleClick(event: videojs.EventTarget.Event): void {\n if (!videojs.dom.isSingleLeftClick(event))\n return;\n\n if (this.player().paused()) {\n this.player().play();\n return;\n }\n\n this.player().pause();\n }\n\n private buildChart(): void {\n if (this.chart)\n return;\n\n const chartDimensions = this.getChartDimensions();\n\n /**\n * The dimensions calculation relies on the control bar and progress control\n * being visible, so if it isn't, we wait for the play event.\n */\n if (!chartDimensions) {\n this.player().one('play', () => this.buildChart());\n return;\n }\n\n const container: HTMLElement = this.el().querySelector('.cv-engagement-chart');\n\n this.chart = Highcharts.chart(container, this.getHighchartOptions(chartDimensions));\n }\n\n private resizeChart(): void {\n const chartDimensions = this.getChartDimensions();\n\n if (!this.chart || !chartDimensions)\n return;\n\n this.chart.setSize(chartDimensions.width, chartDimensions.height);\n }\n\n private destroyChart(): void {\n this.chart?.destroy();\n this.chart = null;\n }\n\n private getChartDimensions(): ChartDimensions {\n const collapserator = this.player().getChild('collapserator');\n const collapseratorHeight = collapserator?.currentHeight();\n\n const width = this.el().clientWidth;\n\n if (!collapseratorHeight || !width)\n return null;\n\n const { height } = this.player().currentDimensions();\n \n return {\n width,\n height: height - collapseratorHeight\n };\n }\n\n private getHighchartOptions({ width, height }: ChartDimensions): Highcharts.Options {\n return {\n ...STATIC_CHART_OPTIONS,\n chart: getChartOptions(width, height),\n yAxis: getYAxisChartOptions(this.options_.heatMap),\n tooltip: getTooltipOptions(this.options_.interactive),\n plotOptions: getPlotOptions(this.moveTimepointIndicator.bind(this)),\n series: [{\n type: 'area',\n data: this.options_.heatMap\n }]\n };\n }\n\n private moveTimepointIndicator(x: number | null): void {\n if (this.options_.onTimepointHover)\n this.options_.onTimepointHover(x);\n\n const indicator: HTMLDivElement = this.el().querySelector('.cv-engagement-timepoint-indicator');\n\n if (x === null) {\n videojs.dom.removeClass(indicator, 'cv-engagement-timepoint-indicator-visible');\n return;\n }\n\n videojs.dom.addClass(indicator, 'cv-engagement-timepoint-indicator-visible');\n indicator.style.left = `${x / this.options_.heatMap.length * 100}%`;\n }\n}\n\nvideojs.registerComponent('EngagementOverlay', EngagementOverlay);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { CogButton } from 'projects/player/components/cog-button/cog-button';\nimport { EngagementOverlay } from 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay';\nimport { EngagementOverlayMenuItem } from 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay-menu-item/engagement-overlay-menu-item';\n\nimport 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface EngagementOverlayPluginOptions {\n heatMap: number[];\n interactive?: Interactive;\n onTimepointHover?: (time: number | null) => void;\n}\n\nclass EngagementOverlayPlugin extends Plugin {\n private options: EngagementOverlayPluginOptions;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => {\n this.initialize();\n });\n }\n \n private initialize(): void {\n if (!this.hasHeatMapData())\n return;\n\n this.player.addChild('engagementOverlay', {\n heatMap: this.options.heatMap,\n interactive: this.options.interactive,\n onTimepointHover: this.options.onTimepointHover\n });\n\n /**\n * Check additionalItemOrder in cog-button.ts if you need to change the order. - Sha\n */\n const cogButton = this.player.getChild('collapserator')?.getChild('cogButton') as CogButton;\n cogButton.addItem({\n ctor: EngagementOverlayMenuItem,\n name: 'EngagementOverlayMenuItem',\n options: { overlayVisible: true }\n });\n }\n\n public toggleOverlay(show: boolean): void {\n const engagementOverlay = this.player.getChild('engagementOverlay') as EngagementOverlay;\n engagementOverlay?.toggleChart(show);\n }\n\n private hasHeatMapData(): boolean {\n return this.options.heatMap?.reduce((acc, val) => acc + val, 0) > 0;\n }\n}\n\nvideojs.registerPlugin('engagementOverlayPlugin', EngagementOverlayPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n engagementOverlayPlugin(options?: EngagementOverlayPluginOptions): EngagementOverlayPlugin;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { InteractiveBarItems } from 'projects/player/plugins/interactive-plugin/components/seek-bar/interactive-bar-items';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nimport './interactive-plugin-styles.scss';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface InteractiveSeekBarPluginOptions {\n interactive: Interactive;\n}\n\n/**\n * This plugin will just render the interactive seek bar (i.e. just the interaction markers).\n * The user won't be able to interact with any of the interactions.\n * Currently this is just used in reports-player\n */\nclass InteractiveSeekBarPlugin extends Plugin {\n private options: InteractiveSeekBarPluginOptions;\n\n constructor(player: VideoJsPlayer, options: InteractiveSeekBarPluginOptions) {\n super(player);\n\n this.options = options;\n\n this.player.one('loadedmetadata', () => this.player.ready(this.initialize.bind(this)));\n }\n\n private initialize(): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n TrackHelper.useMetadataTrack(this.player, 'interactive', this.onTrackLoaded.bind(this));\n\n this.player.addClass('cv-interactive-plugin');\n }\n\n private onTrackLoaded(track: TextTrack): void {\n this.addChildren(track);\n }\n\n private addChildren(track: TextTrack): void {\n const seekBar = this.player.controlBar.getChild('progressControl').getChild('SeekBar');\n\n seekBar.addChild(new InteractiveBarItems(this.player, {\n interactive: this.options.interactive,\n track\n }));\n }\n}\n\nvideojs.registerPlugin('interactiveSeekBarPlugin', InteractiveSeekBarPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n interactiveSeekBarPlugin(options?: InteractiveSeekBarPluginOptions): InteractiveSeekBarPlugin;\n }\n}\n","import { Interactive } from 'libs/shared/interfaces';\n\nimport { ClipData } from 'projects/player/interfaces/models/ClipData';\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\nimport { BasePlayer, BasePlayerOptions } from 'projects/player/players/base-player';\nimport { AnalyticsPlayerType } from 'projects/player/services/analytics-service';\nimport { InteractiveTrackHelper } from 'projects/player/utils/interactive-track-helper';\n\nimport './reports-player.scss';\n\nimport 'projects/player/plugins/engagement-overlay-plugin/engagement-overlay-plugin';\nimport 'projects/player/plugins/clip-plugin/clip-plugin';\nimport 'projects/player/plugins/interactive-plugin/interactive-seek-bar-plugin';\nimport 'projects/player/plugins/old-version-refresh-plugin/old-version-refresh-plugin';\n\nexport interface ReportsPlayerOptions extends BasePlayerOptions {\n heatMap: number[];\n onTimepointHover?: (time: number | null) => void;\n}\n\nexport class ReportsPlayer extends BasePlayer {\n declare protected options: ReportsPlayerOptions;\n private track: TextTrack;\n\n constructor(id: string | Element, options: ReportsPlayerOptions) {\n super(id, options);\n }\n\n protected getPlayerClassName(): string {\n return 'cv-reports-player';\n }\n\n protected getAnalyticsPlayerType(): AnalyticsPlayerType {\n return 'reports-player';\n }\n\n protected async additionalSetup(playbackObject: PlaybackObject): Promise<void> {\n super.additionalSetup(playbackObject);\n\n this.setupEngagementOverlayPlugin(playbackObject);\n this.setupUpClipPlugin(playbackObject);\n this.setupInteractiveSeekBarPlugin(playbackObject);\n }\n\n private setupEngagementOverlayPlugin(playbackObject: PlaybackObject): void {\n this.player.engagementOverlayPlugin({\n heatMap: this.options.heatMap,\n interactive: playbackObject.additionalData?.interactive as Interactive,\n onTimepointHover: this.options.onTimepointHover\n });\n }\n\n private setupUpClipPlugin(playbackObject: PlaybackObject): void {\n const isClip = playbackObject.mediaType === 'MasterClip';\n const isInteractive = playbackObject.mediaType === 'MasterInteractive';\n\n if (!isClip && !isInteractive)\n return;\n\n let clipData: ClipData;\n if (isClip)\n clipData = playbackObject.additionalData;\n \n if (isInteractive) {\n clipData = playbackObject.additionalData?.clipData;\n\n // Not all interactives will have clip data\n if (!clipData)\n return;\n }\n\n if (!clipData)\n throw Error('Invalid clip data');\n\n this.player.clipPlugin({\n startTime: clipData.startTime,\n endTime: clipData.endTime\n });\n }\n\n private setupInteractiveSeekBarPlugin(playbackObject: PlaybackObject): void {\n const interactive = playbackObject.additionalData?.interactive as Interactive;\n\n if (!playbackObject.additionalData?.interactive)\n return;\n\n this.track = InteractiveTrackHelper.getInteractiveTrack(this.player, playbackObject);\n\n this.player.interactiveSeekBarPlugin({ interactive });\n }\n\n protected getSeekBarOptions(): any {\n return {\n ignoreChapters: true\n };\n }\n}\n","import React from 'react';\n\nimport { ReportsPlayer, ReportsPlayerOptions } from 'projects/player/players/reports/reports-player';\n\nexport function ClickViewReportsPlayer(props: ReportsPlayerOptions): React.ReactElement {\n const ref = React.useRef(null);\n const playerRef = React.useRef<ReportsPlayer>(null);\n\n React.useEffect(() => {\n playerRef.current = new ReportsPlayer(ref.current, props);\n }, []);\n\n return (\n <div ref={ref}></div>\n );\n}\n",":local {\n .playerContainer {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n }\n\n .playerPlaceholder {\n width: 100%;\n padding-bottom: 56.25%;\n }\n\n .heatMap {\n height: 1rem;\n }\n\n .heatMapTimepointIndicator {\n border-left: 0.125rem dashed $info;\n margin-left: -0.0625rem;\n position: absolute;\n top: 0;\n bottom: 0;\n opacity: 0;\n visibility: hidden;\n\n &.heatMapTimepointIndicatorVisible {\n opacity: 1;\n visibility: visible;\n }\n }\n\n .partialLoadingContainer {\n height: 24.015625rem;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EngagementHeatMap, EngagementHeatMapLegend } from 'libs/shared/apps/analytics/components/engagement-heat-map/EngagementHeatMap';\nimport { getFullHeatMap } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { Engagement } from 'libs/shared/interfaces';\n\nimport { ClickViewReportsPlayer } from 'projects/player/react/ReportsPlayer';\n\nimport styles from './video-engagement-overlay.module.scss';\n\nconst namespace = 'shared.videoEngagementOverlay';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface VideoEngagementOverlayProps {\n engagement: Engagement;\n viewKey: string;\n imageCdnUrl: string;\n playerApiUrl: string;\n}\n\nexport function VideoEngagementOverlay(props: VideoEngagementOverlayProps): JSX.Element {\n const timepointIndicatorRef = React.useRef<HTMLDivElement>(null);\n\n const heatMap = getFullHeatMap(props.engagement);\n\n function setHoverTimepoint(time: number | null): void {\n const el = timepointIndicatorRef.current;\n\n if (!el)\n return;\n\n if (time === null) {\n el.classList.remove(styles.heatMapTimepointIndicatorVisible);\n return;\n }\n\n el.classList.add(styles.heatMapTimepointIndicatorVisible);\n el.style.left = `${time / heatMap.length * 100}%`;\n }\n\n return (\n <div className='bg-white border rounded overflow-hidden h-100'>\n <div className='position-relative'>\n {/**\n * The below div is an empty 16:9 rectangle which maintains this component's\n * height while the player is loading.\n */\n }\n <div className={styles.playerPlaceholder} />\n <div className={styles.playerContainer}>\n <ClickViewReportsPlayer\n viewKey={props.viewKey}\n playerApi={new URL(props.playerApiUrl)}\n hotkeyElQuerySelector='body'\n heatMap={heatMap}\n onTimepointHover={setHoverTimepoint}\n aspectRatio='16:9'\n />\n </div>\n </div>\n <div className='p-3'>\n <div className='position-relative'>\n <EngagementHeatMap\n engagement={props.engagement}\n className={styles.heatMap}\n />\n <div ref={timepointIndicatorRef} className={styles.heatMapTimepointIndicator} />\n </div>\n <div className='d-flex justify-content-between mt-2'>\n <strong>\n {getPhrase('heatmap')}\n </strong>\n <div className='w-33'>\n <EngagementHeatMapLegend />\n </div>\n </div>\n </div>\n </div>\n );\n}\n",":local {\n .videoContainer {\n width: 44%;\n }\n}","import React from 'react';\n\nimport { EngagementTable } from 'libs/shared/apps/analytics/components/engagement-table/EngagementTable';\nimport { InsightAmountWatched } from 'libs/shared/apps/analytics/components/insights/amount-watched/InsightAmountWatched';\nimport { InsightTotalViews } from 'libs/shared/apps/analytics/components/insights/total-views/InsightTotalViews';\nimport { GroupedAnalyticsCount } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { Config, Engagement, PlayerViewKey } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\n\nimport { PartialInsightsHeatmap } from 'apps/my-shares/components/insights-heatmap/partial-loading/PartialInsightsHeatmap';\nimport { VideoEngagementOverlay } from 'apps/my-shares/components/video-engagement-overlay/VideoEngagementOverlay';\n\nimport styles from './insights-heatmap.module.scss';\n\ninterface InsightsHeatmapProps {\n hasDataLoaded: boolean;\n tableDataLoaded: boolean;\n yearGroups: GroupedAnalyticsCount[];\n aggregateEngagement: Engagement;\n individualEngagement: Engagement[];\n viewKey: PlayerViewKey;\n config: Config;\n users: AnonUser[];\n classroomStudents?: AnonUser[];\n anonymiseUsers: boolean;\n hideStaffResults: boolean;\n}\n\nexport function InsightsHeatmap(props: InsightsHeatmapProps) {\n return (\n <>\n {!props.hasDataLoaded && <PartialInsightsHeatmap />}\n\n <div className='row g-3 mb-3'>\n {props.hasDataLoaded &&\n <>\n <div className='col'>\n <InsightTotalViews\n events={{ yearGroupCount: props.yearGroups } as VideoViewEventResponse}\n emptyStateImage={ImageUrls.EmptyStates.MY_VIDEOS}\n hideStaffResults={props.hideStaffResults}\n />\n </div>\n <div className='col'>\n <InsightAmountWatched engagement={props.individualEngagement} />\n </div>\n <div className={styles.videoContainer}>\n <VideoEngagementOverlay\n engagement={props.aggregateEngagement}\n viewKey={props.viewKey.viewKey}\n playerApiUrl={props.config.playerApiUrl}\n imageCdnUrl={props.config.imageCdnUrl}\n />\n </div>\n </>\n }\n\n {props.tableDataLoaded &&\n <div className='col-12'>\n <EngagementTable\n engagement={props.individualEngagement}\n users={props.users}\n imageCdnUrl={props.config?.imageCdnUrl}\n anonymiseUsers={props.anonymiseUsers}\n classroomStudents={props.classroomStudents}\n border\n enableSort\n showSeparateNameColumns\n />\n </div>\n }\n </div>\n </>\n );\n}\n"],"mappings":"yoCCoBM,EAAY,EAAgB,iBAAiB,wBAAS,EAEtD,GAAwC,CAC5C,QAAS,CAAC,EACV,eAAgB,EAChB,UAAW,CACb,EAMA,SAAS,EAAY,EAA+D,CAClF,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAM,WAAa,cACnC,EAAM,QACJ,CAAA,CAET,CAOA,SAAS,EAAW,EAAqC,CACvD,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAW,kBAAkB,EAAM,OAAO,SAAW,UAAY,cAC3E,EAAU,EAAM,SAAS,CACf,CAAA,CAEjB,CAMA,SAAS,EAAmB,EAAkC,CAC5D,IAAI,EAAM,EASV,OAPA,EAAW,QAAQ,GAAK,CACtB,IAAM,EAAW,KAAK,IAAI,GAAG,EAAE,OAAO,EAElC,EAAW,IACb,EAAM,EACV,CAAC,EAEM,CACT,CAMA,SAAS,EAAsB,EAAoD,CACjF,GAAI,EAAW,KAAM,OAAO,EAAW,KACvC,GAAI,EAAW,SAAW,MAAQ,EAAW,SAAW,IAAA,GAAW,MAAO,MAE5E,CAEA,SAAS,EAAuB,EAAqC,CACnE,OAAQ,EAAR,CACE,IAAK,gBACH,OAAO,EAAU,gBAAgB,EACnC,IAAK,OACH,OAAO,EAAU,WAAW,EAC9B,QACE,OAAO,IACX,CACF,CAEA,SAAS,EAAa,EAAgB,EAAyB,EAAuB,CACpF,GAAI,EAAM,CACR,IAAM,EAAQ,EAAuB,CAAI,EACzC,GAAI,GAAS,CAAC,GAAM,KAAM,MAAO,CAAE,KAAM,EAAO,QAAS,EAAG,CAC9D,CAGA,IAAM,EADW,EAAkB,EAAM,CACvB,CAAA,CAAS,MAAM,GAAG,CAAC,CAAC,OAAO,GAAK,CAAC,CAAC,CAAC,EAErD,MAAO,CACL,KAAM,EAAU,GAChB,QAAS,EAAU,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CACtC,CACF,CAWA,SAAgB,EAAc,EAA6D,CACzF,OAAA,EAAa,YAAc,CACzB,IAAM,EAAkB,EAAmB,EAAM,UAAU,EA4H3D,MAAO,CACL,GA3HiD,EAAM,wBAA0B,CACjF,CACE,GAAI,YACJ,QAAS,CAAE,aAA8D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,WAAa,CAAA,EAC5H,SAAU,OACV,MAAO,GACP,UAAW,EAAgC,IAAmC,CAC5E,IAAM,EAAQ,EAAsB,EAAK,QAAQ,EAC3C,EAAQ,EAAsB,EAAK,QAAQ,EAC3C,CAAE,KAAM,GAAU,EAAa,EAAK,OAAO,UAAW,EAAM,eAAgB,CAAK,EACjF,CAAE,KAAM,GAAU,EAAa,EAAK,OAAO,UAAW,EAAM,eAAgB,CAAK,EACvF,OAAO,EAAQ,EAAQ,EAAI,EAC7B,EACA,MAAO,CAAE,QAAO,IAAK,CAAE,eAAqE,CAC1F,IAAM,EAAgB,EAAsB,CAAQ,EAC9C,CAAE,OAAM,WAAY,EAAa,EAAO,EAAM,eAAgB,CAAa,EACjF,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAa,UAAU,2CAAvB,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,0BACtB,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,EACN,YAAa,EAAM,YACnB,SAAU,EAAW,YAAY,EAAM,CAAO,EAC9C,SAAU,CAAC,EAAM,gBAAkB,CAAC,GAAiB,GAAO,QAAQ,IACpE,eAAgB,EAAM,cACvB,CAAA,CACG,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,wBACb,CACG,CAAA,EACL,IAAkB,iBAAmB,EAAM,wBAC1C,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAA,GACA,IAAK,EACL,QAAS,EAAiB,SAC1B,QAAS,EAAM,sBACf,UAAW,EAAO,QAClB,QAAS,EAAM,sBACf,eAAgB,CAAC,OAAO,EACxB,UAAW,EAAM,qBAClB,CAAA,CAEQ,GAEjB,CACF,EACA,CACE,GAAI,UACJ,QAAS,CAAE,aAA8D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,SAAW,CAAA,EAC1H,SAAU,OACV,MAAO,GACP,UAAW,EAAgC,IAAmC,CAC5E,IAAM,EAAQ,EAAsB,EAAK,QAAQ,EAC3C,EAAQ,EAAsB,EAAK,QAAQ,EAC3C,CAAE,QAAS,GAAa,EAAa,EAAK,OAAO,QAAS,EAAM,eAAgB,CAAK,EACrF,CAAE,QAAS,GAAa,EAAa,EAAK,OAAO,QAAS,EAAM,eAAgB,CAAK,EAC3F,OAAO,EAAW,EAAW,EAAI,EACnC,EACA,MAAO,CAAE,QAAO,IAAK,CAAE,eAAqE,CAC1F,GAAM,CAAE,WAAY,EAAa,EAAO,EAAM,eAAgB,EAAsB,CAAQ,CAAC,EAC7F,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAU,4CACrB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,mBACb,GAAW,EACR,CAAA,CACK,CAAA,CAEjB,CACF,CACF,EAAI,CACF,CACE,GAAI,OACJ,QAAS,CAAE,aAA8D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,MAAQ,CAAA,EACvH,SAAU,OACV,MAAO,GACP,UAAW,EAAgC,IAAmC,CAC5E,IAAM,EAAQ,EAAsB,EAAK,QAAQ,EAC3C,EAAQ,EAAsB,EAAK,QAAQ,EAQjD,OAPc,EACZ,EAAuB,CAAK,EAC5B,EAAkB,EAAK,OAAO,KAAM,EAAM,cAAc,IAC5C,EACZ,EAAuB,CAAK,EAC5B,EAAkB,EAAK,OAAO,KAAM,EAAM,cAAc,GAEnC,EAAI,EAC7B,EACA,MAAO,CAAE,QAAO,IAAK,CAAE,eAAqE,CAC1F,IAAM,EAAgB,EAAsB,CAAQ,EAC9C,CAAE,OAAM,WAAY,EAAa,EAAO,EAAM,eAAgB,CAAa,EACjF,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAa,UAAU,2CAAvB,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,0BACtB,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,EACN,YAAa,EAAM,YACnB,SAAU,EAAW,YAAY,EAAM,CAAO,EAC9C,SAAU,CAAC,EAAM,gBAAkB,CAAC,GAAiB,GAAO,QAAQ,IACpE,eAAgB,EAAM,cACvB,CAAA,CACG,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,6BAAhB,CACG,EAAK,IAAE,CACJ,IACL,IAAkB,iBAAmB,EAAM,wBAC1C,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAA,GACA,IAAK,EACL,QAAS,EAAiB,SAC1B,QAAS,EAAM,sBACf,UAAW,EAAO,QAClB,QAAS,EAAM,sBACf,eAAgB,CAAC,OAAO,EACxB,UAAW,EAAM,qBAClB,CAAA,CAEQ,GAEjB,CACF,CACF,EAIE,CACE,QAAS,CAAE,aAAa,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,OAAS,CAAA,EACvE,SAAU,YAGV,MAAO,EAAM,wBAA0B,GAAK,GAC5C,SAAU,QACV,cAAe,GACf,MAAO,CAAE,YACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAU,4CACrB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAA,SAAM,CAAW,CAAA,CACN,CAAA,CAEjB,EACA,CACE,QAAS,CAAE,aAAa,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,YAAc,CAAA,EAC5E,SAAU,iBAGV,MAAO,EAAM,wBAA0B,GAAK,GAC5C,cAAe,GACf,MAAO,CAAE,YACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAU,iBACrB,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAY,EACZ,OAAQ,EAA0B,WACnC,CAAA,CACU,CAAA,CAEjB,EACA,CACE,QAAS,CAAE,aAAa,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoB,SAAQ,UAAU,SAAW,CAAA,EACzE,SAAU,UAGV,MAAO,EAAM,wBAA0B,IAAM,GAC7C,cAAe,GACf,MAAO,CAAE,IAAK,CAAE,gBACd,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAU,4CACrB,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAY,EACZ,IAAK,EACL,UAAW,GAAG,EAAO,QAAQ,aAC9B,CAAA,CACU,CAAA,CAEjB,CACF,CACF,EAAG,CAAE,EAAM,eAAgB,EAAM,uBAAwB,CAAC,CAC5D,CAEA,SAAgB,EACd,EACA,EACA,EACuB,CACvB,OAAA,EAAa,YAAc,CACzB,IAAM,EAA8B,CAAC,EAE/B,EAAY,IAAI,IAiBtB,GAhBA,GAAY,QAAQ,GAAK,CACvB,IAAM,EAAO,GAAO,KAAK,GACnB,EAAE,IAAM,EAAE,KAAO,EAAE,QACrB,EAAU,IAAI,EAAE,EAAE,EACX,IAGT,GAAI,EAAE,WAAa,EAAE,YAAc,EAAE,UAItC,EAED,EAAK,KAAK,CAAE,GAAG,EAAG,MAAK,CAAC,CAC1B,CAAC,EAEG,GAAmB,OAAQ,CAC7B,IAAM,EAAW,EACd,OAAO,GAAK,CAAC,EAAU,IAAI,EAAE,EAAE,CAAC,CAAC,CACjC,IAAI,IAAS,CAAE,GAAG,GAAkB,OAAQ,EAAK,GAAI,MAAK,EAAyB,EACtF,EAAK,KAAK,GAAG,CAAQ,CACvB,CAEA,OAAO,CACT,EAAG,CAAE,EAAY,EAAO,CAAkB,CAAC,CAC7C,CC9TA,IAAM,EAAoB,CACxB,MAAO,wBACP,OAAQ,gBACR,WAAY,MACZ,KAAM,WACR,EAeA,SAAgB,EAAgB,EAA0C,CACxE,IAAM,EAAU,EAAc,CAC5B,WAAY,EAAM,WAClB,YAAa,EAAM,YACnB,eAAgB,EAAM,eACtB,wBAAyB,EAAM,wBAC/B,sBAAuB,EAAM,sBAC7B,sBAAuB,EAAM,qBAC/B,CAAC,EAEK,EAAO,EAAgB,EAAM,WAAY,EAAM,MAAO,EAAM,iBAAiB,EAKnF,OAHK,EAAK,QAIR,EAAA,EAAA,IAAA,CAAC,EAAD,CACW,UACH,OACN,MAAO,CACL,GAAG,EACH,MAAO,EAAM,OAAS,GAAG,EAAM,MAAM,SAAW,EAAM,KACxD,EACA,WAAY,EAAM,UACnB,CAAA,GAXM,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAI,CAAA,CAaf,CC/CA,SAAgB,EAA2B,EAAqD,CAC9F,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,OAAQ,EAAM,OACd,UAAW,EAAM,UACjB,WAAY,EACZ,YAAY,KACb,CAAA,CAEL,CCNA,IAAM,EAAY,8BACZ,EAAY,EAAgB,iBAAiB,CAAS,EAM5D,SAAgB,EAAqB,EAAkC,CACrE,IAAM,EAAiB,EAAkB,EAAM,UAAU,EACnD,EAAa,KAAK,MAAM,EAAiB,GAAG,EAElD,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAU,OAAO,EACxB,IAAK,EACL,aAAa,sCAEb,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+DAAf,CACG,CAAC,CAAC,EAAM,aACP,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAY,EACZ,OAAQ,EAA0B,WACnC,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,uBACV,OAAO,GAAmB,UACzB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAA,EAAW,OAAO,kBAAkB,QAAS,CAAE,YAAW,CAAI,CAAA,GAC/E,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAA,EAAW,OAAO,YAAc,CAAA,CAElD,CAAA,CACH,CAAA,CAAA,EAEH,CAAC,EAAM,aACN,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAA4B,OAAQ,EAA0B,WAAc,CAAA,CAC5E,CAAA,CAED,GACM,CAAA,CAEjB,sBCpDM,EAAgB,CACpB,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,SACF,EAEA,SAAgB,GAAsB,EAAgB,CACpD,OAAO,EAAK,KAAK,EAAG,KAAS,CAC3B,GAAG,EACH,MAAO,EAAc,EAAM,EAAc,OAC3C,EAAE,CACJ,CCNA,SAAgB,GACd,EACA,EACA,EACA,EACiC,CACjC,IAAM,EAA6B,CAAC,EAcpC,OAVA,EAF2B,EAE3B,EAAa,QAAQ,GAAM,CACzB,IAAM,EAAO,EAAG,MAAQ,UAEpB,CAAC,GAAQ,GAAc,SAAS,EAAK,YAAY,CAAC,IAGtD,EAAO,GAAQ,EAAO,IAAS,EAC/B,EAAO,IAAS,EAAG,MACrB,CAAC,EAEM,GAAmB,EAAY,OAAO,OAAO,KAAK,CAAM,CAAC,CAAC,IAAI,IAAU,CAC7E,KAAM,EAAgB,EAAc,CAAK,EAAI,EAC7C,EAAG,EAAO,GACV,KAAM,KACR,EAAE,EAAG,MAAM,CAAC,CACd,CAEA,SAAgB,EAAgB,EAAuC,CACrE,IAAM,EAAa,EAAK,UAAU,GAAS,EAAM,OAAS,OAAO,EAGjE,GAAI,EAAa,GAAI,CACnB,GAAM,CAAC,GAAe,EAAK,OAAO,EAAY,CAAC,EAE/C,EAAK,KAAK,CAAW,CACvB,CACA,OAAO,EAAK,MAAM,EAAG,IACN,SAAU,EAAE,KAAgB,MAAM,KAAK,CAAC,GAAG,EAEjD,EADM,SAAU,EAAE,KAAgB,MAAM,KAAK,CAAC,GAAG,EAC1C,CACf,CACH,CAEA,SAAgB,GAAmB,EAAuD,CACxF,OAAO,GAAM,QAAQ,EAAG,IAAM,EAAI,EAAE,EAAG,CAAC,GAAK,IAC/C,CC3CA,IAAM,EAAY,2BACZ,EAAY,EAAgB,iBAAiB,CAAS,EAE5D,SAAS,GAAwB,EAAsB,CAGrD,OAFI,IAAS,UACJ,EAAU,MAAM,EAClB,CACT,CAEA,IAAM,GAA2C,CAC/C,MAAO,CACL,KAAM,IACR,EACA,QAAS,CACP,QAAS,EACX,EACA,MAAO,CACL,gBAAiB,cACjB,QAAS,CAAE,EAAG,EAAG,EAAG,CAAE,CACxB,EACA,OAAQ,CACN,UAAW,EACX,aAAc,CAChB,EACA,YAAa,CACX,IAAK,CACH,iBAAkB,GAClB,OAAQ,UACR,WAAY,CACV,QAAS,EACX,EACA,aAAc,GACd,YAAa,EACb,YAAa,UACb,aAAc,EACd,KAAM,KACR,CACF,CACF,EAQA,SAAgB,GAAkB,EAA+B,CAO/D,IAAM,EAAY,EANF,GACd,EAAM,OACN,iBACA,EAAM,iBAAmB,CAAC,OAAO,EAAI,CAAC,EACtC,EAEgC,CAAO,EACnC,EAAa,GAAmB,CAAS,EAE/C,SAAS,EACP,EACoB,CACpB,MAAO,CACL,GAAG,GACH,OAAQ,CAAC,CACP,KAAM,MACN,KAAM,EAAU,OAAO,EACvB,MACF,CAAC,CACH,CACF,CAEA,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAU,OAAO,EAExB,aAAa,0BAEb,IAAK,YAEJ,GAAW,QACV,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,iBAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,YAAW,OAAO,aAAa,QAAS,CAAE,YAAW,CAAI,CAAA,CAAI,CAAA,GAElG,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+CACb,EAAA,EAAA,IAAA,CAAC,GAAA,gBAAD,CACE,WAAY,EAAA,QACZ,QAAS,EAAgB,CAAS,EAClC,eAAgB,CACd,UAAW,OACb,CACD,CAAA,CACE,CAAA,CACL,CAAA,CAAA,GAEF,EAAA,EAAA,KAAA,CAAC,EAAD,CAAY,UAAU,wBAAtB,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CAAkB,IAAK,EAAM,gBAAiB,UAAU,aAAgC,CAAA,GACxF,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAoB,UAAU,eAAK,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,YAAW,OAAO,SAAW,CAAA,CAAqB,CAAA,GACtG,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAiB,UAAU,kBAAQ,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,YAAW,OAAO,YAAc,CAAA,CAAkB,CAAA,CAC5F,GAEH,CAAA,CAEjB,6FE9GA,SAAgB,IAAyB,CACvC,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wBAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gBACb,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,gBAAgB,oCAA2C,CAAA,CAClF,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gBACb,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,gBAAgB,oCAA2C,CAAA,CAClF,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,yBACrB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,gBAAgB,oCAA2C,CAAA,CAClF,CAAA,CACF,KAEL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,yBACb,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mBACb,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,gBAAgB,oCAA2C,CAAA,CAClF,CAAA,CACF,CAAA,CACF,CAAA,CAAA,CAET,CCxBA,IAAM,GAAW,EAAQ,aAAa,UAAU,EAMnC,EAAb,cAA+C,EAAS,CAYtD,YAAY,EAAuB,EAA2C,CAC5E,MAAM,EAAQ,CAAO,EAErB,KAAK,eAAiB,EAAQ,eAC9B,KAAK,OAAO,KAAK,cAAc,CACjC,CAEA,cAA4B,CAC1B,KAAK,OAAO,CAAC,KAAK,cAAc,CAClC,CAEA,OAAe,EAAsB,CACnC,EAAQ,KAAK,SAAS,EAAI,KAAK,UAAU,CAC3C,CAEA,UAAyB,CACvB,EAAQ,IAAI,SAAS,KAAK,SAAU,IAAI,EACxC,KAAK,eAAiB,GACtB,KAAK,OAAO,CAAC,CAAC,wBAAwB,CAAC,CAAC,cAAc,KAAK,cAAc,EACzE,KAAK,OAAO,CAAC,CAAC,SAAS,mCAAmC,CAC5D,CAEA,WAA0B,CACxB,EAAQ,IAAI,YAAY,KAAK,SAAU,IAAI,EAC3C,KAAK,eAAiB,GACtB,KAAK,OAAO,CAAC,CAAC,wBAAwB,CAAC,CAAC,cAAc,KAAK,cAAc,EACzE,KAAK,OAAO,CAAC,CAAC,YAAY,mCAAmC,CAC/D,CAMA,YAAmB,EAAwC,CACzD,EAAM,yBAAyB,CACjC,CAEA,SAAgB,EAAkB,EAAkB,EAAiC,CAKnF,AAEE,KAAK,gBADL,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC3B,IAGlB,KAAK,UACP,KAAK,SAAS,oBAAoB,QAAS,KAAK,YAAY,EAE9D,KAAK,SAAW,EAAQ,IAAI,SAAS,MAAO,CAC1C,UAAW,2DACX,UAAW,oCACb,CAAC,EACD,KAAK,SAAS,iBAAiB,QAAS,KAAK,YAAY,EAMzD,IAAM,EAAK,MAAM,SAAS,EAAS,CACjC,UAAW,iCACX,UAAA;;gDACF,EAAG,CAAU,EAQb,OAFA,EAAG,SAAS,EAAE,CAAC,YAAY,KAAK,QAAQ,EAEjC,CACT,CACF,EAEA,EAAQ,kBAAkB,4BAA6B,CAAyB,mBC1F1E,EAA2B,EAOjC,SAAgB,GAAsB,EAAgD,CACpF,IAAM,EAAY,EAAM,YAAY,WAAW,KAAK,GAAK,CACvD,IAAM,EAAgB,EAAE,UAAY,IAEpC,OAAO,KAAK,MAAM,EAAM,IAAI,IAAM,KAAK,MAAM,CAAa,GACrD,KAAK,KAAK,EAAM,IAAI,IAAM,KAAK,KAAK,CAAa,CACxD,CAAC,EAED,GAAI,CAAC,GAAW,cAAc,OAC5B,OAAO,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAI,CAAA,EAEb,IAAM,EAAe,EAAU,aAAa,OAAS,EACnD,EAAU,aAAa,MAAM,EAAG,EAA2B,CAAC,EAC5D,EAAU,aAEN,EAAqB,EAAU,aAAa,OAAS,EAAa,OAExE,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2CAAf,CACG,EAAa,KAAK,EAAG,KACpB,EAAA,EAAA,IAAA,CAAC,EAAD,CAEE,YAAa,EACb,aAAc,GACd,cAAc,MACf,EAJM,CAIN,CACF,EACA,CAAC,CAAC,IACD,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAW,oHAGV,IAAI,GACF,CAAA,CAEJ,GAET,CCxCA,IAAa,GAA2C,CACtD,MAAO,CACL,KAAM,IACR,EACA,MAAO,CACL,QAAS,GACT,WAAY,EACZ,WAAY,CACd,EACA,OAAQ,CACN,QAAS,EACX,EACA,QAAS,CACP,QAAS,EACX,EACA,KAAM,CACJ,SAAW,CACT,QAAS,iBACT,GAAI,gBACJ,GAAI,EACJ,GAAI,EACJ,GAAI,EACJ,GAAI,EACJ,SAAU,CACP,CACC,QAAS,OACT,OAAQ,CACV,EACC,CACC,QAAS,OACT,OAAQ,CACV,CACF,CACF,CACF,CACF,EAEA,SAAgB,GAAgB,EAAe,EAAyC,CACtF,MAAO,CACL,WAAY,GACZ,QAAS,CAAE,GAAI,EAAG,EAAG,CAAE,EACvB,QACA,QACF,CACF,CAEA,SAAgB,GAAqB,EAA4C,CAG/E,MAAO,CAIL,IANe,KAAK,IAAI,GAAG,CAMtB,EAAW,KAChB,IAAK,EACL,WAAY,EACZ,WAAY,EACZ,cAAe,GACf,YAAa,GACb,UAAW,GACX,QAAS,EACX,CACF,CAEA,SAAgB,GAAkB,EAAsD,CACtF,MAAO,CACL,UAAW,UAAY,CACrB,IAAM,EAA4B,EAChC,GAA6B,EAAa,KAAK,CAAC,EAChD,GAEF,MACE,2GAEW,EAAW,KAAK,CAAC,EAAE,WAC3B,EAAA,gJAGmD,KAAK,EAAE,oBAIjE,EACA,WAAY,SACV,EACA,EACA,EACA,CACA,IACM,EAAO,KAAK,MAAM,UAAY,EAC9B,EAAI,EAAM,MAAQ,EAAa,EAErC,MAAO,CAEL,EAAG,KAAK,IAAI,KAAK,IAAI,EAAG,CAAI,EAAG,CAAI,EACnC,EAAG,KAAK,MAAM,OAChB,CACF,EACA,QAAS,GACT,QAAS,CACX,CACF,CAEA,SAAgB,GAAe,EAA4E,CACzG,MAAO,CACL,KAAM,CACJ,MAAO,CACL,OAAQ,CACN,UAAW,UAAY,CACrB,EAAuB,KAAK,CAAC,CAC/B,EACA,SAAU,UAAY,CACpB,EAAuB,IAAI,CAC7B,CACF,CACF,CACF,EACA,OAAQ,CACN,OAAQ,CACN,QAAS,EACX,CACF,CACF,CACF,CAEA,SAAS,GAA6B,EAA0B,EAAsB,CACpF,OAAA,EAAA,GAAA,qBAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAA6B,OAAmB,aAAc,CAAA,CAChE,CACF,CC3HA,IAAM,GAAY,EAAQ,aAAa,WAAW,EAElD,EAAA,QAAW,IAAI,YAAY,KAAK,GAAG,EACnC,EAAA,QAAW,IAAI,kBAAkB,KAAK,UAAW,WAAW,EAa5D,IAAa,GAAb,cAAuC,EAAU,CAI/C,YAAY,EAAuB,EAAmC,CACpE,MAAM,EAAQ,CAAO,EAErB,KAAK,WAAW,EAChB,KAAK,cAAc,CACrB,CAEA,YAA0B,CACxB,KAAK,OAAO,CAAC,CAAC,UAAY,KAAK,WAAW,CAAC,CAC7C,CAEA,eAA+B,CAC7B,MAAO,uBACT,CAEA,SAAgB,EAAkB,EAAkB,EAA2B,CAI7E,OAAO,MAAM,SAAS,EAAS,CAC7B,GAAG,EACH,UAAW,KAAK,cAAc,EAC9B,wGACF,EAAG,CAAU,CACf,CAEA,YAAmB,EAAqB,CAClC,EACF,KAAK,WAAW,EAEhB,KAAK,aAAa,CACtB,CAEA,eAA8B,CAC5B,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAE7C,KAAK,OAAO,CAAC,CAAC,GAAG,eAAgB,KAAK,WAAW,EAEjD,KAAK,GAAG,KAAK,GAAG,EAAG,UAAW,KAAK,WAAW,EAE9C,KAAK,OAAO,CAAC,CAAC,GAAG,cAAiB,CAChC,KAAK,OAAO,CAAC,CAAC,IAAI,eAAgB,KAAK,WAAW,EAElD,KAAK,IAAI,KAAK,GAAG,EAAG,UAAW,KAAK,WAAW,CACjD,CAAC,CACH,CAEA,YAAoB,EAAwC,CACrD,KAAQ,IAAI,kBAAkB,CAAK,EAGxC,IAAI,KAAK,OAAO,CAAC,CAAC,OAAO,EAAG,CAC1B,KAAK,OAAO,CAAC,CAAC,KAAK,EACnB,MACF,CAEA,KAAK,OAAO,CAAC,CAAC,MAAM,CAFpB,CAGF,CAEA,YAA2B,CACzB,GAAI,KAAK,MACP,OAEF,IAAM,EAAkB,KAAK,mBAAmB,EAMhD,GAAI,CAAC,EAAiB,CACpB,KAAK,OAAO,CAAC,CAAC,IAAI,WAAc,KAAK,WAAW,CAAC,EACjD,MACF,CAEA,IAAM,EAAyB,KAAK,GAAG,CAAC,CAAC,cAAc,sBAAsB,EAE7E,KAAK,MAAQ,EAAA,QAAW,MAAM,EAAW,KAAK,oBAAoB,CAAe,CAAC,CACpF,CAEA,aAA4B,CAC1B,IAAM,EAAkB,KAAK,mBAAmB,EAE5C,CAAC,KAAK,OAAS,CAAC,GAGpB,KAAK,MAAM,QAAQ,EAAgB,MAAO,EAAgB,MAAM,CAClE,CAEA,cAA6B,CAC3B,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IACf,CAEA,oBAA8C,CAE5C,IAAM,EADgB,KAAK,OAAO,CAAC,CAAC,SAAS,eACjB,CAAA,EAAe,cAAc,EAEnD,EAAQ,KAAK,GAAG,CAAC,CAAC,YAExB,GAAI,CAAC,GAAuB,CAAC,EAC3B,OAAO,KAET,GAAM,CAAE,UAAW,KAAK,OAAO,CAAC,CAAC,kBAAkB,EAEnD,MAAO,CACL,QACA,OAAQ,EAAS,CACnB,CACF,CAEA,oBAA4B,CAAE,QAAO,UAA+C,CAClF,MAAO,CACL,GAAG,GACH,MAAO,GAAgB,EAAO,CAAM,EACpC,MAAO,GAAqB,KAAK,SAAS,OAAO,EACjD,QAAS,GAAkB,KAAK,SAAS,WAAW,EACpD,YAAa,GAAe,KAAK,uBAAuB,KAAK,IAAI,CAAC,EAClE,OAAQ,CAAC,CACP,KAAM,OACN,KAAM,KAAK,SAAS,OACtB,CAAC,CACH,CACF,CAEA,uBAA+B,EAAwB,CACjD,KAAK,SAAS,kBAChB,KAAK,SAAS,iBAAiB,CAAC,EAElC,IAAM,EAA4B,KAAK,GAAG,CAAC,CAAC,cAAc,oCAAoC,EAE9F,GAAI,IAAM,KAAM,CACd,EAAQ,IAAI,YAAY,EAAW,2CAA2C,EAC9E,MACF,CAEA,EAAQ,IAAI,SAAS,EAAW,2CAA2C,EAC3E,EAAU,MAAM,KAAO,GAAG,EAAI,KAAK,SAAS,QAAQ,OAAS,IAAI,EACnE,CACF,EAEA,EAAQ,kBAAkB,oBAAqB,EAAiB,ECtKhE,IAAM,GAAS,EAAQ,UAAU,QAAQ,EAQnC,GAAN,cAAsC,EAAO,CAG3C,YAAY,EAAuB,EAAyC,CAC1E,MAAM,EAAQ,CAAO,EAErB,KAAK,QAAU,EAEf,EAAO,UAAY,CACjB,KAAK,WAAW,CAClB,CAAC,CACH,CAEA,YAA2B,CACpB,KAAK,eAAe,IAGzB,KAAK,OAAO,SAAS,oBAAqB,CACxC,QAAS,KAAK,QAAQ,QACtB,YAAa,KAAK,QAAQ,YAC1B,iBAAkB,KAAK,QAAQ,gBACjC,CAAC,GAKiB,KAAK,OAAO,SAAS,eAAe,CAAC,EAAE,SAAS,WAAW,EAAA,CACnE,QAAQ,CAChB,KAAM,EACN,KAAM,4BACN,QAAS,CAAE,eAAgB,EAAK,CAClC,CAAC,EACH,CAEA,cAAqB,EAAqB,CAExC,KAD+B,OAAO,SAAS,mBAC/C,CAAA,EAAmB,YAAY,CAAI,CACrC,CAEA,gBAAkC,CAChC,OAAO,KAAK,QAAQ,SAAS,QAAQ,EAAK,IAAQ,EAAM,EAAK,CAAC,EAAI,CACpE,CACF,EAEA,EAAQ,eAAe,0BAA2B,EAAuB,ECrDzE,IAAM,GAAS,EAAQ,UAAU,QAAQ,EAWnC,GAAN,cAAuC,EAAO,CAG5C,YAAY,EAAuB,EAA0C,CAC3E,MAAM,CAAM,EAEZ,KAAK,QAAU,EAEf,KAAK,OAAO,IAAI,qBAAwB,KAAK,OAAO,MAAM,KAAK,WAAW,KAAK,IAAI,CAAC,CAAC,CACvF,CAEA,YAA2B,CAEzB,EAAY,iBAAiB,KAAK,OAAQ,cAAe,KAAK,cAAc,KAAK,IAAI,CAAC,EAEtF,KAAK,OAAO,SAAS,uBAAuB,CAC9C,CAEA,cAAsB,EAAwB,CAC5C,KAAK,YAAY,CAAK,CACxB,CAEA,YAAoB,EAAwB,CAG1C,KAFqB,OAAO,WAAW,SAAS,iBAAiB,CAAC,CAAC,SAAS,SAE5E,CAAA,CAAQ,SAAS,IAAI,GAAoB,KAAK,OAAQ,CACpD,YAAa,KAAK,QAAQ,YAC1B,OACF,CAAC,CAAC,CACJ,CACF,EAEA,EAAQ,eAAe,2BAA4B,EAAwB,EChC3E,IAAa,GAAb,cAAmC,EAAW,CAI5C,YAAY,EAAsB,EAA+B,CAC/D,MAAM,EAAI,CAAO,CACnB,CAEA,oBAAuC,CACrC,MAAO,mBACT,CAEA,wBAAwD,CACtD,MAAO,gBACT,CAEA,MAAgB,gBAAgB,EAA+C,CAC7E,MAAM,gBAAgB,CAAc,EAEpC,KAAK,6BAA6B,CAAc,EAChD,KAAK,kBAAkB,CAAc,EACrC,KAAK,8BAA8B,CAAc,CACnD,CAEA,6BAAqC,EAAsC,CACzE,KAAK,OAAO,wBAAwB,CAClC,QAAS,KAAK,QAAQ,QACtB,YAAa,EAAe,gBAAgB,YAC5C,iBAAkB,KAAK,QAAQ,gBACjC,CAAC,CACH,CAEA,kBAA0B,EAAsC,CAC9D,IAAM,EAAS,EAAe,YAAc,aACtC,EAAgB,EAAe,YAAc,oBAEnD,GAAI,CAAC,GAAU,CAAC,EACd,OAEF,IAAI,EACJ,GAAI,IACF,EAAW,EAAe,kBAExB,IACF,EAAW,EAAe,gBAAgB,SAGtC,CAAC,IAIP,IAAI,CAAC,EACH,MAAM,MAAM,mBAAmB,EAEjC,KAAK,OAAO,WAAW,CACrB,UAAW,EAAS,UACpB,QAAS,EAAS,OACpB,CAAC,CALgC,CAMnC,CAEA,8BAAsC,EAAsC,CAC1E,IAAM,EAAc,EAAe,gBAAgB,YAE9C,EAAe,gBAAgB,cAGpC,KAAK,MAAQ,GAAuB,oBAAoB,KAAK,OAAQ,CAAc,EAEnF,KAAK,OAAO,yBAAyB,CAAE,aAAY,CAAC,EACtD,CAEA,mBAAmC,CACjC,MAAO,CACL,eAAgB,EAClB,CACF,CACF,EC5FA,SAAgB,GAAuB,EAAiD,CACtF,IAAM,EAAA,EAAY,OAAO,IAAI,EACvB,EAAA,EAAkB,OAAsB,IAAI,EAMlD,OAJA,EAAM,cAAgB,CACpB,EAAU,QAAU,IAAI,GAAc,EAAI,QAAS,CAAK,CAC1D,EAAG,CAAC,CAAC,GAGH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAU,KAAU,CAAA,CAExB,yUEFM,GAAY,EAAgB,iBAAiB,+BAAS,EAS5D,SAAgB,GAAuB,EAAiD,CACtF,IAAM,EAAA,EAA8B,OAAuB,IAAI,EAEzD,EAAU,EAAe,EAAM,UAAU,EAE/C,SAAS,EAAkB,EAA2B,CACpD,IAAM,EAAK,EAAsB,QAE5B,KAGL,IAAI,IAAS,KAAM,CACjB,EAAG,UAAU,OAAO,EAAO,gCAAgC,EAC3D,MACF,CAEA,EAAG,UAAU,IAAI,EAAO,gCAAgC,EACxD,EAAG,MAAM,KAAO,GAAG,EAAO,EAAQ,OAAS,IAAI,EAH/C,CAIF,CAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,yDAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,EAME,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,iBAAoB,CAAA,GAC3C,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,0BACrB,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAM,QACf,UAAW,IAAI,IAAI,EAAM,YAAY,EACrC,sBAAsB,OACb,UACT,iBAAkB,EAClB,YAAY,MACb,CAAA,CACE,CAAA,CACF,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,eAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAY,EAAM,WAClB,UAAW,EAAO,OACnB,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,IAAK,EAAuB,UAAW,EAAO,yBAA4B,CAAA,CAC5E,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+CAAf,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAA,SACG,GAAU,SAAS,CACd,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iBACb,EAAA,EAAA,IAAA,CAAC,GAAD,CAA0B,CAAA,CACvB,CAAA,CACF,GACF,GACF,GAET,mDElDA,SAAgB,GAAgB,EAA6B,CAC3D,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,CAAC,EAAM,gBAAiB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAyB,CAAA,GAElD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wBAAf,CACG,EAAM,gBACL,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gBACb,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,CAAE,eAAgB,EAAM,UAAW,EAC3C,gBAAiB,GAAU,YAAY,UACvC,iBAAkB,EAAM,gBACzB,CAAA,CACE,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gBACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAsB,WAAY,EAAM,oBAAuB,CAAA,CAC5D,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAO,yBACrB,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,WAAY,EAAM,oBAClB,QAAS,EAAM,QAAQ,QACvB,aAAc,EAAM,OAAO,aAC3B,YAAa,EAAM,OAAO,WAC3B,CAAA,CACE,CAAA,CACL,CAAA,CAAA,EAGH,EAAM,kBACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mBACb,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,WAAY,EAAM,qBAClB,MAAO,EAAM,MACb,YAAa,EAAM,QAAQ,YAC3B,eAAgB,EAAM,eACtB,kBAAmB,EAAM,kBACzB,OAAA,GACA,WAAA,GACA,wBAAA,EACD,CAAA,CACE,CAAA,CAEJ,GACL,CAAA,CAAA,CAEN"}
|
|
1
|
+
{"version":3,"file":"DhcRnxkp.chunk.js","names":[],"sources":["../../../../libs/shared/src/apps/analytics/components/engagement-table/engagement-table.module.scss","../../../../libs/shared/src/apps/analytics/components/engagement-table/EngagementTableUtils.tsx","../../../../libs/shared/src/apps/analytics/components/engagement-table/EngagementTable.tsx","../../../../libs/shared/src/components/percentage-indicator/PartialPercentageIndicator.tsx","../../../../libs/shared/src/apps/analytics/components/insights/amount-watched/InsightAmountWatched.tsx","../../../../libs/shared/src/apps/analytics/utils/ChartColourUtils.ts","../../../../libs/shared/src/apps/analytics/utils/SharedUserActivityPieChartUtils.ts","../../../../libs/shared/src/apps/analytics/components/insights/total-views/InsightTotalViews.tsx","../../src/apps/my-shares/components/insights-heatmap/partial-loading/partial-insights-heatmap.module.scss","../../src/apps/my-shares/components/insights-heatmap/partial-loading/PartialInsightsHeatmap.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay-menu-item/engagement-overlay-menu-item.ts","../../../player/src/plugins/engagement-overlay-plugin/components/timepoint-interactions/timepoint-interactions.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay-chart-options.tsx","../../../player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay.ts","../../../player/src/plugins/engagement-overlay-plugin/engagement-overlay-plugin.ts","../../../player/src/plugins/interactive-plugin/interactive-seek-bar-plugin.ts","../../../player/src/players/reports/reports-player.ts","../../../player/src/react/ReportsPlayer.tsx","../../src/apps/my-shares/components/video-engagement-overlay/video-engagement-overlay.module.scss","../../src/apps/my-shares/components/video-engagement-overlay/VideoEngagementOverlay.tsx","../../src/apps/my-shares/components/insights-heatmap/insights-heatmap.module.scss","../../src/apps/my-shares/components/insights-heatmap/InsightsHeatmap.tsx"],"sourcesContent":[":local {\n .heatMap {\n height: 1rem;\n }\n\n // use avatar width\n .avatarContainer {\n width: 2rem;\n height: 2rem;\n }\n\n .cogIcon {\n cursor: pointer;\n color: $gray-900;\n line-height: 1;\n }\n}","import React from 'react';\nimport { Column, ColumnInstance, Row } from 'react-table';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EngagementHeatMap } from 'libs/shared/apps/analytics/components/engagement-heat-map/EngagementHeatMap';\nimport { anonymiseUserName } from 'libs/shared/apps/analytics/utils/AnonymiseUserUtils';\nimport { EngagementAvatar } from 'libs/shared/components/engagement-avatar/EngagementAvatar';\nimport { IconButton } from 'libs/shared/components/icon-button/IconButton';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { CogSvg } from 'libs/shared/images/svg/objects/CogSvg';\nimport { Engagement, EngagementType } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport styles from './engagement-table.module.scss';\n\nconst namespace = 'shared.engagementTable';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst EMPTY_ENGAGEMENT: Partial<Engagement> = {\n heatMap: [],\n engagementRate: 0,\n viewCount: 0\n};\n\ninterface CellWrapperProps {\n className?: string;\n}\n\nfunction CellWrapper(props: React.PropsWithChildren<CellWrapperProps>): JSX.Element {\n return (\n <div className={`${props.className ?? ''}`}>\n {props.children}\n </div>\n );\n}\n\ninterface HeaderCellProps {\n column: ColumnInstance<EngagementTableData>;\n phraseKey: string;\n}\n\nfunction HeaderCell(props: HeaderCellProps): JSX.Element {\n return (\n <CellWrapper className={`d-inline-block ${props.column.isSorted ? 'fw-bold' : ''}`}>\n {getPhrase(props.phraseKey)}\n </CellWrapper>\n );\n}\n\nexport interface EngagementTableData extends Engagement {\n user: AnonUser;\n}\n\nfunction getMaxHeatMapValue(engagement: Engagement[]): number {\n let max = 0;\n\n engagement.forEach(e => {\n const localMax = Math.max(...e.heatMap);\n\n if (localMax > max)\n max = localMax;\n });\n\n return max;\n}\n\n/**\n * Resolves the engagement type, inferring 'anon' for legacy data\n * where type is not set but userId is null.\n */\nfunction resolveEngagementType(engagement: Engagement): EngagementType | undefined {\n if (engagement.type) return engagement.type;\n if (engagement.userId === null || engagement.userId === undefined) return 'anon';\n return undefined;\n}\n\nfunction getEngagementTypeLabel(type: EngagementType): string | null {\n switch (type) {\n case 'student-reach':\n return getPhrase('classroomViews');\n case 'anon':\n return getPhrase('anonymous');\n default:\n return null;\n }\n}\n\nfunction getUsersName(user: AnonUser, anonymiseUsers: boolean, type?: EngagementType) {\n if (type) {\n const label = getEngagementTypeLabel(type);\n if (label && !user?.name) return { name: label, surname: '' };\n }\n\n const fullName = anonymiseUserName(user, anonymiseUsers);\n const nameParts = fullName.split(' ').filter(n => !!n);\n\n return {\n name: nameParts[0],\n surname: nameParts.slice(1).join(' ')\n };\n}\n\ninterface EngagementColumnProps {\n engagement: Engagement[];\n imageCdnUrl: string;\n anonymiseUsers: boolean;\n showSeparateNameColumns?: boolean;\n classroomViewsAppLink?: Core.AppLink;\n classroomViewsTooltip?: string;\n}\n\nexport function useGetColumns(props: EngagementColumnProps): Column<EngagementTableData>[] {\n return React.useMemo(() => {\n const maxHeatMapValue = getMaxHeatMapValue(props.engagement);\n\n const nameColumns: Column<EngagementTableData>[] = props.showSeparateNameColumns ? [\n {\n id: 'firstName',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='firstName' />,\n accessor: 'user',\n width: 63,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const { name: nameA } = getUsersName(rowA.values.firstName, props.anonymiseUsers, typeA);\n const { name: nameB } = getUsersName(rowB.values.firstName, props.anonymiseUsers, typeB);\n return nameA > nameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const effectiveType = resolveEngagementType(original);\n const { name, surname } = getUsersName(value, props.anonymiseUsers, effectiveType);\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className={styles.avatarContainer}>\n <EngagementAvatar\n type={effectiveType}\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(name, surname)}\n imageUrl={!props.anonymiseUsers && !effectiveType && value?.avatar?.url}\n anonymiseUsers={props.anonymiseUsers}\n />\n </span>\n <span className='ms-2 clamp-1'>\n {name}\n </span>\n {effectiveType === 'student-reach' && props.classroomViewsAppLink &&\n <IconButton\n customSize\n svg={CogSvg}\n svgSize={SvgContainerSize.Standard}\n appLink={props.classroomViewsAppLink}\n className={styles.cogIcon}\n tooltip={props.classroomViewsTooltip}\n tooltipTrigger={['hover']}\n ariaLabel={props.classroomViewsTooltip}\n />\n }\n </CellWrapper>\n );\n }\n },\n {\n id: 'surname',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='surname' />,\n accessor: 'user',\n width: 68,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const { surname: surnameA } = getUsersName(rowA.values.surname, props.anonymiseUsers, typeA);\n const { surname: surnameB } = getUsersName(rowB.values.surname, props.anonymiseUsers, typeB);\n return surnameA > surnameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const { surname } = getUsersName(value, props.anonymiseUsers, resolveEngagementType(original));\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className='clamp-1'>\n {surname || ''}\n </span>\n </CellWrapper>\n );\n }\n }\n ] : [\n {\n id: 'name',\n Header: ({ column }: { column: ColumnInstance<EngagementTableData> }) => <HeaderCell column={column} phraseKey='name' />,\n accessor: 'user',\n width: 22,\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const typeA = resolveEngagementType(rowA.original);\n const typeB = resolveEngagementType(rowB.original);\n const nameA = typeA ?\n getEngagementTypeLabel(typeA) :\n anonymiseUserName(rowA.values.user, props.anonymiseUsers);\n const nameB = typeB ?\n getEngagementTypeLabel(typeB) :\n anonymiseUserName(rowB.values.user, props.anonymiseUsers);\n\n return nameA > nameB ? 1 : -1;\n },\n Cell: ({ value, row: { original } }: { value: AnonUser, row: Row<EngagementTableData> }) => {\n const effectiveType = resolveEngagementType(original);\n const { name, surname } = getUsersName(value, props.anonymiseUsers, effectiveType);\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className={styles.avatarContainer}>\n <EngagementAvatar\n type={effectiveType}\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(name, surname)}\n imageUrl={!props.anonymiseUsers && !effectiveType && value?.avatar?.url}\n anonymiseUsers={props.anonymiseUsers}\n />\n </span>\n <span className='ms-2 clamp-1 me-1'>\n {name} {surname}\n </span>\n {effectiveType === 'student-reach' && props.classroomViewsAppLink &&\n <IconButton\n customSize\n svg={CogSvg}\n svgSize={SvgContainerSize.Standard}\n appLink={props.classroomViewsAppLink}\n className={styles.cogIcon}\n tooltip={props.classroomViewsTooltip}\n tooltipTrigger={['hover']}\n ariaLabel={props.classroomViewsTooltip}\n />\n }\n </CellWrapper>\n );\n }\n }\n ];\n\n return [\n ...nameColumns,\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='views' />,\n accessor: 'viewCount',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 47 : 15,\n sortType: 'basic',\n sortDescFirst: true,\n Cell: ({ value }) => (\n <CellWrapper className='d-flex align-items-center h-100'>\n <div>{value}</div>\n </CellWrapper>\n )\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='engagement' />,\n accessor: 'engagementRate',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 79 : 20,\n sortDescFirst: true,\n Cell: ({ value }) => (\n <CellWrapper className='w-33'>\n <PercentageIndicator\n percentage={value}\n layout={PercentageIndicatorLayout.LabelBefore}\n />\n </CellWrapper>\n )\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='heatMap' />,\n accessor: 'heatMap',\n // React table uses flex ratios for widths. I've styled with 5 columns but didn't want to effect the sizing\n // for when it was 4 so we're keeping the new and old values - Sha\n width: props.showSeparateNameColumns ? 230 : 48,\n disableSortBy: true,\n Cell: ({ row: { original } }) => (\n <CellWrapper className='d-flex align-items-center h-100'>\n <EngagementHeatMap\n engagement={original}\n max={maxHeatMapValue}\n className={`${styles.heatMap} flex-grow-1`}\n />\n </CellWrapper>\n )\n }\n ];\n }, [ props.anonymiseUsers, props.showSeparateNameColumns ]);\n}\n\nexport function useGetTableData(\n engagement: Engagement[],\n users: AnonUser[],\n classroomStudents?: AnonUser[]\n): EngagementTableData[] {\n return React.useMemo(() => {\n const data: EngagementTableData[] = [];\n\n const userIdSet = new Set<string>();\n engagement?.forEach(e => {\n const user = users?.find(u => {\n if (u.id && u.id === e.userId) {\n userIdSet.add(u.id);\n return true;\n }\n\n if (u.sessionId && u.sessionId === e.sessionId)\n return true;\n\n return false;\n });\n\n data.push({ ...e, user });\n });\n\n if (classroomStudents?.length) {\n const students = classroomStudents\n .filter(s => !userIdSet.has(s.id))\n .map(user => ({ ...EMPTY_ENGAGEMENT, userId: user.id, user } as EngagementTableData));\n data.push(...students);\n }\n\n return data;\n }, [ engagement, users, classroomStudents ]);\n}\n","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\n\nimport { Table, TableTheme } from 'libs/shared/components/table/Table';\nimport { Engagement } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\n\nimport { useGetColumns, useGetTableData } from './EngagementTableUtils';\n\nconst theme: TableTheme = {\n table: 'bg-white rounded px-0',\n header: 'border-bottom',\n headerCell: 'm-3',\n cell: 'mx-3 my-2'\n};\n\ninterface EngagementTableProps {\n engagement: Engagement[];\n imageCdnUrl: string;\n users?: AnonUser[];\n classroomStudents?: AnonUser[];\n anonymiseUsers: boolean;\n border?: boolean;\n enableSort?: boolean;\n showSeparateNameColumns?: boolean;\n classroomViewsAppLink?: Core.AppLink;\n classroomViewsTooltip?: string;\n}\n\nexport function EngagementTable(props: EngagementTableProps): JSX.Element {\n const columns = useGetColumns({\n engagement: props.engagement,\n imageCdnUrl: props.imageCdnUrl,\n anonymiseUsers: props.anonymiseUsers,\n showSeparateNameColumns: props.showSeparateNameColumns,\n classroomViewsAppLink: props.classroomViewsAppLink,\n classroomViewsTooltip: props.classroomViewsTooltip\n });\n\n const data = useGetTableData(props.engagement, props.users, props.classroomStudents);\n\n if (!data.length)\n return <></>;\n\n return (\n <Table\n columns={columns}\n data={data}\n theme={{\n ...theme,\n table: props.border ? `${theme.table} border` : theme.table\n }}\n enableSort={props.enableSort}\n />\n );\n}\n","import React from 'react';\n\nimport { PercentageIndicator, PercentageIndicatorLayout } from './PercentageIndicator';\n\ninterface PartialPercentageIndicatorProps {\n layout: PercentageIndicatorLayout;\n className?: string;\n}\n\nexport function PartialPercentageIndicator(props: PartialPercentageIndicatorProps): JSX.Element {\n return (\n <PercentageIndicator\n layout={props.layout}\n className={props.className}\n percentage={0}\n customLabel='--%'\n />\n );\n}\n","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { getEngagementRate } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { PartialPercentageIndicator } from 'libs/shared/components/percentage-indicator/PartialPercentageIndicator';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { TimerSvg } from 'libs/shared/images/svg/status/TimerSvg';\nimport { Engagement } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.insightAmountWatched';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightAmountWatchedProps {\n engagement: Engagement[];\n}\n\nexport function InsightAmountWatched(props: InsightAmountWatchedProps) {\n const engagementRate = getEngagementRate(props.engagement);\n const percentage = Math.round(engagementRate * 100);\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svg={TimerSvg}\n svgClassName='bg-light-green text-green'\n >\n <div className='d-flex flex-column align-items-center my-auto gap-2'>\n {!!props.engagement &&\n <>\n <PercentageIndicator\n percentage={engagementRate}\n layout={PercentageIndicatorLayout.LabelInside}\n />\n <p className='text-center'>\n {typeof engagementRate === 'number' ?\n <Text namespace={namespace} phrase='everyoneWatched' options={{ percentage }} /> :\n <Text namespace={namespace} phrase='notWatched' />\n }\n </p>\n </>\n }\n {!props.engagement &&\n <>\n <PartialPercentageIndicator layout={PercentageIndicatorLayout.LabelInside} />\n </>\n }\n </div>\n </InsightCard>\n );\n}\n","const CHART_COLOURS = [\n '#FF9300', // Pizazz\n '#38A2E8', // Picton Blue\n '#7A76E8', // Portage\n '#B679C7', // East Side\n '#F7847B', // Froly\n '#D9584F', // Red (Not in the Primary palette)\n '#FFCD52', // Yellow (Not in the Primary Palette)\n '#5DC786', // Emerald\n '#40BCC3', // Perolous\n '#40C2BB' // Puerto rico\n];\n\nexport function mixinSeriesColours<T>(data: T[]): T[] {\n return data.map((d, idx) => ({\n ...d,\n color: CHART_COLOURS[idx % CHART_COLOURS.length]\n }));\n}\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { HashObject } from 'libs/analytics/interfaces';\n\nimport { BaseAnalyticsEventResponse, GroupedAnalyticsCount } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { UnionEventResponse } from 'libs/shared/apps/analytics/interfaces/UnionEvent';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { mixinSeriesColours } from 'libs/shared/apps/analytics/utils/ChartColourUtils';\n\ntype EventResponseGroupByAttributes = keyof Pick<VideoViewEventResponse, 'contentTypeCount'> |\n keyof Pick<BaseAnalyticsEventResponse, 'userTypeCount' | 'yearGroupCount'>;\n\nexport function groupEvents(\n events: UnionEventResponse,\n groupBy: EventResponseGroupByAttributes,\n groupsToOmit?: string[],\n getSeriesName?: (group: string) => string\n): Highcharts.PointOptionsObject[] {\n const groups: HashObject<number> = {};\n\n const eventCounts = events[groupBy as keyof UnionEventResponse] as GroupedAnalyticsCount[];\n\n eventCounts?.forEach(ev => {\n const name = ev.name || 'Unknown';\n\n if (!name || groupsToOmit?.includes(name.toLowerCase()))\n return;\n\n groups[name] = groups[name] ?? 0;\n groups[name] += ev.count;\n });\n\n return mixinSeriesColours(ArrayHelper.sortBy(Object.keys(groups).map(group => ({\n name: getSeriesName ? getSeriesName(group) : group,\n y: groups[group],\n type: 'pie'\n })), 'name'));\n}\n\nexport function sortByYearGroup(data: Highcharts.PointOptionsObject[]) {\n const staffIndex = data.findIndex(group => group.name === 'Staff');\n\n // Move Staff to last index\n if (staffIndex > -1) {\n const [staffObject] = data.splice(staffIndex, 1);\n\n data.push(staffObject);\n }\n return data.sort((a, b) => {\n const numA = parseInt((a.name as string).match(/\\d+/)?.[0]);\n const numB = parseInt((b.name as string).match(/\\d+/)?.[0]);\n return numA - numB;\n });\n}\n\nexport function getTotalEventCount(data?: Highcharts.PointOptionsObject[]): number | null {\n return data?.reduce((a, b) => a + b.y, 0) ?? null;\n}\n","import React from 'react';\nimport Highcharts from 'highcharts';\nimport { HighchartsReact } from 'highcharts-react-official';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { InsightCard } from 'libs/shared/apps/analytics/components/insight-card/InsightCard';\nimport { CHART_FONT_STYLES } from 'libs/shared/apps/analytics/constants/ChartStyles';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { getTotalEventCount, groupEvents, sortByYearGroup } from 'libs/shared/apps/analytics/utils/SharedUserActivityPieChartUtils';\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { VisibleOnSvg } from 'libs/shared/images/svg/actions/VisibleOnSvg';\n\nconst namespace = 'shared.insightTotalViews';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction mapUserTypeToChartLabel(type: string): string {\n if (type === 'Unknown')\n return getPhrase('anon');\n return type;\n}\n\nconst STATIC_CHART_OPTIONS: Highcharts.Options = {\n title: {\n text: null\n },\n credits: {\n enabled: false\n },\n chart: {\n backgroundColor: 'transparent',\n spacing: [ 0, 0, 0, 0 ]\n },\n legend: {\n itemStyle: CHART_FONT_STYLES,\n itemDistance: 8\n },\n plotOptions: {\n pie: {\n allowPointSelect: true,\n cursor: 'pointer',\n dataLabels: {\n enabled: false\n },\n showInLegend: true,\n borderWidth: 1,\n borderColor: '#ffffff',\n borderRadius: 0,\n size: '80%'\n }\n }\n};\n\ninterface InsightTotalViewsProps {\n events: VideoViewEventResponse;\n emptyStateImage: string;\n hideStaffResults: boolean;\n}\n\nexport function InsightTotalViews(props: InsightTotalViewsProps) {\n const grouped = groupEvents(\n props.events,\n 'yearGroupCount',\n props.hideStaffResults ? ['staff'] : [],\n mapUserTypeToChartLabel\n );\n const chartData = sortByYearGroup(grouped);\n const totalViews = getTotalEventCount(chartData);\n\n function getChartOptions(\n data: Highcharts.PointOptionsObject[]\n ): Highcharts.Options {\n return {\n ...STATIC_CHART_OPTIONS,\n series: [{\n type: 'pie',\n name: getPhrase('title'),\n data\n }]\n };\n }\n\n return (\n <InsightCard\n title={getPhrase('title')}\n // Replace with ultra marine + light colour\n svgClassName='bg-light-blue text-blue'\n // Add visibility icon \n svg={VisibleOnSvg}\n >\n {chartData?.length ? (\n <>\n <p className='mb-0'><Text namespace={namespace} phrase='totalViews' options={{ totalViews }} /></p>\n\n <div className='d-flex justify-content-center h-75'>\n <HighchartsReact\n highcharts={Highcharts}\n options={getChartOptions(chartData)}\n containerProps={{\n className: `w-100`\n }}\n />\n </div>\n </>\n ) : (\n <EmptyState className='pt-0 my-auto'>\n <EmptyState.Image src={props.emptyStateImage} className='w-75 h-auto'></EmptyState.Image>\n <EmptyState.Heading className='h4'><Text namespace={namespace} phrase='noViews' /></EmptyState.Heading>\n <EmptyState.Info className='w-100'><Text namespace={namespace} phrase='notWatched' /></EmptyState.Info>\n </EmptyState>\n )}\n </InsightCard>\n );\n}\n",":local {\n .partialInsights {\n height: 21.5rem;\n }\n\n .videoContainer {\n width: 44%;\n }\n}","import React from 'react';\n\nimport styles from './partial-insights-heatmap.module.scss';\n\nexport function PartialInsightsHeatmap() {\n return (\n <div>\n <div className='row g-3 mb-3'>\n <div className='col'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n <div className='col'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n <div className={styles.videoContainer}>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n </div>\n\n <div className='row g-3 mb-5'>\n <div className='col-12'>\n <div className={`${styles.partialInsights} rounded partial-loading-background`}></div>\n </div>\n </div>\n </div>\n );\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface EngagementOverlayMenuItemOptions extends videojs.MenuItemOptions {\n overlayVisible: boolean;\n}\n\nexport class EngagementOverlayMenuItem extends MenuItem {\n private toggleEl: Element;\n private overlayVisible: boolean;\n\n /**\n * Because we want to bind our listener in createEl\n * and createEl runs in super. We store if we've bounud\n * our handler, so we only call bind once and \n * the call to removeEventListener will still work\n */\n private handlerBound: boolean;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayMenuItemOptions) {\n super(player, options);\n\n this.overlayVisible = options.overlayVisible;\n this.toggle(this.overlayVisible);\n }\n\n public handleToggle(): void {\n this.toggle(!this.overlayVisible);\n }\n\n private toggle(state: boolean): void {\n state ? this.toggleOn() : this.toggleOff();\n }\n\n private toggleOn(): void {\n videojs.dom.addClass(this.toggleEl, 'on');\n this.overlayVisible = true;\n this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible);\n this.player().addClass('cv-reports-player-overlay-visible');\n }\n\n private toggleOff(): void {\n videojs.dom.removeClass(this.toggleEl, 'on');\n this.overlayVisible = false;\n this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible);\n this.player().removeClass('cv-reports-player-overlay-visible');\n }\n\n /**\n * Because we extend MenuItem which will close the menu by default\n * we need to halt the event propogation here\n */\n public handleClick(event: videojs.EventTarget.Event): void {\n event.stopImmediatePropagation();\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): HTMLLIElement {\n /**\n * Bind our event listener only once\n * see the comment where handlerBound is defined\n */\n if (!this.handlerBound) {\n this.handleToggle = this.handleToggle.bind(this);\n this.handlerBound = true;\n }\n\n if (this.toggleEl)\n this.toggleEl.removeEventListener('click', this.handleToggle);\n\n this.toggleEl = videojs.dom.createEl('div', {\n className: `custom-toggle custom-toggle-info toggle-option float-end`,\n innerHTML: '<span class=\"handle\"></span></div>'\n });\n this.toggleEl.addEventListener('click', this.handleToggle);\n\n const innerHTML = `\n <span class=\"vjs-menu-item-text\">Heat Map</span>\n <span class=\"cv-toggle-container\"></span>`;\n\n const el = super.createEl(tagName, {\n className: 'vjs-menu-item cv-cog-menu-item',\n innerHTML\n }, attributes);\n\n /**\n * Indexing into the child this way is only safe to do because\n * we know that the el only has two children\n */\n el.children[1].appendChild(this.toggleEl);\n\n return el;\n }\n}\n\nvideojs.registerComponent('EngagementOverlayMenuItem', EngagementOverlayMenuItem);\n","import React from 'react';\n\nimport { InteractionLabel } from 'libs/shared/components/interactive-questions/InteractionLabel';\nimport { Interactive } from 'libs/shared/interfaces';\n\nconst MAX_INTERACTIONS_TO_SHOW = 3;\n\ninterface TimepointInteractionsProps {\n interactive: Interactive;\n time: number;\n}\n\nexport function TimepointInteractions(props: TimepointInteractionsProps): JSX.Element {\n const timepoint = props.interactive.timepoints.find(t => {\n const timepointTime = t.visibleAt / 1000;\n \n return Math.floor(props.time) === Math.floor(timepointTime)\n || Math.ceil(props.time) === Math.ceil(timepointTime);\n });\n\n if (!timepoint?.interactions?.length)\n return <></>;\n\n const interactions = timepoint.interactions.length > MAX_INTERACTIONS_TO_SHOW ?\n timepoint.interactions.slice(0, MAX_INTERACTIONS_TO_SHOW - 1) :\n timepoint.interactions;\n\n const hiddenInteractions = timepoint.interactions.length - interactions.length;\n\n return (\n <div className='d-flex justify-content-end ms-2'>\n {interactions.map((i, idx) => (\n <InteractionLabel\n key={idx}\n interaction={i}\n showQuestion={false}\n iconClassName='ms-1'\n />\n ))}\n {!!hiddenInteractions &&\n <div\n className={'interaction-type-icon d-flex justify-content-center' +\n ' align-items-center border border-dark text-body ms-1'}\n >\n {`+${hiddenInteractions}`}\n </div>\n }\n </div>\n );\n}\n","import React from 'react';\nimport { renderToStaticMarkup } from 'react-dom/server';\nimport Highcharts from 'highcharts';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { TimepointInteractions } from 'projects/player/plugins/engagement-overlay-plugin/components/timepoint-interactions/timepoint-interactions';\nimport { formatTime } from 'projects/player/utils/formatTime';\n\nexport const STATIC_CHART_OPTIONS: Highcharts.Options = {\n title: {\n text: null\n },\n xAxis: {\n visible: false,\n minPadding: 0,\n maxPadding: 0\n },\n legend: {\n enabled: false\n },\n credits: {\n enabled: false\n },\n defs: {\n gradient: ({\n tagName: 'linearGradient',\n id: 'area-gradient',\n x1: 0,\n y1: 1,\n x2: 0,\n y2: 0,\n children: [\n ({\n tagName: 'stop',\n offset: 0\n } as Highcharts.ASTNode),\n ({\n tagName: 'stop',\n offset: 1\n } as Highcharts.ASTNode)\n ]\n } as Highcharts.ASTNode)\n }\n};\n\nexport function getChartOptions(width: number, height: number): Highcharts.ChartOptions {\n return {\n styledMode: true,\n spacing: [ 15, 0, 0, 0 ],\n width,\n height\n };\n}\n\nexport function getYAxisChartOptions(heatMap: number[]): Highcharts.YAxisOptions {\n const maxValue = Math.max(...heatMap);\n\n return {\n /**\n * To prevent max values from being cut off, we pad them relative to the chart scale.\n */\n max: maxValue * 1.05,\n min: 0,\n minPadding: 0,\n maxPadding: 0,\n allowDecimals: true,\n startOnTick: false,\n endOnTick: false,\n visible: false\n };\n}\n\nexport function getTooltipOptions(interactive?: Interactive): Highcharts.TooltipOptions {\n return {\n formatter: function () {\n const timepointInteractionsHtml = interactive ?\n getTimepointInteractionsHtml(interactive, this.x) :\n '';\n\n return (\n '<div class=\"cv-engagement-tooltip bg-white rounded\">' +\n '<div class=\"d-flex justify-content-between\">' +\n `<strong>${formatTime(this.x)}</strong>` +\n `${timepointInteractionsHtml}` +\n '</div>' +\n '<div class=\"d-flex justify-content-between rounded bg-light cv-view-count-container\">' +\n `<strong>Views</strong> <span class=\"cv-view-count\">${this.y}</span>` +\n '</div>' +\n '</div>'\n );\n },\n positioner: function (\n labelWidth: number,\n labelHeight: number,\n point: Highcharts.TooltipPositionerPointObject\n ) {\n const minX = 0;\n const maxX = this.chart.plotWidth - labelWidth;\n const x = point.plotX - labelWidth / 2;\n \n return {\n // Clamp x between min and max\n x: Math.min(Math.max(x, minX), maxX),\n y: this.chart.plotTop\n };\n },\n useHTML: true,\n padding: 0\n };\n}\n\nexport function getPlotOptions(moveTimepointIndicator: (x: number | null) => void): Highcharts.PlotOptions {\n return {\n area: {\n point: {\n events: {\n mouseOver: function () {\n moveTimepointIndicator(this.x);\n },\n mouseOut: function () {\n moveTimepointIndicator(null);\n }\n }\n }\n },\n series: {\n marker: {\n enabled: false\n }\n }\n };\n}\n\nfunction getTimepointInteractionsHtml(interactive: Interactive, time: number): string {\n return renderToStaticMarkup(\n <TimepointInteractions time={time} interactive={interactive} />\n );\n}\n","import Highcharts from 'highcharts';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport {\n getChartOptions,\n getPlotOptions,\n getTooltipOptions,\n getYAxisChartOptions,\n STATIC_CHART_OPTIONS\n} from './engagement-overlay-chart-options';\n\nimport './engagement-overlay.scss';\n\nconst Component = videojs.getComponent('Component');\n\nHighcharts.AST.allowedTags.push('g');\nHighcharts.AST.allowedAttributes.push('viewBox', 'transform');\n\ninterface ChartDimensions {\n width: number;\n height: number;\n}\n\ninterface EngagementOverlayOptions extends videojs.ComponentOptions {\n heatMap: number[];\n interactive?: Interactive;\n onTimepointHover?: (time: number | null) => void;\n}\n\nexport class EngagementOverlay extends Component {\n public options_: EngagementOverlayOptions;\n private chart: Highcharts.Chart;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayOptions) {\n super(player, options);\n\n this.initialize();\n this.bindListeners();\n }\n\n public initialize(): void {\n this.player().ready(() => this.buildChart());\n }\n\n public buildCSSClass(): string {\n return 'cv-engagement-overlay';\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const innerHTML = '<div class=\"cv-engagement-chart\"></div>' +\n '<div class=\"cv-engagement-timepoint-indicator\"></div>';\n\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass(),\n innerHTML\n }, attributes);\n }\n\n public toggleChart(show: boolean): void {\n if (show)\n this.buildChart();\n else\n this.destroyChart();\n }\n\n private bindListeners(): void {\n this.handleClick = this.handleClick.bind(this);\n this.resizeChart = this.resizeChart.bind(this);\n\n this.player().on('playerresize', this.resizeChart);\n\n this.on(this.el(), 'mouseup', this.handleClick);\n\n this.player().on('dispose', () => {\n this.player().off('playerresize', this.resizeChart);\n\n this.off(this.el(), 'mouseup', this.handleClick);\n });\n }\n\n private handleClick(event: videojs.EventTarget.Event): void {\n if (!videojs.dom.isSingleLeftClick(event))\n return;\n\n if (this.player().paused()) {\n this.player().play();\n return;\n }\n\n this.player().pause();\n }\n\n private buildChart(): void {\n if (this.chart)\n return;\n\n const chartDimensions = this.getChartDimensions();\n\n /**\n * The dimensions calculation relies on the control bar and progress control\n * being visible, so if it isn't, we wait for the play event.\n */\n if (!chartDimensions) {\n this.player().one('play', () => this.buildChart());\n return;\n }\n\n const container: HTMLElement = this.el().querySelector('.cv-engagement-chart');\n\n this.chart = Highcharts.chart(container, this.getHighchartOptions(chartDimensions));\n }\n\n private resizeChart(): void {\n const chartDimensions = this.getChartDimensions();\n\n if (!this.chart || !chartDimensions)\n return;\n\n this.chart.setSize(chartDimensions.width, chartDimensions.height);\n }\n\n private destroyChart(): void {\n this.chart?.destroy();\n this.chart = null;\n }\n\n private getChartDimensions(): ChartDimensions {\n const collapserator = this.player().getChild('collapserator');\n const collapseratorHeight = collapserator?.currentHeight();\n\n const width = this.el().clientWidth;\n\n if (!collapseratorHeight || !width)\n return null;\n\n const { height } = this.player().currentDimensions();\n \n return {\n width,\n height: height - collapseratorHeight\n };\n }\n\n private getHighchartOptions({ width, height }: ChartDimensions): Highcharts.Options {\n return {\n ...STATIC_CHART_OPTIONS,\n chart: getChartOptions(width, height),\n yAxis: getYAxisChartOptions(this.options_.heatMap),\n tooltip: getTooltipOptions(this.options_.interactive),\n plotOptions: getPlotOptions(this.moveTimepointIndicator.bind(this)),\n series: [{\n type: 'area',\n data: this.options_.heatMap\n }]\n };\n }\n\n private moveTimepointIndicator(x: number | null): void {\n if (this.options_.onTimepointHover)\n this.options_.onTimepointHover(x);\n\n const indicator: HTMLDivElement = this.el().querySelector('.cv-engagement-timepoint-indicator');\n\n if (x === null) {\n videojs.dom.removeClass(indicator, 'cv-engagement-timepoint-indicator-visible');\n return;\n }\n\n videojs.dom.addClass(indicator, 'cv-engagement-timepoint-indicator-visible');\n indicator.style.left = `${x / this.options_.heatMap.length * 100}%`;\n }\n}\n\nvideojs.registerComponent('EngagementOverlay', EngagementOverlay);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { CogButton } from 'projects/player/components/cog-button/cog-button';\nimport { EngagementOverlay } from 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay';\nimport { EngagementOverlayMenuItem } from 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay-menu-item/engagement-overlay-menu-item';\n\nimport 'projects/player/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface EngagementOverlayPluginOptions {\n heatMap: number[];\n interactive?: Interactive;\n onTimepointHover?: (time: number | null) => void;\n}\n\nclass EngagementOverlayPlugin extends Plugin {\n private options: EngagementOverlayPluginOptions;\n\n constructor(player: VideoJsPlayer, options: EngagementOverlayPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => {\n this.initialize();\n });\n }\n \n private initialize(): void {\n if (!this.hasHeatMapData())\n return;\n\n this.player.addChild('engagementOverlay', {\n heatMap: this.options.heatMap,\n interactive: this.options.interactive,\n onTimepointHover: this.options.onTimepointHover\n });\n\n /**\n * Check additionalItemOrder in cog-button.ts if you need to change the order. - Sha\n */\n const cogButton = this.player.getChild('collapserator')?.getChild('cogButton') as CogButton;\n cogButton.addItem({\n ctor: EngagementOverlayMenuItem,\n name: 'EngagementOverlayMenuItem',\n options: { overlayVisible: true }\n });\n }\n\n public toggleOverlay(show: boolean): void {\n const engagementOverlay = this.player.getChild('engagementOverlay') as EngagementOverlay;\n engagementOverlay?.toggleChart(show);\n }\n\n private hasHeatMapData(): boolean {\n return this.options.heatMap?.reduce((acc, val) => acc + val, 0) > 0;\n }\n}\n\nvideojs.registerPlugin('engagementOverlayPlugin', EngagementOverlayPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n engagementOverlayPlugin(options?: EngagementOverlayPluginOptions): EngagementOverlayPlugin;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { InteractiveBarItems } from 'projects/player/plugins/interactive-plugin/components/seek-bar/interactive-bar-items';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nimport './interactive-plugin-styles.scss';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface InteractiveSeekBarPluginOptions {\n interactive: Interactive;\n}\n\n/**\n * This plugin will just render the interactive seek bar (i.e. just the interaction markers).\n * The user won't be able to interact with any of the interactions.\n * Currently this is just used in reports-player\n */\nclass InteractiveSeekBarPlugin extends Plugin {\n private options: InteractiveSeekBarPluginOptions;\n\n constructor(player: VideoJsPlayer, options: InteractiveSeekBarPluginOptions) {\n super(player);\n\n this.options = options;\n\n this.player.one('loadedmetadata', () => this.player.ready(this.initialize.bind(this)));\n }\n\n private initialize(): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n TrackHelper.useMetadataTrack(this.player, 'interactive', this.onTrackLoaded.bind(this));\n\n this.player.addClass('cv-interactive-plugin');\n }\n\n private onTrackLoaded(track: TextTrack): void {\n this.addChildren(track);\n }\n\n private addChildren(track: TextTrack): void {\n const seekBar = this.player.controlBar.getChild('progressControl').getChild('SeekBar');\n\n seekBar.addChild(new InteractiveBarItems(this.player, {\n interactive: this.options.interactive,\n track\n }));\n }\n}\n\nvideojs.registerPlugin('interactiveSeekBarPlugin', InteractiveSeekBarPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n interactiveSeekBarPlugin(options?: InteractiveSeekBarPluginOptions): InteractiveSeekBarPlugin;\n }\n}\n","import { Interactive } from 'libs/shared/interfaces';\n\nimport { ClipData } from 'projects/player/interfaces/models/ClipData';\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\nimport { BasePlayer, BasePlayerOptions } from 'projects/player/players/base-player';\nimport { AnalyticsPlayerType } from 'projects/player/services/analytics-service';\nimport { InteractiveTrackHelper } from 'projects/player/utils/interactive-track-helper';\n\nimport './reports-player.scss';\n\nimport 'projects/player/plugins/engagement-overlay-plugin/engagement-overlay-plugin';\nimport 'projects/player/plugins/clip-plugin/clip-plugin';\nimport 'projects/player/plugins/interactive-plugin/interactive-seek-bar-plugin';\nimport 'projects/player/plugins/old-version-refresh-plugin/old-version-refresh-plugin';\n\nexport interface ReportsPlayerOptions extends BasePlayerOptions {\n heatMap: number[];\n onTimepointHover?: (time: number | null) => void;\n}\n\nexport class ReportsPlayer extends BasePlayer {\n declare protected options: ReportsPlayerOptions;\n private track: TextTrack;\n\n constructor(id: string | Element, options: ReportsPlayerOptions) {\n super(id, options);\n }\n\n protected getPlayerClassName(): string {\n return 'cv-reports-player';\n }\n\n protected getAnalyticsPlayerType(): AnalyticsPlayerType {\n return 'reports-player';\n }\n\n protected async additionalSetup(playbackObject: PlaybackObject): Promise<void> {\n super.additionalSetup(playbackObject);\n\n this.setupEngagementOverlayPlugin(playbackObject);\n this.setupUpClipPlugin(playbackObject);\n this.setupInteractiveSeekBarPlugin(playbackObject);\n }\n\n private setupEngagementOverlayPlugin(playbackObject: PlaybackObject): void {\n this.player.engagementOverlayPlugin({\n heatMap: this.options.heatMap,\n interactive: playbackObject.additionalData?.interactive as Interactive,\n onTimepointHover: this.options.onTimepointHover\n });\n }\n\n private setupUpClipPlugin(playbackObject: PlaybackObject): void {\n const isClip = playbackObject.mediaType === 'MasterClip';\n const isInteractive = playbackObject.mediaType === 'MasterInteractive';\n\n if (!isClip && !isInteractive)\n return;\n\n let clipData: ClipData;\n if (isClip)\n clipData = playbackObject.additionalData;\n \n if (isInteractive) {\n clipData = playbackObject.additionalData?.clipData;\n\n // Not all interactives will have clip data\n if (!clipData)\n return;\n }\n\n if (!clipData)\n throw Error('Invalid clip data');\n\n this.player.clipPlugin({\n startTime: clipData.startTime,\n endTime: clipData.endTime\n });\n }\n\n private setupInteractiveSeekBarPlugin(playbackObject: PlaybackObject): void {\n const interactive = playbackObject.additionalData?.interactive as Interactive;\n\n if (!playbackObject.additionalData?.interactive)\n return;\n\n this.track = InteractiveTrackHelper.getInteractiveTrack(this.player, playbackObject);\n\n this.player.interactiveSeekBarPlugin({ interactive });\n }\n\n protected getSeekBarOptions(): any {\n return {\n ignoreChapters: true\n };\n }\n}\n","import React from 'react';\n\nimport { ReportsPlayer, ReportsPlayerOptions } from 'projects/player/players/reports/reports-player';\n\nexport function ClickViewReportsPlayer(props: ReportsPlayerOptions): React.ReactElement {\n const ref = React.useRef(null);\n const playerRef = React.useRef<ReportsPlayer>(null);\n\n React.useEffect(() => {\n playerRef.current = new ReportsPlayer(ref.current, props);\n }, []);\n\n return (\n <div ref={ref}></div>\n );\n}\n",":local {\n .playerContainer {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n }\n\n .playerPlaceholder {\n width: 100%;\n padding-bottom: 56.25%;\n }\n\n .heatMap {\n height: 1rem;\n }\n\n .heatMapTimepointIndicator {\n border-left: 0.125rem dashed $info;\n margin-left: -0.0625rem;\n position: absolute;\n top: 0;\n bottom: 0;\n opacity: 0;\n visibility: hidden;\n\n &.heatMapTimepointIndicatorVisible {\n opacity: 1;\n visibility: visible;\n }\n }\n\n .partialLoadingContainer {\n height: 24.015625rem;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EngagementHeatMap, EngagementHeatMapLegend } from 'libs/shared/apps/analytics/components/engagement-heat-map/EngagementHeatMap';\nimport { getFullHeatMap } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { Engagement } from 'libs/shared/interfaces';\n\nimport { ClickViewReportsPlayer } from 'projects/player/react/ReportsPlayer';\n\nimport styles from './video-engagement-overlay.module.scss';\n\nconst namespace = 'shared.videoEngagementOverlay';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface VideoEngagementOverlayProps {\n engagement: Engagement;\n viewKey: string;\n imageCdnUrl: string;\n playerApiUrl: string;\n}\n\nexport function VideoEngagementOverlay(props: VideoEngagementOverlayProps): JSX.Element {\n const timepointIndicatorRef = React.useRef<HTMLDivElement>(null);\n\n const heatMap = getFullHeatMap(props.engagement);\n\n function setHoverTimepoint(time: number | null): void {\n const el = timepointIndicatorRef.current;\n\n if (!el)\n return;\n\n if (time === null) {\n el.classList.remove(styles.heatMapTimepointIndicatorVisible);\n return;\n }\n\n el.classList.add(styles.heatMapTimepointIndicatorVisible);\n el.style.left = `${time / heatMap.length * 100}%`;\n }\n\n return (\n <div className='bg-white border rounded overflow-hidden h-100'>\n <div className='position-relative'>\n {/**\n * The below div is an empty 16:9 rectangle which maintains this component's\n * height while the player is loading.\n */\n }\n <div className={styles.playerPlaceholder} />\n <div className={styles.playerContainer}>\n <ClickViewReportsPlayer\n viewKey={props.viewKey}\n playerApi={new URL(props.playerApiUrl)}\n hotkeyElQuerySelector='body'\n heatMap={heatMap}\n onTimepointHover={setHoverTimepoint}\n aspectRatio='16:9'\n />\n </div>\n </div>\n <div className='p-3'>\n <div className='position-relative'>\n <EngagementHeatMap\n engagement={props.engagement}\n className={styles.heatMap}\n />\n <div ref={timepointIndicatorRef} className={styles.heatMapTimepointIndicator} />\n </div>\n <div className='d-flex justify-content-between mt-2'>\n <strong>\n {getPhrase('heatmap')}\n </strong>\n <div className='w-33'>\n <EngagementHeatMapLegend />\n </div>\n </div>\n </div>\n </div>\n );\n}\n",":local {\n .videoContainer {\n width: 44%;\n }\n}","import React from 'react';\n\nimport { EngagementTable } from 'libs/shared/apps/analytics/components/engagement-table/EngagementTable';\nimport { InsightAmountWatched } from 'libs/shared/apps/analytics/components/insights/amount-watched/InsightAmountWatched';\nimport { InsightTotalViews } from 'libs/shared/apps/analytics/components/insights/total-views/InsightTotalViews';\nimport { GroupedAnalyticsCount } from 'libs/shared/apps/analytics/interfaces/BaseAnalyticsEvent';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { Config, Engagement, PlayerViewKey } from 'libs/shared/interfaces';\nimport { AnonUser } from 'libs/shared/interfaces/models/interactive-results/AnonUser';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\n\nimport { PartialInsightsHeatmap } from 'apps/my-shares/components/insights-heatmap/partial-loading/PartialInsightsHeatmap';\nimport { VideoEngagementOverlay } from 'apps/my-shares/components/video-engagement-overlay/VideoEngagementOverlay';\n\nimport styles from './insights-heatmap.module.scss';\n\ninterface InsightsHeatmapProps {\n hasDataLoaded: boolean;\n tableDataLoaded: boolean;\n yearGroups: GroupedAnalyticsCount[];\n aggregateEngagement: Engagement;\n individualEngagement: Engagement[];\n viewKey: PlayerViewKey;\n config: Config;\n users: AnonUser[];\n classroomStudents?: AnonUser[];\n anonymiseUsers: boolean;\n hideStaffResults: boolean;\n}\n\nexport function InsightsHeatmap(props: InsightsHeatmapProps) {\n return (\n <>\n {!props.hasDataLoaded && <PartialInsightsHeatmap />}\n\n <div className='row g-3 mb-3'>\n {props.hasDataLoaded &&\n <>\n <div className='col'>\n <InsightTotalViews\n events={{ yearGroupCount: props.yearGroups } as VideoViewEventResponse}\n emptyStateImage={ImageUrls.EmptyStates.MY_VIDEOS}\n hideStaffResults={props.hideStaffResults}\n />\n </div>\n <div className='col'>\n <InsightAmountWatched engagement={props.individualEngagement} />\n </div>\n <div className={styles.videoContainer}>\n <VideoEngagementOverlay\n engagement={props.aggregateEngagement}\n viewKey={props.viewKey.viewKey}\n playerApiUrl={props.config.playerApiUrl}\n imageCdnUrl={props.config.imageCdnUrl}\n />\n </div>\n </>\n }\n\n {props.tableDataLoaded &&\n <div className='col-12'>\n <EngagementTable\n engagement={props.individualEngagement}\n users={props.users}\n imageCdnUrl={props.config?.imageCdnUrl}\n anonymiseUsers={props.anonymiseUsers}\n classroomStudents={props.classroomStudents}\n border\n enableSort\n showSeparateNameColumns\n />\n </div>\n }\n </div>\n </>\n );\n}\n"],"mappings":"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"}
|
|
@@ -222,7 +222,7 @@ ${fp(e)}`),t.map&&!t.map.bytes&&(this.logger_(`going to request init segment.`),
|
|
|
222
222
|
fill='currentColor'
|
|
223
223
|
/>
|
|
224
224
|
</svg>
|
|
225
|
-
`,Uh=class extends Bh{constructor(e,t){super(e,t)}createEl(){let e=Vh.prototype.createEl.call(this,`button`,{className:this.buildCSSClass()},{type:`button`,title:this.controlText_});return e.innerHTML=Hh,this.createControlTextEl(e),e}handleClick(e){e.stopPropagation(),e.preventDefault(),this.options_?.onClick&&this.options_.onClick()}buildCSSClass(){return`cv-remove-video-button`}};Z.registerComponent(`removeVideoButton`,Uh),Uh.prototype.controlText_=`Remove from watch history`;var Wh=function(e){return e.Default=`play`,e.Hover=`hover`,e}({}),Gh=Z.getPlugin(`plugin`),Kh=`cv-preview-mode`,qh=`cv-force-16-9`,Jh=class extends Gh{constructor(e,t){super(e),this.hasSeeked=!1,this.buttonAdded=!1,this.mode=null,this.defaultDisplayMode=`normal`,this.onQualityReady=null,t?.defaultDisplayMode&&(this.defaultDisplayMode=t.defaultDisplayMode),t?.startTime&&(this.startTime=t.startTime),this.onSeek=this.onSeek.bind(this),this.player.one(`seeking`,this.onSeek)}onSeek(){this.hasSeeked=!0}dispose(){this.cleanupQualityListener(),this.player.off(`seeking`,this.onSeek),super.dispose()}getMode(){return this.mode}isHovering(){return this.mode===`hover`}setPlayerMode(e,t,n){this.player.trigger(`flushprogress`);let r=this.mode;if(this.mode=e,e===`hover`){this.buttonAdded||this.addButtons(t,n),this.player.addClass(Kh),this.applyAspectRatioFix(),this.enableSubtitles(),this.mute(),this.setLowQuality(),this.removeActivityTimeout(),this.player.trigger(`resize`);return}r===`hover`&&(this.applyDefaultModeLayout(),this.player.removeClass(Kh),this.player.removeClass(qh),this.disableSubtitles(),this.unmute(),this.cleanupQualityListener(),this.restorePreviousQuality(),this.restoreActivityTimeout(),this.player.trigger(`resize`),this.hasSeeked||=(this.player.currentTime(this.startTime??0),!1))}applyDefaultModeLayout(){let e=this.player.usingPlugin?.(`theatreModePlugin`);this.defaultDisplayMode===`theatre`?(e&&this.player.theatreModePlugin()?.toggleTheatreMode(!0),this.player.fill(!0)):(e&&this.player.theatreModePlugin()?.toggleTheatreMode(!1),this.player.fluid(!0))}applyAspectRatioFix(){let e=()=>{let e=this.player.videoWidth(),t=this.player.videoHeight();if(e>0&&t>0){let n=e/t;Math.abs(n-16/9)<.01||this.player.addClass(qh)}};this.player.readyState()>=1?e():this.player.one(`loadedmetadata`,e)}addButtons(e,t){let n=new Lh(this.player),r=new zh(this.player,{onClickHandler:e}),i=new Uh(this.player,{onClick:t});t&&A.isFunction(t)&&this.player.addChild(i),this.player.addChild(n),this.player.addChild(r),this.buttonAdded=!0}enableSubtitles(){this.player.dataLoaded(()=>this.player.persistSubtitleSettingsPlugin().previewModeSubtitles())}disableSubtitles(){this.player.dataLoaded(()=>this.player.persistSubtitleSettingsPlugin().applyUserPreferences())}mute(){this.player.ready(()=>{this.player.persistVolumePlugin().disable(),this.player.muted(!0)})}unmute(){this.player.ready(()=>{this.player.persistVolumePlugin().applyUserPreferences(),this.player.persistVolumePlugin().enable()})}setLowQuality(){this.player.dataLoaded(()=>{this.mode===`hover`&&(this.player.persistQualitySettingsPlugin().disable(),this.cleanupQualityListener(),this.onQualityReady=()=>{this.mode===`hover`&&this.player.qualityManager().selectLowest()},this.player.on(`quality-levels-changed`,this.onQualityReady),this.player.qualityManager().selectLowest())})}cleanupQualityListener(){this.onQualityReady&&=(this.player.off(`quality-levels-changed`,this.onQualityReady),null)}restorePreviousQuality(){this.player.dataLoaded(()=>{this.player.persistQualitySettingsPlugin().applyUserPreferences(),this.player.persistQualitySettingsPlugin().enable()})}removeActivityTimeout(){this.player.cache_.inactivityTimeout=this.player.options_.inactivityTimeout,this.player.options_.inactivityTimeout=0}restoreActivityTimeout(){this.player.options_.inactivityTimeout=this.player.cache_.inactivityTimeout}};Z.registerPlugin(`playerModePlugin`,Jh);function Yh(e,t){for(let n of e)if(n.quality<=t)return n;return e[e.length-1]}var Xh=`cvplayer-playback-quality:v2`,Zh=`cvplayer-localcache-playback-quality:v2`,Qh=`cvplayer-dash-playback-quality:v1`,$h=`auto`,eg=480*60*1e3;function tg(e){return e?Zh:Xh}var ng={hasStoredPreference(){return P.hasLocalStorage()?!!(P.get(`cvplayer-playback-quality:v2`)||P.get(`cvplayer-localcache-playback-quality:v2`)||P.get(`cvplayer-dash-playback-quality:v1`)):!1},storeProgressive(e,t){P.hasLocalStorage()&&P.set(tg(t),e.toString())},resolveProgressive(e,t=!1){let n=t?e?.playbackQualityLocalCache:e?.playbackQuality,r=(P.hasLocalStorage()?P.get(tg(t)):null)||n||e?.playbackQualityFallback;if(!r)return null;let i=parseInt(r);return isNaN(i)?null:i},resolveDash(){if(!P.hasLocalStorage())return $h;let e=P.get(Qh);if(!e)return $h;try{let t=JSON.parse(e);if(typeof t?.quality==`number`&&typeof t?.expiresAt==`number`&&t.expiresAt>Date.now())return t.quality}catch{}return $h},storeDashLock(e){if(!P.hasLocalStorage())return;let t={quality:e,expiresAt:Date.now()+eg};P.set(Qh,JSON.stringify(t))},clearDashLock(){P.hasLocalStorage()&&P.remove(Qh)}};function rg(e,t){let n=e.currentTime(),r=!e.paused(),i=e.hasStarted();e.src(t);let a=()=>{e.off(`error`,o),e.currentTime()!==n&&e.currentTime(n),r&&e.play()?.catch(()=>void 0),i&&e.hasStarted(!0)},o=()=>e.off(`loadedmetadata`,a);e.one(`loadedmetadata`,a),e.one(`error`,o)}var ig=`application/dash+xml`,ag={sortFilesByQuality(e){return{...e,progressive:[...e.progressive].sort((e,t)=>t.quality-e.quality)}},getSignedDashUrl(e,t){let n=e.manifests?.dashUrl;if(n)return`${n}?viewKey=${t}`},getDashSource(e,t,n){let r=ag.getSignedDashUrl(e,t);if(r)return{src:r,type:ig,useBandwidthFromLocalStorage:!n}},getDefaultProgressiveFile(e,t,n){let r=n?.playbackQuality??ng.resolveProgressive(t,!!n);return r===null?e.progressive[0]:Yh(e.progressive,r)},planSources(e){let t=ag.getDashSource(e.files,e.viewKey,e.activeLocalCache),n=ag.getDefaultProgressiveFile(e.files,e.settings,e.activeLocalCache),r=[];return t&&r.push(t),n&&r.push({src:n.url,type:n.mimeType}),{sources:r,defaultFile:n}},applyFile(e,t){rg(e,{src:t.url,type:t.mimeType})}};function og(e){return cg(e)?.BANDWIDTH}function sg(e){return cg(e)?.CODECS}function cg(e){return(e.tech?.(!0))?.vhs?.playlistController_?.mediaTypes_?.AUDIO?.activePlaylistLoader?.media?.()?.attributes}function lg(e){let t=e.isFullscreen?.()??!1,n=e.usingPlugin?.(`playerModePlugin`)?e.playerModePlugin()?.isHovering?.()??!1:!1,r=e.usingPlugin?.(`theatreModePlugin`)?e.theatreModePlugin()?.getTheatreMode?.()??!1:!1;return t?`fullscreen`:n?`hover`:r?`theatre`:`default`}var ug=`segment-metadata`,dg={getTrack(e){return hh.getTrack(e,`metadata`,ug)??null},isTrack(e){return e?.kind===`metadata`&&e.label===ug},getOnScreenSegment(e){let t=dg.getTrack(e);if(!t?.cues?.length)return null;let n=t.activeCues;return n?.length?n[n.length-1].value??null:null}};function fg(e){return dg.getOnScreenSegment(e)?.codecs||(e.tech?.(!0))?.vhs?.playlists?.media?.()?.attributes?.CODECS}var pg=1e3*60*60*8,mg=class{constructor(e){this.options=e,this.initialize()}logStream(){let e=`v:${this.options.videoId}`,t=this.getPlayerMetrics();x.cacheExists(e)||(this.collectionApiClient.log({type:k.WebPlayerStream,actionContext:this.getActionContext(),data:{...this.getAnalyticsData(),player:t},eventVersion:E.V3}),x&&x.cacheSet(e,null,300))}logVideoProgress(e,t,n){let r=this.getAnalyticsData(),i=this.getPlayerMetrics(),a=n?k.PreviewStreamProgress:k.StreamProgress,o=e.map(e=>({type:a,actionContext:this.getActionContext(),data:{...r,player:i,progress:e},eventVersion:E.V2}));for(let e of t)o.push({type:k.StreamBuffering,actionContext:this.getActionContext(),data:{...r,player:i,buffering:e},eventVersion:E.V2});this.collectionApiClient.log(o)}logUserAction(e,t){let n={...this.getAnalyticsData(),...e},r={...this.getActionContext(),...t};this.collectionApiClient.log({type:t.actionType,data:n,actionContext:r,eventVersion:t.eventVersion||E.V2})}getAnalyticsData(){let e={video:{id:this.options.videoId},flags:{isUsingLocalCache:this.options.isUsingLocalCache,isQualityUserPreference:ng.hasStoredPreference(),isAutoQuality:this.options.player.qualityManager?.()?.isAuto()??!1},...this.options.additionalAnalyticsData||{}};this.options.shareId&&(e.video.shareId=this.options.shareId);let t=this.getEntityType();return t===D.Interactive?e.interactive={id:+this.options.mediaId}:t===D.Clip&&(e.clip={id:+this.options.mediaId}),e}initialize(){this.setupCollectionApiClient(),se.lockWindowSession(this.options.userId,pg),this.options.player.one(`dispose`,()=>se.unlockWindowSession(this.options.userId))}setupCollectionApiClient(){this.collectionApiClient=new re({productName:`player.web`,productVersion:this.options.productVersion,regionName:this.options.regionName,collectionApiUrls:this.options.collectionApiUrls,collectionApiClientId:this.options.collectionApiClientId,getUser:()=>this.getCurrentUser(),shouldLog:ie.shouldLog,formatData:ie.formatData})}async getCurrentUser(){return{id:this.options.userId,customerId:this.options.customerId,sessionId:this.options.authSessionId}}getActionContext(){return{entity:this.getEntityType(),location:this.getLocationContext(),productArea:void 0,descriptor:this.options.isEmbedded?ne.Embedded:void 0,workflowPhase:void 0}}getEntityType(){switch(this.options.mediaType){case`MasterVideo`:return D.Video;case`MasterInteractive`:return D.Interactive;case`MasterClip`:return D.Clip}}getLocationContext(){switch(this.options.playerType){case`player`:return O.Player;case`interactive-player`:return O.InteractivePlayer;case`create-clip-player`:return O.CreateClipPlayer}}getPlayerMetrics(){let e=this.options.player,t=e.qualityManager?.()?.getActive();return{mode:lg(e),width:e.currentWidth(),height:e.currentHeight(),quality:t?.quality?.toString(),qualityLabel:t?.displayName,preset:t?.preset,tech:e.techName_,playbackType:e.currentType?.()===`application/dash+xml`?`dash`:`progressive`,videoCodec:fg(e),audioBitrate:og(e),audioCodec:sg(e)}}},hg=e(t(((e,t)=>{function n(e){if(e&&typeof e==`object`){var t=e.which||e.keyCode||e.charCode;t&&(e=t)}if(typeof e==`number`)return o[e];var n=String(e),a=r[n.toLowerCase()];if(a)return a;var a=i[n.toLowerCase()];if(a)return a;if(n.length===1)return n.charCodeAt(0)}n.isEventKey=function(e,t){if(e&&typeof e==`object`){var n=e.which||e.keyCode||e.charCode;if(n==null)return!1;if(typeof t==`string`){var a=r[t.toLowerCase()];if(a)return a===n;var a=i[t.toLowerCase()];if(a)return a===n}else if(typeof t==`number`)return t===n;return!1}},e=t.exports=n;var r=e.code=e.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,"pause/break":19,"caps lock":20,esc:27,space:32,"page up":33,"page down":34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,delete:46,command:91,"left command":91,"right command":93,"numpad *":106,"numpad +":107,"numpad -":109,"numpad .":110,"numpad /":111,"num lock":144,"scroll lock":145,"my computer":182,"my calculator":183,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222},i=e.aliases={windows:91,"⇧":16,"⌥":18,"⌃":17,"⌘":91,ctl:17,control:17,option:18,pause:19,break:19,caps:20,return:13,escape:27,spc:32,spacebar:32,pgup:33,pgdn:34,ins:45,del:46,cmd:91};for(a=97;a<123;a++)r[String.fromCharCode(a)]=a-32;for(var a=48;a<58;a++)r[a-48]=a;for(a=1;a<13;a++)r[`f`+a]=a+111;for(a=0;a<10;a++)r[`numpad `+a]=a+96;var o=e.names=e.title={};for(a in r)o[r[a]]=a;for(var s in i)r[s]=i[s]}))());function gg(e){document[e.fsApi_.fullscreenEnabled]&&(e.isFullscreen()?e.exitFullscreen():e.requestFullscreen())}function _g(e){let t=e.theatreModePlugin().getTheatreMode();e.theatreModePlugin().toggleTheatreMode(!t,{shouldLog:!0})}function vg(e){let t=e.volume(),n=e.lastVolume_();if(t===0){let t=n<.1?.1:n;e.volume(t),e.muted(!1)}else e.muted(!e.muted())}function yg(e){e.paused()?e.play():e.pause()}function bg(e,t){e.currentTime(e.currentTime()+t)}function xg(e,t){t>0&&e.muted()&&e.muted(!1),e.volume(e.volume()+t)}function Sg(e){let t=e.target;return t.tagName.toLowerCase()===`video`||!![`video-js`,`vjs-tech`].find(e=>t.classList.contains(e))}var Cg={f:gg,m:vg,k:yg,space:yg,t:_g,left:e=>bg(e,-5),right:e=>bg(e,5),j:e=>bg(e,-10),l:e=>bg(e,10),up:e=>xg(e,.05),down:e=>xg(e,-.05)};function wg(e,t,n){if(e.ctrlKey||e.metaKey||e.altKey)return;let r=(0,hg.default)(e),i=[`up`,`down`].includes(r);if(i&&!e.shiftKey||!i&&e.shiftKey||r===`t`&&!n.allowTheatreMode||r===`f`&&!n.allowFullscreen||!Cg[r])return;Cg[r](t,e);let a=Sg(e),o=[`space`].includes(r);(a||o)&&(e.preventDefault(),e.stopPropagation())}var Tg=function(e){return e.PhysicallyChapteredVideo=`physically-chaptered-video`,e}({}),Eg={name:`@clickview/player`,version:`1.54.0-rc.2`,description:`ClickView Player`,main:`dist/player-app.js`,type:`module`,scripts:{"type-check":`tsc --noEmit`,"build-app":`node ../../../node_modules/vite/bin/vite.js build --config vite.config.app.ts`,"build-styles":`node ../../../node_modules/vite/bin/vite.js build --config vite.config.styles.ts`,build:`npm run type-check && npm run build-player && npm run build-interactive-player`,"build-player":`node ../../../node_modules/vite/bin/vite.js build --config vite.player.config.ts`,"build-interactive-player":`node ../../../node_modules/vite/bin/vite.js build --config vite.interactive-player.config.ts`,"build-font":`cross-env NODE_ENV=development npm run start`,test:`jest`,"test-watch":`jest --watch`,"test-harness":`npm run build && node ../../../node_modules/vite/bin/vite.js --config vite.test-harness.config.ts`},repository:{type:`git`,url:`https://gitlab.cvinternal.net/front-end/clickview`},author:`Matt Trengrove, Cameron Hill, Shale Kuzmanovski`,license:`ISC`,devDependencies:{"@clickview/player-font":`0.0.17`,"@types/chromecast-caf-sender":`1.0.3`,"@types/cropperjs":`1.3.0`,"@types/draft-js":`0.10.44`,"@types/node-polyglot":`0.4.34`,"@types/react-draft-wysiwyg":`1.13.1`,"@types/signalr-no-jquery":`0.1.3`,"@types/simplebar":`5.1.1`,"@types/video.js":`7.3.58`,jest:`29.6.4`,"ts-jest":`29.1.1`,"vite-plugin-mkcert":`1.17.12`},dependencies:{"@microsoft/signalr":`5.0.2`,"@types/react-canvas-draw":`1.2.1`,cropperjs:`1.5.6`,"draft-convert":`2.1.10`,"draft-js":`0.11.7`,keycode:`2.2.0`,"node-polyglot":`2.3.0`,"react-canvas-draw":`1.2.1`,"react-draft-wysiwyg":`1.15.0`,"react-textarea-autosize":`8.3.2`,"signalr-no-jquery":`0.2.0`,simplebar:`5.3.0`,"simplebar-react":`2.3.0`,"video.js":`8.20.0`}},Dg=class{constructor(e){this.controller=null,this.logger=Z.log.createLogger(`quality`),this.player=e}setController(e){this.controller?.dispose(),this.controller=e,this.notifyLevelsChanged(),e?.getSelected()&&this.notifyQualityChanged(`system`)}getController(){return this.controller}getLevels(){return this.controller?.getLevels()??[]}getSelected(){return this.controller?.getSelected()??null}getActive(){return this.controller?.getActive()??null}select(e,t){this.controller?.select(e,t)}selectPreferred(e){let t=Yh(this.getLevels(),e);t&&this.select(t.id)}selectLowest(){let e=this.getLevels(),t=e[e.length-1];t&&this.select(t.id)}supportsAuto(){return this.controller?.supportsAuto()??!1}isAuto(){return this.controller?.isAuto()??!1}selectAuto(e){this.controller?.selectAuto(e)}notifyLevelsChanged(){let e=this.getLevels();this.logger.debug(`Levels changed: ${e.map(e=>e.displayName).join(`, `)||`none`}`),this.player.trigger(`quality-levels-changed`),this.player.trigger(`cv-updatecog`),this.player.trigger(`resizemenus`)}notifyQualityChanged(e){let t=this.getSelected();this.logger.debug(`Quality changed to ${t?.displayName??`none`} (origin: ${e})`),this.player.trigger(`quality-changed`,{origin:e}),this.player.trigger(`cv-quality-change`,t?.id)}dispose(){this.controller?.dispose(),this.controller=null}},Og=new WeakMap;function kg(){let e=Og.get(this);if(e)return e;let t=new Dg(this);return Og.set(this,t),this.one(`dispose`,()=>{t.dispose(),Og.delete(this)}),t}Z.registerPlugin(`qualityManager`,kg);var Ag={SMALL:450,MEDIUM:650},jg=Z.getPlugin(`plugin`),Mg=class extends jg{constructor(e,t){super(e),this.options=t,this.configureMenuDimensions=this.configureMenuDimensions.bind(this),this.initialize()}initialize(){this.player.ready(this.configureMenuDimensions),this.player.one(`play`,this.configureMenuDimensions),this.player.on(`resize`,this.configureMenuDimensions),this.player.on(`fullscreenchange`,this.configureMenuDimensions),this.player.on(`resizemenus`,this.configureMenuDimensions),this.player.on(`ready`,this.configureMenuDimensions)}dispose(){this.player.off(`resize`,this.configureMenuDimensions),this.player.off(`fullscreenchange`,this.configureMenuDimensions),this.player.off(`resizemenus`,this.configureMenuDimensions),this.player.off(`ready`,this.configureMenuDimensions),super.dispose()}configureMenuDimensions(){let e=e=>{if(this.options.mobile)return;let t=this.player.getChild(`collapserator`),n=t.getChild(`volumePanel`),r=t.children_.indexOf(n);t.removeChild(n),t.addChild(`volumePanel`,{inline:e,playerOptions:this.player.options_.playerOptions},r),this.player.trigger(`volumechange`)},t=this.player.isFullscreen();if(t&&!this.options.mobile){let t=this.player.whiteboardModePlugin().side;if(e(t!==`top`),t===`left`||t===`right`||t===`top`){let e=this.player.currentWidth();this.player.el().querySelectorAll(`.vjs-menu`).forEach(t=>{t.style.paddingTop=null,t.style.marginBottom=null,t.style.width=`calc(${e}px - 4em)`});return}}t||e(!0);let n=this.player.currentWidth(),r=this.player.currentHeight()/n*100,i=this.player.el().querySelector(`.cv-collapsorator`),a=this.player.el().querySelectorAll(`.vjs-menu`),o=i&&i.offsetHeight;if(!o){this.player.one(`play`,this.configureMenuDimensions);return}this.options.seekBarName===`CreateClipSeekBar`&&(o+=22),!(!a||!a.length)&&a.forEach(e=>{!t&&this.options.overflowControls?e.style.paddingTop=`80%`:e.style.paddingTop=`calc(${r}% - ${o}px)`,e.style.marginBottom=`${o}px`,e.style.width=null,e.querySelector(`.vjs-menu-content`)&&(n<=Ag.SMALL?this.player.addClass(`cv-player-small`):this.player.removeClass(`cv-player-small`))})}};Z.registerPlugin(`configureMenuDimensionsPlugin`,Mg);var Ng=Z.getPlugin(`plugin`),Pg=`cvplayer-volume`,Fg=`cvplayer-mute`,Ig=class extends Ng{constructor(e){super(e),this.enabled=!0,this.player.ready(()=>this.initialize())}initialize(){if(this.player.options_.mobile){this.removeVolumeControl();return}P.hasLocalStorage()&&(this.saveVolumeState=this.saveVolumeState.bind(this),this.player.on(`volumechange`,this.saveVolumeState),this.applyUserPreferences())}applyUserPreferences(){let e=P.get(Pg),t=P.get(Fg);e&&this.player.volume(+e),t&&this.player.muted(t===`true`)}saveVolumeState(){this.enabled&&(P.set(Pg,this.player.volume().toString()),P.set(Fg,this.player.muted().toString()))}removeVolumeControl(){this.player.volume(1);let e=this.player.getChild(`collapserator`),t=e.getChild(`volumePanel`);e.removeChild(t)}enable(){this.enabled=!0}disable(){this.enabled=!1}dispose(){this.player.off(`volumechange`,this.saveVolumeState),super.dispose()}};Z.registerPlugin(`persistVolumePlugin`,Ig);var Lg=Z.getPlugin(`plugin`),Rg=`cvplayer-playback-rate`,zg=class extends Lg{constructor(e,t){super(e),this.options=t,this.player.dataLoaded(()=>this.initialize())}initialize(){if(!P.hasLocalStorage())return;this.savePlaybackRate=this.savePlaybackRate.bind(this),this.player.on(`ratechange`,this.savePlaybackRate),this.one(`dispose`,()=>{this.player.off(`ratechange`,this.savePlaybackRate)});let e=+P.get(Rg);this.player.playbackRates()?.some(t=>t===e)&&this.player.playbackRate(e)}savePlaybackRate(){let e=this.player.playbackRate().toString();this.setDefaultPlaybackRate(+e),P.set(Rg,e),this.options.analyticsService?.logUserAction({rate:e},{actionType:k.Select,workflowPhase:T.Complete,descriptor:C.ChangeSpeed,entity:D.PlaybackSpeed,eventVersion:E.V3})}setDefaultPlaybackRate(e){this.player.defaultPlaybackRate(e)}setPlaybackRateWithoutPersisting(e){this.player.off(`ratechange`,this.savePlaybackRate),this.player.playbackRate(e),this.setDefaultPlaybackRate(e),this.player.on(`ratechange`,this.savePlaybackRate)}};Z.registerPlugin(`persistPlaybackRatePlugin`,zg);var Bg=Z.getPlugin(`plugin`),Vg=class extends Bg{constructor(e){super(e),this.fullscreenBecauseOfRotate=!1,this.player.supportsFullScreen()&&(this.onRotate=this.onRotate.bind(this),this.onFullscreenChange=this.onFullscreenChange.bind(this),this.player.ready(()=>this.initialize()))}initialize(){this.player.on(`fullscreenchange`,this.onFullscreenChange),window.addEventListener(`orientationchange`,this.onRotate)}dispose(){this.player.off(`fullscreenchange`,this.onFullscreenChange),window.removeEventListener(`orientationchange`,this.onRotate)}onFullscreenChange(){this.player.isFullscreen()||(this.fullscreenBecauseOfRotate=!1)}onRotate(){let e=this.getAngle();if(e!==90&&e!==-90&&e!==270){this.fullscreenBecauseOfRotate&&this.player.isFullscreen()&&this.player.exitFullscreen();return}this.player.requestFullscreen(),this.fullscreenBecauseOfRotate=!0}getAngle(){return typeof window.screen?.orientation?.angle==`number`?window.screen.orientation.angle:0}};Z.registerPlugin(`fullscreenOnRotatePlugin`,Vg);var Hg=`
|
|
225
|
+
`,Uh=class extends Bh{constructor(e,t){super(e,t)}createEl(){let e=Vh.prototype.createEl.call(this,`button`,{className:this.buildCSSClass()},{type:`button`,title:this.controlText_});return e.innerHTML=Hh,this.createControlTextEl(e),e}handleClick(e){e.stopPropagation(),e.preventDefault(),this.options_?.onClick&&this.options_.onClick()}buildCSSClass(){return`cv-remove-video-button`}};Z.registerComponent(`removeVideoButton`,Uh),Uh.prototype.controlText_=`Remove from watch history`;var Wh=function(e){return e.Default=`play`,e.Hover=`hover`,e}({}),Gh=Z.getPlugin(`plugin`),Kh=`cv-preview-mode`,qh=`cv-force-16-9`,Jh=class extends Gh{constructor(e,t){super(e),this.hasSeeked=!1,this.buttonAdded=!1,this.mode=null,this.defaultDisplayMode=`normal`,this.onQualityReady=null,t?.defaultDisplayMode&&(this.defaultDisplayMode=t.defaultDisplayMode),t?.startTime&&(this.startTime=t.startTime),this.onSeek=this.onSeek.bind(this),this.player.one(`seeking`,this.onSeek)}onSeek(){this.hasSeeked=!0}dispose(){this.cleanupQualityListener(),this.player.off(`seeking`,this.onSeek),super.dispose()}getMode(){return this.mode}isHovering(){return this.mode===`hover`}setPlayerMode(e,t,n){this.player.trigger(`flushprogress`);let r=this.mode;if(this.mode=e,e===`hover`){this.buttonAdded||this.addButtons(t,n),this.player.addClass(Kh),this.applyAspectRatioFix(),this.enableSubtitles(),this.mute(),this.setLowQuality(),this.removeActivityTimeout(),this.player.trigger(`resize`);return}r===`hover`&&(this.applyDefaultModeLayout(),this.player.removeClass(Kh),this.player.removeClass(qh),this.disableSubtitles(),this.unmute(),this.cleanupQualityListener(),this.restorePreviousQuality(),this.restoreActivityTimeout(),this.player.trigger(`resize`),this.hasSeeked||=(this.player.currentTime(this.startTime??0),!1))}applyDefaultModeLayout(){let e=this.player.usingPlugin?.(`theatreModePlugin`);this.defaultDisplayMode===`theatre`?(e&&this.player.theatreModePlugin()?.toggleTheatreMode(!0),this.player.fill(!0)):(e&&this.player.theatreModePlugin()?.toggleTheatreMode(!1),this.player.fluid(!0))}applyAspectRatioFix(){let e=()=>{let e=this.player.videoWidth(),t=this.player.videoHeight();if(e>0&&t>0){let n=e/t;Math.abs(n-16/9)<.01||this.player.addClass(qh)}};this.player.readyState()>=1?e():this.player.one(`loadedmetadata`,e)}addButtons(e,t){let n=new Lh(this.player),r=new zh(this.player,{onClickHandler:e}),i=new Uh(this.player,{onClick:t});t&&A.isFunction(t)&&this.player.addChild(i),this.player.addChild(n),this.player.addChild(r),this.buttonAdded=!0}enableSubtitles(){this.player.dataLoaded(()=>this.player.persistSubtitleSettingsPlugin().previewModeSubtitles())}disableSubtitles(){this.player.dataLoaded(()=>this.player.persistSubtitleSettingsPlugin().applyUserPreferences())}mute(){this.player.ready(()=>{this.player.persistVolumePlugin().disable(),this.player.muted(!0)})}unmute(){this.player.ready(()=>{this.player.persistVolumePlugin().applyUserPreferences(),this.player.persistVolumePlugin().enable()})}setLowQuality(){this.player.dataLoaded(()=>{this.mode===`hover`&&(this.player.persistQualitySettingsPlugin().disable(),this.cleanupQualityListener(),this.onQualityReady=()=>{this.mode===`hover`&&this.player.qualityManager().selectLowest()},this.player.on(`quality-levels-changed`,this.onQualityReady),this.player.qualityManager().selectLowest())})}cleanupQualityListener(){this.onQualityReady&&=(this.player.off(`quality-levels-changed`,this.onQualityReady),null)}restorePreviousQuality(){this.player.dataLoaded(()=>{this.player.persistQualitySettingsPlugin().applyUserPreferences(),this.player.persistQualitySettingsPlugin().enable()})}removeActivityTimeout(){this.player.cache_.inactivityTimeout=this.player.options_.inactivityTimeout,this.player.options_.inactivityTimeout=0}restoreActivityTimeout(){this.player.options_.inactivityTimeout=this.player.cache_.inactivityTimeout}};Z.registerPlugin(`playerModePlugin`,Jh);function Yh(e,t){for(let n of e)if(n.quality<=t)return n;return e[e.length-1]}var Xh=`cvplayer-playback-quality:v2`,Zh=`cvplayer-localcache-playback-quality:v2`,Qh=`cvplayer-dash-playback-quality:v1`,$h=`auto`,eg=480*60*1e3;function tg(e){return e?Zh:Xh}var ng={hasStoredPreference(){return P.hasLocalStorage()?!!(P.get(`cvplayer-playback-quality:v2`)||P.get(`cvplayer-localcache-playback-quality:v2`)||P.get(`cvplayer-dash-playback-quality:v1`)):!1},storeProgressive(e,t){P.hasLocalStorage()&&P.set(tg(t),e.toString())},resolveProgressive(e,t=!1){let n=t?e?.playbackQualityLocalCache:e?.playbackQuality,r=(P.hasLocalStorage()?P.get(tg(t)):null)||n||e?.playbackQualityFallback;if(!r)return null;let i=parseInt(r);return isNaN(i)?null:i},resolveDash(){if(!P.hasLocalStorage())return $h;let e=P.get(Qh);if(!e)return $h;try{let t=JSON.parse(e);if(typeof t?.quality==`number`&&typeof t?.expiresAt==`number`&&t.expiresAt>Date.now())return t.quality}catch{}return $h},storeDashLock(e){if(!P.hasLocalStorage())return;let t={quality:e,expiresAt:Date.now()+eg};P.set(Qh,JSON.stringify(t))},clearDashLock(){P.hasLocalStorage()&&P.remove(Qh)}};function rg(e,t){let n=e.currentTime(),r=!e.paused(),i=e.hasStarted();e.src(t);let a=()=>{e.off(`error`,o),e.currentTime()!==n&&e.currentTime(n),r&&e.play()?.catch(()=>void 0),i&&e.hasStarted(!0)},o=()=>e.off(`loadedmetadata`,a);e.one(`loadedmetadata`,a),e.one(`error`,o)}var ig=`application/dash+xml`,ag={sortFilesByQuality(e){return{...e,progressive:[...e.progressive].sort((e,t)=>t.quality-e.quality)}},getSignedDashUrl(e,t){let n=e.manifests?.dashUrl;if(n)return`${n}?viewKey=${t}`},getDashSource(e,t,n){let r=ag.getSignedDashUrl(e,t);if(r)return{src:r,type:ig,useBandwidthFromLocalStorage:!n}},getDefaultProgressiveFile(e,t,n){let r=n?.playbackQuality??ng.resolveProgressive(t,!!n);return r===null?e.progressive[0]:Yh(e.progressive,r)},planSources(e){let t=ag.getDashSource(e.files,e.viewKey,e.activeLocalCache),n=ag.getDefaultProgressiveFile(e.files,e.settings,e.activeLocalCache),r=[];return t&&r.push(t),n&&r.push({src:n.url,type:n.mimeType}),{sources:r,defaultFile:n}},applyFile(e,t){rg(e,{src:t.url,type:t.mimeType})}};function og(e){return cg(e)?.BANDWIDTH}function sg(e){return cg(e)?.CODECS}function cg(e){return(e.tech?.(!0))?.vhs?.playlistController_?.mediaTypes_?.AUDIO?.activePlaylistLoader?.media?.()?.attributes}function lg(e){let t=e.isFullscreen?.()??!1,n=e.usingPlugin?.(`playerModePlugin`)?e.playerModePlugin()?.isHovering?.()??!1:!1,r=e.usingPlugin?.(`theatreModePlugin`)?e.theatreModePlugin()?.getTheatreMode?.()??!1:!1;return t?`fullscreen`:n?`hover`:r?`theatre`:`default`}var ug=`segment-metadata`,dg={getTrack(e){return hh.getTrack(e,`metadata`,ug)??null},isTrack(e){return e?.kind===`metadata`&&e.label===ug},getOnScreenSegment(e){let t=dg.getTrack(e);if(!t?.cues?.length)return null;let n=t.activeCues;return n?.length?n[n.length-1].value??null:null}};function fg(e){return dg.getOnScreenSegment(e)?.codecs||(e.tech?.(!0))?.vhs?.playlists?.media?.()?.attributes?.CODECS}var pg=1e3*60*60*8,mg=class{constructor(e){this.options=e,this.initialize()}logStream(){let e=`v:${this.options.videoId}`,t=this.getPlayerMetrics();x.cacheExists(e)||(this.collectionApiClient.log({type:k.WebPlayerStream,actionContext:this.getActionContext(),data:{...this.getAnalyticsData(),player:t},eventVersion:E.V3}),x&&x.cacheSet(e,null,300))}logVideoProgress(e,t,n){let r=this.getAnalyticsData(),i=this.getPlayerMetrics(),a=n?k.PreviewStreamProgress:k.StreamProgress,o=e.map(e=>({type:a,actionContext:this.getActionContext(),data:{...r,player:i,progress:e},eventVersion:E.V2}));for(let e of t)o.push({type:k.StreamBuffering,actionContext:this.getActionContext(),data:{...r,player:i,buffering:e},eventVersion:E.V2});this.collectionApiClient.log(o)}logUserAction(e,t){let n={...this.getAnalyticsData(),...e},r={...this.getActionContext(),...t};this.collectionApiClient.log({type:t.actionType,data:n,actionContext:r,eventVersion:t.eventVersion||E.V2})}getAnalyticsData(){let e={video:{id:this.options.videoId},flags:{isUsingLocalCache:this.options.isUsingLocalCache,isQualityUserPreference:ng.hasStoredPreference(),isAutoQuality:this.options.player.qualityManager?.()?.isAuto()??!1},...this.options.additionalAnalyticsData||{}};this.options.shareId&&(e.video.shareId=this.options.shareId);let t=this.getEntityType();return t===D.Interactive?e.interactive={id:+this.options.mediaId}:t===D.Clip&&(e.clip={id:+this.options.mediaId}),e}initialize(){this.setupCollectionApiClient(),se.lockWindowSession(this.options.userId,pg),this.options.player.one(`dispose`,()=>se.unlockWindowSession(this.options.userId))}setupCollectionApiClient(){this.collectionApiClient=new re({productName:`player.web`,productVersion:this.options.productVersion,regionName:this.options.regionName,collectionApiUrls:this.options.collectionApiUrls,collectionApiClientId:this.options.collectionApiClientId,getUser:()=>this.getCurrentUser(),shouldLog:ie.shouldLog,formatData:ie.formatData})}async getCurrentUser(){return{id:this.options.userId,customerId:this.options.customerId,sessionId:this.options.authSessionId}}getActionContext(){return{entity:this.getEntityType(),location:this.getLocationContext(),productArea:void 0,descriptor:this.options.isEmbedded?ne.Embedded:void 0,workflowPhase:void 0}}getEntityType(){switch(this.options.mediaType){case`MasterVideo`:return D.Video;case`MasterInteractive`:return D.Interactive;case`MasterClip`:return D.Clip}}getLocationContext(){switch(this.options.playerType){case`player`:return O.Player;case`interactive-player`:return O.InteractivePlayer;case`create-clip-player`:return O.CreateClipPlayer}}getPlayerMetrics(){let e=this.options.player,t=e.qualityManager?.()?.getActive();return{mode:lg(e),width:e.currentWidth(),height:e.currentHeight(),quality:t?.quality?.toString(),qualityLabel:t?.displayName,preset:t?.preset,tech:e.techName_,playbackType:e.currentType?.()===`application/dash+xml`?`dash`:`progressive`,videoCodec:fg(e),audioBitrate:og(e),audioCodec:sg(e)}}},hg=e(t(((e,t)=>{function n(e){if(e&&typeof e==`object`){var t=e.which||e.keyCode||e.charCode;t&&(e=t)}if(typeof e==`number`)return o[e];var n=String(e),a=r[n.toLowerCase()];if(a)return a;var a=i[n.toLowerCase()];if(a)return a;if(n.length===1)return n.charCodeAt(0)}n.isEventKey=function(e,t){if(e&&typeof e==`object`){var n=e.which||e.keyCode||e.charCode;if(n==null)return!1;if(typeof t==`string`){var a=r[t.toLowerCase()];if(a)return a===n;var a=i[t.toLowerCase()];if(a)return a===n}else if(typeof t==`number`)return t===n;return!1}},e=t.exports=n;var r=e.code=e.codes={backspace:8,tab:9,enter:13,shift:16,ctrl:17,alt:18,"pause/break":19,"caps lock":20,esc:27,space:32,"page up":33,"page down":34,end:35,home:36,left:37,up:38,right:39,down:40,insert:45,delete:46,command:91,"left command":91,"right command":93,"numpad *":106,"numpad +":107,"numpad -":109,"numpad .":110,"numpad /":111,"num lock":144,"scroll lock":145,"my computer":182,"my calculator":183,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222},i=e.aliases={windows:91,"⇧":16,"⌥":18,"⌃":17,"⌘":91,ctl:17,control:17,option:18,pause:19,break:19,caps:20,return:13,escape:27,spc:32,spacebar:32,pgup:33,pgdn:34,ins:45,del:46,cmd:91};for(a=97;a<123;a++)r[String.fromCharCode(a)]=a-32;for(var a=48;a<58;a++)r[a-48]=a;for(a=1;a<13;a++)r[`f`+a]=a+111;for(a=0;a<10;a++)r[`numpad `+a]=a+96;var o=e.names=e.title={};for(a in r)o[r[a]]=a;for(var s in i)r[s]=i[s]}))());function gg(e){document[e.fsApi_.fullscreenEnabled]&&(e.isFullscreen()?e.exitFullscreen():e.requestFullscreen())}function _g(e){let t=e.theatreModePlugin().getTheatreMode();e.theatreModePlugin().toggleTheatreMode(!t,{shouldLog:!0})}function vg(e){let t=e.volume(),n=e.lastVolume_();if(t===0){let t=n<.1?.1:n;e.volume(t),e.muted(!1)}else e.muted(!e.muted())}function yg(e){e.paused()?e.play():e.pause()}function bg(e,t){e.currentTime(e.currentTime()+t)}function xg(e,t){t>0&&e.muted()&&e.muted(!1),e.volume(e.volume()+t)}function Sg(e){let t=e.target;return t.tagName.toLowerCase()===`video`||!![`video-js`,`vjs-tech`].find(e=>t.classList.contains(e))}var Cg={f:gg,m:vg,k:yg,space:yg,t:_g,left:e=>bg(e,-5),right:e=>bg(e,5),j:e=>bg(e,-10),l:e=>bg(e,10),up:e=>xg(e,.05),down:e=>xg(e,-.05)};function wg(e,t,n){if(e.ctrlKey||e.metaKey||e.altKey)return;let r=(0,hg.default)(e),i=[`up`,`down`].includes(r);if(i&&!e.shiftKey||!i&&e.shiftKey||r===`t`&&!n.allowTheatreMode||r===`f`&&!n.allowFullscreen||!Cg[r])return;Cg[r](t,e);let a=Sg(e),o=[`space`].includes(r);(a||o)&&(e.preventDefault(),e.stopPropagation())}var Tg=function(e){return e.PhysicallyChapteredVideo=`physically-chaptered-video`,e}({}),Eg={name:`@clickview/player`,version:`1.54.0-rc.3`,description:`ClickView Player`,main:`dist/player-app.js`,type:`module`,scripts:{"type-check":`tsc --noEmit`,"build-app":`node ../../../node_modules/vite/bin/vite.js build --config vite.config.app.ts`,"build-styles":`node ../../../node_modules/vite/bin/vite.js build --config vite.config.styles.ts`,build:`npm run type-check && npm run build-player && npm run build-interactive-player`,"build-player":`node ../../../node_modules/vite/bin/vite.js build --config vite.player.config.ts`,"build-interactive-player":`node ../../../node_modules/vite/bin/vite.js build --config vite.interactive-player.config.ts`,"build-font":`cross-env NODE_ENV=development npm run start`,test:`jest`,"test-watch":`jest --watch`,"test-harness":`npm run build && node ../../../node_modules/vite/bin/vite.js --config vite.test-harness.config.ts`},repository:{type:`git`,url:`https://gitlab.cvinternal.net/front-end/clickview`},author:`Matt Trengrove, Cameron Hill, Shale Kuzmanovski`,license:`ISC`,devDependencies:{"@clickview/player-font":`0.0.17`,"@types/chromecast-caf-sender":`1.0.3`,"@types/cropperjs":`1.3.0`,"@types/draft-js":`0.10.44`,"@types/node-polyglot":`0.4.34`,"@types/react-draft-wysiwyg":`1.13.1`,"@types/signalr-no-jquery":`0.1.3`,"@types/simplebar":`5.1.1`,"@types/video.js":`7.3.58`,jest:`29.6.4`,"ts-jest":`29.1.1`,"vite-plugin-mkcert":`1.17.12`},dependencies:{"@microsoft/signalr":`5.0.2`,"@types/react-canvas-draw":`1.2.1`,cropperjs:`1.5.6`,"draft-convert":`2.1.10`,"draft-js":`0.11.7`,keycode:`2.2.0`,"node-polyglot":`2.3.0`,"react-canvas-draw":`1.2.1`,"react-draft-wysiwyg":`1.15.0`,"react-textarea-autosize":`8.3.2`,"signalr-no-jquery":`0.2.0`,simplebar:`5.3.0`,"simplebar-react":`2.3.0`,"video.js":`8.20.0`}},Dg=class{constructor(e){this.controller=null,this.logger=Z.log.createLogger(`quality`),this.player=e}setController(e){this.controller?.dispose(),this.controller=e,this.notifyLevelsChanged(),e?.getSelected()&&this.notifyQualityChanged(`system`)}getController(){return this.controller}getLevels(){return this.controller?.getLevels()??[]}getSelected(){return this.controller?.getSelected()??null}getActive(){return this.controller?.getActive()??null}select(e,t){this.controller?.select(e,t)}selectPreferred(e){let t=Yh(this.getLevels(),e);t&&this.select(t.id)}selectLowest(){let e=this.getLevels(),t=e[e.length-1];t&&this.select(t.id)}supportsAuto(){return this.controller?.supportsAuto()??!1}isAuto(){return this.controller?.isAuto()??!1}selectAuto(e){this.controller?.selectAuto(e)}notifyLevelsChanged(){let e=this.getLevels();this.logger.debug(`Levels changed: ${e.map(e=>e.displayName).join(`, `)||`none`}`),this.player.trigger(`quality-levels-changed`),this.player.trigger(`cv-updatecog`),this.player.trigger(`resizemenus`)}notifyQualityChanged(e){let t=this.getSelected();this.logger.debug(`Quality changed to ${t?.displayName??`none`} (origin: ${e})`),this.player.trigger(`quality-changed`,{origin:e}),this.player.trigger(`cv-quality-change`,t?.id)}dispose(){this.controller?.dispose(),this.controller=null}},Og=new WeakMap;function kg(){let e=Og.get(this);if(e)return e;let t=new Dg(this);return Og.set(this,t),this.one(`dispose`,()=>{t.dispose(),Og.delete(this)}),t}Z.registerPlugin(`qualityManager`,kg);var Ag={SMALL:450,MEDIUM:650},jg=Z.getPlugin(`plugin`),Mg=class extends jg{constructor(e,t){super(e),this.options=t,this.configureMenuDimensions=this.configureMenuDimensions.bind(this),this.initialize()}initialize(){this.player.ready(this.configureMenuDimensions),this.player.one(`play`,this.configureMenuDimensions),this.player.on(`resize`,this.configureMenuDimensions),this.player.on(`fullscreenchange`,this.configureMenuDimensions),this.player.on(`resizemenus`,this.configureMenuDimensions),this.player.on(`ready`,this.configureMenuDimensions)}dispose(){this.player.off(`resize`,this.configureMenuDimensions),this.player.off(`fullscreenchange`,this.configureMenuDimensions),this.player.off(`resizemenus`,this.configureMenuDimensions),this.player.off(`ready`,this.configureMenuDimensions),super.dispose()}configureMenuDimensions(){let e=e=>{if(this.options.mobile)return;let t=this.player.getChild(`collapserator`),n=t.getChild(`volumePanel`),r=t.children_.indexOf(n);t.removeChild(n),t.addChild(`volumePanel`,{inline:e,playerOptions:this.player.options_.playerOptions},r),this.player.trigger(`volumechange`)},t=this.player.isFullscreen();if(t&&!this.options.mobile){let t=this.player.whiteboardModePlugin().side;if(e(t!==`top`),t===`left`||t===`right`||t===`top`){let e=this.player.currentWidth();this.player.el().querySelectorAll(`.vjs-menu`).forEach(t=>{t.style.paddingTop=null,t.style.marginBottom=null,t.style.width=`calc(${e}px - 4em)`});return}}t||e(!0);let n=this.player.currentWidth(),r=this.player.currentHeight()/n*100,i=this.player.el().querySelector(`.cv-collapsorator`),a=this.player.el().querySelectorAll(`.vjs-menu`),o=i&&i.offsetHeight;if(!o){this.player.one(`play`,this.configureMenuDimensions);return}this.options.seekBarName===`CreateClipSeekBar`&&(o+=22),!(!a||!a.length)&&a.forEach(e=>{!t&&this.options.overflowControls?e.style.paddingTop=`80%`:e.style.paddingTop=`calc(${r}% - ${o}px)`,e.style.marginBottom=`${o}px`,e.style.width=null,e.querySelector(`.vjs-menu-content`)&&(n<=Ag.SMALL?this.player.addClass(`cv-player-small`):this.player.removeClass(`cv-player-small`))})}};Z.registerPlugin(`configureMenuDimensionsPlugin`,Mg);var Ng=Z.getPlugin(`plugin`),Pg=`cvplayer-volume`,Fg=`cvplayer-mute`,Ig=class extends Ng{constructor(e){super(e),this.enabled=!0,this.player.ready(()=>this.initialize())}initialize(){if(this.player.options_.mobile){this.removeVolumeControl();return}P.hasLocalStorage()&&(this.saveVolumeState=this.saveVolumeState.bind(this),this.player.on(`volumechange`,this.saveVolumeState),this.applyUserPreferences())}applyUserPreferences(){let e=P.get(Pg),t=P.get(Fg);e&&this.player.volume(+e),t&&this.player.muted(t===`true`)}saveVolumeState(){this.enabled&&(P.set(Pg,this.player.volume().toString()),P.set(Fg,this.player.muted().toString()))}removeVolumeControl(){this.player.volume(1);let e=this.player.getChild(`collapserator`),t=e.getChild(`volumePanel`);e.removeChild(t)}enable(){this.enabled=!0}disable(){this.enabled=!1}dispose(){this.player.off(`volumechange`,this.saveVolumeState),super.dispose()}};Z.registerPlugin(`persistVolumePlugin`,Ig);var Lg=Z.getPlugin(`plugin`),Rg=`cvplayer-playback-rate`,zg=class extends Lg{constructor(e,t){super(e),this.options=t,this.player.dataLoaded(()=>this.initialize())}initialize(){if(!P.hasLocalStorage())return;this.savePlaybackRate=this.savePlaybackRate.bind(this),this.player.on(`ratechange`,this.savePlaybackRate),this.one(`dispose`,()=>{this.player.off(`ratechange`,this.savePlaybackRate)});let e=+P.get(Rg);this.player.playbackRates()?.some(t=>t===e)&&this.player.playbackRate(e)}savePlaybackRate(){let e=this.player.playbackRate().toString();this.setDefaultPlaybackRate(+e),P.set(Rg,e),this.options.analyticsService?.logUserAction({rate:e},{actionType:k.Select,workflowPhase:T.Complete,descriptor:C.ChangeSpeed,entity:D.PlaybackSpeed,eventVersion:E.V3})}setDefaultPlaybackRate(e){this.player.defaultPlaybackRate(e)}setPlaybackRateWithoutPersisting(e){this.player.off(`ratechange`,this.savePlaybackRate),this.player.playbackRate(e),this.setDefaultPlaybackRate(e),this.player.on(`ratechange`,this.savePlaybackRate)}};Z.registerPlugin(`persistPlaybackRatePlugin`,zg);var Bg=Z.getPlugin(`plugin`),Vg=class extends Bg{constructor(e){super(e),this.fullscreenBecauseOfRotate=!1,this.player.supportsFullScreen()&&(this.onRotate=this.onRotate.bind(this),this.onFullscreenChange=this.onFullscreenChange.bind(this),this.player.ready(()=>this.initialize()))}initialize(){this.player.on(`fullscreenchange`,this.onFullscreenChange),window.addEventListener(`orientationchange`,this.onRotate)}dispose(){this.player.off(`fullscreenchange`,this.onFullscreenChange),window.removeEventListener(`orientationchange`,this.onRotate)}onFullscreenChange(){this.player.isFullscreen()||(this.fullscreenBecauseOfRotate=!1)}onRotate(){let e=this.getAngle();if(e!==90&&e!==-90&&e!==270){this.fullscreenBecauseOfRotate&&this.player.isFullscreen()&&this.player.exitFullscreen();return}this.player.requestFullscreen(),this.fullscreenBecauseOfRotate=!0}getAngle(){return typeof window.screen?.orientation?.angle==`number`?window.screen.orientation.angle:0}};Z.registerPlugin(`fullscreenOnRotatePlugin`,Vg);var Hg=`
|
|
226
226
|
<svg viewBox="0 0 2420 383">
|
|
227
227
|
<title>ClickView Logo</title>
|
|
228
228
|
<path fill="#f8981d" d="M317.302 140.594c38.928 22.475 38.928 78.663 0 101.137L87.93 374.159c-51.737 29.87-109.635-28.028-79.764-79.765l42.745-74.035a58.39 58.39 0 0 0 0-58.392L8.165 87.929C-21.705 36.193 36.193-21.705 87.93 8.165z"/>
|
|
@@ -256,4 +256,4 @@ ${fp(e)}`),t.map&&!t.map.bytes&&(this.logger_(`going to request init segment.`),
|
|
|
256
256
|
<path d="M268.06 2.91764L254.192 14.8403L262.401 17.4661L258.324 27.0679L272.192 15.1453L263.983 12.5194L268.06 2.91764Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
|
257
257
|
</svg>
|
|
258
258
|
`})}};Z.registerComponent(`ErrorDisplay`,Rb);var zb=Z.getComponent(`FullscreenToggle`),Bb=`Fullscreen (f)`,Vb=class extends zb{handleFullscreenChange(){zb.prototype.handleFullscreenChange.call(this),this.controlText(Bb)}};Z.registerComponent(`FullscreenToggle`,Vb),Vb.prototype.controlText_=Bb;var Hb=Z.getComponent(`MuteToggle`),Ub=`Mute (m)`,Wb=`Unmute (m)`,Gb=class extends Hb{updateControlText_(){let e=this.player_.muted()||this.player_.volume()===0?Wb:Ub;this.controlText_!==e&&this.controlText(e)}};Z.registerComponent(`MuteToggle`,Gb),Gb.prototype.controlText_=Ub;var Kb=Z.getComponent(`Player`),qb=e=>e.indexOf(`#`)===0?e.slice(1):e,Jb=3,Yb,Xb=class e{static{this.options_={viewKey:null,controls:!0,playbackRates:[.25,.5,.75,1,1.25,1.5,1.75,2],playerApi:new URL(`http://localhost:52000`),enableLocalCache:!0,eventLogging:!0,allowFullscreen:!0}}constructor(t,n){if(this.streamLogged=!1,this.options=Z.obj.merge({},e.options_,n),this.options.playerApi===null)throw Error(`PlayerApi required`);this.initialize(),this.createEl(t),this.buildVideoJs(),this.options.splash&&this.setupSplash(this.options.splash),this.bindEventListeners(),this.setupSeekBar(),this.fetchConfig(),this.logStream=this.logStream.bind(this),this.player.ready(()=>{this._configurePlugins(),this.options.setup&&this.options.setup(this.options,this.player),this.fetch().catch(e=>this.handleFetchError(e))})}initialize(){}_configurePlugins(){this.player.configureMenuDimensionsPlugin({mobile:this.options.mobile,overflowControls:this.options.overflowControls,seekBarName:this.getSeekBarName()}),this.player.progressReporterPlugin({onFlush:this.onFlushProgress=this.onFlushProgress.bind(this)}),this.player.persistVolumePlugin(),!this.options.mobile&&this.options.allowFullscreen&&this.player.fullscreenOnRotatePlugin(),this.player.touchControls(),this.player.playerModePlugin({defaultDisplayMode:this.options.nextDefaultDisplayMode,startTime:this.options.startTime}),this.options.getExternalLink&&this.player.openExternallyPlugin({getExternalLink:this.options.getExternalLink}),this.player.oldVersionRefreshPlugin?.(),this.configurePlugins()}configurePlugins(){}onFlushProgress(e,t){let n=this.player.playerModePlugin().isHovering();this.analyticsService?.logVideoProgress(e,t,n)}buildVideoJs(){return this.player=Z(this.el,this.getPlayerOptions())}getInactivityTimeout(){if(typeof this.options.inactivityTimeout==`number`)return this.options.inactivityTimeout;let e=500;return(this.options.mobile||Z.browser.IS_IOS||Z.browser.IS_ANDROID)&&(e=3e3),e}getFluid(){return!(this.options.theatreMode||this.options.embed||this.options.mobile)}getFill(){return!!(this.options.theatreMode||this.options.embed||this.options.mobile)}getPlayerOptions(){let e=Kb.prototype.options_.children;return e=e.filter(e=>!(e===`bigPlayButton`||e===`posterImage`)),{controls:this.options.controls,fluid:this.getFluid(),fill:this.getFill(),inactivityTimeout:this.getInactivityTimeout(),controlBar:{children:[`timeWrapper`,`progressControl`]},children:[...e,{name:`collapserator`,children:Ph.filter(e=>!(e===`fullscreenToggle`&&!this.options.allowFullscreen||e===`playbackRateMenuButton`&&!this.options.playbackRates?.length))},`playPauseFeedback`,`controlBarGradient`],userActions:{hotkeys:e=>wg(e,this.player,this.options)},playbackRates:this.options.playbackRates,techOrder:[`html5`],html5:{nativeTextTracks:!1},playsinline:!0,aspectRatio:this.options.aspectRatio,mobile:this.options.mobile,allowTheatreMode:this.options.allowTheatreMode,deferMenus:this.options.deferMenus,muted:this.options.muted,devicesConfig:this.options.devicesConfig}}async getPlaybackObject(){if(this.options.offlinePlaybackObject)return this.options.offlinePlaybackObject;let e=this.options.fetch;if(this.options.fetch===void 0&&(e=e=>{let t=`${this.options.playerApi.origin}/api/playback?viewKey=${e}`;return ze.get(t)}),!this.options.viewKey)throw Error(`Please specify a viewKey or a fetch function`);let t=await e(this.options.viewKey);if(!t)throw Error(`Error fetching playback object`);return t}setChaptersInternal(e,t){let n=hh.getTrack(this.player,`chapters`,null);n||=this.player.addTextTrack(`chapters`),[...n.cues.cues_].forEach(e=>n.removeCue(e)),e.forEach(e=>{n.addCue({startTime:e.timestamp,endTime:e.endTimestamp,text:e.name})}),t&&n.trigger({type:`cv:cuechange`,target:n}),n.trigger({type:`loadeddata`,target:n})}setChapters(e){this.setChaptersInternal(e,!0)}setPlayerMode(e,t,n){this.player.playerModePlugin().setPlayerMode(e,t,n)}getPlayerMode(){return this.player.playerModePlugin().getMode()}setFavourite(e,t){this.player.favouritePlugin().setFavourite(e,t)}async fetch(){let e=await this.getPlaybackObject();if(this.isDisposed())return;let t=e.mediaType===`MasterClip`,n=e.additionalData?.clipData;e.chapters?.list?.length>0&&!t&&!n&&this.setChaptersInternal(e.chapters.list,!1),this.player.localCache({localCacheAddresses:e.localCacheAddresses??[],enabled:this.options.enableLocalCache??!0}),this.player.mediaSources({files:e.files,viewKey:this.options.viewKey,settings:e.settings}),this.player.handleNetworkErrors({playerApi:this.options.playerApi,fileToken:e.files.fileToken}),e.subtitles.list.length>0&&e.subtitles.list.forEach(e=>{if(e.mimeType!==`text/vtt`)return;let t=this.player.addRemoteTextTrack({kind:`subtitles`,src:e.url,language:e.language,label:e.label},!0);if(hh.sanitizeTrack(t.track,this.player),this.options.allowTranscript){let t=this.player.addRemoteTextTrack({kind:`metadata`,src:e.url+(e.url.includes(`?`)?`&`:`?`)+`fullSentences=true`,language:e.language,label:`transcript`},!0);t.track.isClickViewProduced=e.isClickViewProduced,hh.sanitizeTrack(t.track,this.player)}}),e.posterUrl&&this.player.poster(le.createUrl(e.posterUrl,{size:ce.Large})),this.setupSplash({title:e.title,posterUrl:e.posterUrl,episodeNumber:e.episodeNumber,ratingCode:e.ratingCode,seasonNumber:e.seasonNumber,seriesName:e.seriesName}),this.additionalSetup(e),this.handleAutoplay(e),this.options.startTime&&(this.player.currentTime(this.options.startTime),this.player.one(`canplay`,()=>{this.player.currentTime(this.options.startTime)})),this.player.trigger(`cv-playback-data-loaded`,e)}handleFetchError(e){let t=e.message;e instanceof Re&&e.response?.type===Tg.PhysicallyChapteredVideo&&(t=`Video cannot be played because it is either corrupt or damaged.`),this.player.error(t),this.options.onError&&this.options.onError(e)}async fetchConfig(){if(Yb||this.options.fetch||this.options.offlinePlaybackObject)return;let e=`${this.options.playerApi.origin}/api/config`;Yb=await ze.get(e),!this.isDisposed()&&this.trigger(`config:loaded`)}additionalSetup(e){this.player.whiteboardModePlugin(),this.player.deferMenusPlugin();let t=this.options.enableLocalCache&&!!e.localCacheAddresses?.length;Yb?this.setupAnalyticsService(e,t):this.one(`config:loaded`,()=>this.setupAnalyticsService(e,t)),this.analyticsService||!this.isAnalyticsEnabled()?this.setupAnalyticsDependentPlugins(e):this.one(`analytics:loaded`,()=>this.setupAnalyticsDependentPlugins(e))}setupAnalyticsService(e,t){this.options.eventLogging&&(this.analyticsService=new mg({player:this.player,collectionApiUrls:Yb.collectionApi.urls,collectionApiClientId:Yb.collectionApi.clientId,productVersion:Eg.version,authSessionId:e.viewerAuthSessionId,videoId:e.videoId,mediaId:e.mediaId,userId:e.viewerId,shareId:e.shareId,customerId:e.viewerCustomerId,mediaType:e.mediaType,playerType:this.getAnalyticsPlayerType(),isEmbedded:this.options.embed,isUsingLocalCache:t,additionalAnalyticsData:this.getAdditionalAnalyticsData(e),regionName:e.instanceRegion||this.options.sharerInstanceRegion||oe.CvApSoutheast1}),this.on(`timeupdate`,this.logStream),this.trigger(`analytics:loaded`))}setupAnalyticsDependentPlugins(e){this.player.persistSubtitleSettingsPlugin({showSubtitles:e.settings?.showSubtitles,subtitleSize:e.settings?.playbackSubtitleSizeDefault,analyticsService:this.analyticsService}),this.player.persistQualitySettingsPlugin({playbackQuality:e.settings?.playbackQuality,playbackQualityLocalCache:e.settings?.playbackQualityLocalCache,playbackQualityFallback:e.settings?.playbackQualityFallback,analyticsService:this.analyticsService}),this.player.persistPlaybackRatePlugin({analyticsService:this.analyticsService})}getAdditionalAnalyticsData(e){return{}}isAnalyticsEnabled(){return this.options.fetch||this.options.offlinePlaybackObject?!1:this.options.eventLogging}handleAutoplay(e){this.options.autoplay&&this.player.ready(()=>{this.player.play().catch(()=>{this.isDisposed()||this.showSplash()})})}logStream(){this.analyticsService&&(this.player.currentTime()<Jb||this.streamLogged||this.player.playerModePlugin().getMode()!==Wh.Hover&&(this.analyticsService.logStream(),this.streamLogged=!0,this.off(`timeupdate`,this.logStream)))}getAnalyticsPlayerType(){return`player`}createEl(e){let t;typeof e==`string`?(e=qb(e),t=Z.dom.$(`#`+e)):t=e;let n=`video-js`;return this.getPlayerClassName()&&(n+=` ${this.getPlayerClassName()}`),this.el=Z.dom.createEl(`video`,{},{class:n}),t.appendChild(this.el),this.el}getPlayerClassName(){return``}on(e,t){this.player.on(e,t)}one(e,t){this.player.one(e,t)}off(e,t){this.player.off(e,t)}trigger(e,t){return this.player.trigger(e,t)}dispose(){this.player.dispose()}ready(e){this.player.ready(e)}isDisposed(){return this.player.isDisposed()}play(){this.player.play()}pause(){this.player.pause()}isPaused(){return this.player.paused()}currentTime(e){return this.player.currentTime(e)}muted(e){return this.player.muted(e)}duration(){return this.player.duration()}isFullscreen(){return this.player.isFullscreen()}requestFullscreen(){this.player.requestFullscreen()}exitFullscreen(){this.player.exitFullscreen()}playbackRate(e){return this.player.playbackRate(e)}quality(e){let t=this.player.qualityManager();if(e===`auto`){t.selectAuto();return}if(e){t.select(e.toString());return}return t.getSelected()?.id}subtitles(e){let t=this.player.textTracks();for(let n=0;n<t.length;n++){let r=t[n];if(r.kind===`subtitles`){if(e!==void 0){r.label===e?r.mode=`showing`:r.mode=`disabled`;continue}if(r.mode===`showing`)return r.label}}}bindEventListeners(){let e=e=>e.preventDefault();if(this.showSplash=this.showSplash.bind(this),this.hideSplash=this.hideSplash.bind(this),this.player.on(`ended`,this.showSplash),this.player.on(`play`,this.hideSplash),this.player.tech(!0).on(`contextmenu`,e),this.player.one(`dispose`,()=>{this.off(`ended`,this.showSplash),this.off(`play`,this.hideSplash),this.player.tech(!0).off(`contextmenu`,e)}),!this.options.hotkeyElQuerySelector)return;let t=Z.dom.$(this.options.hotkeyElQuerySelector);t&&(this.player.on(t,`keydown`,this.player.handleKeyDown),this.player.one(`dispose`,()=>{this.player.off(t,`keydown`,this.player.handleKeyDown)}))}setupSeekBar(){let e=this.getSeekBarName(),t=this.player.controlBar.getChild(`progressControl`);t.addChild(e,{...this.getSeekBarOptions(),playerOptions:this.player.options_.playerOptions}),t.setSeekBarName(e)}setupSplash(e){this._splashAdded||(this._splashAdded=!0,this.player.addChild(`posterImage`,{embed:this.options.embed,...e}),this.player.addChild(`bigPlayButton`),this.options.autoplay?this.hideSplash():this.showSplash())}showSplash(){this.player.hasStarted(!1),this.player.getChild(`posterImage`).show(),this.player.getChild(`bigPlayButton`).show()}hideSplash(){this.player.getChild(`posterImage`).hide(),this.player.getChild(`bigPlayButton`).hide()}getSeekBarOptions(){return{}}getSeekBarName(){return`ChapterSeekBar`}};export{ry as a,a_ as c,_h as d,hh as f,ze as h,dy as i,ig as l,Z as m,Gy as n,Nv as o,ih as p,fy as r,jv as s,Xb as t,vh as u};
|
|
259
|
-
//# sourceMappingURL=
|
|
259
|
+
//# sourceMappingURL=Dqn0sInF.chunk.js.map
|