@clickview/lite 0.103.0-rc.0 → 0.103.1
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 +447 -447
- package/dist/bundles.json +1 -1
- package/dist/en.json +1 -1
- package/dist/scripts/{BXosUOUS.chunk.js → 14z5Gy8L.chunk.js} +2 -2
- package/dist/scripts/{BXosUOUS.chunk.js.map → 14z5Gy8L.chunk.js.map} +1 -1
- package/dist/scripts/{BqkK_0Jk2.chunk.js → B4AZn1xm2.chunk.js} +2 -2
- package/dist/scripts/{BqkK_0Jk2.chunk.js.map → B4AZn1xm2.chunk.js.map} +1 -1
- package/dist/scripts/{_wBbQ-0z2.chunk.js → BBndy2td2.chunk.js} +2 -2
- package/dist/scripts/{_wBbQ-0z2.chunk.js.map → BBndy2td2.chunk.js.map} +1 -1
- package/dist/scripts/{DBdkd4Ag2.chunk.js → BFH_tnSb2.chunk.js} +3 -3
- package/dist/scripts/{DBdkd4Ag2.chunk.js.map → BFH_tnSb2.chunk.js.map} +1 -1
- package/dist/scripts/{BhgNNQjX.chunk.js → BOQck-Qs.chunk.js} +2 -2
- package/dist/scripts/{BhgNNQjX.chunk.js.map → BOQck-Qs.chunk.js.map} +1 -1
- package/dist/scripts/{_eRiDJm1.chunk.js → Ba4uGz_V.chunk.js} +2 -2
- package/dist/scripts/{_eRiDJm1.chunk.js.map → Ba4uGz_V.chunk.js.map} +1 -1
- package/dist/scripts/{Bx6qaXLc.chunk.js → Bdbe2u0R.chunk.js} +2 -2
- package/dist/scripts/{Bx6qaXLc.chunk.js.map → Bdbe2u0R.chunk.js.map} +1 -1
- package/dist/scripts/{C4CuJJXy2.chunk.js → BeW5XQTb2.chunk.js} +2 -2
- package/dist/scripts/{C4CuJJXy2.chunk.js.map → BeW5XQTb2.chunk.js.map} +1 -1
- package/dist/scripts/{syYCrnUX.chunk.js → BgoVmaXQ.chunk.js} +2 -2
- package/dist/scripts/{syYCrnUX.chunk.js.map → BgoVmaXQ.chunk.js.map} +1 -1
- package/dist/scripts/{B5DWwtp0.chunk.js → BjA9XV5y.chunk.js} +2 -2
- package/dist/scripts/{B5DWwtp0.chunk.js.map → BjA9XV5y.chunk.js.map} +1 -1
- package/dist/scripts/{BYMMqtaN.chunk.js → BqdHoEFM.chunk.js} +2 -2
- package/dist/scripts/{BYMMqtaN.chunk.js.map → BqdHoEFM.chunk.js.map} +1 -1
- package/dist/scripts/{BIvmcqND2.chunk.js → CCUznsdX2.chunk.js} +2 -2
- package/dist/scripts/{BIvmcqND2.chunk.js.map → CCUznsdX2.chunk.js.map} +1 -1
- package/dist/scripts/{BsNCh4UD.chunk.js → CFqL2Hm5.chunk.js} +3 -3
- package/dist/scripts/{BsNCh4UD.chunk.js.map → CFqL2Hm5.chunk.js.map} +1 -1
- package/dist/scripts/{BE8Ze3Fa2.chunk.js → CHmbcl4Y2.chunk.js} +2 -2
- package/dist/scripts/{BE8Ze3Fa2.chunk.js.map → CHmbcl4Y2.chunk.js.map} +1 -1
- package/dist/scripts/{Dp8z_udC.chunk.js → CIzlhCeS.chunk.js} +2 -2
- package/dist/scripts/{Dp8z_udC.chunk.js.map → CIzlhCeS.chunk.js.map} +1 -1
- package/dist/scripts/{CO8EIpI8.chunk.js → CXUrMkZu.chunk.js} +2 -2
- package/dist/scripts/{CO8EIpI8.chunk.js.map → CXUrMkZu.chunk.js.map} +1 -1
- package/dist/scripts/{DLqG-wwP.chunk.js → CYrelpYt.chunk.js} +2 -2
- package/dist/scripts/{DLqG-wwP.chunk.js.map → CYrelpYt.chunk.js.map} +1 -1
- package/dist/scripts/{wmwWqIeA.chunk.js → CfrfHGSh.chunk.js} +2 -2
- package/dist/scripts/{wmwWqIeA.chunk.js.map → CfrfHGSh.chunk.js.map} +1 -1
- package/dist/scripts/{B5M-3wpn.chunk.js → CjwT65ug.chunk.js} +2 -2
- package/dist/scripts/{B5M-3wpn.chunk.js.map → CjwT65ug.chunk.js.map} +1 -1
- package/dist/scripts/{B-aaIChO2.chunk.js → CsCjBSq62.chunk.js} +2 -2
- package/dist/scripts/{B-aaIChO2.chunk.js.map → CsCjBSq62.chunk.js.map} +1 -1
- package/dist/scripts/{ygwO7HPs2.chunk.js → DIaT_eGy2.chunk.js} +2 -2
- package/dist/scripts/{ygwO7HPs2.chunk.js.map → DIaT_eGy2.chunk.js.map} +1 -1
- package/dist/scripts/{DXRsxBJw.chunk.js → DTliAJ8L.chunk.js} +2 -2
- package/dist/scripts/{DXRsxBJw.chunk.js.map → DTliAJ8L.chunk.js.map} +1 -1
- package/dist/scripts/{DE5jvfAx2.chunk.js → D_t70KgV2.chunk.js} +2 -2
- package/dist/scripts/{DE5jvfAx2.chunk.js.map → D_t70KgV2.chunk.js.map} +1 -1
- package/dist/scripts/{Dc01PBv1.chunk.js → Dn2EPvQj.chunk.js} +2 -2
- package/dist/scripts/{Dc01PBv1.chunk.js.map → Dn2EPvQj.chunk.js.map} +1 -1
- package/dist/scripts/{RuVwpX36.chunk.js → Drh1bb9z.chunk.js} +2 -2
- package/dist/scripts/{RuVwpX36.chunk.js.map → Drh1bb9z.chunk.js.map} +1 -1
- package/dist/scripts/{YzhKditE.chunk.js → ESLgHTNq.chunk.js} +2 -2
- package/dist/scripts/{YzhKditE.chunk.js.map → ESLgHTNq.chunk.js.map} +1 -1
- package/dist/scripts/{DfSzsD3P.chunk.js → FysETOFv.chunk.js} +2 -2
- package/dist/scripts/{DfSzsD3P.chunk.js.map → FysETOFv.chunk.js.map} +1 -1
- package/dist/scripts/QVwuOts3.chunk.js +12 -0
- package/dist/scripts/QVwuOts3.chunk.js.map +1 -0
- package/dist/scripts/{OmYpHs7g.chunk.js → _Cm5O72d.chunk.js} +3 -3
- package/dist/scripts/{OmYpHs7g.chunk.js.map → _Cm5O72d.chunk.js.map} +1 -1
- package/dist/scripts/{app-BzCWmnrr.js → app-BHlllGhO.js} +4 -4
- package/dist/scripts/{app-BzCWmnrr.js.map → app-BHlllGhO.js.map} +1 -1
- package/dist/scripts/{C46080Xd.chunk.js → dxqgnrOi.chunk.js} +2 -2
- package/dist/scripts/{C46080Xd.chunk.js.map → dxqgnrOi.chunk.js.map} +1 -1
- package/dist/scripts/{BCTM3KG42.chunk.js → kLCNzxrH2.chunk.js} +2 -2
- package/dist/scripts/{BCTM3KG42.chunk.js.map → kLCNzxrH2.chunk.js.map} +1 -1
- package/dist/scripts/{CfVIZBcI2.chunk.js → wpRpI9h02.chunk.js} +2 -2
- package/dist/scripts/{CfVIZBcI2.chunk.js.map → wpRpI9h02.chunk.js.map} +1 -1
- package/package.json +1 -1
- package/dist/scripts/QrUfkwZX.chunk.js +0 -12
- package/dist/scripts/QrUfkwZX.chunk.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{o as e}from"./DAXXjFlN.chunk.js";import{n as t}from"./D8uRDrkd.chunk.js";import{t as n}from"./CQyJ7YGa.chunk.js";import{t as r}from"./C2w0pmFW.chunk.js";import{t as i}from"./wrLrTezN.chunk.js";import{t as a}from"./C1SLt-ar.chunk.js";import{t as o}from"./C5j5LRut2.chunk.js";import{t as s}from"./DQgG9njb.chunk.js";import{t as ee}from"./PgzMrOyM.chunk.js";import{n as te}from"./BIzu5ufQ.chunk.js";import{t as c}from"./9LNlP5yJ.chunk.js";import{t as l}from"./Vp01-r6R.chunk.js";import{n as u}from"./CpFtf-tI2.chunk.js";import{t as ne}from"./CSl1Z1eB2.chunk.js";import{n as d,t as f}from"./5M7zYOWU.chunk.js";import{t as p}from"./PwsbPKjN2.chunk.js";import{t as m}from"./Ib9eoq_Y.chunk.js";import{d as h,i as g,p as _,t as re}from"./DXRsxBJw.chunk.js";import{n as ie,t as ae}from"./DLqG-wwP.chunk.js";import"./BXosUOUS.chunk.js";import{a as v,c as y,i as b,n as x,o as oe,r as se,s as S,t as C}from"./SxYliR8q.chunk.js";import{n as w,t as T}from"./Dkw9Ir-p.chunk.js";import{t as E}from"./v4yEqcBz.chunk.js";import"./CO8EIpI8.chunk.js";var D=e(r()),O={heatMap:`_heatMap_u3po2_1`,avatarContainer:`_avatarContainer_u3po2_4`,cogIcon:`_cogIcon_u3po2_8`},k=i(),A=n.encloseNamespace(`shared.engagementTable`),ce={heatMap:[],engagementRate:0,viewCount:0};function j(e){return(0,k.jsx)(`div`,{className:`${e.className??``}`,children:e.children})}function M(e){return(0,k.jsx)(j,{className:`d-inline-block ${e.column.isSorted?`fw-bold`:``}`,children:A(e.phraseKey)})}function N(e){let t=0;return e.forEach(e=>{let n=Math.max(...e.heatMap);n>t&&(t=n)}),t}function P(e){if(e.type)return e.type;if(e.userId===null||e.userId===void 0)return`anon`}function F(e){switch(e){case`student-reach`:return A(`classroomViews`);case`anon`:return A(`anonymous`);default:return null}}function I(e,t,n){if(n){let t=F(n);if(t&&!e?.name)return{name:t,surname:``}}let r=d(e,t).split(` `).filter(e=>!!e);return{name:r[0],surname:r.slice(1).join(` `)}}function L(e){return D.useMemo(()=>{let n=N(e.engagement);return[...e.showSeparateNameColumns?[{id:`firstName`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`firstName`}),accessor:`user`,width:63,sortType:(t,n)=>{let r=P(t.original),i=P(n.original),{name:a}=I(t.values.firstName,e.anonymiseUsers,r),{name:o}=I(n.values.firstName,e.anonymiseUsers,i);return a>o?1:-1},Cell:({value:n,row:{original:r}})=>{let i=P(r),{name:a,surname:s}=I(n,e.anonymiseUsers,i);return(0,k.jsxs)(j,{className:`d-flex align-items-center h-100`,children:[(0,k.jsx)(`span`,{className:O.avatarContainer,children:(0,k.jsx)(f,{type:i,imageCdnUrl:e.imageCdnUrl,initials:o.getInitials(a,s),imageUrl:!e.anonymiseUsers&&!i&&n?.avatar?.url,anonymiseUsers:e.anonymiseUsers})}),(0,k.jsx)(`span`,{className:`ms-2 clamp-1`,children:a}),i===`student-reach`&&e.classroomViewsAppLink&&(0,k.jsx)(c,{customSize:!0,svg:E,svgSize:t.Standard,appLink:e.classroomViewsAppLink,className:O.cogIcon,tooltip:e.classroomViewsTooltip,tooltipTrigger:[`hover`],ariaLabel:e.classroomViewsTooltip})]})}},{id:`surname`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`surname`}),accessor:`user`,width:68,sortType:(t,n)=>{let r=P(t.original),i=P(n.original),{surname:a}=I(t.values.surname,e.anonymiseUsers,r),{surname:o}=I(n.values.surname,e.anonymiseUsers,i);return a>o?1:-1},Cell:({value:t,row:{original:n}})=>{let{surname:r}=I(t,e.anonymiseUsers,P(n));return(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(`span`,{className:`clamp-1`,children:r||``})})}}]:[{id:`name`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`name`}),accessor:`user`,width:22,sortType:(t,n)=>{let r=P(t.original),i=P(n.original);return(r?F(r):d(t.values.user,e.anonymiseUsers))>(i?F(i):d(n.values.user,e.anonymiseUsers))?1:-1},Cell:({value:n,row:{original:r}})=>{let i=P(r),{name:a,surname:s}=I(n,e.anonymiseUsers,i);return(0,k.jsxs)(j,{className:`d-flex align-items-center h-100`,children:[(0,k.jsx)(`span`,{className:O.avatarContainer,children:(0,k.jsx)(f,{type:i,imageCdnUrl:e.imageCdnUrl,initials:o.getInitials(a,s),imageUrl:!e.anonymiseUsers&&!i&&n?.avatar?.url,anonymiseUsers:e.anonymiseUsers})}),(0,k.jsxs)(`span`,{className:`ms-2 clamp-1 me-1`,children:[a,` `,s]}),i===`student-reach`&&e.classroomViewsAppLink&&(0,k.jsx)(c,{customSize:!0,svg:E,svgSize:t.Standard,appLink:e.classroomViewsAppLink,className:O.cogIcon,tooltip:e.classroomViewsTooltip,tooltipTrigger:[`hover`],ariaLabel:e.classroomViewsTooltip})]})}}],{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`views`}),accessor:`viewCount`,width:e.showSeparateNameColumns?47:15,sortType:`basic`,sortDescFirst:!0,Cell:({value:e})=>(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(`div`,{children:e})})},{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`engagement`}),accessor:`engagementRate`,width:e.showSeparateNameColumns?79:20,sortDescFirst:!0,Cell:({value:e})=>(0,k.jsx)(j,{className:`w-33`,children:(0,k.jsx)(T,{percentage:e,layout:w.LabelBefore})})},{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`heatMap`}),accessor:`heatMap`,width:e.showSeparateNameColumns?230:48,disableSortBy:!0,Cell:({row:{original:e}})=>(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(v,{engagement:e,max:n,className:`${O.heatMap} flex-grow-1`})})}]},[e.anonymiseUsers,e.showSeparateNameColumns])}function R(e,t,n){return D.useMemo(()=>{let r=[],i=new Set;if(e?.forEach(e=>{let n=t?.find(t=>t.id&&t.id===e.userId?(i.add(t.id),!0):!!(t.sessionId&&t.sessionId===e.sessionId));r.push({...e,user:n})}),n?.length){let e=n.filter(e=>!i.has(e.id)).map(e=>({...ce,userId:e.id,user:e}));r.push(...e)}return r},[e,t,n])}var z={table:`bg-white rounded px-0`,header:`border-bottom`,headerCell:`m-3`,cell:`mx-3 my-2`};function B(e){let t=L({engagement:e.engagement,imageCdnUrl:e.imageCdnUrl,anonymiseUsers:e.anonymiseUsers,showSeparateNameColumns:e.showSeparateNameColumns,classroomViewsAppLink:e.classroomViewsAppLink,classroomViewsTooltip:e.classroomViewsTooltip}),n=R(e.engagement,e.users,e.classroomStudents);return n.length?(0,k.jsx)(p,{columns:t,data:n,theme:{...z,table:e.border?`${z.table} border`:z.table},enableSort:e.enableSort}):(0,k.jsx)(k.Fragment,{})}function V(e){return(0,k.jsx)(T,{layout:e.layout,className:e.className,percentage:0,customLabel:`--%`})}var H=`shared.insightAmountWatched`,U=n.encloseNamespace(H);function W(e){let t=S(e.engagement),n=Math.round(t*100);return(0,k.jsx)(b,{title:U(`title`),svg:s,svgClassName:`bg-light-green text-green`,children:(0,k.jsxs)(`div`,{className:`d-flex flex-column align-items-center my-auto gap-2`,children:[!!e.engagement&&(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(T,{percentage:t,layout:w.LabelInside}),(0,k.jsx)(`p`,{className:`text-center`,children:typeof t==`number`?(0,k.jsx)(u,{namespace:H,phrase:`everyoneWatched`,options:{percentage:n}}):(0,k.jsx)(u,{namespace:H,phrase:`notWatched`})})]}),!e.engagement&&(0,k.jsx)(k.Fragment,{children:(0,k.jsx)(V,{layout:w.LabelInside})})]})})}var G=e(se()),le=x(),K=[`#FF9300`,`#38A2E8`,`#7A76E8`,`#B679C7`,`#F7847B`,`#D9584F`,`#FFCD52`,`#5DC786`,`#40BCC3`,`#40C2BB`];function ue(e){return e.map((e,t)=>({...e,color:K[t%K.length]}))}function de(e,t,n,r){let i={};return e[t]?.forEach(e=>{let t=e.name||`Unknown`;!t||n?.includes(t.toLowerCase())||(i[t]=i[t]??0,i[t]+=e.count)}),ue(a.sortBy(Object.keys(i).map(e=>({name:r?r(e):e,y:i[e],type:`pie`})),`name`))}function q(e){let t=e.findIndex(e=>e.name===`Staff`);if(t>-1){let[n]=e.splice(t,1);e.push(n)}return e.sort((e,t)=>parseInt(e.name.match(/\d+/)?.[0])-parseInt(t.name.match(/\d+/)?.[0]))}function fe(e){return e?.reduce((e,t)=>e+t.y,0)??null}var J=`shared.insightTotalViews`,Y=n.encloseNamespace(J);function pe(e){return e===`Unknown`?Y(`anon`):e}var me={title:{text:null},credits:{enabled:!1},chart:{backgroundColor:`transparent`,spacing:[0,0,0,0]},legend:{itemStyle:C,itemDistance:8},plotOptions:{pie:{allowPointSelect:!0,cursor:`pointer`,dataLabels:{enabled:!1},showInLegend:!0,borderWidth:1,borderColor:`#ffffff`,borderRadius:0,size:`80%`}}};function he(e){let t=q(de(e.events,`yearGroupCount`,e.hideStaffResults?[`staff`]:[],pe)),n=fe(t);function r(e){return{...me,series:[{type:`pie`,name:Y(`title`),data:e}]}}return(0,k.jsx)(b,{title:Y(`title`),svgClassName:`bg-light-blue text-blue`,svg:ne,children:t?.length?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-0`,children:(0,k.jsx)(u,{namespace:J,phrase:`totalViews`,options:{totalViews:n}})}),(0,k.jsx)(`div`,{className:`d-flex justify-content-center h-75`,children:(0,k.jsx)(le.HighchartsReact,{highcharts:G.default,options:r(t),containerProps:{className:`w-100`}})})]}):(0,k.jsxs)(l,{className:`pt-0 my-auto`,children:[(0,k.jsx)(l.Image,{src:e.emptyStateImage,className:`w-75 h-auto`}),(0,k.jsx)(l.Heading,{className:`h4`,children:(0,k.jsx)(u,{namespace:J,phrase:`noViews`})}),(0,k.jsx)(l.Info,{className:`w-100`,children:(0,k.jsx)(u,{namespace:J,phrase:`notWatched`})})]})})}var X={partialInsights:`_partialInsights_1vk2g_1`,videoContainer:`_videoContainer_1vk2g_4`};function ge(){return(0,k.jsxs)(`div`,{children:[(0,k.jsxs)(`div`,{className:`row g-3 mb-3`,children:[(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})}),(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})}),(0,k.jsx)(`div`,{className:X.videoContainer,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})})]}),(0,k.jsx)(`div`,{className:`row g-3 mb-5`,children:(0,k.jsx)(`div`,{className:`col-12`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})})})]})}var _e=_.getComponent(`MenuItem`),Z=class extends _e{constructor(e,t){super(e,t),this.overlayVisible=t.overlayVisible,this.toggle(this.overlayVisible)}handleToggle(){this.toggle(!this.overlayVisible)}toggle(e){e?this.toggleOn():this.toggleOff()}toggleOn(){_.dom.addClass(this.toggleEl,`on`),this.overlayVisible=!0,this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible),this.player().addClass(`cv-reports-player-overlay-visible`)}toggleOff(){_.dom.removeClass(this.toggleEl,`on`),this.overlayVisible=!1,this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible),this.player().removeClass(`cv-reports-player-overlay-visible`)}handleClick(e){e.stopImmediatePropagation()}createEl(e,t,n){this.handlerBound||=(this.handleToggle=this.handleToggle.bind(this),!0),this.toggleEl&&this.toggleEl.removeEventListener(`click`,this.handleToggle),this.toggleEl=_.dom.createEl(`div`,{className:`custom-toggle custom-toggle-info toggle-option float-end`,innerHTML:`<span class="handle"></span></div>`}),this.toggleEl.addEventListener(`click`,this.handleToggle);let r=super.createEl(e,{className:`vjs-menu-item cv-cog-menu-item`,innerHTML:`
|
|
1
|
+
import{o as e}from"./DAXXjFlN.chunk.js";import{n as t}from"./D8uRDrkd.chunk.js";import{t as n}from"./CQyJ7YGa.chunk.js";import{t as r}from"./C2w0pmFW.chunk.js";import{t as i}from"./wrLrTezN.chunk.js";import{t as a}from"./C1SLt-ar.chunk.js";import{t as o}from"./C5j5LRut2.chunk.js";import{t as s}from"./DQgG9njb.chunk.js";import{t as ee}from"./PgzMrOyM.chunk.js";import{n as te}from"./BIzu5ufQ.chunk.js";import{t as c}from"./9LNlP5yJ.chunk.js";import{t as l}from"./Vp01-r6R.chunk.js";import{n as u}from"./CpFtf-tI2.chunk.js";import{t as ne}from"./CSl1Z1eB2.chunk.js";import{n as d,t as f}from"./5M7zYOWU.chunk.js";import{t as p}from"./PwsbPKjN2.chunk.js";import{t as m}from"./Ib9eoq_Y.chunk.js";import{d as h,i as g,p as _,t as re}from"./DTliAJ8L.chunk.js";import{n as ie,t as ae}from"./CYrelpYt.chunk.js";import"./14z5Gy8L.chunk.js";import{a as v,c as y,i as b,n as x,o as oe,r as se,s as S,t as C}from"./SxYliR8q.chunk.js";import{n as w,t as T}from"./Dkw9Ir-p.chunk.js";import{t as E}from"./v4yEqcBz.chunk.js";import"./CXUrMkZu.chunk.js";var D=e(r()),O={heatMap:`_heatMap_u3po2_1`,avatarContainer:`_avatarContainer_u3po2_4`,cogIcon:`_cogIcon_u3po2_8`},k=i(),A=n.encloseNamespace(`shared.engagementTable`),ce={heatMap:[],engagementRate:0,viewCount:0};function j(e){return(0,k.jsx)(`div`,{className:`${e.className??``}`,children:e.children})}function M(e){return(0,k.jsx)(j,{className:`d-inline-block ${e.column.isSorted?`fw-bold`:``}`,children:A(e.phraseKey)})}function N(e){let t=0;return e.forEach(e=>{let n=Math.max(...e.heatMap);n>t&&(t=n)}),t}function P(e){if(e.type)return e.type;if(e.userId===null||e.userId===void 0)return`anon`}function F(e){switch(e){case`student-reach`:return A(`classroomViews`);case`anon`:return A(`anonymous`);default:return null}}function I(e,t,n){if(n){let t=F(n);if(t&&!e?.name)return{name:t,surname:``}}let r=d(e,t).split(` `).filter(e=>!!e);return{name:r[0],surname:r.slice(1).join(` `)}}function L(e){return D.useMemo(()=>{let n=N(e.engagement);return[...e.showSeparateNameColumns?[{id:`firstName`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`firstName`}),accessor:`user`,width:63,sortType:(t,n)=>{let r=P(t.original),i=P(n.original),{name:a}=I(t.values.firstName,e.anonymiseUsers,r),{name:o}=I(n.values.firstName,e.anonymiseUsers,i);return a>o?1:-1},Cell:({value:n,row:{original:r}})=>{let i=P(r),{name:a,surname:s}=I(n,e.anonymiseUsers,i);return(0,k.jsxs)(j,{className:`d-flex align-items-center h-100`,children:[(0,k.jsx)(`span`,{className:O.avatarContainer,children:(0,k.jsx)(f,{type:i,imageCdnUrl:e.imageCdnUrl,initials:o.getInitials(a,s),imageUrl:!e.anonymiseUsers&&!i&&n?.avatar?.url,anonymiseUsers:e.anonymiseUsers})}),(0,k.jsx)(`span`,{className:`ms-2 clamp-1`,children:a}),i===`student-reach`&&e.classroomViewsAppLink&&(0,k.jsx)(c,{customSize:!0,svg:E,svgSize:t.Standard,appLink:e.classroomViewsAppLink,className:O.cogIcon,tooltip:e.classroomViewsTooltip,tooltipTrigger:[`hover`],ariaLabel:e.classroomViewsTooltip})]})}},{id:`surname`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`surname`}),accessor:`user`,width:68,sortType:(t,n)=>{let r=P(t.original),i=P(n.original),{surname:a}=I(t.values.surname,e.anonymiseUsers,r),{surname:o}=I(n.values.surname,e.anonymiseUsers,i);return a>o?1:-1},Cell:({value:t,row:{original:n}})=>{let{surname:r}=I(t,e.anonymiseUsers,P(n));return(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(`span`,{className:`clamp-1`,children:r||``})})}}]:[{id:`name`,Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`name`}),accessor:`user`,width:22,sortType:(t,n)=>{let r=P(t.original),i=P(n.original);return(r?F(r):d(t.values.user,e.anonymiseUsers))>(i?F(i):d(n.values.user,e.anonymiseUsers))?1:-1},Cell:({value:n,row:{original:r}})=>{let i=P(r),{name:a,surname:s}=I(n,e.anonymiseUsers,i);return(0,k.jsxs)(j,{className:`d-flex align-items-center h-100`,children:[(0,k.jsx)(`span`,{className:O.avatarContainer,children:(0,k.jsx)(f,{type:i,imageCdnUrl:e.imageCdnUrl,initials:o.getInitials(a,s),imageUrl:!e.anonymiseUsers&&!i&&n?.avatar?.url,anonymiseUsers:e.anonymiseUsers})}),(0,k.jsxs)(`span`,{className:`ms-2 clamp-1 me-1`,children:[a,` `,s]}),i===`student-reach`&&e.classroomViewsAppLink&&(0,k.jsx)(c,{customSize:!0,svg:E,svgSize:t.Standard,appLink:e.classroomViewsAppLink,className:O.cogIcon,tooltip:e.classroomViewsTooltip,tooltipTrigger:[`hover`],ariaLabel:e.classroomViewsTooltip})]})}}],{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`views`}),accessor:`viewCount`,width:e.showSeparateNameColumns?47:15,sortType:`basic`,sortDescFirst:!0,Cell:({value:e})=>(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(`div`,{children:e})})},{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`engagement`}),accessor:`engagementRate`,width:e.showSeparateNameColumns?79:20,sortDescFirst:!0,Cell:({value:e})=>(0,k.jsx)(j,{className:`w-33`,children:(0,k.jsx)(T,{percentage:e,layout:w.LabelBefore})})},{Header:({column:e})=>(0,k.jsx)(M,{column:e,phraseKey:`heatMap`}),accessor:`heatMap`,width:e.showSeparateNameColumns?230:48,disableSortBy:!0,Cell:({row:{original:e}})=>(0,k.jsx)(j,{className:`d-flex align-items-center h-100`,children:(0,k.jsx)(v,{engagement:e,max:n,className:`${O.heatMap} flex-grow-1`})})}]},[e.anonymiseUsers,e.showSeparateNameColumns])}function R(e,t,n){return D.useMemo(()=>{let r=[],i=new Set;if(e?.forEach(e=>{let n=t?.find(t=>t.id&&t.id===e.userId?(i.add(t.id),!0):!!(t.sessionId&&t.sessionId===e.sessionId));r.push({...e,user:n})}),n?.length){let e=n.filter(e=>!i.has(e.id)).map(e=>({...ce,userId:e.id,user:e}));r.push(...e)}return r},[e,t,n])}var z={table:`bg-white rounded px-0`,header:`border-bottom`,headerCell:`m-3`,cell:`mx-3 my-2`};function B(e){let t=L({engagement:e.engagement,imageCdnUrl:e.imageCdnUrl,anonymiseUsers:e.anonymiseUsers,showSeparateNameColumns:e.showSeparateNameColumns,classroomViewsAppLink:e.classroomViewsAppLink,classroomViewsTooltip:e.classroomViewsTooltip}),n=R(e.engagement,e.users,e.classroomStudents);return n.length?(0,k.jsx)(p,{columns:t,data:n,theme:{...z,table:e.border?`${z.table} border`:z.table},enableSort:e.enableSort}):(0,k.jsx)(k.Fragment,{})}function V(e){return(0,k.jsx)(T,{layout:e.layout,className:e.className,percentage:0,customLabel:`--%`})}var H=`shared.insightAmountWatched`,U=n.encloseNamespace(H);function W(e){let t=S(e.engagement),n=Math.round(t*100);return(0,k.jsx)(b,{title:U(`title`),svg:s,svgClassName:`bg-light-green text-green`,children:(0,k.jsxs)(`div`,{className:`d-flex flex-column align-items-center my-auto gap-2`,children:[!!e.engagement&&(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(T,{percentage:t,layout:w.LabelInside}),(0,k.jsx)(`p`,{className:`text-center`,children:typeof t==`number`?(0,k.jsx)(u,{namespace:H,phrase:`everyoneWatched`,options:{percentage:n}}):(0,k.jsx)(u,{namespace:H,phrase:`notWatched`})})]}),!e.engagement&&(0,k.jsx)(k.Fragment,{children:(0,k.jsx)(V,{layout:w.LabelInside})})]})})}var G=e(se()),le=x(),K=[`#FF9300`,`#38A2E8`,`#7A76E8`,`#B679C7`,`#F7847B`,`#D9584F`,`#FFCD52`,`#5DC786`,`#40BCC3`,`#40C2BB`];function ue(e){return e.map((e,t)=>({...e,color:K[t%K.length]}))}function de(e,t,n,r){let i={};return e[t]?.forEach(e=>{let t=e.name||`Unknown`;!t||n?.includes(t.toLowerCase())||(i[t]=i[t]??0,i[t]+=e.count)}),ue(a.sortBy(Object.keys(i).map(e=>({name:r?r(e):e,y:i[e],type:`pie`})),`name`))}function q(e){let t=e.findIndex(e=>e.name===`Staff`);if(t>-1){let[n]=e.splice(t,1);e.push(n)}return e.sort((e,t)=>parseInt(e.name.match(/\d+/)?.[0])-parseInt(t.name.match(/\d+/)?.[0]))}function fe(e){return e?.reduce((e,t)=>e+t.y,0)??null}var J=`shared.insightTotalViews`,Y=n.encloseNamespace(J);function pe(e){return e===`Unknown`?Y(`anon`):e}var me={title:{text:null},credits:{enabled:!1},chart:{backgroundColor:`transparent`,spacing:[0,0,0,0]},legend:{itemStyle:C,itemDistance:8},plotOptions:{pie:{allowPointSelect:!0,cursor:`pointer`,dataLabels:{enabled:!1},showInLegend:!0,borderWidth:1,borderColor:`#ffffff`,borderRadius:0,size:`80%`}}};function he(e){let t=q(de(e.events,`yearGroupCount`,e.hideStaffResults?[`staff`]:[],pe)),n=fe(t);function r(e){return{...me,series:[{type:`pie`,name:Y(`title`),data:e}]}}return(0,k.jsx)(b,{title:Y(`title`),svgClassName:`bg-light-blue text-blue`,svg:ne,children:t?.length?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-0`,children:(0,k.jsx)(u,{namespace:J,phrase:`totalViews`,options:{totalViews:n}})}),(0,k.jsx)(`div`,{className:`d-flex justify-content-center h-75`,children:(0,k.jsx)(le.HighchartsReact,{highcharts:G.default,options:r(t),containerProps:{className:`w-100`}})})]}):(0,k.jsxs)(l,{className:`pt-0 my-auto`,children:[(0,k.jsx)(l.Image,{src:e.emptyStateImage,className:`w-75 h-auto`}),(0,k.jsx)(l.Heading,{className:`h4`,children:(0,k.jsx)(u,{namespace:J,phrase:`noViews`})}),(0,k.jsx)(l.Info,{className:`w-100`,children:(0,k.jsx)(u,{namespace:J,phrase:`notWatched`})})]})})}var X={partialInsights:`_partialInsights_1vk2g_1`,videoContainer:`_videoContainer_1vk2g_4`};function ge(){return(0,k.jsxs)(`div`,{children:[(0,k.jsxs)(`div`,{className:`row g-3 mb-3`,children:[(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})}),(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})}),(0,k.jsx)(`div`,{className:X.videoContainer,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})})]}),(0,k.jsx)(`div`,{className:`row g-3 mb-5`,children:(0,k.jsx)(`div`,{className:`col-12`,children:(0,k.jsx)(`div`,{className:`${X.partialInsights} rounded partial-loading-background`})})})]})}var _e=_.getComponent(`MenuItem`),Z=class extends _e{constructor(e,t){super(e,t),this.overlayVisible=t.overlayVisible,this.toggle(this.overlayVisible)}handleToggle(){this.toggle(!this.overlayVisible)}toggle(e){e?this.toggleOn():this.toggleOff()}toggleOn(){_.dom.addClass(this.toggleEl,`on`),this.overlayVisible=!0,this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible),this.player().addClass(`cv-reports-player-overlay-visible`)}toggleOff(){_.dom.removeClass(this.toggleEl,`on`),this.overlayVisible=!1,this.player().engagementOverlayPlugin().toggleOverlay(this.overlayVisible),this.player().removeClass(`cv-reports-player-overlay-visible`)}handleClick(e){e.stopImmediatePropagation()}createEl(e,t,n){this.handlerBound||=(this.handleToggle=this.handleToggle.bind(this),!0),this.toggleEl&&this.toggleEl.removeEventListener(`click`,this.handleToggle),this.toggleEl=_.dom.createEl(`div`,{className:`custom-toggle custom-toggle-info toggle-option float-end`,innerHTML:`<span class="handle"></span></div>`}),this.toggleEl.addEventListener(`click`,this.handleToggle);let r=super.createEl(e,{className:`vjs-menu-item cv-cog-menu-item`,innerHTML:`
|
|
2
2
|
<span class="vjs-menu-item-text">Heat Map</span>
|
|
3
3
|
<span class="cv-toggle-container"></span>`},n);return r.children[1].appendChild(this.toggleEl),r}};_.registerComponent(`EngagementOverlayMenuItem`,Z);var ve=e(te(),1),Q=3;function ye(e){let t=e.interactive.timepoints.find(t=>{let n=t.visibleAt/1e3;return Math.floor(e.time)===Math.floor(n)||Math.ceil(e.time)===Math.ceil(n)});if(!t?.interactions?.length)return(0,k.jsx)(k.Fragment,{});let n=t.interactions.length>Q?t.interactions.slice(0,Q-1):t.interactions,r=t.interactions.length-n.length;return(0,k.jsxs)(`div`,{className:`d-flex justify-content-end ms-2`,children:[n.map((e,t)=>(0,k.jsx)(m,{interaction:e,showQuestion:!1,iconClassName:`ms-1`},t)),!!r&&(0,k.jsx)(`div`,{className:`interaction-type-icon d-flex justify-content-center align-items-center border border-dark text-body ms-1`,children:`+${r}`})]})}var be={title:{text:null},xAxis:{visible:!1,minPadding:0,maxPadding:0},legend:{enabled:!1},credits:{enabled:!1},defs:{gradient:{tagName:`linearGradient`,id:`area-gradient`,x1:0,y1:1,x2:0,y2:0,children:[{tagName:`stop`,offset:0},{tagName:`stop`,offset:1}]}}};function xe(e,t){return{styledMode:!0,spacing:[15,0,0,0],width:e,height:t}}function Se(e){return{max:Math.max(...e)*1.05,min:0,minPadding:0,maxPadding:0,allowDecimals:!0,startOnTick:!1,endOnTick:!1,visible:!1}}function Ce(e){return{formatter:function(){let t=e?Te(e,this.x):``;return`<div class="cv-engagement-tooltip bg-white rounded"><div class="d-flex justify-content-between"><strong>${g(this.x)}</strong>${t}</div><div class="d-flex justify-content-between rounded bg-light cv-view-count-container"><strong>Views</strong> <span class="cv-view-count">${this.y}</span></div></div>`},positioner:function(e,t,n){let r=this.chart.plotWidth-e,i=n.plotX-e/2;return{x:Math.min(Math.max(i,0),r),y:this.chart.plotTop}},useHTML:!0,padding:0}}function we(e){return{area:{point:{events:{mouseOver:function(){e(this.x)},mouseOut:function(){e(null)}}}},series:{marker:{enabled:!1}}}}function Te(e,t){return(0,ve.renderToStaticMarkup)((0,k.jsx)(ye,{time:t,interactive:e}))}var Ee=_.getComponent(`Component`);G.default.AST.allowedTags.push(`g`),G.default.AST.allowedAttributes.push(`viewBox`,`transform`);var De=class extends Ee{constructor(e,t){super(e,t),this.initialize(),this.bindListeners()}initialize(){this.player().ready(()=>this.buildChart())}buildCSSClass(){return`cv-engagement-overlay`}createEl(e,t,n){return super.createEl(e,{...t,className:this.buildCSSClass(),innerHTML:`<div class="cv-engagement-chart"></div><div class="cv-engagement-timepoint-indicator"></div>`},n)}toggleChart(e){e?this.buildChart():this.destroyChart()}bindListeners(){this.handleClick=this.handleClick.bind(this),this.resizeChart=this.resizeChart.bind(this),this.player().on(`playerresize`,this.resizeChart),this.on(this.el(),`mouseup`,this.handleClick),this.player().on(`dispose`,()=>{this.player().off(`playerresize`,this.resizeChart),this.off(this.el(),`mouseup`,this.handleClick)})}handleClick(e){if(_.dom.isSingleLeftClick(e)){if(this.player().paused()){this.player().play();return}this.player().pause()}}buildChart(){if(this.chart)return;let e=this.getChartDimensions();if(!e){this.player().one(`play`,()=>this.buildChart());return}let t=this.el().querySelector(`.cv-engagement-chart`);this.chart=G.default.chart(t,this.getHighchartOptions(e))}resizeChart(){let e=this.getChartDimensions();!this.chart||!e||this.chart.setSize(e.width,e.height)}destroyChart(){this.chart?.destroy(),this.chart=null}getChartDimensions(){let e=this.player().getChild(`collapserator`)?.currentHeight(),t=this.el().clientWidth;if(!e||!t)return null;let{height:n}=this.player().currentDimensions();return{width:t,height:n-e}}getHighchartOptions({width:e,height:t}){return{...be,chart:xe(e,t),yAxis:Se(this.options_.heatMap),tooltip:Ce(this.options_.interactive),plotOptions:we(this.moveTimepointIndicator.bind(this)),series:[{type:`area`,data:this.options_.heatMap}]}}moveTimepointIndicator(e){this.options_.onTimepointHover&&this.options_.onTimepointHover(e);let t=this.el().querySelector(`.cv-engagement-timepoint-indicator`);if(e===null){_.dom.removeClass(t,`cv-engagement-timepoint-indicator-visible`);return}_.dom.addClass(t,`cv-engagement-timepoint-indicator-visible`),t.style.left=`${e/this.options_.heatMap.length*100}%`}};_.registerComponent(`EngagementOverlay`,De);var Oe=_.getPlugin(`plugin`),ke=class extends Oe{constructor(e,t){super(e,t),this.options=t,e.ready(()=>{this.initialize()})}initialize(){this.hasHeatMapData()&&(this.player.addChild(`engagementOverlay`,{heatMap:this.options.heatMap,interactive:this.options.interactive,onTimepointHover:this.options.onTimepointHover}),(this.player.getChild(`collapserator`)?.getChild(`cogButton`)).addItem({ctor:Z,name:`EngagementOverlayMenuItem`,options:{overlayVisible:!0}}))}toggleOverlay(e){this.player.getChild(`engagementOverlay`)?.toggleChart(e)}hasHeatMapData(){return this.options.heatMap?.reduce((e,t)=>e+t,0)>0}};_.registerPlugin(`engagementOverlayPlugin`,ke);var Ae=_.getPlugin(`plugin`),je=class extends Ae{constructor(e,t){super(e),this.options=t,this.player.one(`loadedmetadata`,()=>this.player.ready(this.initialize.bind(this)))}initialize(){h.useMetadataTrack(this.player,`interactive`,this.onTrackLoaded.bind(this)),this.player.addClass(`cv-interactive-plugin`)}onTrackLoaded(e){this.addChildren(e)}addChildren(e){this.player.controlBar.getChild(`progressControl`).getChild(`SeekBar`).addChild(new ae(this.player,{interactive:this.options.interactive,track:e}))}};_.registerPlugin(`interactiveSeekBarPlugin`,je);var Me=class extends re{constructor(e,t){super(e,t)}getPlayerClassName(){return`cv-reports-player`}getAnalyticsPlayerType(){return`reports-player`}async additionalSetup(e){super.additionalSetup(e),this.setupEngagementOverlayPlugin(e),this.setupUpClipPlugin(e),this.setupInteractiveSeekBarPlugin(e)}setupEngagementOverlayPlugin(e){this.player.engagementOverlayPlugin({heatMap:this.options.heatMap,interactive:e.additionalData?.interactive,onTimepointHover:this.options.onTimepointHover})}setupUpClipPlugin(e){let t=e.mediaType===`MasterClip`,n=e.mediaType===`MasterInteractive`;if(!t&&!n)return;let r;if(t&&(r=e.additionalData),!(n&&(r=e.additionalData?.clipData,!r))){if(!r)throw Error(`Invalid clip data`);this.player.clipPlugin({startTime:r.startTime,endTime:r.endTime})}}setupInteractiveSeekBarPlugin(e){let t=e.additionalData?.interactive;e.additionalData?.interactive&&(this.track=ie.getInteractiveTrack(this.player,e),this.player.interactiveSeekBarPlugin({interactive:t}))}getSeekBarOptions(){return{ignoreChapters:!0}}};function Ne(e){let t=D.useRef(null),n=D.useRef(null);return D.useEffect(()=>{n.current=new Me(t.current,e)},[]),(0,k.jsx)(`div`,{ref:t})}var $={playerContainer:`_playerContainer_odup3_1`,playerPlaceholder:`_playerPlaceholder_odup3_8`,heatMap:`_heatMap_odup3_12`,heatMapTimepointIndicator:`_heatMapTimepointIndicator_odup3_15`,heatMapTimepointIndicatorVisible:`_heatMapTimepointIndicatorVisible_odup3_24`,partialLoadingContainer:`_partialLoadingContainer_odup3_28`},Pe=n.encloseNamespace(`shared.videoEngagementOverlay`);function Fe(e){let t=D.useRef(null),n=y(e.engagement);function r(e){let r=t.current;if(r){if(e===null){r.classList.remove($.heatMapTimepointIndicatorVisible);return}r.classList.add($.heatMapTimepointIndicatorVisible),r.style.left=`${e/n.length*100}%`}}return(0,k.jsxs)(`div`,{className:`bg-white border rounded overflow-hidden h-100`,children:[(0,k.jsxs)(`div`,{className:`position-relative`,children:[(0,k.jsx)(`div`,{className:$.playerPlaceholder}),(0,k.jsx)(`div`,{className:$.playerContainer,children:(0,k.jsx)(Ne,{viewKey:e.viewKey,playerApi:new URL(e.playerApiUrl),hotkeyElQuerySelector:`body`,heatMap:n,onTimepointHover:r,aspectRatio:`16:9`})})]}),(0,k.jsxs)(`div`,{className:`p-3`,children:[(0,k.jsxs)(`div`,{className:`position-relative`,children:[(0,k.jsx)(v,{engagement:e.engagement,className:$.heatMap}),(0,k.jsx)(`div`,{ref:t,className:$.heatMapTimepointIndicator})]}),(0,k.jsxs)(`div`,{className:`d-flex justify-content-between mt-2`,children:[(0,k.jsx)(`strong`,{children:Pe(`heatmap`)}),(0,k.jsx)(`div`,{className:`w-33`,children:(0,k.jsx)(oe,{})})]})]})]})}var Ie={videoContainer:`_videoContainer_1lnnd_1`};function Le(e){return(0,k.jsxs)(k.Fragment,{children:[!e.hasDataLoaded&&(0,k.jsx)(ge,{}),(0,k.jsxs)(`div`,{className:`row g-3 mb-3`,children:[e.hasDataLoaded&&(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(he,{events:{yearGroupCount:e.yearGroups},emptyStateImage:ee.EmptyStates.MY_VIDEOS,hideStaffResults:e.hideStaffResults})}),(0,k.jsx)(`div`,{className:`col`,children:(0,k.jsx)(W,{engagement:e.individualEngagement})}),(0,k.jsx)(`div`,{className:Ie.videoContainer,children:(0,k.jsx)(Fe,{engagement:e.aggregateEngagement,viewKey:e.viewKey.viewKey,playerApiUrl:e.config.playerApiUrl,imageCdnUrl:e.config.imageCdnUrl})})]}),e.tableDataLoaded&&(0,k.jsx)(`div`,{className:`col-12`,children:(0,k.jsx)(B,{engagement:e.individualEngagement,users:e.users,imageCdnUrl:e.config?.imageCdnUrl,anonymiseUsers:e.anonymiseUsers,classroomStudents:e.classroomStudents,border:!0,enableSort:!0,showSeparateNameColumns:!0})})]})]})}export{Le as t};
|
|
4
|
-
//# sourceMappingURL=
|
|
4
|
+
//# sourceMappingURL=Dn2EPvQj.chunk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dc01PBv1.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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"}
|
|
1
|
+
{"version":3,"file":"Dn2EPvQj.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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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./DAXXjFlN.chunk.js";import{_ as t}from"./BftnFbcr.chunk.js";import{t as n}from"./DMnm3Ewv.chunk.js";import{n as ee}from"./B785hxeE.chunk.js";import{t as r}from"./CQyJ7YGa.chunk.js";import{t as te}from"./e57H3T-k.chunk.js";import{t as i}from"./C2w0pmFW.chunk.js";import{t as a}from"./wrLrTezN.chunk.js";import{t as o}from"./BXTI9cmX.chunk.js";import{d as ne,u as s}from"./BX0wDJmp.chunk.js";import{y as re}from"./NlCAcBdo.chunk.js";import{t as ie}from"./oPIkfKWW2.chunk.js";import{t as ae}from"./CcDvlSWl2.chunk.js";import{t as oe}from"./DbSUQ2A12.chunk.js";import{t as se}from"./DtGDVg4O2.chunk.js";import{t as c}from"./8U-YTgZd.chunk.js";import{t as l}from"./DsXWD-Sn.chunk.js";import{t as u}from"./DdsRCMkN.chunk.js";import{t as d}from"./D_gWf2lC.chunk.js";import{t as f}from"./ZwDDc8Zd.chunk.js";import{t as p}from"./BWaKdG0l.chunk.js";import{n as ce,t as le}from"./A8xLZrSw.chunk.js";import{t as ue}from"./CMLErBju.chunk.js";import{t as m}from"./POQS3gV6.chunk.js";import{t as de}from"./BQKcAczf.chunk.js";import{l as h,r as g}from"./
|
|
2
|
-
//# sourceMappingURL=
|
|
1
|
+
import{o as e}from"./DAXXjFlN.chunk.js";import{_ as t}from"./BftnFbcr.chunk.js";import{t as n}from"./DMnm3Ewv.chunk.js";import{n as ee}from"./B785hxeE.chunk.js";import{t as r}from"./CQyJ7YGa.chunk.js";import{t as te}from"./e57H3T-k.chunk.js";import{t as i}from"./C2w0pmFW.chunk.js";import{t as a}from"./wrLrTezN.chunk.js";import{t as o}from"./BXTI9cmX.chunk.js";import{d as ne,u as s}from"./BX0wDJmp.chunk.js";import{y as re}from"./NlCAcBdo.chunk.js";import{t as ie}from"./oPIkfKWW2.chunk.js";import{t as ae}from"./CcDvlSWl2.chunk.js";import{t as oe}from"./DbSUQ2A12.chunk.js";import{t as se}from"./DtGDVg4O2.chunk.js";import{t as c}from"./8U-YTgZd.chunk.js";import{t as l}from"./DsXWD-Sn.chunk.js";import{t as u}from"./DdsRCMkN.chunk.js";import{t as d}from"./D_gWf2lC.chunk.js";import{t as f}from"./ZwDDc8Zd.chunk.js";import{t as p}from"./BWaKdG0l.chunk.js";import{n as ce,t as le}from"./A8xLZrSw.chunk.js";import{t as ue}from"./CMLErBju.chunk.js";import{t as m}from"./POQS3gV6.chunk.js";import{t as de}from"./BQKcAczf.chunk.js";import{l as h,r as g}from"./_Cm5O72d.chunk.js";import{t as _}from"./DR9DEoQL.chunk.js";import{t as v}from"./DW51cSV_2.chunk.js";import{t as y}from"./CmV-znIi2.chunk.js";import{t as b}from"./CjGfwvo12.chunk.js";import{n as x}from"./B-eFTZdx2.chunk.js";import{t as S}from"./DMZ_X3HL.chunk.js";import{t as C}from"./DMaQV7L2.chunk.js";import{t as w}from"./CETzluXN.chunk.js";import{t as T}from"./D0n6BTgT.chunk.js";import{t as E}from"./BmR4qY-v2.chunk.js";import{t as D}from"./cX5MHowe.chunk.js";import{t as O}from"./BIO-5Tfr2.chunk.js";import{y as k}from"./wpRpI9h02.chunk.js";import{n as A,r as j,t as M}from"./CsCjBSq62.chunk.js";var N=e(i()),P=a(),F=r.encloseNamespace(`shared.play`),I={notFound:b,forbidden:{privacy:m}};L.defaultProps={queryParams:{}};function L(e){let{context:r,contextId:i,playNext:a,mtv:m,resourceId:b}=e.queryParams,{commonVideoProps:L,hasCommonVideoPropsCompleted:R}=E({locationContext:re.PlayPage,mtv:m}),{hasPermissions:fe}=de(),{activePresentation:z}=f(),{hasPlayPageTranscript:B,hasNewSearch:V,clickViewLive:H}=ae(null),U=s(S.streamableLearning()),W=s(ie.currentUser()),G=s(l.video(e.id)),K=y({objectId:G.data?.id,objectTypeId:G.data?.typeId}),pe=s(K.canViewClips&&se.videoClips(e.id)),me=s(K.canViewInteractives&&c.videoInteractives(e.id)),he=s(z&&C.audiencesByPresentationId(z.id)),{shouldFetchTranscript:q,shouldShowTranscript:ge}=M(e.id),{subtitles:_e,chapters:ve}=s(q&&W.data?.contentRegion&&j.chaptersAndSubtitles(e.id,W.data.contentRegion))?.data||{},J=_e?.filter(e=>!e.customer),Y=ne(J&&J.length>0?J.map(e=>j.subtitleVtt(e.url,e)):[]),ye=J?.filter(e=>Y.data.find(t=>t.id===e.id))||[],X=s(d.config()),be=k(),xe=s(G.statusCode===n.Forbidden&&l.video(e.id,oe.StripMetadata)),Se=w(e.id),Z=g({video:G.data,context:r,contextId:i,moviesAndTv:m,currentUser:W.data}),Q=h(e.id,!0),$=s(l.regionAlternatives(e.id)),Ce=D({name:G.data?.name});return le(ce.getVideoMetadata({content:G.data,regionAlternatives:$.data,phraseContext:{phraseHandler:F,titlePhrase:`pageTitle`,descriptionPhrase:`pageDescription`},canonicalLink:_.getCanonicalLink({stripPresentationSlug:!0,customAppLink:v.getAppLink(G.data,{},e.presentationSlug)}),allowIndexing:_.allowIndexing(),hrefLang:_.getContentHrefLang($.data,(e,t)=>({application:o.VIDEOS,action:u.Videos.PLAY_VIDEO,args:[null,e,te.slugify(t)]}))})),T(G,I,{forbidden:!0}),O(Z.videos??[]),x({id:e.id,app:`videos`}),ue(xe),N.useEffect(()=>{H||!G.data||!U.data||!H&&G.data.libraries?.data.find(e=>e.id===U.data.objectId)&&t.throw(new p)},[G.hasCompleted,U.hasCompleted,H]),G.data&&W.hasCompleted&&Q.hasCompleted&&R?(0,P.jsx)(A,{presentationSlug:e.presentationSlug,video:G.data,clips:pe.data?.data,interactives:me.data?.data,curriculums:Se,relatedVideos:Z,currentUser:W.data,pointsOfInterest:Q.items,playNext:a,featureAccess:K,audiences:he.data,params:e.queryParams,canManageVideoAccess:fe(ee.ManageVideoAccess),shouldShowSideTableOfContents:be,tableOfContentsId:e.queryParams?.tocId,breadcrumbs:Ce,commonVideoProps:L,hasTheatreMode:B,shouldShowTranscript:ge&&(!q||Y.data?.length>0),vttSubtitles:Y.data||[],subtitles:ye,chapters:ve,isBot:_.isBot(),playerApiUrl:X.data?.playerApiUrl,hasNewSearch:V,liteUrl:X.data.liteUrl,resourcePopupId:b}):(0,P.jsx)(P.Fragment,{})}export{L as PlayView};
|
|
2
|
+
//# sourceMappingURL=Drh1bb9z.chunk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuVwpX36.chunk.js","names":[],"sources":["../../src/shared/views/play/PlayView.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { HashObject } from 'libs/common/react/interfaces/HashObject';\nimport { TextHelper } from 'libs/common/react/utils/TextHelper';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { PermissionFilterOption } from 'libs/shared/enums/PermissionFilterOption';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { VideoNotFoundError } from 'libs/shared/errors/videos/video-not-found/VideoNotFoundError';\nimport { VideoPrivateError } from 'libs/shared/errors/videos/video-private/VideoPrivateError';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClipRequests } from 'libs/shared/flight-requests/ClipRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { LibraryRequests } from 'libs/shared/flight-requests/LibraryRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoRequests } from 'libs/shared/flight-requests/VideoRequests';\nimport { useBreadcrumbs } from 'libs/shared/hooks/useBreadcrumbs';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { ClipCollection, Config, CurrentUser, InteractiveCollection, PresentationAudience, RegionAlternative, Video, VttSubtitleResponse } from 'libs/shared/interfaces';\nimport { PlayViewQueryParams } from 'libs/shared/interfaces/query-params/PlayViewQueryParams';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\nimport { TranscriptRequests, TranscriptResponse } from 'shared/flight-requests/TranscriptRequests';\nimport { useActivePresentation } from 'shared/hooks/presentations/useActivePresentation';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDeepLinks } from 'shared/hooks/useDeepLinks';\nimport { useFetchPointsOfInterest } from 'shared/hooks/useFetchPointsOfInterest';\nimport { useGetRelatedVideos } from 'shared/hooks/useGetRelatedVideos';\nimport { useVideoFeatureAccess } from 'shared/hooks/useVideoFeatureAccess';\nimport { useVideoMixin } from 'shared/hooks/useVideoMixin';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\nimport { VideoAppLinkHelper } from 'shared/utils/VideoAppLinkHelper';\nimport { useShouldShowSideTableOfContents } from 'shared/views/play/hooks/useShouldShowTableOfContents';\nimport { useShowTranscriptForVideo } from 'shared/views/play/hooks/useShowVideoTranscript';\n\nimport { PlayPage } from './components/play-page/PlayPage';\n\nconst namespace = 'shared.play';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst videoErrors = {\n notFound: VideoNotFoundError,\n forbidden: {\n privacy: VideoPrivateError\n }\n};\n\nexport interface PlayViewProps {\n presentationSlug: string;\n id: string;\n queryParams?: PlayViewQueryParams;\n}\n\nPlayView.defaultProps = {\n queryParams: {}\n};\n\nexport function PlayView(props: PlayViewProps): React.ReactElement {\n const { context, contextId, playNext, mtv, resourceId } = props.queryParams;\n\n const {\n commonVideoProps,\n hasCommonVideoPropsCompleted\n } = useCommonVideoProps({ locationContext: LocationContext.PlayPage, mtv });\n\n const { hasPermissions } = usePermissions();\n\n const { activePresentation } = useActivePresentation();\n const { hasPlayPageTranscript, hasNewSearch, clickViewLive } = useSettings(null);\n\n const streamableLibrary = Flight.useBasicFetch<HashObject>(LibraryRequests.streamableLearning());\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const video = Flight.useBasicFetch<Video>(VideoRequests.video(props.id));\n\n const featureAccess = useVideoFeatureAccess({\n objectId: video.data?.id,\n objectTypeId: video.data?.typeId\n });\n \n const clips = Flight.useBasicFetch<ClipCollection>(\n featureAccess.canViewClips && ClipRequests.videoClips(props.id)\n );\n const interactives = Flight.useBasicFetch<InteractiveCollection>(\n featureAccess.canViewInteractives && InteractiveRequests.videoInteractives(props.id)\n );\n \n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n activePresentation &&\n AudienceRequests.audiencesByPresentationId(activePresentation.id)\n );\n\n const { shouldFetchTranscript, shouldShowTranscript } = useShowTranscriptForVideo(props.id);\n const transcript = Flight.useBasicFetch<TranscriptResponse>(\n shouldFetchTranscript && currentUser.data?.contentRegion &&\n TranscriptRequests.chaptersAndSubtitles(props.id, currentUser.data.contentRegion)\n );\n const { subtitles: allSubtitles, chapters } = transcript?.data || {};\n // only show transcript for ClickView produced subtitle\n const subtitles = allSubtitles?.filter(subtitle => !subtitle.customer);\n\n const captionsRequests = (subtitles && subtitles.length > 0) ?\n subtitles.map(subtitle => TranscriptRequests.subtitleVtt(subtitle.url, subtitle)) :\n [];\n const captions = Flight.useBasicFetchAll<VttSubtitleResponse>(captionsRequests);\n const filteredSubtitles = subtitles?.filter(\n subtitle => captions.data.find(caption => caption.id === subtitle.id)\n ) || [];\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const shouldShowSideTableOfContents = useShouldShowSideTableOfContents();\n\n const strippedVideo = Flight.useBasicFetch<Video>(video.statusCode === HttpStatus.Forbidden &&\n VideoRequests.video(props.id, PermissionFilterOption.StripMetadata));\n\n const curriculums = useCurriculums(props.id);\n\n const relatedVideos = useGetRelatedVideos({\n video: video.data,\n context,\n contextId,\n moviesAndTv: mtv,\n currentUser: currentUser.data\n });\n const pointsOfInterest = useFetchPointsOfInterest(props.id, true);\n\n const regionAlternatives = Flight.useBasicFetch<RegionAlternative[]>(\n VideoRequests.regionAlternatives(props.id)\n );\n\n const breadcrumbs = useBreadcrumbs({ name: video.data?.name });\n\n useSetPageMetadata(PageMetadataHelper.getVideoMetadata({\n content: video.data,\n regionAlternatives: regionAlternatives.data,\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: VideoAppLinkHelper.getAppLink(video.data, {}, props.presentationSlug)\n }),\n allowIndexing: SeoHelper.allowIndexing(),\n hrefLang: SeoHelper.getContentHrefLang(regionAlternatives.data, (id: string, name: string) => ({\n application: AppChannels.VIDEOS,\n action: Actions.Videos.PLAY_VIDEO,\n args: [ null, id, TextHelper.slugify(name) ]\n }))\n }));\n\n useHandleObjectError(video, videoErrors, { forbidden: true });\n useVideoMixin(relatedVideos.videos ?? []);\n useDeepLinks({ id: props.id, app: 'videos' });\n useCannotConsumeError(strippedVideo);\n\n React.useEffect(() => {\n if (clickViewLive)\n return;\n\n if (!video.data || !streamableLibrary.data)\n return;\n \n if (!clickViewLive && video.data.libraries?.data.find(library => library.id === streamableLibrary.data.objectId))\n Core.ErrorHelper.throw(new NotFoundError());\n }, [ video.hasCompleted, streamableLibrary.hasCompleted, clickViewLive ]);\n\n const dataLoaded = (\n video.data &&\n currentUser.hasCompleted &&\n pointsOfInterest.hasCompleted &&\n hasCommonVideoPropsCompleted\n );\n\n if (!dataLoaded)\n return <></>;\n\n return (\n <PlayPage\n presentationSlug={props.presentationSlug}\n video={video.data}\n clips={clips.data?.data}\n interactives={interactives.data?.data}\n curriculums={curriculums}\n relatedVideos={relatedVideos}\n currentUser={currentUser.data}\n pointsOfInterest={pointsOfInterest.items}\n playNext={playNext}\n featureAccess={featureAccess}\n audiences={audiences.data}\n params={props.queryParams}\n canManageVideoAccess={hasPermissions(PermissionName.ManageVideoAccess)}\n shouldShowSideTableOfContents={shouldShowSideTableOfContents}\n tableOfContentsId={props.queryParams?.tocId}\n breadcrumbs={breadcrumbs}\n commonVideoProps={commonVideoProps}\n hasTheatreMode={hasPlayPageTranscript}\n shouldShowTranscript={shouldShowTranscript && (!shouldFetchTranscript || captions.data?.length > 0)}\n vttSubtitles={captions.data || []}\n subtitles={filteredSubtitles}\n chapters={chapters}\n isBot={SeoHelper.isBot()}\n playerApiUrl={config.data?.playerApiUrl}\n hasNewSearch={hasNewSearch}\n liteUrl={config.data.liteUrl}\n resourcePopupId={resourceId}\n />\n );\n}\n"],"mappings":"8oDAoDM,EAAY,EAAgB,iBAAiB,aAAS,EAEtD,EAAc,CAClB,SAAU,EACV,UAAW,CACT,QAAS,CACX,CACF,EAQA,EAAS,aAAe,CACtB,YAAa,CAAC,CAChB,EAEA,SAAgB,EAAS,EAA0C,CACjE,GAAM,CAAE,UAAS,YAAW,WAAU,MAAK,cAAe,EAAM,YAE1D,CACJ,mBACA,gCACE,EAAoB,CAAE,gBAAiB,GAAgB,SAAU,KAAI,CAAC,EAEpE,CAAE,mBAAmB,GAAe,EAEpC,CAAE,sBAAuB,EAAsB,EAC/C,CAAE,wBAAuB,eAAc,iBAAkB,GAAY,IAAI,EAEzE,EAAoB,EAAiC,EAAgB,mBAAmB,CAAC,EAEzF,EAAc,EAAkC,GAAa,YAAY,CAAC,EAC1E,EAAQ,EAA4B,EAAc,MAAM,EAAM,EAAE,CAAC,EAEjE,EAAgB,EAAsB,CAC1C,SAAU,EAAM,MAAM,GACtB,aAAc,EAAM,MAAM,MAC5B,CAAC,EAEK,GAAQ,EACZ,EAAc,cAAgB,GAAa,WAAW,EAAM,EAAE,CAChE,EACM,GAAe,EACnB,EAAc,qBAAuB,EAAoB,kBAAkB,EAAM,EAAE,CACrF,EAEM,GAAY,EAChB,GACA,EAAiB,0BAA0B,EAAmB,EAAE,CAClE,EAEM,CAAE,wBAAuB,yBAAyB,EAA0B,EAAM,EAAE,EAKpF,CAAE,UAAW,GAAc,aAJd,EACjB,GAAyB,EAAY,MAAM,eAC3C,EAAmB,qBAAqB,EAAM,GAAI,EAAY,KAAK,aAAa,CAEpC,CAAA,EAAY,MAAQ,CAAC,EAE7D,EAAY,IAAc,OAAO,GAAY,CAAC,EAAS,QAAQ,EAK/D,EAAW,GAHS,GAAa,EAAU,OAAS,EACxD,EAAU,IAAI,GAAY,EAAmB,YAAY,EAAS,IAAK,CAAQ,CAAC,EAChF,CAAC,CAC2E,EACxE,GAAoB,GAAW,OACnC,GAAY,EAAS,KAAK,KAAK,GAAW,EAAQ,KAAO,EAAS,EAAE,CACtE,GAAK,CAAC,EACA,EAAS,EAA6B,EAAe,OAAO,CAAC,EAE7D,GAAgC,EAAiC,EAEjE,GAAgB,EAA4B,EAAM,aAAe,EAAW,WAChF,EAAc,MAAM,EAAM,GAAI,GAAuB,aAAa,CAAC,EAE/D,GAAc,EAAe,EAAM,EAAE,EAErC,EAAgB,EAAoB,CACxC,MAAO,EAAM,KACb,UACA,YACA,YAAa,EACb,YAAa,EAAY,IAC3B,CAAC,EACK,EAAmB,EAAyB,EAAM,GAAI,EAAI,EAE1D,EAAqB,EACzB,EAAc,mBAAmB,EAAM,EAAE,CAC3C,EAEM,GAAc,EAAe,CAAE,KAAM,EAAM,MAAM,IAAK,CAAC,EAgD7D,OA9CA,GAAmB,GAAmB,iBAAiB,CACrD,QAAS,EAAM,KACf,mBAAoB,EAAmB,KACvC,cAAe,CACb,cAAe,EACf,YAAa,YACb,kBAAmB,iBACrB,EACA,cAAe,EAAU,iBAAiB,CACxC,sBAAuB,GACvB,cAAe,EAAmB,WAAW,EAAM,KAAM,CAAC,EAAG,EAAM,gBAAgB,CACrF,CAAC,EACD,cAAe,EAAU,cAAc,EACvC,SAAU,EAAU,mBAAmB,EAAmB,MAAO,EAAY,KAAkB,CAC7F,YAAa,EAAY,OACzB,OAAQ,EAAQ,OAAO,WACvB,KAAM,CAAE,KAAM,EAAI,GAAW,QAAQ,CAAI,CAAE,CAC7C,EAAE,CACJ,CAAC,CAAC,EAEF,EAAqB,EAAO,EAAa,CAAE,UAAW,EAAK,CAAC,EAC5D,EAAc,EAAc,QAAU,CAAC,CAAC,EACxC,EAAa,CAAE,GAAI,EAAM,GAAI,IAAK,QAAS,CAAC,EAC5C,GAAsB,EAAa,EAEnC,EAAM,cAAgB,CAChB,GAGA,CAAC,EAAM,MAAQ,CAAC,EAAkB,MAGlC,CAAC,GAAiB,EAAM,KAAK,WAAW,KAAK,KAAK,GAAW,EAAQ,KAAO,EAAkB,KAAK,QAAQ,GAC7G,EAAiB,MAAM,IAAI,CAAe,CAC9C,EAAG,CAAE,EAAM,aAAc,EAAkB,aAAc,CAAc,CAAC,EAGtE,EAAM,MACN,EAAY,cACZ,EAAiB,cACjB,GAOA,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,iBAAkB,EAAM,iBACxB,MAAO,EAAM,KACb,MAAO,GAAM,MAAM,KACnB,aAAc,GAAa,MAAM,KACpB,eACE,gBACf,YAAa,EAAY,KACzB,iBAAkB,EAAiB,MACzB,WACK,gBACf,UAAW,GAAU,KACrB,OAAQ,EAAM,YACd,qBAAsB,GAAe,GAAe,iBAAiB,EACtC,iCAC/B,kBAAmB,EAAM,aAAa,MACzB,eACK,mBAClB,eAAgB,EAChB,qBAAsB,KAAyB,CAAC,GAAyB,EAAS,MAAM,OAAS,GACjG,aAAc,EAAS,MAAQ,CAAC,EAChC,UAAW,GACD,YACV,MAAO,EAAU,MAAM,EACvB,aAAc,EAAO,MAAM,aACb,eACd,QAAS,EAAO,KAAK,QACrB,gBAAiB,CAClB,CAAA,GA/BM,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAI,CAAA,CAiCf"}
|
|
1
|
+
{"version":3,"file":"Drh1bb9z.chunk.js","names":[],"sources":["../../src/shared/views/play/PlayView.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\nimport { HashObject } from 'libs/common/react/interfaces/HashObject';\nimport { TextHelper } from 'libs/common/react/utils/TextHelper';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { PermissionFilterOption } from 'libs/shared/enums/PermissionFilterOption';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { VideoNotFoundError } from 'libs/shared/errors/videos/video-not-found/VideoNotFoundError';\nimport { VideoPrivateError } from 'libs/shared/errors/videos/video-private/VideoPrivateError';\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { ClipRequests } from 'libs/shared/flight-requests/ClipRequests';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { LibraryRequests } from 'libs/shared/flight-requests/LibraryRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoRequests } from 'libs/shared/flight-requests/VideoRequests';\nimport { useBreadcrumbs } from 'libs/shared/hooks/useBreadcrumbs';\nimport { useCannotConsumeError } from 'libs/shared/hooks/useCannotConsumeError';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { ClipCollection, Config, CurrentUser, InteractiveCollection, PresentationAudience, RegionAlternative, Video, VttSubtitleResponse } from 'libs/shared/interfaces';\nimport { PlayViewQueryParams } from 'libs/shared/interfaces/query-params/PlayViewQueryParams';\nimport { PageMetadataHelper } from 'libs/shared/utils/PageMetadataHelper';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\nimport { TranscriptRequests, TranscriptResponse } from 'shared/flight-requests/TranscriptRequests';\nimport { useActivePresentation } from 'shared/hooks/presentations/useActivePresentation';\nimport { useCommonVideoProps } from 'shared/hooks/useCommonVideoProps';\nimport { useCurriculums } from 'shared/hooks/useCurriculums';\nimport { useDeepLinks } from 'shared/hooks/useDeepLinks';\nimport { useFetchPointsOfInterest } from 'shared/hooks/useFetchPointsOfInterest';\nimport { useGetRelatedVideos } from 'shared/hooks/useGetRelatedVideos';\nimport { useVideoFeatureAccess } from 'shared/hooks/useVideoFeatureAccess';\nimport { useVideoMixin } from 'shared/hooks/useVideoMixin';\nimport { SeoHelper } from 'shared/utils/SeoHelper';\nimport { VideoAppLinkHelper } from 'shared/utils/VideoAppLinkHelper';\nimport { useShouldShowSideTableOfContents } from 'shared/views/play/hooks/useShouldShowTableOfContents';\nimport { useShowTranscriptForVideo } from 'shared/views/play/hooks/useShowVideoTranscript';\n\nimport { PlayPage } from './components/play-page/PlayPage';\n\nconst namespace = 'shared.play';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst videoErrors = {\n notFound: VideoNotFoundError,\n forbidden: {\n privacy: VideoPrivateError\n }\n};\n\nexport interface PlayViewProps {\n presentationSlug: string;\n id: string;\n queryParams?: PlayViewQueryParams;\n}\n\nPlayView.defaultProps = {\n queryParams: {}\n};\n\nexport function PlayView(props: PlayViewProps): React.ReactElement {\n const { context, contextId, playNext, mtv, resourceId } = props.queryParams;\n\n const {\n commonVideoProps,\n hasCommonVideoPropsCompleted\n } = useCommonVideoProps({ locationContext: LocationContext.PlayPage, mtv });\n\n const { hasPermissions } = usePermissions();\n\n const { activePresentation } = useActivePresentation();\n const { hasPlayPageTranscript, hasNewSearch, clickViewLive } = useSettings(null);\n\n const streamableLibrary = Flight.useBasicFetch<HashObject>(LibraryRequests.streamableLearning());\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const video = Flight.useBasicFetch<Video>(VideoRequests.video(props.id));\n\n const featureAccess = useVideoFeatureAccess({\n objectId: video.data?.id,\n objectTypeId: video.data?.typeId\n });\n \n const clips = Flight.useBasicFetch<ClipCollection>(\n featureAccess.canViewClips && ClipRequests.videoClips(props.id)\n );\n const interactives = Flight.useBasicFetch<InteractiveCollection>(\n featureAccess.canViewInteractives && InteractiveRequests.videoInteractives(props.id)\n );\n \n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n activePresentation &&\n AudienceRequests.audiencesByPresentationId(activePresentation.id)\n );\n\n const { shouldFetchTranscript, shouldShowTranscript } = useShowTranscriptForVideo(props.id);\n const transcript = Flight.useBasicFetch<TranscriptResponse>(\n shouldFetchTranscript && currentUser.data?.contentRegion &&\n TranscriptRequests.chaptersAndSubtitles(props.id, currentUser.data.contentRegion)\n );\n const { subtitles: allSubtitles, chapters } = transcript?.data || {};\n // only show transcript for ClickView produced subtitle\n const subtitles = allSubtitles?.filter(subtitle => !subtitle.customer);\n\n const captionsRequests = (subtitles && subtitles.length > 0) ?\n subtitles.map(subtitle => TranscriptRequests.subtitleVtt(subtitle.url, subtitle)) :\n [];\n const captions = Flight.useBasicFetchAll<VttSubtitleResponse>(captionsRequests);\n const filteredSubtitles = subtitles?.filter(\n subtitle => captions.data.find(caption => caption.id === subtitle.id)\n ) || [];\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const shouldShowSideTableOfContents = useShouldShowSideTableOfContents();\n\n const strippedVideo = Flight.useBasicFetch<Video>(video.statusCode === HttpStatus.Forbidden &&\n VideoRequests.video(props.id, PermissionFilterOption.StripMetadata));\n\n const curriculums = useCurriculums(props.id);\n\n const relatedVideos = useGetRelatedVideos({\n video: video.data,\n context,\n contextId,\n moviesAndTv: mtv,\n currentUser: currentUser.data\n });\n const pointsOfInterest = useFetchPointsOfInterest(props.id, true);\n\n const regionAlternatives = Flight.useBasicFetch<RegionAlternative[]>(\n VideoRequests.regionAlternatives(props.id)\n );\n\n const breadcrumbs = useBreadcrumbs({ name: video.data?.name });\n\n useSetPageMetadata(PageMetadataHelper.getVideoMetadata({\n content: video.data,\n regionAlternatives: regionAlternatives.data,\n phraseContext: {\n phraseHandler: getPhrase,\n titlePhrase: 'pageTitle',\n descriptionPhrase: 'pageDescription'\n },\n canonicalLink: SeoHelper.getCanonicalLink({\n stripPresentationSlug: true,\n customAppLink: VideoAppLinkHelper.getAppLink(video.data, {}, props.presentationSlug)\n }),\n allowIndexing: SeoHelper.allowIndexing(),\n hrefLang: SeoHelper.getContentHrefLang(regionAlternatives.data, (id: string, name: string) => ({\n application: AppChannels.VIDEOS,\n action: Actions.Videos.PLAY_VIDEO,\n args: [ null, id, TextHelper.slugify(name) ]\n }))\n }));\n\n useHandleObjectError(video, videoErrors, { forbidden: true });\n useVideoMixin(relatedVideos.videos ?? []);\n useDeepLinks({ id: props.id, app: 'videos' });\n useCannotConsumeError(strippedVideo);\n\n React.useEffect(() => {\n if (clickViewLive)\n return;\n\n if (!video.data || !streamableLibrary.data)\n return;\n \n if (!clickViewLive && video.data.libraries?.data.find(library => library.id === streamableLibrary.data.objectId))\n Core.ErrorHelper.throw(new NotFoundError());\n }, [ video.hasCompleted, streamableLibrary.hasCompleted, clickViewLive ]);\n\n const dataLoaded = (\n video.data &&\n currentUser.hasCompleted &&\n pointsOfInterest.hasCompleted &&\n hasCommonVideoPropsCompleted\n );\n\n if (!dataLoaded)\n return <></>;\n\n return (\n <PlayPage\n presentationSlug={props.presentationSlug}\n video={video.data}\n clips={clips.data?.data}\n interactives={interactives.data?.data}\n curriculums={curriculums}\n relatedVideos={relatedVideos}\n currentUser={currentUser.data}\n pointsOfInterest={pointsOfInterest.items}\n playNext={playNext}\n featureAccess={featureAccess}\n audiences={audiences.data}\n params={props.queryParams}\n canManageVideoAccess={hasPermissions(PermissionName.ManageVideoAccess)}\n shouldShowSideTableOfContents={shouldShowSideTableOfContents}\n tableOfContentsId={props.queryParams?.tocId}\n breadcrumbs={breadcrumbs}\n commonVideoProps={commonVideoProps}\n hasTheatreMode={hasPlayPageTranscript}\n shouldShowTranscript={shouldShowTranscript && (!shouldFetchTranscript || captions.data?.length > 0)}\n vttSubtitles={captions.data || []}\n subtitles={filteredSubtitles}\n chapters={chapters}\n isBot={SeoHelper.isBot()}\n playerApiUrl={config.data?.playerApiUrl}\n hasNewSearch={hasNewSearch}\n liteUrl={config.data.liteUrl}\n resourcePopupId={resourceId}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./DAXXjFlN.chunk.js";import{y as e}from"./BftnFbcr.chunk.js";import{t}from"./CQyJ7YGa.chunk.js";import{t as n}from"./C2w0pmFW.chunk.js";import{t as r}from"./wrLrTezN.chunk.js";import{u as i}from"./BX0wDJmp.chunk.js";import{t as a}from"./DIqO2TFN.chunk.js";import{t as o}from"./DTGfiG8Y.chunk.js";import{t as s}from"./oPIkfKWW2.chunk.js";import{t as c}from"./DsXWD-Sn.chunk.js";import{t as l}from"./D_gWf2lC.chunk.js";import{t as u}from"./FbPIRcRM2.chunk.js";import{n as d,t as f}from"./BGhJ8TEx.chunk.js";import{t as p}from"./
|
|
2
|
-
//# sourceMappingURL=
|
|
1
|
+
import"./DAXXjFlN.chunk.js";import{y as e}from"./BftnFbcr.chunk.js";import{t}from"./CQyJ7YGa.chunk.js";import{t as n}from"./C2w0pmFW.chunk.js";import{t as r}from"./wrLrTezN.chunk.js";import{u as i}from"./BX0wDJmp.chunk.js";import{t as a}from"./DIqO2TFN.chunk.js";import{t as o}from"./DTGfiG8Y.chunk.js";import{t as s}from"./oPIkfKWW2.chunk.js";import{t as c}from"./DsXWD-Sn.chunk.js";import{t as l}from"./D_gWf2lC.chunk.js";import{t as u}from"./FbPIRcRM2.chunk.js";import{n as d,t as f}from"./BGhJ8TEx.chunk.js";import{t as p}from"./_Cm5O72d.chunk.js";import{t as m}from"./CYrPnKaS.chunk.js";import{t as h}from"./dEqScqMh2.chunk.js";import{t as g}from"./D1EthTiX.chunk.js";import{t as _}from"./BghRSiDw2.chunk.js";n();var v=r(),y=t.encloseNamespace(`views.upsellProductInfoView`);function b(t){let n=i(s.currentUser()),r=n.data?.instanceRegion,b=i(l.config()),x=u(),{applink:S}=m(),C=x.upsellPresentationType===o.Subject?`welcomeToClickView`:`welcomeToClickViewLive`,w=(b.data?.liteUrl.includes(`staging`)?a.TutorialVideoHighlight[C].staging:a.TutorialVideoHighlight[C].production)?.[r],T=i(w&&c.sharedVideo(w.VIDEO,w.SHARE)),E=i(w&&f.createViewKey(w.SHARE,d.Share)),D=i(w.SHARE&&_.getShareObject(w.SHARE)),O=()=>{t.closePopup(),e.trigger(S)},k=n.hasCompleted&&b.hasCompleted,A=!w||T.hasCompleted&&E.hasCompleted,j=k&&A,M=!!T.data&&!!E.data,N=y(x.upsellPresentationType===o.Subject?`cv`:`cvlive`);return(0,v.jsxs)(h,{size:`lg`,closePopup:t.closePopup,showLoadingSpinner:!j,title:y(`header`,{productName:N}),children:[j&&M&&(0,v.jsx)(p,{config:b.data,currentUser:n.data,video:T?.data,viewKey:E.data,presentationSlug:null,shareLink:D.data,autoplay:!0}),(0,v.jsx)(`p`,{className:`mt-3`,children:y(`infoText`,{productName:N})}),(0,v.jsxs)(g,{children:[(0,v.jsx)(g.Cancel,{onClick:t.closePopup}),(0,v.jsx)(g.Submit,{onClick:O,text:y(`submitText`),variant:`dark`})]})]})}export{b as UpsellProductInfoView};
|
|
2
|
+
//# sourceMappingURL=ESLgHTNq.chunk.js.map
|