@clickview/lite 0.64.0-rc.1 → 0.64.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles.json +1 -1
- package/dist/css/{7153-lite-0cc5db0db7.chunk.css → 2962-lite-2002c62a24.chunk.css} +0 -1
- package/dist/css/{1857-lite-324255d395.chunk.css → 6173-lite-911f35513f.chunk.css} +0 -1
- package/dist/css/{2083-lite-6cb1775e12.chunk.css → 7324-lite-238bd550b7.chunk.css} +0 -1
- package/dist/css/{9013-lite-620f218839.chunk.css → 9013-lite-3c31b606c5.chunk.css} +2 -2
- package/dist/languages/en.json +1 -1
- package/dist/scripts/1216-899540dc73-lite.chunk.js +2 -0
- package/dist/scripts/1216-899540dc73-lite.chunk.js.map +1 -0
- package/dist/scripts/1820-b572681b3a-lite.chunk.js +2 -0
- package/dist/scripts/1820-b572681b3a-lite.chunk.js.map +1 -0
- package/dist/scripts/229-ac9f12e165-lite.chunk.js +2 -0
- package/dist/scripts/229-ac9f12e165-lite.chunk.js.map +1 -0
- package/dist/scripts/2712-a851ddc3c3-lite.chunk.js +2 -0
- package/dist/scripts/2712-a851ddc3c3-lite.chunk.js.map +1 -0
- package/dist/scripts/{2788-eca70707c6-lite.chunk.js → 2788-c8ae3be73f-lite.chunk.js} +1 -1
- package/dist/scripts/2788-c8ae3be73f-lite.chunk.js.map +1 -0
- package/dist/scripts/{7153-0ed8513e59-lite.chunk.js → 2962-7f2e4412f0-lite.chunk.js} +2 -2
- package/dist/scripts/{7153-0ed8513e59-lite.chunk.js.map → 2962-7f2e4412f0-lite.chunk.js.map} +1 -1
- package/dist/scripts/2988-b602b64344-lite.chunk.js +2 -0
- package/dist/scripts/2988-b602b64344-lite.chunk.js.map +1 -0
- package/dist/scripts/3180-c1f065183d-lite.chunk.js +2 -0
- package/dist/scripts/3180-c1f065183d-lite.chunk.js.map +1 -0
- package/dist/scripts/3549-111225ff0e-lite.chunk.js +2 -0
- package/dist/scripts/3549-111225ff0e-lite.chunk.js.map +1 -0
- package/dist/scripts/4591-f78fa6c784-lite.chunk.js +2 -0
- package/dist/scripts/4591-f78fa6c784-lite.chunk.js.map +1 -0
- package/dist/scripts/4667-5101904582-lite.chunk.js +2 -0
- package/dist/scripts/4667-5101904582-lite.chunk.js.map +1 -0
- package/dist/scripts/4718-1426986e1d-lite.chunk.js +2 -0
- package/dist/scripts/4718-1426986e1d-lite.chunk.js.map +1 -0
- package/dist/scripts/{5056-6057435479-lite.chunk.js → 5056-65c739468f-lite.chunk.js} +1 -1
- package/dist/scripts/5056-65c739468f-lite.chunk.js.map +1 -0
- package/dist/scripts/5201-98ee21febb-lite.chunk.js +2 -0
- package/dist/scripts/5201-98ee21febb-lite.chunk.js.map +1 -0
- package/dist/scripts/5595-79068997ce-lite.chunk.js +2 -0
- package/dist/scripts/5595-79068997ce-lite.chunk.js.map +1 -0
- package/dist/scripts/5770-f88f6d9c00-lite.chunk.js +2 -0
- package/dist/scripts/5770-f88f6d9c00-lite.chunk.js.map +1 -0
- package/dist/scripts/5896-60133bfdad-lite.chunk.js +3 -0
- package/dist/scripts/5896-60133bfdad-lite.chunk.js.map +1 -0
- package/dist/scripts/6173-7f9939c29e-lite.chunk.js +3 -0
- package/dist/scripts/6173-7f9939c29e-lite.chunk.js.map +1 -0
- package/dist/scripts/6181-9d7668c9e4-lite.chunk.js +3 -0
- package/dist/scripts/6181-9d7668c9e4-lite.chunk.js.map +1 -0
- package/dist/scripts/6455-37039eb687-lite.chunk.js +2 -0
- package/dist/scripts/6455-37039eb687-lite.chunk.js.map +1 -0
- package/dist/scripts/6623-84b33c6856-lite.chunk.js +3 -0
- package/dist/scripts/6623-84b33c6856-lite.chunk.js.map +1 -0
- package/dist/scripts/6919-8f60ca2263-lite.chunk.js +2 -0
- package/dist/scripts/6919-8f60ca2263-lite.chunk.js.map +1 -0
- package/dist/scripts/7267-1f5006c9c5-lite.chunk.js +2 -0
- package/dist/scripts/7267-1f5006c9c5-lite.chunk.js.map +1 -0
- package/dist/scripts/{2083-7daacf0112-lite.chunk.js → 7324-ee20e73ac1-lite.chunk.js} +2 -2
- package/dist/scripts/{2083-7daacf0112-lite.chunk.js.map → 7324-ee20e73ac1-lite.chunk.js.map} +1 -1
- package/dist/scripts/7434-fef3ea4e89-lite.chunk.js +2 -0
- package/dist/scripts/7434-fef3ea4e89-lite.chunk.js.map +1 -0
- package/dist/scripts/7443-4866d0c9ab-lite.chunk.js +3 -0
- package/dist/scripts/7443-4866d0c9ab-lite.chunk.js.map +1 -0
- package/dist/scripts/8416-7d71a55a14-lite.chunk.js +2 -0
- package/dist/scripts/8416-7d71a55a14-lite.chunk.js.map +1 -0
- package/dist/scripts/8465-01b0f72699-lite.chunk.js +2 -0
- package/dist/scripts/8465-01b0f72699-lite.chunk.js.map +1 -0
- package/dist/scripts/9013-6fcc58f028-lite.chunk.js +2 -0
- package/dist/scripts/9013-6fcc58f028-lite.chunk.js.map +1 -0
- package/dist/scripts/9264-998d93d1c2-lite.chunk.js +2 -0
- package/dist/scripts/9264-998d93d1c2-lite.chunk.js.map +1 -0
- package/dist/scripts/9894-0fba5cf702-lite.chunk.js +3 -0
- package/dist/scripts/9894-0fba5cf702-lite.chunk.js.map +1 -0
- package/dist/scripts/bundle-48f54fe5c2.min.js +3 -0
- package/dist/scripts/bundle-48f54fe5c2.min.js.map +1 -0
- package/package.json +1 -1
- package/dist/scripts/1755-462bcd99e9-lite.chunk.js +0 -2
- package/dist/scripts/1755-462bcd99e9-lite.chunk.js.map +0 -1
- package/dist/scripts/180-6c4779f6ab-lite.chunk.js +0 -2
- package/dist/scripts/180-6c4779f6ab-lite.chunk.js.map +0 -1
- package/dist/scripts/1820-3b5d0a340d-lite.chunk.js +0 -2
- package/dist/scripts/1820-3b5d0a340d-lite.chunk.js.map +0 -1
- package/dist/scripts/1857-d3af9d98eb-lite.chunk.js +0 -3
- package/dist/scripts/1857-d3af9d98eb-lite.chunk.js.map +0 -1
- package/dist/scripts/229-900e650427-lite.chunk.js +0 -2
- package/dist/scripts/229-900e650427-lite.chunk.js.map +0 -1
- package/dist/scripts/2788-eca70707c6-lite.chunk.js.map +0 -1
- package/dist/scripts/3180-22edf4c9fc-lite.chunk.js +0 -2
- package/dist/scripts/3180-22edf4c9fc-lite.chunk.js.map +0 -1
- package/dist/scripts/3549-30d3b1cd05-lite.chunk.js +0 -2
- package/dist/scripts/3549-30d3b1cd05-lite.chunk.js.map +0 -1
- package/dist/scripts/3776-0027340c98-lite.chunk.js +0 -2
- package/dist/scripts/3776-0027340c98-lite.chunk.js.map +0 -1
- package/dist/scripts/4591-3e8dddd0e9-lite.chunk.js +0 -2
- package/dist/scripts/4591-3e8dddd0e9-lite.chunk.js.map +0 -1
- package/dist/scripts/4667-f3882f2379-lite.chunk.js +0 -2
- package/dist/scripts/4667-f3882f2379-lite.chunk.js.map +0 -1
- package/dist/scripts/4718-16d6e39561-lite.chunk.js +0 -2
- package/dist/scripts/4718-16d6e39561-lite.chunk.js.map +0 -1
- package/dist/scripts/5056-6057435479-lite.chunk.js.map +0 -1
- package/dist/scripts/5201-7d3867d027-lite.chunk.js +0 -2
- package/dist/scripts/5201-7d3867d027-lite.chunk.js.map +0 -1
- package/dist/scripts/5595-10e586779d-lite.chunk.js +0 -2
- package/dist/scripts/5595-10e586779d-lite.chunk.js.map +0 -1
- package/dist/scripts/5896-5d2f32c59e-lite.chunk.js +0 -3
- package/dist/scripts/5896-5d2f32c59e-lite.chunk.js.map +0 -1
- package/dist/scripts/6181-50a39979ec-lite.chunk.js +0 -3
- package/dist/scripts/6181-50a39979ec-lite.chunk.js.map +0 -1
- package/dist/scripts/6455-2f45be17cf-lite.chunk.js +0 -2
- package/dist/scripts/6455-2f45be17cf-lite.chunk.js.map +0 -1
- package/dist/scripts/6623-ebbffb59b3-lite.chunk.js +0 -3
- package/dist/scripts/6623-ebbffb59b3-lite.chunk.js.map +0 -1
- package/dist/scripts/6919-cb2de57c2e-lite.chunk.js +0 -2
- package/dist/scripts/6919-cb2de57c2e-lite.chunk.js.map +0 -1
- package/dist/scripts/7267-c2d30dd339-lite.chunk.js +0 -2
- package/dist/scripts/7267-c2d30dd339-lite.chunk.js.map +0 -1
- package/dist/scripts/7434-c34ca23a21-lite.chunk.js +0 -2
- package/dist/scripts/7434-c34ca23a21-lite.chunk.js.map +0 -1
- package/dist/scripts/7443-7c72de0cb9-lite.chunk.js +0 -3
- package/dist/scripts/7443-7c72de0cb9-lite.chunk.js.map +0 -1
- package/dist/scripts/8022-0656cce655-lite.chunk.js +0 -2
- package/dist/scripts/8022-0656cce655-lite.chunk.js.map +0 -1
- package/dist/scripts/9013-adc5d3517a-lite.chunk.js +0 -2
- package/dist/scripts/9013-adc5d3517a-lite.chunk.js.map +0 -1
- package/dist/scripts/9155-87c9030ce9-lite.chunk.js +0 -2
- package/dist/scripts/9155-87c9030ce9-lite.chunk.js.map +0 -1
- package/dist/scripts/9264-750b3d6ea0-lite.chunk.js +0 -2
- package/dist/scripts/9264-750b3d6ea0-lite.chunk.js.map +0 -1
- package/dist/scripts/9894-bc34edcd67-lite.chunk.js +0 -3
- package/dist/scripts/9894-bc34edcd67-lite.chunk.js.map +0 -1
- package/dist/scripts/bundle-e02b7c5d7f.min.js +0 -3
- package/dist/scripts/bundle-e02b7c5d7f.min.js.map +0 -1
- package/dist/css/{6455-lite-fe0bc6d95f.chunk.css → 6455-lite-c07987d46c.chunk.css} +1 -1
- /package/dist/css/{9155-lite-447d345417.chunk.css → 8465-lite-447d345417.chunk.css} +0 -0
- /package/dist/scripts/{1857-d3af9d98eb-lite.chunk.js.LICENSE.txt → 5896-60133bfdad-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{5896-5d2f32c59e-lite.chunk.js.LICENSE.txt → 6173-7f9939c29e-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{6181-50a39979ec-lite.chunk.js.LICENSE.txt → 6181-9d7668c9e4-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{6623-ebbffb59b3-lite.chunk.js.LICENSE.txt → 6623-84b33c6856-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{7443-7c72de0cb9-lite.chunk.js.LICENSE.txt → 7443-4866d0c9ab-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{9894-bc34edcd67-lite.chunk.js.LICENSE.txt → 9894-0fba5cf702-lite.chunk.js.LICENSE.txt} +0 -0
- /package/dist/scripts/{bundle-e02b7c5d7f.min.js.LICENSE.txt → bundle-48f54fe5c2.min.js.LICENSE.txt} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scripts/1857-d3af9d98eb-lite.chunk.js","mappings":";kMACA,SAAgB,QAAU,QAAQ,OAAS,+GCQ3C,IAAMA,EAAY,2BAEZC,EAAc,UAIdC,EAAe,UAAa,CAHf,UACA,YAIbC,EAAgB,CAAE,EAAG,IAAM,IAAM,GAAK,IAAM,GAElD,SAASC,EAAmBC,EAAeC,GACzC,OAAKD,EAGEH,EAAaG,EAAQC,GAAKC,MAFxBN,CAGX,CAEA,SAASO,EAAYC,EAAgBH,GAGnC,IAFA,IAAMI,EAAqB,GAElBC,EAAI,EAAGA,EAAIF,EAAKG,OAAQD,IAAK,CACpC,IAAME,EAAgBF,EAAI,GAAKF,EAAKE,EAAI,GAClCG,EAAeL,EAAKE,GACpBI,EAAYJ,EAAIF,EAAKG,OAAS,GAAKH,EAAKE,EAAI,GAM9CG,IAAiBD,GAAiBC,IAAiBC,GAGvDL,EAASM,KAAK,GAAD,OAAIZ,EAAmBU,EAAcR,GAAI,YAAI,IAAMG,EAAKG,OAASD,EAAC,KAChF,CAED,MAAO,6BAAP,OAAoCD,EAASO,KAAK,KAAI,IACxD,CAEM,SAAUC,IACd,IAAMZ,EAAMa,KAAKb,IAAG,MAARa,KAAYhB,GAClBiB,EAA8B,IAAMjB,EAAcS,OAExD,OACE,uBAAKS,UAAU,wCACb,gBAACC,EAAA,EAAI,CAACtB,UAAWA,EAAWuB,OAAO,SACnC,uBAAKF,UAAS,kCAA6B,WACxClB,EAAcqB,KAAI,SAACC,EAAKC,GAAG,OAC1B,uBACEC,IAAKD,EACLE,MAAO,CACLC,MAAO,GAAF,OAAKT,EAA2B,KACrCU,gBAAiB1B,EAAmBqB,EAAKnB,KAE3C,KAGN,gBAACgB,EAAA,EAAI,CAACtB,UAAWA,EAAWuB,OAAO,SAGzC,CAQM,SAAUQ,EAAkBC,aAC1BC,GAAU,OAAeD,EAAME,YAC/B5B,EAAe,QAAT,EAAA0B,EAAM1B,WAAG,QAAIa,KAAKb,IAAG,MAARa,oDAAYc,ujBAErC,OACE,uBACEZ,UAAS,yBAAoB,UAAc,YAAmB,QAAf,EAAAW,EAAMX,iBAAS,QAAI,IAClEO,MAAO,CACLO,WAAY3B,EAAYyB,EAAS3B,KAIzC,8DCvFA,SAAgB,KAAO,QAAQ,MAAQ,SCajC,SAAU8B,EAAYJ,GAC1B,OACE,2BAASX,UAAU,4DACjB,uBAAKA,UAAS,iBAAYW,EAAMK,SAAW,kBAAoB,qBAAoB,UACjF,uBAAKhB,UAAS,UAAK,OAAW,YAAIW,EAAMM,aAAY,qEAClD,gBAACC,EAAA,EAAY,CAACC,QAASR,EAAMQ,QAASC,KAAMF,EAAAG,EAAA,SAE9C,uBAAKrB,UAAU,2BACb,sBAAIA,UAAU,WAAWW,EAAMW,OAC9BX,EAAMK,UAAY,qBAAGhB,UAAU,oCAAoCW,EAAMK,WAEpD,iBAAhBL,EAAMY,OACZ,uBAAKvB,UAAS,UAAK,QAAY,sFAC5BW,EAAMY,QAIZZ,EAAMa,SAGb,oCClCO,IAAMC,EAAoB,CAC/BC,SAAU,OACVC,WAAY,uMACZC,WAAY,MACZC,MAAO,uECaT,SAASC,EACPC,EACAC,GAEA,MAAO,CACLC,cAAeF,EAAYG,GAC3BC,kBAAmBJ,EAAYK,WAC/BC,UAAW,CAAEC,MAAON,EAAOM,MAAOC,IAAKP,EAAOO,KAC9CC,QAASR,EAAOS,OAChBC,oBAAqBV,EAAOW,QAEhC,CAEO,IAAMC,EAA6B,CAMxCC,qBAAoB,SAClBC,EACAC,EACAhB,EACAC,EACAgB,EACAC,EACAC,EACAC,GAEA,MAAO,CACLC,IAAKJ,EAAoB,gDACkBF,EAAa,qBAAaC,GAAqB,gDAC/CD,EAAa,qBAAaC,GACrEzC,KAAK,OAAuB,0BAAD,OAA2BwC,EAAa,YAAIC,GAAyBf,GAChG5C,KAAM0C,EAA4BC,EAAaC,GAC/CqB,KAAM,SACNC,WAAW,EACXC,WAAY,SAACnE,GACX,OAAO,OAAP,wBACKA,GAAI,CACPoE,SAAUpE,EAAKoE,SAASrD,KAAI,SAACsD,GAC3B,OAAKA,EAAQC,MAASD,EAAQE,UAGvB,OAAP,wBACKF,GAAO,CACVG,WAAY,CACVD,UAAWF,EAAQE,UACnBD,KAAMD,EAAQC,QANTD,CASX,KAEJ,EACAR,QAAAA,EACAC,MAAAA,EACAC,OAAAA,EAEJ,EAMAU,KAAI,SACFf,EACAC,EACAe,EACA1E,EACA6D,EACAC,EACAC,GAEA,MAAO,CACLC,IAAK,oCAAF,OAAsCU,GACzCxD,IAAK,eAAF,OAAiBwD,EAAQ,YAAI1E,EAAK2E,UACrCV,KAAM,QACNjE,KAAAA,EACAkE,WAAW,EACXU,iBAAkB,0BAAF,OAA4BlB,EAAa,YAAIC,GAC7DE,QAAAA,EACAC,MAAAA,EACAC,OAAAA,EAEJ,EAEAc,eAAc,SAAC7E,GACb,MAAO,CACLgE,IAAK,gEACL9C,IAAK,+BACL+C,KAAM,SACNjE,KAAAA,EAEJ,EAEA8E,yBAAwB,SAAC9E,GACvB,MAAO,CACLgE,IAAK,6CACL9C,IAAK,6BACLlB,KAAAA,EACAiE,KAAM,SACNC,WAAW,EAEf,qFCjHI,SAAUa,EACdpB,EACAqB,EACApB,SAEMjB,EAAc,kBAAkC,mBAEhDsC,EAAsB,oBAA4CtB,GACtE,wBAAwCA,IAEpCuB,EAAc,qBAA4D,QAAxB,EAAAD,EAAoBjF,YAAI,eAAE0D,gBAChF,gBAAgCuB,EAAoBjF,KAAK0D,gBAErDyB,IAAuBxC,EAAY3C,QAAUkF,EAAYlF,QAAWgF,EAE1E,OAAO,kBAA2CG,GAChD,EAAAC,EAAA,qBACEH,EAAoBjF,KAAK0D,cACzBuB,EAAoBjF,KAAK8C,GACzBH,EAAY3C,KACZgF,EACApB,GAEN,kBCxBM,SAAUyB,EAAe5D,GAC7B,OAAQ,IAAI6D,MAAM5E,KAAK6E,KAAK9D,EAAW+D,gBAAiBC,KAAK,MAAM1E,KAAI,SAAC2E,EAAGzE,GAAG,OAAKQ,EAAWD,QAAQP,IAAQ,CAAC,GACjH,0HCmBM0E,EAA8B,CAClCC,SAAU,IACVC,UAAW,CACTC,OAAQ,IACRC,UAAW,IACXC,OAAQ,IACRC,QAAS,KAEXC,WAAY,IACZC,oBAAqB,KAGjB,SAAUC,EACdC,GAMkC,IALlCC,EAAA,uDAA+B,CAAC,EAKhCC,EAAA,uDAAgC,CAAC,EAEjC,GAAKF,EAAL,CAGA,IAAIG,EAGFA,EADmB,iBAAVH,EACIA,EAEAA,EAAKI,OAGpB,IAAMC,EAAW,OAAH,wBACTf,GACAW,GAGAE,GAGA,yBAAmCA,KAGpCA,IAAe,mBAMfA,IAAe,aAMfA,IAAe,cAUdD,EAAUL,YACb,aAAuB,IAAIQ,EAASR,YAN/BK,EAAUV,WACb,aAAuB,IAAIa,EAASb,UAAUI,SAX3CM,EAAUX,UACb,aAAuB,IAAIc,EAASd,UAPjCW,EAAUJ,qBACb,aAAuB,IAAI,KAvBvB,CA6CV,8DCxFA,SAASQ,EAAiBC,GACxB,OAAOA,EAAW7F,KAAI,SAAA8F,GAAG,OAAIA,EAAIL,UAAU,IAAEhG,KAAK,IACpD,CAGM,SAAUsG,EACdC,EACAC,EACAC,GAEA,IAAML,EAAatB,MAAM4B,QAAQH,GAAeA,EAAc,CAACA,IAE/D,IAAAI,YAAU,WACRP,EAAWQ,SAAQ,SAAAP,IACjB,OAAgBA,EAAIL,WAAYQ,EAAcC,EAChD,GACF,GAAG,CAAEN,EAAiBC,GAAaI,EAAcC,GACnD,8DCnBM,SAAUI,IACd,aAAgB,WAEd,OADA,uBACO,kBAAM,wBAAiC,CAChD,GAAG,GACL,+KCRA,SAAgB,QAAU,QAAQ,gBAAkB,+GCcpD,IACMC,EAAYC,EAAA,mBADA,0BAOlB,SAASC,EAAYjG,SACnB,OACE,uBAAKX,UAAS,UAAoB,QAAf,EAAAW,EAAMX,iBAAS,QAAI,KACnCW,EAAMa,SAGb,CAOA,SAASqF,EAAWlG,GAClB,OACE,gBAACiG,EAAW,CAAC5G,UAAS,yBAAoBW,EAAMmG,OAAOC,SAAW,UAAY,KAC3EL,EAAU/F,EAAMqG,WAGvB,CAmCM,SAAUC,EAActG,GAC5B,OAAO,WAAc,WACnB,IA/BwBE,EACtB5B,EA8BIiI,GA/BkBrG,EA+BmBF,EAAME,WA9B/C5B,EAAM,EAEV4B,EAAW2F,SAAQ,SAAAW,GACjB,MAAMC,EAAWtH,KAAKb,IAAG,MAARa,oDAAYqH,EAAEvG,6jBAE3BwG,EAAWnI,IACbA,EAAMmI,EACV,IAEOnI,GAuBL,MAAO,CACL,CACEoI,OAAQ,SAAF,OAAKP,EAAM,EAANA,OAAM,OAAO,gBAACD,EAAU,CAACC,OAAQA,EAAQE,UAAU,QAAS,EACvExG,MAAO,GACP8G,SAAU,OACVC,SAAU,SAACC,EAAgCC,GAIzC,OAHc,OAAkBD,EAAKE,OAAOC,KAAMhH,EAAMiH,iBAC1C,OAAkBH,EAAKC,OAAOC,KAAMhH,EAAMiH,gBAEjC,GAAK,CAC9B,EACAC,KAAM,SAAF,GAAgB,MA/BNF,EAAoCC,EAElDE,EA6BS9I,EAAK,EAALA,MACP,GAhCY2I,EAgC2B3I,EAhCS4I,EAgCFjH,EAAMiH,eA5BrD,CACLlE,MAHIoE,GADW,OAAkBH,EAAMC,GACdG,MAAM,KAAK/F,QAAO,SAAAgG,GAAC,QAAMA,CAAC,KAGnC,GAChBC,QAASH,EAAUI,MAAM,GAAGtI,KAAK,OA0BnB8D,EAAI,EAAJA,KAAMuE,EAAO,EAAPA,QACd,OACE,gBAACrB,EAAW,CAAC5G,UAAU,mCACrB,wBAAMA,UAAW,mBACf,gBAACmI,EAAA,EAAM,CACLC,YAAazH,EAAMyH,YACnBC,SAAUC,EAAA,cAAuB5E,EAAMuE,GACvCM,UAAW5H,EAAMiH,gBAAkB,WAAY5I,EAAoB,QAAZ,EAAAA,EAAMwJ,cAAM,eAAEpF,IAAM,KAC3EqF,kBAAmB,cAAezJ,KAGtC,wBAAMgB,UAAW,gBACd0D,EAAI,IAAGuE,GAIhB,GAEF,CACEZ,OAAQ,SAAF,OAAKP,EAAM,EAANA,OAAM,OAAO,gBAACD,EAAU,CAACC,OAAQA,EAAQE,UAAU,SAAU,EACxEM,SAAU,YACV9G,MAAO,GACP+G,SAAU,QACVmB,eAAe,EACfb,KAAM,SAAF,OAAK7I,EAAK,EAALA,MAAK,OACZ,gBAAC4H,EAAW,CAAC5G,UAAU,mCACrB,2BAAMhB,GACM,GAGlB,CACEqI,OAAQ,SAAF,OAAKP,EAAM,EAANA,OAAM,OAAO,gBAACD,EAAU,CAACC,OAAQA,EAAQE,UAAU,cAAe,EAC7EM,SAAU,iBACV9G,MAAO,GACP+G,SAAU,QACVmB,eAAe,EACfb,KAAM,SAAF,OAAK7I,EAAK,EAALA,MAAK,OACZ,gBAAC4H,EAAW,CAAC5G,UAAU,QACrB,gBAAC2I,EAAA,EAAmB,CAClBC,WAAY5J,EACZ6J,OAAQF,EAAA,gBAEE,GAGlB,CACEtB,OAAQ,SAAF,OAAKP,EAAM,EAANA,OAAM,OAAO,gBAACD,EAAU,CAACC,OAAQA,EAAQE,UAAU,WAAY,EAC1EM,SAAU,UACV9G,MAAO,GACPsI,eAAe,EACfjB,KAAM,SAAF,OAAYkB,EAAQ,EAAfC,IAAOD,SAAQ,OACtB,gBAACnC,EAAW,CAAC5G,UAAU,mCACrB,gBAACU,EAAA,EAAiB,CAChBG,WAAYkI,EACZ9J,IAAKiI,EACLlH,UAAS,UAAK,UAAc,kBAElB,GAItB,GAAG,CAACW,EAAMiH,gBACZ,CClJA,IAAMqB,EAAoB,CACxBC,MAAO,4CACPC,OAAQ,gBACRC,WAAY,MACZC,KAAM,aAWF,SAAUC,EAAgB3I,GAC9B,IDqIAE,EACA0I,EACAC,ECvIMC,EAAUxC,EAAc,CAC5BpG,WAAYF,EAAME,WAClBuH,YAAazH,EAAMyH,YACnBR,eAAgBjH,EAAMiH,iBAGlBxI,GD+HNyB,EC/H6BF,EAAME,WDgInC0I,EChI+C5I,EAAM4I,MDiIrDC,ECjI4D7I,EAAM6I,mBDmI3D,WAAc,WACnB,IAAMpK,EAA8B,GAapC,OAXAyB,EAAW2F,SAAQ,SAAAW,SACXQ,EAAO4B,aAAK,EAALA,EAAOG,MAAK,SAAAC,GAAC,OAAIA,EAAEzH,KAAOiF,EAAE1E,MAAM,IACzCmB,EAAmF,QAAtE,EAAA4F,aAAkB,EAAlBA,EAAoBE,MAAK,SAAAE,GAAI,MAAC,OAAY,QAAZ,EAAAA,EAAEhG,kBAAU,eAAED,aAAcwD,EAAExD,SAAS,WAAC,eAAEC,WAGvF+D,EACFvI,EAAKO,KAAK,OAAD,wBAAMwH,GAAC,CAAEQ,KAAAA,KACX/D,GACPxE,EAAKO,KAAK,OAAD,wBAAMwH,GAAC,CAAEQ,KAAM/D,IAC5B,IAEOxE,CACT,GAAG,CAACmK,aAAK,EAALA,EAAOhK,UChJX,OAAKH,EAAKG,OAIR,gBAACsK,EAAA,EAAK,CACJJ,QAASA,EACTrK,KAAMA,EACN6J,MAAOA,EACPa,YAAU,IAPL,gCAUX,gBClCM,SAAUC,EAA2BpJ,GACzC,OACE,gBAACgI,EAAA,EAAmB,CAClBE,OAAQlI,EAAMkI,OACd7I,UAAWW,EAAMX,UACjB4I,WAAY,EACZoB,YAAY,OAGlB,2BCNM,EAAY,8BACZ,EAAYrD,EAAA,mBAAiC,GAO7C,SAAUsD,EAAqBtJ,SAC7BuJ,GAAiC,QAAhB,EAAAvJ,EAAME,kBAAU,eAAEqJ,gBAAiB,EAAIvJ,EAAME,WAAWqJ,eAAiB,KAC1FtB,EAAa9I,KAAKqK,MAAwC,IAAlCxJ,EAAME,WAAWqJ,gBAEzCE,GAAoBzJ,EAAM0J,OAAOd,QACjC5I,EAAM0J,OAAOC,aACb3J,EAAM0J,OAAOE,gBAEnB,OACE,gBAACxJ,EAAA,EAAW,CACVO,MAAO,EAAU,SACjBH,QAAS,WACTF,aAAa,6BAEb,uBAAKjB,UAAU,yDACVW,EAAME,YACP,gCACE,gBAAC8H,EAAA,EAAmB,CAClBC,WAAYsB,EACZrB,OAAQF,EAAA,gBAEV,qBAAG3I,UAAU,eACgB,iBAAnBkK,EACJE,EACA,gBAACnK,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,kBAAkBsK,QAAS,CAAE5B,WAAAA,KAC9D,gBAAC3I,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,eAAesK,QAAS,CAAE5B,WAAAA,KAC/D,gBAAC3I,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,kBAK3CS,EAAME,YACN,gCACE,gBAACkJ,EAA0B,CAAClB,OAAQF,EAAA,kBAMhD,mEC3DM8B,EAAgB,CACpB,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,gICII,EAAY,2BACZ,EAAY9D,EAAA,mBAAiC,GAE7C+D,EAA2C,CAC/CpJ,MAAO,CACLqJ,KAAM,MAERC,QAAS,CACPC,SAAS,GAEXC,MAAO,CACLrK,gBAAiB,cACjBsK,QAAS,CAAE,EAAG,EAAG,EAAG,IAEtBC,OAAQ,CACNC,UAAW,IACXC,aAAc,GAEhBC,YAAa,CACXC,IAAK,CACHC,kBAAkB,EAClBC,OAAQ,UACRC,WAAY,CACVV,SAAS,GAEXW,cAAc,EACdC,YAAa,EACbrK,KAAM,SAUN,SAAUsK,EAAkB/K,GAChC,ICCiCvB,IAxCjCuM,EAEAC,EACAC,EAEMC,EAEAC,EDgCAC,ECfF,SAA0B5M,GAC9B,QAAM6M,EAAa7M,EAAK8M,WAAU,SAAAC,GAAK,MAAmB,UAAfA,EAAMzI,IAAgB,IAGjE,GAAIuI,GAAc,EAAG,CACnB,IAAOG,KAAehN,EAAKiN,OAAOJ,EAAY,KAAE,s4BAA9B,GAElB7M,EAAKkN,QAAQF,EACd,CACD,OAAOhN,EAAKmN,MAAK,SAACC,EAAGC,WAGnB,OAFaC,SAAwC,QAA9B,EAAAF,EAAE9I,KAAgBiJ,MAAM,cAAM,eAAG,IAC3CD,SAAwC,QAA9B,EAAAD,EAAE/I,KAAgBiJ,MAAM,cAAM,eAAG,GAE1D,GACF,CDCoBC,ECvClBjB,EDuC8ChL,EAAMgL,OCrCpDC,EDqC8E,GCpC9EC,EDoDA,SAAuBM,GACrB,MAAiB,YAAVA,EAAsB,QAAUA,CACzC,ECpDML,EAA6B,CAAC,EAIpCC,OAFMA,EAAcJ,EDgCwC,oBC9B5DI,EAAavF,SAAQ,SAAAqG,SACdA,EAAGnJ,QAAQkI,aAAY,EAAZA,EAAckB,SAASD,EAAGnJ,KAAKqJ,kBAG/CjB,EAAOe,EAAGnJ,MAAuB,QAAf,EAAAoI,EAAOe,EAAGnJ,aAAK,QAAI,EACrCoI,EAAOe,EAAGnJ,OAASmJ,EAAGtL,MACxB,IAE0ByL,EAAA,SAAmBC,OAAOC,KAAKpB,GAAQ3L,KAAI,SAAAgM,GAAK,MAAK,CAC7EzI,KAAMmI,EAAgBA,EAAcM,GAASA,EAC7CgB,EAAGrB,EAAOK,GACV9I,KAAM,MACP,IAAI,QFpBOlD,KAAI,SAACiN,EAAG/M,GAAG,OAAK,+BACvB+M,GAAC,CACJvL,MAAO4I,EAAcpK,EAAMoK,EAAclL,SAAO,MCqC5C8N,ECCmC,QAAlC,EAAAjO,OAD0BA,EDAK4M,QCC3B,EAAJ5M,EAAMkO,QAAO,SAACd,EAAGC,GAAC,OAAKD,EAAIC,EAAEU,CAAC,GAAE,UAAE,QAAI,KDkB7C,OACE,gBAACpM,EAAA,EAAW,CACVO,MAAO,EAAU,SAEjBL,aAAa,0BAEbE,QAAS,iBAER6K,aAAS,EAATA,EAAWzM,QACV,gCACE,qBAAGS,UAAU,QAAO,gBAACC,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,aAAasK,QAAS,CAAE6C,WAAAA,MAE/E,uBAAKrN,UAAU,sCACb,gBAAC,IAAe,CACduN,WAAY,IACZ/C,QAhCZ,SACEpL,GAEA,OAAO,OAAP,wBACKsL,GAAoB,CACvB8C,OAAQ,CAAC,CACPnK,KAAM,MACNK,KAAM,EAAU,SAChBtE,KAAAA,KAGN,CAqBqBqO,CAAgBzB,GACzB0B,eAAgB,CACd1N,UAAW,aAMnB,gBAAC2N,EAAA,EAAU,CAAC3N,UAAU,gBACpB,gBAAC2N,EAAA,QAAgB,CAACC,IAAKjN,EAAMkN,gBAAiB7N,UAAU,gBACxD,gBAAC2N,EAAA,UAAkB,CAAC3N,UAAU,MAAK,gBAACC,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,aACtE,gBAACyN,EAAA,OAAe,CAAC3N,UAAU,SAAQ,gBAACC,EAAA,EAAI,CAACtB,UAAW,EAAWuB,OAAO,iBAKhF,wnDErGA,IAMa4N,GAA0B,YAYrC,WAAYC,EAAuBvD,GAAyC,MAIzC,mGAJyC,UAC1E,oZAAMuD,EAAQvD,KAETwD,eAAiBxD,EAAQwD,eAC9B,EAAKC,OAAO,EAAKD,gBAAgB,CACnC,CAAC,oUAEM,WACLE,KAAKD,QAAQC,KAAKF,eACpB,GAAC,oBAEO,SAAOG,GACbA,EAAQD,KAAKE,WAAaF,KAAKG,WACjC,GAAC,sBAEO,WACN,kBAAqBH,KAAKI,SAAU,MACpCJ,KAAKF,gBAAiB,EACtBE,KAAKH,SAASQ,0BAA0BC,cAAcN,KAAKF,gBAC3DE,KAAKH,SAASU,SAAS,oCACzB,GAAC,uBAEO,WACN,qBAAwBP,KAAKI,SAAU,MACvCJ,KAAKF,gBAAiB,EACtBE,KAAKH,SAASQ,0BAA0BC,cAAcN,KAAKF,gBAC3DE,KAAKH,SAASW,YAAY,oCAC5B,GAEA,yBAIO,SAAYC,GACjBA,EAAMC,0BACR,GAAC,sBAEM,SAASC,EAAkBC,EAAkBC,GAK7Cb,KAAKc,eACRd,KAAKe,aAAef,KAAKe,aAAaC,KAAKhB,MAC3CA,KAAKc,cAAe,GAGlBd,KAAKI,UACPJ,KAAKI,SAASa,oBAAoB,QAASjB,KAAKe,cAElDf,KAAKI,SAAW,kBAAqB,MAAO,CAC1CtO,UAAW,2DACXoP,UAAW,uCAEblB,KAAKI,SAASe,iBAAiB,QAASnB,KAAKe,cAE7C,UAIMK,KAAE,2GAAkBT,EAAS,CACjC7O,UAAW,iCACXoP,UANgB,6GAOfL,IAQH,OAFAO,EAAG9N,SAAS,GAAG+N,YAAYrB,KAAKI,UAEzBgB,CACT,qFAAC,CApFoC,CANtB,kBAAqB,aA6FtC,uBAA0B,4BAA6BxB,gCCnFjD,SAAU0B,GAAsB7O,SAC9B8O,EAAY9O,EAAM2D,YAAYoL,WAAWhG,MAAK,SAAA5E,GAClD,IAAM6K,EAAgB7K,EAAE8K,UAAY,IAEpC,OAAO9P,KAAK+P,MAAMlP,EAAMmP,QAAUhQ,KAAK+P,MAAMF,IACxC7P,KAAK6E,KAAKhE,EAAMmP,QAAUhQ,KAAK6E,KAAKgL,EAC3C,IAEA,KAA4B,QAAvB,EAAAF,aAAS,EAATA,EAAWM,oBAAY,eAAExQ,QAC5B,OAAO,iCAET,IAAMwQ,EAAeN,EAAUM,aAAaxQ,OAlBb,EAmB3BkQ,EAAUM,aAAa7H,MAAM,EAAG8H,GAChCP,EAAUM,aAERE,EAAqBR,EAAUM,aAAaxQ,OAASwQ,EAAaxQ,OAExE,OACE,uBAAKS,UAAU,mCACZ+P,EAAa5P,KAAI,SAACb,EAAGe,GAAG,OACvB,gBAAC6P,GAAA,EAAgB,CACf5P,IAAKD,EACL8P,YAAa7Q,EACb8Q,cAAc,EACdC,cAAc,QACd,MAEDJ,GACD,uBACEjQ,UAAW,4GAC8C,WAEpDiQ,IAKf,ovBCxCO,IAAM,GAA2C,CACtD3O,MAAO,CACLqJ,KAAM,MAER2F,MAAO,CACLC,SAAS,EACTC,WAAY,EACZC,WAAY,GAEdzF,OAAQ,CACNH,SAAS,GAEXD,QAAS,CACPC,SAAS,GAEX6F,KAAM,CACJrR,SAAW,CACTwP,QAAS,iBACT3M,GAAI,gBACJyO,GAAI,EACJC,GAAI,EACJC,GAAI,EACJC,GAAI,EACJtP,SAAU,CACP,CACCqN,QAAS,OACTkC,OAAQ,GAET,CACClC,QAAS,OACTkC,OAAQ,OAOZ,SAAUtD,GAAgBjN,EAAewQ,GAC7C,MAAO,CACLC,YAAY,EACZlG,QAAS,CAAE,GAAI,EAAG,EAAG,GACrBvK,MAAAA,EACAwQ,OAAAA,EAEJ,w4CCtCA,IAAME,GAAY,kBAAqB,aAEvC,yBAAgC,KAChC,+BAAsC,UAAW,aAa1C,IAAMC,GAAkB,YAI7B,WAAYpD,EAAuBvD,GAAiC,MAI7C,mGAJ6C,UAClE,oZAAMuD,EAAQvD,KAET4G,aACL,EAAKC,gBAAgB,CACvB,CAAC,kUAEM,WAAU,WACfnD,KAAKH,SAASuD,OAAM,kBAAM,EAAKC,YAAY,GAC7C,GAAC,2BAEM,WACL,MAAO,uBACT,GAAC,sBAEM,SAAS1C,EAAkBC,EAAkBC,GAClD,UAGA,oHAAsBF,EAAS,OAAF,wBACxBC,GAAU,CACb9O,UAAWkO,KAAKsD,gBAChBpC,UANgB,iGAOfL,GACL,GAAC,yBAEM,SAAY0C,GACbA,EACFvD,KAAKqD,aAELrD,KAAKwD,cACT,GAAC,2BAEO,WAAa,WACnBxD,KAAKyD,YAAczD,KAAKyD,YAAYzC,KAAKhB,MACzCA,KAAK0D,YAAc1D,KAAK0D,YAAY1C,KAAKhB,MAEzCA,KAAKH,SAAS8D,GAAG,eAAgB3D,KAAK0D,aAEtC1D,KAAK2D,GAAG3D,KAAKoB,KAAM,UAAWpB,KAAKyD,aAEnCzD,KAAKH,SAAS8D,GAAG,WAAW,WAC1B,EAAK9D,SAAS+D,IAAI,eAAgB,EAAKF,aAEvC,EAAKE,IAAI,EAAKxC,KAAM,UAAW,EAAKqC,YACtC,GACF,GAAC,yBAEO,SAAYhD,GACb,2BAA8BA,KAG/BT,KAAKH,SAASgE,SAChB7D,KAAKH,SAASiE,OAIhB9D,KAAKH,SAASkE,QAChB,GAAC,wBAEO,WAAU,WAChB,IAAI/D,KAAKpD,MAAT,CAGA,IAAMoH,EAAkBhE,KAAKiE,qBAM7B,GAAKD,EAAL,CAKA,IAAME,EAAyBlE,KAAKoB,KAAK+C,cAAc,wBAEvDnE,KAAKpD,MAAQ,UAAiBsH,EAAWlE,KAAKoE,oBAAoBJ,GAJjE,MAFChE,KAAKH,SAASwE,IAAI,QAAQ,kBAAM,EAAKhB,YAAY,GAT3C,CAgBV,GAAC,yBAEO,WACN,IAAMW,EAAkBhE,KAAKiE,qBAExBjE,KAAKpD,OAAUoH,GAGpBhE,KAAKpD,MAAM0H,QAAQN,EAAgB1R,MAAO0R,EAAgBlB,OAC5D,GAAC,0BAEO,iBACI,QAAV,EAAA9C,KAAKpD,aAAK,SAAE2H,UACZvE,KAAKpD,MAAQ,IACf,GAAC,gCAEO,WACN,IAAM4H,EAAgBxE,KAAKH,SAAS4E,SAAS,iBACvCC,EAAsBF,aAAa,EAAbA,EAAeG,gBAErCrS,EAAQ0N,KAAKoB,KAAKwD,YAExB,OAAKF,GAAwBpS,EAKtB,CACLA,MAAAA,EACAwQ,OAJiB9C,KAAKH,SAASgF,oBAAzB/B,OAIW4B,GANV,IAQX,GAAC,iCAEO,SAAoB,GAAkC,IDlCjCI,EAzDMpS,EAkBH0D,ECyEF9D,EAAK,EAALA,MAAOwQ,EAAM,EAANA,OACnC,OAAO,OAAP,wBACK,IAAoB,CACvBlG,MAAO2C,GAAgBjN,EAAOwQ,GAC9BiC,OD/F+BrS,EC+FHsN,KAAKgF,SAAStS,QD5FvC,CAIL3B,IAAgB,KANDa,KAAKb,IAAG,MAARa,KAAI,GAAQc,IAO3BuS,IAAK,EACL3C,WAAY,EACZC,WAAY,EACZ2C,eAAe,EACfC,aAAa,EACbC,WAAW,EACX/C,SAAS,ICkFPgD,SD9E4BjP,EC8ED4J,KAAKgF,SAAS5O,YD7EtC,CACLkP,UAAW,WACT,IAAMC,EAA4BnP,EA0DxC,SAAsCA,EAA0BwL,GAC9D,OAAO,KAAA4D,sBACL,gBAAClE,GAAqB,CAACM,KAAMA,EAAMxL,YAAaA,IAEpD,CA7DUqP,CAA6BrP,EAAa4J,KAAK0F,GAC/C,GAEJ,MACE,mGACgD,mBACnC,EAAAC,GAAA,GAAW3F,KAAK0F,GAAE,aAAW,UACrCH,GAHL,8FAKyF,6DACjCvF,KAAKf,EAAC,WAN9D,cAUJ,EACA2G,WAAY,SACVC,EACAC,EACAC,GAEA,IACMC,EAAOhG,KAAKpD,MAAMqJ,UAAYJ,EAC9BH,EAAIK,EAAMG,MAAQL,EAAa,EAErC,MAAO,CAELH,EAAG9T,KAAKqT,IAAIrT,KAAKb,IAAI2U,EANV,GAMoBM,GAC/B/G,EAAGe,KAAKpD,MAAMuJ,QAElB,EACAC,SAAS,EACTC,QAAS,IC4CPpJ,aDxCyB6H,ECwCG9E,KAAK8E,uBAAuB9D,KAAKhB,MDvC1D,CACLsG,KAAM,CACJP,MAAO,CACLtI,OAAQ,CACN8I,UAAW,WACTzB,EAAuB9E,KAAK0F,EAC9B,EACAc,SAAU,WACR1B,EAAuB,KACzB,KAINxF,OAAQ,CACNmH,OAAQ,CACN9J,SAAS,MCyBX2C,OAAQ,CAAC,CACPnK,KAAM,OACNjE,KAAM8O,KAAKgF,SAAStS,WAG1B,GAAC,oCAEO,SAAuBgT,GACzB1F,KAAKgF,SAAS0B,kBAChB1G,KAAKgF,SAAS0B,iBAAiBhB,GAEjC,IAAMiB,EAA4B3G,KAAKoB,KAAK+C,cAAc,sCAEhD,OAANuB,GAKJ,kBAAqBiB,EAAW,6CAChCA,EAAUtU,MAAMuU,KAAO,GAAH,OAAMlB,EAAI1F,KAAKgF,SAAStS,QAAQrB,OAAS,IAAG,MAL9D,qBAAwBsV,EAAW,4CAMvC,qFAAC,CA9I4B,CAAQ3D,0kCAiJvC,uBAA0B,oBAAqBC,ICtK/C,IAQM4D,GAAwB,YAG5B,WAAYhH,EAAuBvD,GAAuC,MAOrE,mGAPqE,UACxE,oZAAMuD,EAAQvD,KAETA,QAAUA,EAEfuD,EAAOuD,OAAM,WACX,EAAKF,YACP,IAAG,CACL,CAAC,mUAEO,iBACDlD,KAAK8G,mBAGV9G,KAAKH,OAAOkH,SAAS,oBAAqB,CACxCrU,QAASsN,KAAK1D,QAAQ5J,QACtB0D,YAAa4J,KAAK1D,QAAQlG,YAC1BsQ,iBAAkB1G,KAAK1D,QAAQoK,oBAGsB,QAArC,EAAA1G,KAAKH,OAAO4E,SAAS,wBAAgB,eAAEA,SAAS,cACxDuC,QAAQ,CAChBC,MAAO,EACPC,KAAMtH,GACNpK,KAAM,4BACN8G,QAAS,CAAEwD,gBAAgB,KAE/B,GAAC,2BAEM,SAAcyD,GACnB,IAAM4D,EAAoBnH,KAAKH,OAAO4E,SAAS,qBAC/C0C,SAAAA,EAAmBC,YAAY7D,EACjC,GAAC,4BAEO,iBACN,OAA2B,QAApB,EAAAvD,KAAK1D,QAAQ5J,eAAO,eAAE0M,QAAO,SAACiI,EAAKnV,GAAG,OAAKmV,EAAMnV,CAAG,GAAE,IAAK,CACpE,oFAAC,CAvC2B,CARf,eAAkB,WAkDjC,oBAAuB,0BAA2B2U,wnCCnDlD,IAWMS,GAAyB,YAG7B,WAAYzH,EAAuBvD,GAAwC,MAKc,mGALd,UACzE,oZAAMuD,KAEDvD,QAAUA,EAEf,EAAKuD,OAAOwE,IAAI,kBAAkB,kBAAM,EAAKxE,OAAOuD,MAAM,EAAKF,WAAWlC,KAAK,GAAM,IAAE,CACzF,CAAC,mUAEO,WAEN,cAAqBhB,KAAKH,OAAQ,WAAY,cAAeG,KAAKuH,cAAcvG,KAAKhB,OAErFA,KAAKH,OAAOU,SAAS,wBACvB,GAAC,2BAEO,SAAciH,GACpBxH,KAAKyH,YAAYD,EACnB,GAAC,yBAEO,SAAYA,GACFxH,KAAKH,OAAO6H,WAAWjD,SAAS,mBAAmBA,SAAS,WAEpEsC,SAAS,IAAI,KAAoB/G,KAAKH,OAAQ,CACpDzJ,YAAa4J,KAAK1D,QAAQlG,YAC1BoR,MAAAA,IAEJ,oFAAC,CA7B4B,CAXhB,eAAkB,ovPA2CjC,oBAAuB,2BAA4BF,QCjCtCK,GAAc,YAIzB,WAAY3T,EAAsBsI,GAA6B,8fACvDtI,EAAIsI,GACZ,CAAC,0UAES,WACR,MAAO,mBACT,GAAC,oCAES,WACR,MAAO,gBACT,GAAC,6BAEe,SAAgBsL,GAA8B,8QAC5D,EAAMC,gBAAe,UAACD,GAEtB5H,KAAK8H,6BAA6BF,GAClC5H,KAAK+H,kBAAkBH,GACvB5H,KAAKgI,8BAA8BJ,GAAgB,2TACpD,0CAEO,SAA6BA,SACnC5H,KAAKH,OAAOQ,wBAAwB,CAClC3N,QAASsN,KAAK1D,QAAQ5J,QACtB0D,YAA0C,QAA7B,EAAAwR,EAAeK,sBAAc,eAAE7R,YAC5CsQ,iBAAkB1G,KAAK1D,QAAQoK,kBAEnC,GAAC,+BAEO,SAAkBkB,SAOpBM,EANEC,EAAsC,eAA7BP,EAAeQ,UACxBC,EAA6C,sBAA7BT,EAAeQ,UAErC,IAAKD,GAAWE,KAIZF,IACFD,EAAWN,EAAeK,iBAExBI,IACFH,EAAwC,QAA7B,EAAAN,EAAeK,sBAAc,eAAEC,WAD5C,CAQA,IAAKA,EACH,MAAMI,MAAM,qBAEdtI,KAAKH,OAAO0I,WAAW,CACrBC,UAAWN,EAASM,UACpBC,QAASP,EAASO,SAPnB,CASH,GAAC,2CAEO,SAA8Bb,WAC9BxR,EAA2C,QAA7B,EAAAwR,EAAeK,sBAAc,eAAE7R,aAEjB,QAA7B,EAAAwR,EAAeK,sBAAc,eAAE7R,eAGpC4J,KAAKwH,MAAQ,yBAA2CxH,KAAKH,OAAQ+H,GAErE5H,KAAKH,OAAO6I,yBAAyB,CAAEtS,YAAAA,IACzC,GAAC,+BAES,WACR,MAAO,CACLuS,gBAAgB,EAEpB,qFAAC,CA3EwB,CAAQ,MCf7B,SAAUC,GAAuBnW,GACrC,IAAMoW,EAAM,WACNC,EAAY,WAMlB,OAJA,aAAgB,WACdA,EAAUC,QAAU,IAAIpB,GAAckB,EAAIE,QAAStW,EACrD,GAAG,IAGD,uBAAKoW,IAAKA,GAEd,CCdA,UAAgB,gBAAkB,QAAQ,kBAAoB,QAAQ,QAAU,QAAQ,0BAA4B,QAAQ,iCAAmC,QAAQ,wBAA0B,SCWjM,IACM,GAAYpQ,EAAA,mBADA,iCAUZ,SAAUuQ,GAAuBvW,GACrC,IAAMwW,EAAwB,WAExBvW,GAAU,QAAeD,EAAME,YAiBrC,OACE,uBAAKb,UAAU,8DACb,uBAAKA,UAAU,qBAMb,uBAAKA,UAAW,uBAChB,uBAAKA,UAAW,oBACd,gBAAC8W,GAAsB,CACrBM,QAASzW,EAAMyW,QACfC,UAAW,IAAIC,IAAI3W,EAAM4W,cACzBC,sBAAsB,OACtB5W,QAASA,EACTgU,iBA9BV,SAA2B9E,GACzB,IAAMR,EAAK6H,EAAsBF,QAE5B3H,IAGQ,OAATQ,GAKJR,EAAGmI,UAAUC,IAAI,qCACjBpI,EAAG/O,MAAMuU,KAAO,GAAH,OAAMhF,EAAOlP,EAAQrB,OAAS,IAAG,MAL5C+P,EAAGmI,UAAUE,OAAO,qCAMxB,EAkBUC,YAAY,WAIlB,uBAAK5X,UAAU,OACb,uBAAKA,UAAU,qBACb,gBAACU,EAAA,EAAiB,CAChBG,WAAYF,EAAME,WAClBb,UAAW,aAEb,uBAAK+W,IAAKI,EAAuBnX,UAAW,gCAE9C,uBAAKA,UAAU,uCACb,8BACG,GAAU,YAEb,uBAAKA,UAAU,QACb,gBAACU,EAAA,EAAuB,SAMpC,4BChFA,UAAgB,gBAAkB,QAAQ,eAAiB,SCGrD,SAAUmX,KACd,OACE,2BACE,uBAAK7X,UAAU,gBACb,uBAAKA,UAAU,OACb,uBAAKA,UAAS,UAAK,mBAAsB,0CAE3C,uBAAKA,UAAU,OACb,uBAAKA,UAAS,UAAK,mBAAsB,0CAE3C,uBAAKA,UAAW,mBACd,uBAAKA,UAAS,UAAK,mBAAsB,2CAI7C,uBAAKA,UAAU,gBACb,uBAAKA,UAAU,UACb,uBAAKA,UAAS,UAAK,mBAAsB,2CAKnD,CCzBA,UAAgB,eAAiB,gHCqCjC,IACM,GAAY2G,EAAA,mBADA,0BAQZ,SAAUmR,GAAoBnX,2BAC3BiH,MAAkB,OAAsB,wBAA8B,w4BAAxD,IAErB,EAAAnB,EAAA,KAEA,IAAM1E,EAAc,kBAAkCgW,EAAA,iBAChDC,EAAeC,GAAA,kBAA4BtX,EAAMuX,QAASvX,EAAMwX,QAChEC,EAAQ,kBAAiCJ,GACzCK,EAAS,kBAA6BC,EAAA,YAEtCC,EAAwB,+BACxBC,EAAyB,gCAEzBpU,EAAa,gCACd,SAAkB,UAA+BoU,KACjD,OAAkBD,IAGjBE,GAAU,OACd9X,EAAMwX,SAAWO,EAAA,gBAAoC,QAAV,EAAAN,EAAMhZ,YAAI,eAAE8C,IACvDkC,GACA,GAEIuU,EAAkB,WACtB,WAAK,QAAC,SAAwB,QAAtB,EAAY,QAAZ,EAAAF,EAAQrZ,YAAI,eAAEoE,gBAAQ,eAAEkG,MAAK,SAAAkP,GAAI,MAAC,OAAY,QAAZ,EAAAA,EAAEhV,kBAAU,eAAED,SAAS,IAAC,GAClE,CAAC8U,EAAQrZ,OAELyZ,EAAe9W,EAAY3C,OAASuB,EAAMwX,SAAWO,EAAA,eAA0BD,EAAQrZ,MAEvF0Z,EAAsB,kBAC1BD,GAAgBE,EAAA,sBACdpY,EAAMuX,QACN9T,EACArC,EAAY3C,KAAK8C,GACjByW,IAIEK,EAAuB,kBAAmDH,GAC9EE,EAAA,uBAAuCpY,EAAMuX,QAAS9T,EAA+B,QAAhB,EAAArC,EAAY3C,YAAI,eAAE8C,GAAIyW,IAE7F,GAA6B,QACI,QAA/B,EAAyB,QAAzB,EAAAK,EAAqB5Z,YAAI,eAAEA,YAAI,eAAEe,KAAI,SAAAiN,GAAC,OAAIA,EAAE3K,MAAM,IAAET,OAAOiX,WAAY,IADjE1P,EAAK,EAALA,MAAO2P,EAAS,EAATA,UAITC,EAAa,kBAA6CN,GAC9DE,EAAA,QAAwB3U,EAAezD,EAAMuX,QAAyB,QAAhB,EAAAnW,EAAY3C,YAAI,eAAE8C,GAAIyW,IAExEvB,EAAU,kBACdgC,EAAA,gBAA6BzY,EAAMuX,QAASmB,EAAA,kBAG9C,EAAAC,GAAA,GAAmB,CAAEhY,MAAO8W,EAAMhZ,KAAO,GAAU,YAAa,CAAEgZ,MAAiB,QAAV,EAAAA,EAAMhZ,YAAI,eAAEsE,OAAU,QAC/F,OAAqB0U,GAErB,ICnGiCmB,EAC3BrM,EDkGAsM,EACJzX,EAAY3C,MACZ+Z,EAAW/Z,MACXgZ,EAAMhZ,MACN0Z,EAAoB1Z,MACpBgY,EAAQhY,OACPuB,EAAMwX,SAAWO,EAAA,eAA0BD,EAAQrZ,MAEhDqa,KAAoBT,EAAqB5Z,MAAU4Z,EAAqB5Z,KAAKA,KAAKG,QAAW2Z,GAE7F7O,EAAS,OAAH,wBACPkO,GACAC,GAaL,OACE,uBAAKxY,UAAU,QACb,gBAAC0Z,GAAA,EAAkB,CACjBtB,MAAOA,EAAMhZ,KACbmZ,sBAAuBA,EACvBC,uBAAwBA,EACxBmB,KAfAhZ,EAAMwX,SAAWO,EAAA,eACZ,SAA2B/X,EAAMuX,QAAS,UAAW7N,GAE1D1J,EAAMwX,SAAWO,EAAA,QACZ,SAAoB/X,EAAMuX,QAAS,UAAW7N,IAEhD,SAAqB1J,EAAMuX,QAAS,UAAW7N,MAYlDmP,GAAiB,gBAAC3B,GAAsB,MAE1C,uBAAK7X,UAAU,gBACZwZ,GACC,gCACE,uBAAKxZ,UAAU,OACb,gBAAC0L,EAAiB,CAACC,OAAQwN,EAAW/Z,KAAMyO,gBAAiB+L,GAAA,2BAE/D,uBAAK5Z,UAAU,OACb,gBAACiK,EAAoB,CAACpJ,WAAYiY,EAAoB1Z,KAAMiL,OAAQkO,KAEtE,uBAAKvY,UAAW,mBACd,gBAACkX,GAAsB,CACrBrW,WAAYiY,EAAoB1Z,KAChCgY,QAASA,EAAQhY,KAAKgY,QACtBG,aAAcc,EAAOjZ,KAAKmY,aAC1BnP,YAAaiQ,EAAOjZ,KAAKgJ,gBAMhCqR,GACC,gBAACnQ,EAAe,CACdhJ,KC7JuBiZ,ED6JC,OAAD,wBAAMhB,GAA0BC,GC5J3DtL,EAAiB,GAEvBD,OAAOC,KAAKqM,GAAS/S,SAAQ,SAAClG,GAC5B,IAAMF,EAAMmZ,EAAQjZ,GAEfF,GAGL8M,EAAKvN,KAAK,GAAD,OAAIW,EAAG,YAAIoE,MAAM4B,QAAQlG,GAAOA,EAAIR,KAAK,KAAOQ,GAC3D,IAEO8M,EAAKtN,KAAK,MDkJPiB,WAAYmY,EAAqB5Z,KAAKA,KACtCmK,MAAOA,EACPnB,YAAwB,QAAX,EAAAiQ,EAAOjZ,YAAI,eAAEgJ,YAC1BR,eAAgBA,EAChB4B,mBAAgC,QAAZ,EAAAiP,EAAQrZ,YAAI,eAAEoE,YAM9C,o5CExKA,IAcaqW,EAAW,YAUtB,WAAY9L,EAAuBvD,GAA0B,MAI3D,+FAJ2D,SAC3D,gZAAMuD,SAGoB+L,IAAtBtP,EAAQkM,UACV,MAAMF,MAAM,sBAGd,QAAwBsD,IAApBtP,EAAQmM,QACV,MAAMH,MAAM,oBAGd,GAAIhM,EAAQkM,UAAYlM,EAAQmM,QAC9B,MAAMH,MAAM,8CAuBX,OApBH,EAAKuD,WAAaC,WAAWxP,EAAQkM,UAAUuD,YAAY,IAC3D,EAAKC,SAAWF,WAAWxP,EAAQmM,QAAQsD,YAAY,IAGvD,EAAKE,cAAgB,EAAKpM,OAAOqM,MAAMlL,KAAKnB,GAC5C,EAAKsM,iBAAmB,EAAKtM,OAAOuM,SAASpL,KAAKnB,GAClD,EAAKwM,oBAAsB,EAAKxM,OAAOyM,YAAYtL,KAAKnB,GACxD,EAAK0M,iBAAmB,EAAK1M,OAAO2M,SAASxL,KAAKnB,GAGlD,EAAKA,OAAOqM,MAAQ,EAAKA,MAAMlL,KAAK,GACpC,EAAKnB,OAAOuM,SAAW,EAAKA,SAASpL,KAAK,GAC1C,EAAKnB,OAAOyM,YAAc,EAAKA,YAAYtL,KAAK,GAChD,EAAKnB,OAAO2M,SAAW,EAAKA,SAASxL,KAAK,GAE1C,EAAKkC,aAEL,EAAKrD,OAAOuD,OAAM,WAEhB,EAAKvD,OAAO4M,QAAQ,iBACtB,IAAG,CACL,CAEA,8TAGA,WACE,IAAM/V,EAAgBsJ,KAAKmM,mBAE3B,OAAInM,KAAK6L,WAAanV,EACbA,EAEFsJ,KAAK6L,UACd,GAEA,mBAGA,WACE,IAAMnV,EAAgBsJ,KAAKmM,mBAI3B,OAAIzV,GAAiB,EACZsJ,KAAKgM,SAGVhM,KAAKgM,SAAWtV,EACXA,EAEFsJ,KAAKgM,QACd,GAAC,qBAEM,qBACLhM,KAAKH,OAAO+D,IAAI,aAAc5D,KAAK0M,cACnC1M,KAAKH,OAAO+D,IAAI,OAAQ5D,KAAK2M,QAG7B3M,KAAKH,OAAOqM,MAAQlM,KAAKiM,cACzBjM,KAAKH,OAAOuM,SAAWpM,KAAKmM,iBAC5BnM,KAAKH,OAAOyM,YAActM,KAAKqM,oBAC/BrM,KAAKH,OAAO2M,SAAWxM,KAAKuM,iBAG5BvM,KAAKH,OAAO4M,QAAQ,qBAEpB,0GACF,GAAC,wBAEO,WACNzM,KAAK0M,aAAe1M,KAAK0M,aAAa1L,KAAKhB,MAC3CA,KAAK2M,OAAS3M,KAAK2M,OAAO3L,KAAKhB,MAE/BA,KAAKH,OAAO8D,GAAG,aAAc3D,KAAK0M,cAClC1M,KAAKH,OAAO8D,GAAG,OAAQ3D,KAAK2M,OAC9B,GAAC,oBAEO,WAEF3M,KAAK4M,UACP5M,KAAKH,OAAOyM,YAAY,EAE5B,GAAC,0BAEO,WACN,IAAMA,EAActM,KAAK6M,gBAAe,GAGpCP,EAActM,KAAK8M,QAChB9M,KAAK4M,WACR5M,KAAKH,OAAOkE,QACZ/D,KAAKH,OAAO4M,QAAQ,SAEpBzM,KAAK4M,UAAW,IAMpB5M,KAAK4M,UAAW,EAGZN,EAAetM,KAAK+M,UAvIO,IAwI7B/M,KAAKqM,oBAAoBrM,KAAK+M,WAAW,GAE7C,GAAC,mBAEO,WACN,OAAO/M,KAAK6M,gBAAe,GAAS7M,KAAK8M,OAC3C,GAAC,sBAEO,SAASE,GAWf,OATIA,GAAWA,EAAU,IACEhN,KAAKmM,mBAG5Bc,QAAQ1V,KAAK,qEAEbyI,KAAKmM,iBAAiBa,IAGnBhN,KAAK8M,QAAU9M,KAAK+M,SAC7B,GAAC,yBAEO,SAAYC,GAClB,GAAuB,iBAAZA,EACT,OAAOhN,KAAK6M,gBAAe,GAGqB,IAAlD,IAAMK,EAAmBF,EAAUhN,KAAK+M,UAAU,mBALXI,EAAW,iCAAXA,EAAW,kBAOlDnN,KAAKqM,oBAAoBa,EAAkBC,EAG7C,GAEA,4BAIQ,SAAeC,GACrB,IAAMC,EAAoBrN,KAAKqM,sBAC3BzK,EAAO,EASX,OAPIyL,GAAqBrN,KAAK+M,YAC5BnL,EAAOyL,EAAoBrN,KAAK+M,WAIlC/M,KAAKH,OAAOyN,WAAWhB,YAAc1K,EAEjCwL,EACKxL,EAEFyL,CACT,GAAC,sBAEO,WAIN,IAHA,IAAME,EAAOvN,KAAKuM,mBACZiB,EAAS,GAENpc,EAAI,EAAGA,EAAImc,EAAKlc,OAAQD,IAC/Boc,EAAOpc,GAAK,CACVQ,KAAKb,IAAI,EAAGwc,EAAKnZ,MAAMhD,GAAK4O,KAAK+M,WACjCnb,KAAKqT,IAAIrT,KAAKb,IAAI,EAAGwc,EAAKlZ,IAAIjD,GAAK4O,KAAK+M,WAAY/M,KAAKH,OAAOuM,aAIpE,OAAO,qBAAyBoB,EAClC,oFAAC,CApMqB,CAdT,cAAkB,WAqNjC,mBAAuB,aAAc7B,2iDChNrC,IAMa8B,EAAmB,YAI9B,WAAY5N,EAAuBvD,GAAkC,6GACnE,gZAAMuD,EAAQvD,KAEToR,WAAapR,EAAQiF,UAC1B,EAAKoM,MAAQrR,EAAQiF,UAAUG,UAAY,IAE3C,IAAMkM,EAAmBtR,EAAQiF,UAAUM,aAAa,GAGnD+L,GACH,EAAKC,OAEP,IAAQC,EAAgBC,EAAA,cAAkCH,EAAiB3D,QAAnE6D,YAMM,OALd,EAAKE,EAAE,yBAAyBzE,UAAUC,IAAIsE,GAG9C,EAAKG,YAAYL,EAAiBpY,MAElC,EAAK0Y,SAAS,CAChB,CAAC,oUAEM,WACL,MAAO,2BAAP,uCACF,GAAC,sBAEM,SAASvN,EAAkBC,EAAkBC,GASlD,OARW,EAAH,oBAAG,CAAH,CAAkBF,EAAS,OAAF,wBAC5BC,GAAU,CACb9O,UAAWkO,KAAKsD,kBAAe,+BAE5BzC,GAAU,CACbsN,SAAU,KAId,GAAC,oBAEM,WACL,IAAM/B,EAAWpM,KAAKoO,QAAQhC,WACxB9Z,EAAQ0N,KAAK2N,MAAQvB,EAE1BpM,KAAKoB,KAAqB/O,MAAMuU,KAAgB,IAARtU,EAAe,IAGpDA,EAAQ,KAAOA,EAAQ,EACzB0N,KAAK6N,OAEL7N,KAAKuD,MACT,GAAC,yBAEM,SAAYtK,GACjBA,EAAEoV,kBACFrO,KAAKoO,QAAQ9B,YAAYtM,KAAK2N,MAChC,oFAAC,CAzD6B,CANd,iBAAqB,6lDCCvC,IAOaW,EAAoB,YAI/B,WAAYzO,EAAuBvD,GAAmC,MAkBjE,mGAlBiE,UACpE,gZAAMuD,EAAQvD,KAETiS,OAASjS,EAAQkL,MACtB,EAAKgH,aAAelS,EAAQlG,YAE5B,EAAKqY,iBAAmB,EAAKA,iBAAiBzN,KAAK,GACnD,EAAK0N,uBAAyB,EAAKA,uBAAuB1N,KAAK,GAE/D,EAAK0N,yBAEJ,EAAKH,OAAe5K,GAAG,eAAgB,EAAK+K,wBAE7C,EAAKN,QAAQzK,GAAG,iBAAkB,EAAK8K,kBACvC,EAAKL,QAAQzK,GAAG,WAAW,WACxB,EAAK4K,OAAe3K,IAAI,gBAEzB,EAAKwK,QAAQxK,IAAI,iBAAkB,EAAK6K,iBAC1C,IAAG,CACL,CAAC,oUAEM,WACL,MAAO,4BAAP,uCACF,GAAC,sBAEM,SAAS9N,EAAkBC,EAAkBC,GAClD,OAAO,EAAP,oBAAO,CAAP,CAAsBF,EAAS,OAAF,wBACxBC,GAAU,CACb9O,UAAWkO,KAAKsD,kBACfzC,GACL,GAAC,oBAEM,WACLb,KAAK2O,UAAUrW,SAAQ,SAACsW,GACtBA,EAAMV,QACR,GACF,GAAC,oCAEO,WAAsB,aAC5B,GAAKlO,KAAKuO,OAAV,ynBASA,CAAIvO,KAAK2O,WAAWrW,SAAQ,SAAAsW,GAC1B,EAAKC,YAAYD,EACnB,IAEA,IAAK,IAAIxd,EAAI,EAAGA,EAAI4O,KAAKuO,OAAOO,KAAKzd,OAAQD,IAAK,CAChD,IAAM2d,EAAM/O,KAAKuO,OAAOO,KAAK1d,GACvBmQ,EAAYvB,KAAKgP,iBAAiBD,EAAItS,MAEvC8E,IAAoC,QAAtB,EAAAA,EAAUM,oBAAY,eAAExQ,SAG3C2O,KAAK+G,SAAS,IAAI0G,EAAmBzN,KAAKoO,QAAS,CACjD7M,UAAWA,IAEd,CAtBO,CAuBV,GAAC,8BAEO,WACNvB,KAAKkO,QACP,GAAC,8BAEO,SAAiBla,SACvB,OAAmC,QAA5B,EAAAgM,KAAKwO,aAAahN,kBAAU,eAAEhG,MAAK,SAAA5E,GAAC,OAAIA,EAAE5C,GAAGib,aAAejb,EAAGib,UAAU,GAClF,oFAAC,CA3E8B,CAPf,iBAAqB,gDCFhC,IAAMC,EAAyB,CACpCC,oBAAmB,SAACtP,EAAuB+H,SACnCJ,EAAQ3H,EAAOuP,aAAa,WAAY,eAExChZ,EAAcwR,EAAeK,eAAe7R,YAC5CiZ,EAAmD,QAAtC,EAAAzH,EAAeK,eAAeC,gBAAQ,eAAEM,UAsB3D,OApBApS,EAAYoL,WAAWlJ,SAAQ,SAAA1B,SACzB4R,EAAY5R,EAAE8K,UAAY,IAC1B+G,EAAU7R,EAAE0Y,WAAa9G,EAAa5R,EAAE0Y,WAAa,IAAQ9G,EAAY,EAEzE6G,IACF7G,GAAa6G,EACb5G,GAAW4G,IAGM,QAAd,EAAAzY,EAAEiL,oBAAY,eAAExQ,SAGrBmW,EAAM+H,OAAO,CAEX/G,UAAW5W,KAAKb,IAAI,KAAOyX,EAAY,MACvCC,QAAAA,EACAhM,KAAM7F,EAAE5C,IAEZ,IAEOwT,CACT","sources":["file:///app/packages/libs/shared/src/apps/analytics/components/engagement-heat-map/engagement-heat-map.scss","file:///app/packages/libs/shared/src/apps/analytics/components/engagement-heat-map/EngagementHeatMap.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insight-card/insight-card.scss","file:///app/packages/libs/shared/src/apps/analytics/components/insight-card/InsightCard.tsx","file:///app/packages/libs/shared/src/apps/analytics/constants/ChartStyles.ts","file:///app/packages/libs/shared/src/apps/analytics/flight-requests/InteractiveResultsRequests.ts","file:///app/packages/libs/shared/src/apps/analytics/hooks/UseFetchInteractiveResults.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/EngagementUtils.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/hooks/useLockContentWidth.ts","file:///app/packages/libs/shared/src/apps/analytics/components/engagement-table/engagement-table.scss","file:///app/packages/libs/shared/src/apps/analytics/components/engagement-table/EngagementTableUtils.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/engagement-table/EngagementTable.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PartialPercentageIndicator.tsx","file:///app/packages/libs/shared/src/apps/analytics/components/insights/amount-watched/InsightAmountWatched.tsx","file:///app/packages/libs/shared/src/apps/analytics/utils/ChartColourUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/components/insights/total-views/InsightTotalViews.tsx","file:///app/packages/libs/shared/src/apps/analytics/utils/SharedUserActivityPieChartUtils.ts","file:///app/packages/projects/player/src/plugins/engagement-overlay-plugin/components/engagement-overlay-menu-item/engagement-overlay-menu-item.ts","file:///app/packages/projects/player/src/plugins/engagement-overlay-plugin/components/timepoint-interactions/timepoint-interactions.tsx","file:///app/packages/projects/player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay-chart-options.tsx","file:///app/packages/projects/player/src/plugins/engagement-overlay-plugin/components/engagement-overlay/engagement-overlay.ts","file:///app/packages/projects/player/src/plugins/engagement-overlay-plugin/engagement-overlay-plugin.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/interactive-seek-bar-plugin.ts","file:///app/packages/projects/player/src/players/reports/reports-player.ts","file:///app/packages/projects/player/src/react/ReportsPlayer.tsx","file:///app/packages/projects/lite/src/apps/insights/components/video-engagement-overlay/video-engagement-overlay.scss","file:///app/packages/projects/lite/src/apps/insights/components/video-engagement-overlay/VideoEngagementOverlay.tsx","file:///app/packages/projects/lite/src/apps/insights/views/heatmap/partial-loading/partial-insights-heatmap.scss","file:///app/packages/projects/lite/src/apps/insights/views/heatmap/partial-loading/PartialInsightsHeatmap.tsx","file:///app/packages/projects/lite/src/apps/insights/views/heatmap/insights-heatmap.scss","file:///app/packages/projects/lite/src/apps/insights/views/heatmap/InsightsHeatmapView.tsx","file:///app/packages/libs/shared/src/apps/analytics/utils/FilterParamUtils.ts","file:///app/packages/projects/player/src/plugins/clip-plugin/clip-plugin.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/seek-bar/interactive-bar-item.ts","file:///app/packages/projects/player/src/plugins/interactive-plugin/components/seek-bar/interactive-bar-items.ts","file:///app/packages/projects/player/src/utils/interactive-track-helper.ts"],"sourcesContent":["// extracted by mini-css-extract-plugin\nexport default {\"heatMap\":\"epapa\",\"legend\":\"uhH4p\"};","import React from 'react';\nimport chroma from 'chroma-js';\n\nimport { getFullHeatMap } from 'libs/shared/apps/analytics/utils/EngagementUtils';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { Engagement } from 'libs/shared/interfaces';\n\nimport styles from './engagement-heat-map.scss';\n\nconst namespace = 'shared.engagementHeatMap';\n\nconst ZERO_COLOUR = '#f1f1f1';\nconst MIN_COLOUR = '#daf07d';\nconst MAX_COLOUR = '#08bd1a';\n\nconst COLOUR_SCALE = chroma.scale([ MIN_COLOUR, MAX_COLOUR ]);\n\nconst LEGEND_VALUES = [ 0, 0.01, 0.25, 0.5, 0.75, 1 ];\n\nfunction getBackgroundColor(value: number, max: number): string {\n if (!value)\n return ZERO_COLOUR;\n\n return COLOUR_SCALE(value / max).hex();\n}\n\nfunction getGradient(data: number[], max: number): string {\n const gradient: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const previousValue = i > 0 && data[i - 1];\n const currentValue = data[i];\n const nextValue = i < data.length - 1 && data[i + 1];\n\n /**\n * We want to capture colour changes but if a value has the same value\n * of both of its neighbours, we can skip it.\n */\n if (currentValue === previousValue && currentValue === nextValue)\n continue;\n\n gradient.push(`${getBackgroundColor(currentValue, max)} ${100 / data.length * i}%`);\n }\n\n return `linear-gradient(to right, ${gradient.join(',')})`;\n}\n\nexport function EngagementHeatMapLegend(): JSX.Element {\n const max = Math.max(...LEGEND_VALUES);\n const legendSquareWidthPercentage = 100 / LEGEND_VALUES.length;\n\n return (\n <div className='d-flex justify-content-between w-100'>\n <Text namespace={namespace} phrase='less' />\n <div className={`d-flex mx-1 flex-grow-1 ${styles.legend}`}>\n {LEGEND_VALUES.map((val, idx) => (\n <div\n key={idx}\n style={{\n width: `${legendSquareWidthPercentage}%`,\n backgroundColor: getBackgroundColor(val, max)\n }}\n />\n ))}\n </div>\n <Text namespace={namespace} phrase='more' />\n </div>\n );\n}\n\ninterface EngagementHeatMapProps {\n engagement: Engagement;\n max?: number;\n className?: string;\n}\n\nexport function EngagementHeatMap(props: EngagementHeatMapProps): JSX.Element {\n const heatMap = getFullHeatMap(props.engagement);\n const max = props.max ?? Math.max(...heatMap);\n\n return (\n <div\n className={`border rounded ${styles.heatMap} ${props.className ?? ''}`}\n style={{\n background: getGradient(heatMap, max)\n }}\n />\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"icon\":\"sAmpy\",\"count\":\"faDs4\"};","import React from 'react';\n\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\n\nimport styles from './insight-card.scss';\n\ninterface InsightCardProps extends React.PropsWithChildren {\n svgName: string;\n svgClassName: string;\n title: string;\n subtitle?: string;\n count?: number;\n}\n\nexport function InsightCard(props: InsightCardProps) {\n return (\n <section className='d-flex flex-column border border-light rounded p-3 h-100'>\n <div className={`d-flex ${props.subtitle ? 'align-items-top' : 'align-items-center'} mb-2`}>\n <div className={`${styles.icon} ${props.svgClassName} rounded-circle d-flex justify-content-center align-items-center`}>\n <SvgContainer svgName={props.svgName} size={SvgContainerSize.Small} />\n </div>\n <div className='d-flex flex-column ms-2'>\n <h2 className='h6 mb-0'>{props.title}</h2>\n {props.subtitle && <p className='text-secondary font-size-sm mb-0'>{props.subtitle}</p>}\n </div>\n {typeof props.count === 'number' && (\n <div className={`${styles.count} d-flex justify-content-center align-items-center bg-light rounded-circle ms-auto`}>\n {props.count}\n </div>\n )}\n </div>\n {props.children}\n </section>\n );\n}","export const CHART_FONT_STYLES = {\n fontSize: '12px',\n fontFamily: `\"Inter\",-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,\"Noto Sans\",\"Liberation Sans\",sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\"`,\n fontWeight: '400',\n color: '#313543'\n};","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { Flight } from 'libs/common/react/index';\n\nimport { MarkInteractiveAnswer } from 'libs/shared/apps/analytics/interfaces/MarkInteractiveAnswer';\nimport { InteractiveResultsReport } from 'libs/shared/apps/analytics/interfaces/requests/InteractiveResultsReport';\nimport { InteractivesPendingReviewsRequest } from 'libs/shared/apps/analytics/interfaces/requests/InteractivesPendingReviewsRequest';\nimport { AnalyticsRequestFilter, CurrentUser, InteractiveResultSet } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\ninterface InteractiveResultFilters {\n currentUserId: string;\n currentCustomerId: string;\n dateRange?: { start: string, end: string }\n userIds?: string | string[];\n classroomsAndGroups?: string | string[];\n}\n\nfunction getInteractiveResultFilters(\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter\n): InteractiveResultFilters {\n return {\n currentUserId: currentUser.id,\n currentCustomerId: currentUser.customerId,\n dateRange: { start: filter.start, end: filter.end },\n userIds: filter.userId,\n classroomsAndGroups: filter.groupId\n };\n}\n\nexport const InteractiveResultsRequests = {\n /** \n * This endpoint returns data with a lot of duplicated ids,\n * e.g. student answers to the same question will have the same id.\n * Because of that, we don't normalize.\n */\n interactiveResultSet(\n interactiveId: string,\n interactiveMetadataId: string,\n currentUser: CurrentUser,\n filter: AnalyticsRequestFilter,\n includePublicResults: boolean,\n success?: (data: InteractiveResultSet) => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: includePublicResults ?\n `/api/domain/v3/analytics/interactives/${interactiveId}/metadata/${interactiveMetadataId}` :\n `/api/domain/v2/analytics/interactives/${interactiveId}/metadata/${interactiveMetadataId}`,\n key: getAnalyticsRequestKey(`interactive:result:set:${interactiveId}:${interactiveMetadataId}`, filter),\n data: getInteractiveResultFilters(currentUser, filter),\n type: HttpVerbs.POST,\n normalize: false,\n formatData: (data: any) => {\n return {\n ...data,\n students: data.students.map((student: any) => {\n if (!student.name || !student.profileId)\n return student;\n\n return {\n ...student,\n publicUser: {\n profileId: student.profileId,\n name: student.name\n }\n };\n })\n };\n },\n success,\n error,\n always\n };\n },\n \n /**\n * As the response from `interactiveResultSet` isn't normalised, we need to invalidate the cache\n * to update the results data.\n */\n mark(\n interactiveId: string,\n interactiveMetadataId: string,\n answerId: string,\n data: MarkInteractiveAnswer,\n success?: () => void,\n error?: (data: any) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/answers/${answerId}`,\n key: `mark:answer:${answerId}:${data.resultId}`,\n type: HttpVerbs.PUT,\n data,\n normalize: false,\n invalidationKeys: `interactive:result:set:${interactiveId}:${interactiveMetadataId}`,\n success,\n error,\n always\n };\n },\n\n pendingReviews(data: InteractivesPendingReviewsRequest): Flight.Request {\n return {\n url: `/api/domain/v1/analytics/interactives/pending-reviews/summary`,\n key: `interactives:pending:reviews`,\n type: HttpVerbs.POST,\n data\n };\n },\n\n interactiveResultsReport(data: InteractiveResultsReport): Flight.Request {\n return {\n url: '{gateway}/v2/analytics/interactives/report',\n key: 'interactive:results:report',\n data,\n type: HttpVerbs.POST,\n normalize: false\n };\n }\n};","import { Flight } from 'libs/common/flight';\n\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { AnalyticsRequestFilter, CurrentUser, Interactive, InteractiveMetadata, InteractiveResultSet } from 'libs/shared/interfaces';\n\nexport function useFetchInteractiveResults(\n interactiveMetadataId: string,\n requestFilter: AnalyticsRequestFilter,\n includePublicResults?: boolean\n): Flight.Response<InteractiveResultSet> {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(!!interactiveMetadataId &&\n InteractiveRequests.interactiveMetadata(interactiveMetadataId));\n\n const interactive = Flight.useBasicFetch<Interactive>(!!interactiveMetadata.data?.interactiveId &&\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId));\n\n const shouldFetchResults = !!currentUser.data && !!interactive.data && (!!requestFilter);\n\n return Flight.useBasicFetch<InteractiveResultSet>(shouldFetchResults &&\n InteractiveResultsRequests.interactiveResultSet(\n interactiveMetadata.data.interactiveId,\n interactiveMetadata.data.id,\n currentUser.data,\n requestFilter,\n includePublicResults\n ));\n}","import { Engagement } from 'libs/shared/interfaces';\n\n/**\n * The heat map in the API response won't contain trailing zeros so we need to add those\n * in manually.\n */\nexport function getFullHeatMap(engagement: Engagement): number[] {\n return (new Array(Math.ceil(engagement.videoDuration))).fill(null).map((t, idx) => engagement.heatMap[idx] || 0);\n}","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import React from 'react';\n\nimport { LayoutHelper } from 'libs/shared/utils/LayoutHelper';\n\nexport function useLockContentWidth(): void {\n React.useEffect(() => {\n LayoutHelper.lockContentWidth();\n return () => LayoutHelper.unlockContentWidth();\n }, []);\n}","// extracted by mini-css-extract-plugin\nexport default {\"heatMap\":\"rwDjh\",\"avatarContainer\":\"kW4ZM\"};","import React from 'react';\nimport { Column, ColumnInstance, Row } from 'react-table';\n\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 { Avatar } from 'libs/shared/components/avatar/Avatar';\nimport { PercentageIndicator, PercentageIndicatorLayout } from 'libs/shared/components/percentage-indicator/PercentageIndicator';\nimport { Engagement, StudentResults, User } from 'libs/shared/interfaces';\nimport { PublicInteractiveUser } from 'libs/shared/interfaces/models/interactive-results/PublicInteractiveUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nimport styles from './engagement-table.scss';\n\nconst namespace = 'shared.engagementTable';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\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: User | PublicInteractiveUser;\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\nfunction getUsersName(user: User | PublicInteractiveUser, anonymiseUsers: boolean) {\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}\n\nexport function useGetColumns(props: EngagementColumnProps): Column<EngagementTableData>[] {\n return React.useMemo(() => {\n const maxHeatMapValue = getMaxHeatMapValue(props.engagement);\n\n return [\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='name' />,\n width: 22,\n accessor: 'user',\n sortType: (rowA: Row<EngagementTableData>, rowB: Row<EngagementTableData>) => {\n const nameA = anonymiseUserName(rowA.values.user, props.anonymiseUsers);\n const nameB = anonymiseUserName(rowB.values.user, props.anonymiseUsers);\n\n return nameA > nameB ? 1 : -1;\n },\n Cell: ({ value }) => {\n const { name, surname } = getUsersName(value, props.anonymiseUsers);\n return (\n <CellWrapper className='d-flex align-items-center h-100'>\n <span className={styles.avatarContainer}>\n <Avatar\n imageCdnUrl={props.imageCdnUrl}\n initials={UserHelper.getInitials(name, surname)}\n imageUrl={!props.anonymiseUsers && `avatar` in value ? value.avatar?.url : null}\n showAnonymousUser={'profileId' in value}\n />\n </span>\n <span className={'ms-2 clamp-1'}>\n {name} {surname}\n </span>\n </CellWrapper>\n );\n }\n },\n {\n Header: ({ column }) => <HeaderCell column={column} phraseKey='views' />,\n accessor: 'viewCount',\n width: 15,\n sortType: 'basic', // Default is 'alphanumeric' which would treat the numbers as strings\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 width: 20,\n sortType: 'basic', // Default is 'alphanumeric' which would treat the numbers as strings\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 width: 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]);\n}\n\nexport function useGetTableData(\n engagement: Engagement[],\n users?: User[],\n interactiveResults?: StudentResults[]\n): EngagementTableData[] {\n return React.useMemo(() => {\n const data: EngagementTableData[] = [];\n\n engagement.forEach(e => {\n const user = users?.find(u => u.id === e.userId);\n const publicUser = interactiveResults?.find(r => r.publicUser?.profileId === e.profileId)?.publicUser;\n\n // Omit deleted users\n if (user)\n data.push({ ...e, user });\n else if (publicUser)\n data.push({ ...e, user: publicUser });\n });\n\n return data;\n }, [users?.length]);\n}","import React from 'react';\n\nimport { Table, TableTheme } from 'libs/shared/components/table/Table';\nimport { StudentResults, User } from 'libs/shared/interfaces';\nimport { Engagement } from 'libs/shared/interfaces';\n\nimport { useGetColumns, useGetTableData } from './EngagementTableUtils';\n\nconst theme: TableTheme = {\n table: 'bg-white border border-light 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?: User[];\n interactiveResults?: StudentResults[];\n anonymiseUsers: boolean;\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 });\n\n const data = useGetTableData(props.engagement, props.users, props.interactiveResults);\n\n if (!data.length)\n return <></>;\n\n return (\n <Table\n columns={columns}\n data={data}\n theme={theme}\n enableSort\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}","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 { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\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 { Engagement } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightAmountWatched';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightAmountWatchedProps {\n engagement: Engagement;\n params: FilterQueryParams;\n}\n\nexport function InsightAmountWatched(props: InsightAmountWatchedProps) {\n const engagementRate = props.engagement?.engagementRate > 0 ? props.engagement.engagementRate : null;\n const percentage = Math.round(props.engagement.engagementRate * 100);\n\n const everyoneSelected = !props.params.users\n && !props.params.classrooms\n && !props.params.classroomGroups;\n\n return (\n <InsightCard\n title={getPhrase('title')}\n svgName={cvSvgLibrary.Timer}\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 ? everyoneSelected ?\n <Text namespace={namespace} phrase='everyoneWatched' options={{ percentage }} />\n : <Text namespace={namespace} phrase='usersWatched' 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}","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}","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 { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.insightTotalViews';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\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: 0,\n size: '80%'\n }\n }\n};\n\ninterface InsightTotalViewsProps {\n events: VideoViewEventResponse;\n emptyStateImage: string;\n}\n\nexport function InsightTotalViews(props: InsightTotalViewsProps) {\n const chartData = sortByYearGroup(groupEvents(props.events, 'yearGroupCount', [], getSeriesName));\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 function getSeriesName(group: string): string {\n return group === 'Unknown' ? 'Staff' : group;\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 svgName={cvSvgLibrary.VisibleOn}\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}","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 if (!ev.name || groupsToOmit?.includes(ev.name.toLowerCase()))\n return;\n\n groups[ev.name] = groups[ev.name] ?? 0;\n groups[ev.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 first index\n if (staffIndex > -1) {\n const [staffObject] = data.splice(staffIndex, 1);\n\n data.unshift(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}","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}","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}","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);","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 const cogButton = this.player.getChild('collapserator')?.getChild('cogButton') as CogButton;\n cogButton.addItem({\n index: 0,\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}","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.useTrack(this.player, 'metadata', '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}","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';\n\nexport interface ReportsPlayerOptions extends BasePlayerOptions {\n heatMap: number[];\n onTimepointHover?: (time: number | null) => void;\n}\n\nexport class ReportsPlayer extends BasePlayer {\n 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();\n const playerRef = React.useRef<ReportsPlayer>();\n\n React.useEffect(() => {\n playerRef.current = new ReportsPlayer(ref.current, props);\n }, []);\n\n return (\n <div ref={ref}></div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"playerContainer\":\"hXVIx\",\"playerPlaceholder\":\"fhZb2\",\"heatMap\":\"PP9cQ\",\"heatMapTimepointIndicator\":\"kQ5NO\",\"heatMapTimepointIndicatorVisible\":\"J1dev\",\"partialLoadingContainer\":\"xEqEk\"};","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.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>();\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 border-light 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}","// extracted by mini-css-extract-plugin\nexport default {\"partialInsights\":\"x4ubh\",\"videoContainer\":\"Vcovm\"};","import React from 'react';\n\nimport styles from './partial-insights-heatmap.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}","// extracted by mini-css-extract-plugin\nexport default {\"videoContainer\":\"ps_UZ\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\nimport { Flight } from 'libs/common/react/index';\n\nimport { EngagementTable } from 'libs/shared/apps/analytics/components/engagement-table/EngagementTable';\nimport { InsightAmountWatched } from 'libs/shared/apps/analytics/components/insights/amount-watched/InsightAmountWatched';\nimport { InsightTotalViews } from 'libs/shared/apps/analytics/components/insights/total-views/InsightTotalViews';\nimport { useChunkedUsersResponse } from 'libs/shared/apps/analytics/hooks/UseEngagementUsers';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { VideoViewEventResponse } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { AnalyticsFilterHelper } from 'libs/shared/apps/analytics/utils/AnalyticsFilterUtils';\nimport { getAudienceParams } from 'libs/shared/apps/analytics/utils/AudienceUtils';\nimport { getInsightsDateRangePresets, getStartEndParams } from 'libs/shared/apps/analytics/utils/DateRangeUtils';\nimport { getFilterParamsKey } from 'libs/shared/apps/analytics/utils/FilterParamUtils';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { MediaIdType } from 'libs/shared/enums/MediaIdType';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { PlayerRequests } from 'libs/shared/flight-requests/PlayerRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoViewRequests } from 'libs/shared/flight-requests/VideoViewRequests';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useLockContentWidth } from 'libs/shared/hooks/useLockContentWidth';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { AnalyticsRequestFilter, Config, CurrentUser, Engagement, IndividualEngagementResponse, PlayerViewKey, VideoTypes } from 'libs/shared/interfaces';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { ViewModelKeys } from 'shared/constants/LiteViewModels';\n\nimport { VideoEngagementOverlay } from 'apps/insights/components/video-engagement-overlay/VideoEngagementOverlay';\nimport { getInsightsClipTabs, getInsightsInteractiveTabs, getInsightsVideoTabs } from 'apps/insights/utils/InsightsAppLinkUtils';\nimport { InsightsHeaderView } from 'apps/insights/views/header/InsightsHeaderView';\nimport { PartialInsightsHeatmap } from 'apps/insights/views/heatmap/partial-loading/PartialInsightsHeatmap';\n\nimport styles from './insights-heatmap.scss';\n\nconst namespace = 'shared.insightsHeatmap';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\ninterface InsightsHeatmapViewProps {\n videoId: string;\n typeId: MasterType;\n}\n\nexport function InsightsHeatmapView(props: InsightsHeatmapViewProps) {\n const [anonymiseUsers] = useViewModel<boolean>(ViewModelKeys.ANONYMISE_USERS);\n\n useLockContentWidth();\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const videoRequest = VideoHelper.getVideoRequest(props.videoId, props.typeId);\n const video = Flight.useBasicFetch<VideoTypes>(videoRequest);\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const audienceAppLinkParams = AnalyticsFilterHelper.getAudienceAppLinkParams();\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n\n const requestFilter: AnalyticsRequestFilter = {\n ...getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams),\n ...getAudienceParams(audienceAppLinkParams)\n };\n\n const results = useFetchInteractiveResults(\n props.typeId === MasterType.Interactive && video.data?.id,\n requestFilter,\n true\n );\n const hasPublicResult = React.useMemo(\n () => !!results.data?.students?.find(s => s.publicUser?.profileId),\n [results.data]\n );\n const readyToFetch = currentUser.data && (props.typeId !== MasterType.Interactive || results.data);\n\n const aggregateEngagement = Flight.useBasicFetch<Engagement>(\n readyToFetch && VideoViewRequests.aggregateEngagement(\n props.videoId,\n requestFilter,\n currentUser.data.id,\n hasPublicResult\n )\n );\n\n const individualEngagement = Flight.useBasicFetch<IndividualEngagementResponse>(readyToFetch &&\n VideoViewRequests.individualEngagement(props.videoId, requestFilter, currentUser.data?.id, hasPublicResult));\n\n const { users, isLoading } = useChunkedUsersResponse(\n individualEngagement.data?.data?.map(d => d.userId).filter(Boolean) || []\n );\n\n const videoViews = Flight.useBasicFetch<VideoViewEventResponse>(readyToFetch &&\n VideoViewRequests.views(requestFilter, props.videoId, currentUser.data?.id, hasPublicResult));\n\n const viewKey = Flight.useBasicFetch<PlayerViewKey>(\n PlayerRequests.createViewKey(props.videoId, MediaIdType.MasterObject)\n );\n\n useSetPageMetadata({ title: video.data ? getPhrase('pageTitle', { video: video.data?.name }) : null });\n useHandleObjectError(video);\n\n const hasDataLoaded =\n currentUser.data &&\n videoViews.data &&\n video.data &&\n aggregateEngagement.data &&\n viewKey.data &&\n (props.typeId !== MasterType.Interactive || results.data);\n\n const tableDataLoaded = !!individualEngagement.data && (!individualEngagement.data.data.length || !isLoading);\n\n const params = {\n ...audienceAppLinkParams,\n ...dateRangeAppLinkParams\n };\n\n function getInsightsTabs() {\n if (props.typeId === MasterType.Interactive)\n return getInsightsInteractiveTabs(props.videoId, 'heatmap', params);\n\n if (props.typeId === MasterType.Clip)\n return getInsightsClipTabs(props.videoId, 'heatmap', params);\n\n return getInsightsVideoTabs(props.videoId, 'heatmap', params);\n }\n\n return (\n <div className='px-3'>\n <InsightsHeaderView\n video={video.data}\n audienceAppLinkParams={audienceAppLinkParams}\n dateRangeAppLinkParams={dateRangeAppLinkParams}\n tabs={getInsightsTabs()}\n />\n\n {!hasDataLoaded && <PartialInsightsHeatmap />}\n\n <div className='row g-3 mb-3'>\n {hasDataLoaded &&\n <>\n <div className='col'>\n <InsightTotalViews events={videoViews.data} emptyStateImage={ImageUrls.EmptyStates.MY_VIDEOS} />\n </div>\n <div className='col'>\n <InsightAmountWatched engagement={aggregateEngagement.data} params={audienceAppLinkParams} />\n </div>\n <div className={styles.videoContainer}>\n <VideoEngagementOverlay\n engagement={aggregateEngagement.data}\n viewKey={viewKey.data.viewKey}\n playerApiUrl={config.data.playerApiUrl}\n imageCdnUrl={config.data.imageCdnUrl}\n />\n </div>\n </>\n }\n\n {tableDataLoaded &&\n <EngagementTable\n key={getFilterParamsKey({ ...audienceAppLinkParams, ...dateRangeAppLinkParams })}\n engagement={individualEngagement.data.data}\n users={users}\n imageCdnUrl={config.data?.imageCdnUrl}\n anonymiseUsers={anonymiseUsers}\n interactiveResults={results.data?.students}\n />\n }\n </div>\n </div>\n );\n}","import { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\n\nexport function getFilterParamsKey(filters: FilterQueryParams): string {\n const keys: string[] = [];\n\n Object.keys(filters).forEach((key: keyof FilterQueryParams) => {\n const val = filters[key];\n\n if (!val)\n return;\n\n keys.push(`${key}:${Array.isArray(val) ? val.join(',') : val}`);\n });\n\n return keys.join(':');\n}","import videojs, { VideoJsPlayer } from 'video.js';\n\nconst Plugin = videojs.getPlugin('plugin');\n\n/**\n * TODO:\n * The value below is set quite high to compensate for the ridiculous amount of drift that can occur\n * when casting to a Vivi device. This is a temporary fix until we can get Vivi to fix the issue on their end.\n */\nconst CLIP_SEEK_DRIFT_IN_SECONDS = 10;\n\nexport interface ClipPluginOptions {\n startTime: number;\n endTime: number;\n}\n\nexport class ClipPlugin extends Plugin {\n private _clipStart: number;\n private _clipEnd: number;\n private _isEnded: boolean;\n\n private playerEndedFn: () => boolean;\n private playerDurationFn: (seconds?: number) => number;\n private playerCurrentTimeFn: (seconds?: number, ...args: any[]) => number;\n private playerbufferedFn: () => TimeRanges;\n\n constructor(player: VideoJsPlayer, options: ClipPluginOptions) {\n super(player);\n\n // validate clip start/end\n if (options.startTime === undefined) {\n throw Error('Invalid clip start');\n }\n\n if (options.endTime === undefined) {\n throw Error('Invalid clip end');\n }\n\n if (options.startTime > options.endTime) {\n throw Error('Clip start cannot be greater than clip end');\n }\n\n this._clipStart = parseFloat(options.startTime.toPrecision(4));\n this._clipEnd = parseFloat(options.endTime.toPrecision(4));\n\n // save old player functions\n this.playerEndedFn = this.player.ended.bind(player);\n this.playerDurationFn = this.player.duration.bind(player);\n this.playerCurrentTimeFn = this.player.currentTime.bind(player);\n this.playerbufferedFn = this.player.buffered.bind(player);\n\n // overwrite the base player function with our new fancy ones\n this.player.ended = this.ended.bind(this);\n this.player.duration = this.duration.bind(this);\n this.player.currentTime = this.currentTime.bind(this);\n this.player.buffered = this.buffered.bind(this);\n\n this.initialize();\n\n this.player.ready(() => {\n // manually trigger a duation change since we have a new duration from the clip\n this.player.trigger('durationchange');\n });\n }\n\n /**\n * Ensure that the clip start is not greater than the total video duration\n */\n public get clipStart(): number {\n const videoDuration = this.playerDurationFn();\n\n if (this._clipStart > videoDuration)\n return videoDuration;\n\n return this._clipStart;\n }\n\n /**\n * Ensure that the clip end is not greater than the total video duration\n */\n public get clipEnd(): number {\n const videoDuration = this.playerDurationFn();\n\n // The video duration may not have been determined yet, so we can't do\n // any clamping right now..\n if (videoDuration <= 0)\n return this._clipEnd;\n\n // Clamp the clip end to the video duration\n if (this._clipEnd > videoDuration)\n return videoDuration;\n\n return this._clipEnd;\n }\n\n public dispose(): void {\n this.player.off('timeupdate', this.onTimeUpdate);\n this.player.off('play', this.onPlay);\n\n // put the original functions back\n this.player.ended = this.playerEndedFn;\n this.player.duration = this.playerDurationFn;\n this.player.currentTime = this.playerCurrentTimeFn;\n this.player.buffered = this.playerbufferedFn;\n\n // trigger another durationchange since the duration will now go back to the original\n this.player.trigger('durationchange');\n\n super.dispose();\n }\n\n private initialize(): void {\n this.onTimeUpdate = this.onTimeUpdate.bind(this);\n this.onPlay = this.onPlay.bind(this);\n\n this.player.on('timeupdate', this.onTimeUpdate);\n this.player.on('play', this.onPlay);\n }\n\n private onPlay(): void {\n // if we try to play but the clip has ended, go back to the start\n if (this._isEnded) {\n this.player.currentTime(0);\n }\n }\n\n private onTimeUpdate(): void {\n const currentTime = this.getCurrentTime(false);\n\n // check ended\n if (currentTime > this.clipEnd) {\n if (!this._isEnded) {\n this.player.pause();\n this.player.trigger('ended');\n \n this._isEnded = true;\n }\n\n return;\n }\n\n this._isEnded = false;\n\n // ensure video is playing from the correct clip start (taking into account some seek drift)\n if (currentTime < (this.clipStart - CLIP_SEEK_DRIFT_IN_SECONDS)) {\n this.playerCurrentTimeFn(this.clipStart, true);\n }\n }\n\n private ended(): boolean {\n return this.getCurrentTime(false) > this.clipEnd;\n }\n\n private duration(seconds?: number): number {\n // set the underlying player duration (and cache) if it hasn't been set already\n if (seconds && seconds > 0) {\n const existingDuration = this.playerDurationFn();\n\n if (existingDuration)\n console.info('The duration of the player has already been set. This is a no-op.');\n else\n this.playerDurationFn(seconds);\n }\n \n return this.clipEnd - this.clipStart;\n }\n\n private currentTime(seconds?: number, ...args: any[]): number {\n if (typeof seconds !== 'number') {\n return this.getCurrentTime(true);\n }\n\n const correctedSeconds = seconds + this.clipStart;\n\n this.playerCurrentTimeFn(correctedSeconds, args);\n\n return;\n }\n\n /**\n * Gets the current time of the video and updates the videojs currentTime cache\n * @param clipTime Set to true to return the current time in the context of a clip\n */\n private getCurrentTime(clipTime: boolean): number {\n const playerCurrentTime = this.playerCurrentTimeFn();\n let time = 0;\n\n if (playerCurrentTime >= this.clipStart) {\n time = playerCurrentTime - this.clipStart;\n }\n\n // ensure that the videojs currentTime cache reflects our fake time\n this.player.getCache().currentTime = time;\n\n if (clipTime)\n return time;\n\n return playerCurrentTime;\n }\n\n private buffered(): TimeRanges {\n const buff = this.playerbufferedFn();\n const ranges = [];\n\n for (let i = 0; i < buff.length; i++) {\n ranges[i] = [\n Math.max(0, buff.start(i) - this.clipStart),\n Math.min(Math.max(0, buff.end(i) - this.clipStart), this.player.duration())\n ];\n }\n\n return videojs.createTimeRanges(ranges as any);\n }\n}\n\nvideojs.registerPlugin('clipPlugin', ClipPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n clipPlugin(options: ClipPluginOptions): void;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Timepoint } from 'libs/shared/interfaces';\nimport { InteractionTypeHelper } from 'libs/shared/utils/interaction-type-helper/InteractionTypeHelper';\n\nimport './interactive-bar-item.scss';\n\nconst Component = videojs.getComponent('Button');\n\ninterface InteractiveBarItemOptions extends videojs.ComponentOptions {\n timepoint: Timepoint;\n}\n\nexport class InteractiveBarItem extends Component {\n private timepoint_: Timepoint;\n private time_: number;\n\n constructor(player: VideoJsPlayer, options: InteractiveBarItemOptions) {\n super(player, options);\n\n this.timepoint_ = options.timepoint;\n this.time_ = options.timepoint.visibleAt / 1000;\n\n const firstInteraction = options.timepoint.interactions[0];\n\n // if we have no interaction, hide this timepoint\n if (!firstInteraction)\n this.hide();\n\n const { bgClassName } = InteractionTypeHelper.getTypeInfo(firstInteraction.typeId);\n this.$('.vjs-icon-placeholder').classList.add(bgClassName);\n\n // set the control text to the interaction name for screen readers\n this.controlText(firstInteraction.name);\n\n this.update();\n }\n\n public buildCSSClass(): string {\n return `cv-interactive-bar-item ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): HTMLButtonElement {\n const el = super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, {\n ...attributes,\n tabIndex: 0\n });\n\n return el;\n }\n\n public update(): void {\n const duration = this.player_.duration();\n const width = this.time_ / duration;\n\n (this.el() as HTMLElement).style.left = (width * 100) + '%';\n\n // hide items outside of bounds\n if (width > 100 || width < 0)\n this.hide();\n else\n this.show();\n }\n\n public handleClick(e: Event): void {\n e.stopPropagation();\n this.player_.currentTime(this.time_);\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Interactive, Timepoint } from 'libs/shared/interfaces';\n\nimport { InteractiveBarItem } from './interactive-bar-item';\n\nimport './interactive-bar-items.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface InteractiveBarItemsOptions extends videojs.SliderOptions {\n track: TextTrack;\n interactive: Interactive;\n}\n\nexport class InteractiveBarItems extends Component {\n private track_: TextTrack;\n private interactive_: Interactive;\n\n constructor(player: VideoJsPlayer, options: InteractiveBarItemsOptions) {\n super(player, options);\n\n this.track_ = options.track;\n this.interactive_ = options.interactive;\n\n this.onDurationChange = this.onDurationChange.bind(this);\n this.createInteractionItems = this.createInteractionItems.bind(this);\n\n this.createInteractionItems();\n\n (this.track_ as any).on('cv:cuechange', this.createInteractionItems);\n\n this.player_.on('durationchange', this.onDurationChange);\n this.player_.on('dispose', () => {\n (this.track_ as any).off('cv:cuechange');\n\n this.player_.off('durationchange', this.onDurationChange);\n });\n }\n\n public buildCSSClass(): string {\n return `cv-interactive-bar-items ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n }\n\n public update(): void {\n this.children_.forEach((child: InteractiveBarItem) => {\n child.update();\n });\n }\n\n private createInteractionItems(): void {\n if (!this.track_)\n return;\n\n /**\n * Removing existing children\n *\n * We have to clone the array here otherwise\n * the forEach only removes every 2nd item\n */\n [...this.children_].forEach(child => {\n this.removeChild(child);\n });\n\n for (let i = 0; i < this.track_.cues.length; i++) {\n const cue = this.track_.cues[i] as any;\n const timepoint = this.getTimepointById(cue.text);\n\n if (!timepoint || !timepoint.interactions?.length)\n continue;\n\n this.addChild(new InteractiveBarItem(this.player_, {\n timepoint: timepoint\n }));\n }\n }\n\n private onDurationChange(): void {\n this.update();\n }\n\n private getTimepointById(id: string): Timepoint | null {\n return this.interactive_.timepoints?.find(t => t.id.toString() === id.toString());\n }\n}\n","import { VideoJsPlayer } from 'video.js';\n\nimport { Interactive } from 'libs/shared/interfaces';\n\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\n\nexport const InteractiveTrackHelper = {\n getInteractiveTrack(player: VideoJsPlayer, playbackObject: PlaybackObject): TextTrack {\n const track = player.addTextTrack('metadata', 'interactive') as unknown as TextTrack;\n\n const interactive = playbackObject.additionalData.interactive as Interactive;\n const clipOffset = playbackObject.additionalData.clipData?.startTime;\n\n interactive.timepoints.forEach(t => {\n let startTime = t.visibleAt / 1000;\n let endTime = t.visibleFor ? startTime + (t.visibleFor / 1000) : startTime + 1;\n\n if (clipOffset) {\n startTime += clipOffset;\n endTime += clipOffset;\n }\n\n if (!t.interactions?.length)\n return;\n\n track.addCue({\n // Handles calling currentTime() with the exact time of the timepoint\n startTime: Math.max(0.001, startTime - 0.001),\n endTime,\n text: t.id\n } as any);\n });\n\n return track;\n }\n};"],"names":["namespace","ZERO_COLOUR","COLOUR_SCALE","LEGEND_VALUES","getBackgroundColor","value","max","hex","getGradient","data","gradient","i","length","previousValue","currentValue","nextValue","push","join","EngagementHeatMapLegend","Math","legendSquareWidthPercentage","className","Text","phrase","map","val","idx","key","style","width","backgroundColor","EngagementHeatMap","props","heatMap","engagement","background","InsightCard","subtitle","svgClassName","SvgContainer","svgName","size","S","title","count","children","CHART_FONT_STYLES","fontSize","fontFamily","fontWeight","color","getInteractiveResultFilters","currentUser","filter","currentUserId","id","currentCustomerId","customerId","dateRange","start","end","userIds","userId","classroomsAndGroups","groupId","InteractiveResultsRequests","interactiveResultSet","interactiveId","interactiveMetadataId","includePublicResults","success","error","always","url","type","normalize","formatData","students","student","name","profileId","publicUser","mark","answerId","resultId","invalidationKeys","pendingReviews","interactiveResultsReport","useFetchInteractiveResults","requestFilter","interactiveMetadata","interactive","shouldFetchResults","I","getFullHeatMap","Array","ceil","videoDuration","fill","t","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","isArray","useEffect","forEach","useLockContentWidth","getPhrase","LanguageService","CellWrapper","HeaderCell","column","isSorted","phraseKey","useGetColumns","maxHeatMapValue","e","localMax","Header","accessor","sortType","rowA","rowB","values","user","anonymiseUsers","Cell","nameParts","split","n","surname","slice","Avatar","imageCdnUrl","initials","UserHelper","imageUrl","avatar","showAnonymousUser","sortDescFirst","PercentageIndicator","percentage","layout","disableSortBy","original","row","theme","table","header","headerCell","cell","EngagementTable","users","interactiveResults","columns","find","u","r","Table","enableSort","PartialPercentageIndicator","customLabel","InsightAmountWatched","engagementRate","round","everyoneSelected","params","classrooms","classroomGroups","options","CHART_COLOURS","STATIC_CHART_OPTIONS","text","credits","enabled","chart","spacing","legend","itemStyle","itemDistance","plotOptions","pie","allowPointSelect","cursor","dataLabels","showInLegend","borderWidth","InsightTotalViews","events","groupsToOmit","getSeriesName","groups","eventCounts","chartData","staffIndex","findIndex","group","staffObject","splice","unshift","sort","a","b","parseInt","match","sortByYearGroup","ev","includes","toLowerCase","ArrayHelper","Object","keys","y","d","totalViews","reduce","highcharts","series","getChartOptions","containerProps","EmptyState","src","emptyStateImage","EngagementOverlayMenuItem","player","overlayVisible","toggle","this","state","toggleOn","toggleOff","toggleEl","engagementOverlayPlugin","toggleOverlay","addClass","removeClass","event","stopImmediatePropagation","tagName","properties","attributes","handlerBound","handleToggle","bind","removeEventListener","innerHTML","addEventListener","el","appendChild","TimepointInteractions","timepoint","timepoints","timepointTime","visibleAt","floor","time","interactions","MAX_INTERACTIONS_TO_SHOW","hiddenInteractions","InteractionLabel","interaction","showQuestion","iconClassName","xAxis","visible","minPadding","maxPadding","defs","x1","y1","x2","y2","offset","height","styledMode","Component","EngagementOverlay","initialize","bindListeners","ready","buildChart","buildCSSClass","show","destroyChart","handleClick","resizeChart","on","off","paused","play","pause","chartDimensions","getChartDimensions","container","querySelector","getHighchartOptions","one","setSize","destroy","collapserator","getChild","collapseratorHeight","currentHeight","clientWidth","currentDimensions","moveTimepointIndicator","yAxis","options_","min","allowDecimals","startOnTick","endOnTick","tooltip","formatter","timepointInteractionsHtml","renderToStaticMarkup","getTimepointInteractionsHtml","x","formatTime","positioner","labelWidth","labelHeight","point","maxX","plotWidth","plotX","plotTop","useHTML","padding","area","mouseOver","mouseOut","marker","onTimepointHover","indicator","left","EngagementOverlayPlugin","hasHeatMapData","addChild","addItem","index","ctor","engagementOverlay","toggleChart","acc","InteractiveSeekBarPlugin","onTrackLoaded","track","addChildren","controlBar","ReportsPlayer","playbackObject","additionalSetup","setupEngagementOverlayPlugin","setupUpClipPlugin","setupInteractiveSeekBarPlugin","additionalData","clipData","isClip","mediaType","isInteractive","Error","clipPlugin","startTime","endTime","interactiveSeekBarPlugin","ignoreChapters","ClickViewReportsPlayer","ref","playerRef","current","VideoEngagementOverlay","timepointIndicatorRef","viewKey","playerApi","URL","playerApiUrl","hotkeyElQuerySelector","classList","add","remove","aspectRatio","PartialInsightsHeatmap","InsightsHeatmapView","UserRequests","videoRequest","VideoHelper","videoId","typeId","video","config","ConfigRequests","audienceAppLinkParams","dateRangeAppLinkParams","results","MasterType","hasPublicResult","s","readyToFetch","aggregateEngagement","VideoViewRequests","individualEngagement","Boolean","isLoading","videoViews","PlayerRequests","MediaIdType","useSetPageMetadata","filters","hasDataLoaded","tableDataLoaded","InsightsHeaderView","tabs","ImageUrls","ClipPlugin","undefined","_clipStart","parseFloat","toPrecision","_clipEnd","playerEndedFn","ended","playerDurationFn","duration","playerCurrentTimeFn","currentTime","playerbufferedFn","buffered","trigger","onTimeUpdate","onPlay","_isEnded","getCurrentTime","clipEnd","clipStart","seconds","console","correctedSeconds","args","clipTime","playerCurrentTime","getCache","buff","ranges","InteractiveBarItem","timepoint_","time_","firstInteraction","hide","bgClassName","InteractionTypeHelper","$","controlText","update","tabIndex","player_","stopPropagation","InteractiveBarItems","track_","interactive_","onDurationChange","createInteractionItems","children_","child","removeChild","cues","cue","getTimepointById","toString","InteractiveTrackHelper","getInteractiveTrack","addTextTrack","clipOffset","visibleFor","addCue"],"sourceRoot":""}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[229],{50690:(e,t,n)=>{n.d(t,{b:()=>a});var r=n(12788),a={renderInPortalIfExists:function(e,t){return t?(0,r.createPortal)(e,t):e}}},84963:(e,t,n)=>{n.d(t,{r:()=>u});var r=n(32735),a=n(23481),o=n(83914),i=n(36532),l=n(35223);const c={tag:"XRj8d",tooltip:"X6mLk"};var s="specialEventCalendar.comingSoonTag";function u(e){return r.createElement(i.u,{title:a.T.getPhrase(s,"tooltip"),spanHackClassName:"d-block ".concat(c.tooltip),spanHack:!0},r.createElement("div",{className:"d-flex text-dark align-items-center ".concat(c.tag," ").concat(e.className)},r.createElement(o.x,{svgName:l.vn.Timer}),!e.onlyIcon&&a.T.getPhrase(s,"comingSoon")))}},73679:(e,t,n)=>{n.d(t,{s:()=>i});var r=n(32735),a=n(36848);const o={dateItem:"I3SBm",label:"PRORs",body:"RfiM_",bodyDay:"ZOVny",bodyRange:"vYhXN",bodyMonth:"mYslO",month:"EPkkQ"};function i(e){var t,n,i;return r.createElement(a.F,{appLink:null===(t=e.getAppLink)||void 0===t?void 0:t.call(e),className:"text-decoration-none text-center bg-white text-dark border border-3 ".concat(null===(n=e.theme)||void 0===n?void 0:n.border," rounded-3 d-block fw-semibold ").concat(e.className),analyticsData:e.analyticsData,analyticsOptions:e.analyticsOptions},r.createElement("div",{className:"position-relative ".concat(o.dateItem)},r.createElement("div",{className:"".concat(null===(i=e.theme)||void 0===i?void 0:i.background," py-1 ").concat(o.label," d-flex align-items-center justify-content-center")},e.label?e.label:r.createElement(r.Fragment,null," ")),r.createElement("div",{className:"".concat(function(){switch(e.body.type){case"range":return o.bodyRange;case"day":return o.bodyDay;case"month":return o.bodyMonth}}()," ").concat(o.body," my-2")},e.body.text),r.createElement("div",{className:"mb-0 ".concat(o.month)},e.month)))}},44522:(e,t,n)=>{n.d(t,{p:()=>k,v:()=>N});var r=n(32735),a=n(110),o=n(50690),i=n(84963),l=n(73679),c=n(83657),s=n(23481),u=n(36848),d=n(83914),m=n(35223),f="shared.backButton";function v(e){var t=Object.assign({textShadow:!0},e),n=t.backToName,a=t.appLink,o=t.color,i=t.extraClasses,l=t.textShadow,c=n?s.T.getPhrase(f,"backTo",{backToName:n}):s.T.getPhrase(f,"back"),v="black"===o?"":"text-white",h=l?"text-shadow":"";return r.createElement(u.F,{appLink:a,className:"d-inline-flex align-items-center h5 mb-0 ".concat(i," ").concat(v," ").concat(h)},r.createElement(d.x,{svgName:m.vn.ChevronLeft,size:d.S.Medium}),r.createElement("span",{className:"ms-1"},c))}v.defaultProps={color:"black",extraClasses:""};var h=n(36518),b=n(83345),p=n(10587),g=n(94232),y=n(54610),E=n(79967),C=n(67453);const S={bannerContent:"sSCTB",actionsContainer:"Z5WI2",bannerContentWithLogo:"rgs7Q",container:"M51HJ",logoContainer:"vkeJk",logoContainerLeft:"M3U9B",logoHeading:"EtRwC",specialEventContainer:"rOxDc",headingLarge:"_8pnV",heading:"JXVBH"};var w="".concat(p.y[y.__.Banners].width,":").concat(p.y[y.__.Banners].height);function A(e){return e.length<160?"h1":S.headingLarge}var k=r.memo((function(e){var t,n,s,u,d=e.heading,m=e.banner,f=e.imageCdnUrl,p=e.actions,k=e.sortComponent,N=e.blockColourClass,x=e.specialEvent,I=r.useContext(g.n),L=(0,E.k)().xxl?1920:1200,F=r.useMemo((function(){if(!x||e.showComingSoon)return!1;var t=a.O.format(new Date,"YYYY-MM-DD");return x.endDate?x.startDate<=t&&x.endDate>=t:x.startDate===t}),[x]),O=e.imageOptions||{width:L,ratio:w,resizeType:y.Nq.Cover},M=!!m&&!!f&&C.j.createBannerUrl(m,{fallbackBaseUrl:f,fallbackCategoryName:d,type:y.__.Banners},O),P={className:"banner banner-header ".concat(e.bannerClassName),style:M?{backgroundImage:"url('".concat(M,"')")}:{}};!m&&N&&(delete P.style,P.className+=" ".concat(N));var T=e.detailsComponent;return o.b.renderInPortalIfExists(r.createElement("header",Object.assign({},P),r.createElement("div",{className:"container ".concat(S.container," position-relative inner-banner")},e.backButtonAppLink&&r.createElement("div",{className:"pt-3"},r.createElement(v,{appLink:e.backButtonAppLink,backToName:e.backButtonText,extraClasses:e.backButtonClasses,color:"white"})),r.createElement("div",{className:"".concat(e.alignLogoLeft?"position-absolute top-50 start-0 translate-middle-y w-100 ps-4":"".concat(S.bannerContent," px-2 ").concat((null===(t=e.logo)||void 0===t?void 0:t.url)?S.bannerContentWithLogo:""))},!!x&&r.createElement("div",{className:"position-relative ".concat(S.specialEventContainer)},r.createElement(l.s,{body:{type:x.endDate?"range":"day",text:x.endDate?"".concat(a.O.format(x.startDate,"DD"),"-").concat(a.O.format(x.endDate,"DD")):a.O.format(x.startDate,"DD")},month:function(e){return e.endDate?a.O.isSame(e.startDate,e.endDate,"month")?a.O.format(e.startDate,"MMMM"):"".concat(a.O.format(e.startDate,"MMM")," - ").concat(a.O.format(e.endDate,"MMM")):a.O.format(e.startDate,"MMMM")}(x),theme:e.calendarTheme})),r.createElement("div",null,F&&r.createElement("div",{className:"rounded-pill py-1 px-2 my-1 me-1 fw-semibold bg-light-blue lh-1 d-inline-block"},r.createElement(b.x,{namespace:"shared.bannerHeader",phrase:"onToday"})),e.showComingSoon&&r.createElement(i.r,{className:"pe-2 fw-semibold mb-1 rounded-pill justify-content-start text-nowrap"}),r.createElement("div",{className:"d-flex align-items-center"},e.alignLogoLeft&&r.createElement("div",{className:"".concat(S.logoContainerLeft," d-none d-md-block partial-loading-background rounded-circle overflow-hidden me-3")},(null===(n=e.logo)||void 0===n?void 0:n.url)&&r.createElement(h.w,{src:C.j.createUrl(null===(s=e.logo)||void 0===s?void 0:s.url,{size:y.h2.Medium})})),r.createElement("h1",{className:"text-white text-shadow pe-3 position-static ".concat(S.heading," ").concat(A(d)," ").concat(e.alignLogoLeft?"w-50":"")},d,T&&r.createElement(T,null)))),!!p&&r.createElement("div",{className:S.actionsContainer},r.createElement(c.e,{actions:p,sortComponent:k,actionsDropdownClassName:e.actionsDropdownClassName}))),!e.alignLogoLeft&&!!(null===(u=e.logo)||void 0===u?void 0:u.url)&&r.createElement("div",{className:S.logoContainer},r.createElement("img",{src:C.j.createUrl(e.logo.url,{size:y.h2.Small}),className:"rounded-circle"})))),null==I?void 0:I.container)}),(function(e,t){var n,r;return e.actions===t.actions&&e.heading===t.heading&&(null===(n=e.logo)||void 0===n?void 0:n.url)===(null===(r=t.logo)||void 0===r?void 0:r.url)}));function N(){var e=r.useContext(g.n);return o.b.renderInPortalIfExists(r.createElement("div",{className:"partial-banner partial-loading-background ".concat(S.banner)}),null==e?void 0:e.container)}},49935:(e,t,n)=>{n.d(t,{Oo:()=>h,b2:()=>b});var r=n(32735),a=n(23481),o=n(36848),i=n(86764),l=n(3747),c=n(5859),s=n(35223),u=n(83914);function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o,i,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=o.call(n)).done)&&(l.push(r.value),l.length!==t);c=!0);}catch(e){s=!0,a=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(s)throw a}}return l}}(e,t)||function(e,t){if(e){if("string"==typeof e)return m(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?m(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function m(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var f=a.T.encloseNamespace("shared.breadcrumbComponent"),v=r.forwardRef((function(e,t){var n=e.breadcrumb,a=n.name,i=n.appLink,l=n.active,c=e.withBackIcon,d=a,m=null;return d.length>48&&(d=a.slice(0,48)+"...",m=a),r.createElement("li",{className:"breadcrumb-item".concat(l?" active":""),title:m},l?r.createElement("strong",null,d):r.createElement(o.F,{appLink:i,ref:t},c&&r.createElement(u.x,{svgName:s.vn.ChevronLeft,size:u.S.Small}),r.createElement("span",{className:c?"ms-2":""},d)))})),h=function(e){var t=e.breadcrumbs,n=(0,l.a)(i.r.XS),a=(null==t?void 0:t.length)||0,o=d(r.useState(!1),2),c=o[0],s=o[1],u=d(r.useState(!1),2),m=u[0],h=u[1],b=r.useRef();if(r.useEffect((function(){var e,n=null!==(e=null==t?void 0:t.reduce((function(e,t){return e+t.name.length}),0))&&void 0!==e?e:0;a>4&&n>64&&s(!0)}),[null==t?void 0:t.length]),r.useLayoutEffect((function(){var e;m&&(null===(e=b.current)||void 0===e||e.focus())}),[b.current,m]),!a||n&&a<2)return r.createElement(r.Fragment,null);if(n)return r.createElement("nav",{"aria-label":"breadcrumb"},r.createElement("ol",{className:"breadcrumb m-0 p-0"},r.createElement(v,{breadcrumb:t[a-2],withBackIcon:!0})));var p=r.createElement(v,{breadcrumb:t[0]}),g=a>2?r.createElement(v,{breadcrumb:t[1]}):r.createElement(r.Fragment,null),y=a>3?r.createElement(v,{breadcrumb:t[a-2]}):r.createElement(r.Fragment,null),E=a>1?r.createElement(v,{breadcrumb:t[a-1]}):r.createElement(r.Fragment,null),C=t.slice(2,a-2);return r.createElement("nav",{"aria-label":"breadcrumb"},r.createElement("ol",{className:"breadcrumb m-0 p-0"},p,g,c?r.createElement("li",{className:"breadcrumb-item"},r.createElement("button",{className:"btn-link",onClick:function(){s(!1),h(!0)},"aria-label":f("expand")},"...")):C.map((function(e,t){return r.createElement(v,{key:t,breadcrumb:e,ref:0===t?b:null})})),y,E))},b=r.memo((function(e){var t=e.numItems,n=void 0===t?3:t;return(0,l.a)(i.r.XS)?r.createElement("div",{className:"partial-loading-background",style:{height:"1.3125rem",width:"6rem"}}):r.createElement("nav",{"aria-label":"breadcrumb"},r.createElement("ol",{className:"breadcrumb m-0 p-0"},c.u.getPartialLoadingItems({numItems:n}).map((function(e,t){var n=e.width;return r.createElement("li",{key:t,className:"breadcrumb-item"},r.createElement("span",{className:"d-inline-block partial-loading-background",style:{width:n},dangerouslySetInnerHTML:{__html:" "}}))}))))}))},71020:(e,t,n)=>{n.d(t,{_:()=>u});var r=n(32735),a=n(80247),o=n(34152),i=n(83914),l=n(35223);const c={container:"VwD1b",spinner:"eJ85e"};function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function u(e){var t,n,u=(t=(0,o.YD)(),n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o,i,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=o.call(n)).done)&&(l.push(r.value),l.length!==t);c=!0);}catch(e){s=!0,a=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(s)throw a}}return l}}(t,n)||function(e,t){if(e){if("string"==typeof e)return s(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),d=u[0],m=u[1];return r.useEffect((function(){var t;e.fetchOnScroll&&m&&!e.isFetching&&(null===(t=e.fetchNext)||void 0===t||t.call(e,e.nextCursor))}),[m,e.isFetching]),r.createElement("div",{className:"p-3 text-center ".concat(c.container),ref:d},e.isFetching?r.createElement(a.Z,{as:"span",animation:"border",role:"status",className:c.spinner}):r.createElement(i.x,{svgName:l.vn.ChevronDown,className:"svg-container cursor-pointer",size:i.S.Large,onClick:function(){var t;return null===(t=e.fetchNext)||void 0===t?void 0:t.call(e,e.nextCursor)}}))}u.defaultProps={fetchOnScroll:!1}},94644:(e,t,n)=>{n.d(t,{r:()=>u});var r=n(50242),a=n(81886),o=n(67058),i=n(14553),l=n(49267),c=n(49075),s={notFound:o.d,forbidden:{rating:i.q,yearLevel:i.q,region:l.a,privacy:i.q},badRequest:c._,internalServerError:c._};function u(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(e){var o;o="number"==typeof e?e:e.status;var i=Object.assign(Object.assign({},s),t);o&&a.Q.Ry.isStatusCodeError(o)&&(o!==r.o.InternalServer?o!==r.o.NotFound?o!==r.o.Forbidden?n.badRequest||a.Q.Ry.throw(new i.badRequest):n.forbidden||a.Q.Ry.throw(new i.forbidden.privacy):n.notFound||a.Q.Ry.throw(new i.notFound):n.internalServerError||a.Q.Ry.throw(new c._))}}},60115:(e,t,n)=>{n.d(t,{K:()=>s});var r=n(32735),a=n(50242),o=n(91967),i=400,l=n(45719);function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function s(e,t,n,s,u,d){var m,f,v,h,b=(m=(0,r.useState)(0),f=2,function(e){if(Array.isArray(e))return e}(m)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o,i,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=o.call(n)).done)&&(l.push(r.value),l.length!==t);c=!0);}catch(e){s=!0,a=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(s)throw a}}return l}}(m,f)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?c(e,t):void 0}}(m,f)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),p=b[0],g=b[1],y=t,E=(0,l.P)((function(t){if(!e)return null;var n=e(t);return n?n.key:null}),s,u);return v={fetchNextPage:function(){if(t&&e&&E)return g((function(e){return e+1})),y(E.nextCursor)},hasMore:!!(null==E?void 0:E.nextCursor),isFetching:null==E?void 0:E.isFetching,scrollContainer:d},h=function(){if(!v.isFetching){if(v.scrollContainer){var e=v.scrollContainer;if(e.getBoundingClientRect().height+e.scrollTop<e.scrollHeight-i)return}else if(window.innerHeight+document.documentElement.scrollTop<document.documentElement.scrollHeight-i)return;v.fetchNextPage()}},(0,r.useEffect)((function(){var e=o.q.throttle(h,200),t=v.scrollContainer||window;return v.hasMore&&t.addEventListener("scroll",e),function(){return t.removeEventListener("scroll",e)}}),[v.hasMore,v.fetchNextPage,v.scrollContainer]),(0,r.useEffect)((function(){E&&E.shouldInitialFetch&&t&&(y(),g((function(e){return e+1})))}),[null==E?void 0:E.shouldInitialFetch,t]),(0,r.useEffect)((function(){var e,t;if((null==E?void 0:E.statusCode)&&o.q.isFunction(n)){var r=+(null===(t=null===(e=E.statusCode)||void 0===e?void 0:e.toString())||void 0===t?void 0:t.substr(0,1));r!==a.k.ClientError&&r!==a.k.ServerError||n(p,E.statusCode)}}),[null==E?void 0:E.statusCode]),{items:null==E?void 0:E.items,hasMore:!!(null==E?void 0:E.nextCursor),nextCursor:null==E?void 0:E.nextCursor,isFetching:null==E?void 0:E.isFetching,totalItems:null==E?void 0:E.totalItems,hasFirstPageCompleted:null==E?void 0:E.hasFirstPageCompleted}}},63719:(e,t,n)=>{n.d(t,{h:()=>l});var r=n(32735),a=n(77316);function o(e,t){if(e){if("string"==typeof e)return i(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function l(e){var t,n,l=(t=r.useMemo((function(){return a.p.getBuilder()}),[]),n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o,i,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=o.call(n)).done)&&(l.push(r.value),l.length!==t);c=!0);}catch(e){s=!0,a=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(s)throw a}}return l}}(t,n)||o(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),c=l[0],s=(0,l[1])(c);return s&&e?[].concat(function(e){return function(e){if(Array.isArray(e))return i(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||o(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(s),[Object.assign(Object.assign({},e),{active:!0})]):s}},5859:(e,t,n)=>{function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}n.d(t,{u:()=>o});var a={numItems:5,minWidth:50,maxWidth:100},o={getPartialLoadingItems:function(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=Object.assign(Object.assign({},a),t);return(e=Array(n.numItems),function(e){if(Array.isArray(e))return r(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return r(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()).map((function(){return{width:"".concat(Math.max(Math.floor(Math.random()*n.maxWidth),n.minWidth),"px")}}))}}},44110:(e,t,n)=>{n.d(t,{i:()=>i});var r=n(20354),a=n(89454),o=n(86698),i=function(){var e=(0,o.y)({redirectOnError:!0}),t=e.activePresentation,n=e.getFallbackPresentation,i=t||n();return r.a.useBasicFetch(!!i&&a.O.presentationAudiences(i.id))}},97816:(e,t,n)=>{n.d(t,{V:()=>f});var r=n(32735),a=n(20354),o=n(75896),i=n(21750),l=n(31949),c=n(1575),s=n(31908);function u(e,t){if(e){if("string"==typeof e)return d(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?d(e,t):void 0}}function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var m=50;function f(e){var t,n,f=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},v=a.a.useBasicFetch(l.N.currentUser()),h=r.useRef(new Set),b=function(e){return e?Array.isArray(e)?e.filter((function(e){return!!e&&(s.M.isVideo(e)||s.M.isClip(e))})):"data"in e?e.data.filter((function(e){return!!e&&(s.M.isVideo(e)||s.M.isClip(e))})):[]:[]}(e),p=b.map((function(e){return e.id})),g=(t=r.useState([]),n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o,i,l=[],c=!0,s=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=o.call(n)).done)&&(l.push(r.value),l.length!==t);c=!0);}catch(e){s=!0,a=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(s)throw a}}return l}}(t,n)||u(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),y=g[0],E=g[1];r.useEffect((function(){if((null==p?void 0:p.length)&&v.hasCompleted){var e=[];p.forEach((function(t){h.current.has(t)||(e.push(t),h.current.add(t))})),e.length&&E((function(t){var n=function(e){return function(e){if(Array.isArray(e))return d(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||u(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(t);return o.m.chunk(e,m).forEach((function(e){var t;n.push(c.R.videoMixinAssocs(e,f.flightNamespace)),(null===(t=v.data)||void 0===t?void 0:t.isAuthenticated)&&n.push(i.x.hasCurriculumLinks(e,null,f.flightNamespace))})),n}))}}),[null==p?void 0:p.length,v.hasCompleted]),a.a.useBasicFetchAll(y)}},16641:(e,t,n)=>{n.r(t),n.d(t,{FavouritesView:()=>Z});var r=n(32735),a=n(70680),o=n(23481),i=n(20354),l=n(65858),c=n(44522),s=n(49935),u=n(71020),d=n(83345),m=n(74696),f=n(13231),v=n(51365),h=n(16714),b=n(94644),p=n(39151),g=n(1666),y=n(63419),E=n(31949),C=n(69883),S=n(63719),w=n(60115),A=n(22902),k=n(79612),N=n(99742),x=n(51855),I=n(27638),L=n(44110),F=n(97816),O=n(10741),M=n(22490),P=n(82431),T=n(23232),j=n(14070),D=n(97291);const B={image:"ZfpQv"};var R="shared.favouritesEmptyState",_=o.T.encloseNamespace(R);function U(){return r.createElement(d.D.Provider,{value:R},r.createElement(T.u,null,r.createElement(T.u.Image,{src:N.W.EmptyStates.FAVOURITED_VIDEOS,altText:_("info"),className:B.image}),r.createElement(T.u.Heading,{className:"h3"},r.createElement(d.x,{phrase:"heading"})),r.createElement(T.u.Info,null,r.createElement(d.x,{phrase:"info"})),r.createElement(T.u.Cta,{text:o.T.getPhrase(R,"cta"),appLink:{application:D.O.DASHBOARD,action:j.e.Dashboard.HOME}})))}function V(){return r.createElement(d.D.Provider,{value:R},r.createElement(T.u,null,r.createElement(T.u.Image,{src:N.W.EmptyStates.FAVOURITED_VIDEOS_PUBLIC,altText:_("publicInfo")}),r.createElement(T.u.Heading,null,r.createElement(d.x,{phrase:"publicHeading"})),r.createElement(T.u.Info,null,r.createElement(d.x,{phrase:"publicInfo"})),r.createElement(T.u.Cta,{text:o.T.getPhrase(R,"publicCta"),appLink:{application:D.O.SIGN_UP,action:j.e.SignUp.SIGN_UP},analyticsData:{},analyticsOptions:{actionType:l.Vw.Click,location:l.LZ.MyFavouritesLanding,entity:l.py.AppLink,workflowPhase:l.eu.Start,descriptor:l.Yu.SignUp}})))}var H=n(26323),W=n(35223),G=n(31908),$=n(10671),Q="shared.favourites";const Y={banner:"FEWd3"};var q="shared.favourites";function Z(){var e,t,n,T=(0,a.I0)(),j=(0,C.Z)(),D=(0,I.u)(l.LZ.VideoThumbnail),B=D.setFavourite,R=D.canFavourite,_=(0,x.G)().isPlugin,Z=function(){var e=(0,$._)({location:$.i.VideoItem}),t=(0,I.u)(l.LZ.VideoThumbnail).setFavourite;return Object.assign(Object.assign({},e),{getVideoActions:function(n){return G.M.getCanBeConsumed(n).canConsume?e.getVideoActions(n):[{label:o.T.getPhrase(Q,"removeFromFavourites"),svgName:W.vn.Delete,button:!1,className:"btn btn-link text-danger",onClick:function(){return t(n,!1)}}]}})}();(0,k.M)({title:o.T.getPhrase(q,"pageTitle")});var z=(0,A.T)(),X=z.hasLocalPermissions,J=z.hasPermissions,K=i.a.useBasicFetch(E.N.currentUser()),ee=i.a.useBasicFetch((null===(e=K.data)||void 0===e?void 0:e.isAuthenticated)&&g.h.yearGroups(K.data.customerId)),te=i.a.useBasicFetch(p.L.config()),ne=function(e){return y.P.getFavourites(K.data.id,e)},re=function(e){return i.a.getFetch(T)(ne(e))},ae=!X(h.E.ViewMyFavouritesLanding)&&K.hasCompleted,oe=(0,w.K)(!!ae&&ne,re,(function(e,t){if(1===e)return(0,b.r)(t);j.error(o.T.getPhrase(q,"error"))})),ie=oe.items,le=oe.hasMore,ce=oe.isFetching;(0,F.V)(ie);var se=(0,L.i)(),ue=(0,S.h)({name:o.T.getPhrase(q,"header")}),de=(0,H.B)(null===(t=K.data)||void 0===t?void 0:t.id),me=de.count;return de.isLoading?r.createElement(r.Fragment,null):X(h.E.ViewMyFavouritesLanding)?r.createElement(V,null):r.createElement(v.M.Provider,{value:Z},r.createElement("div",{className:"p-3"},r.createElement(c.p,{heading:o.T.getPhrase(q,"header"),banner:{url:N.W.FAVOURITES_PLAYLIST.FAV_PLAYLIST_BANNER},bannerClassName:"".concat(Y.banner," bg-pink"),imageCdnUrl:null===(n=te.data)||void 0===n?void 0:n.imageCdnUrl,detailsComponent:function(){return r.createElement("div",{className:"mb-n1 font-size-normal fw-normal mt-1"},r.createElement(d.x,{namespace:q,phrase:"videos",options:{smartCount:me}}))}}),(null==ue?void 0:ue.length)&&r.createElement("div",{className:"border-bottom pb-3"},r.createElement(s.Oo,{breadcrumbs:ue})),ie?ie.length?r.createElement("div",{className:"mt-2"},r.createElement(f.E4,{videos:ie,yearGroups:ee.data,getVideoAppLink:M.W.getAppLink,hasPermissions:J,getSubTextAppLink:function(e){return P.j.getSeriesAppLink(e.series)},setFavourite:B,canFavourite:R,presentationAudiences:se.data,getPreviewQuestionsAppLink:function(e){return O.j.getPreviewQuestionsAppLink(e)},isPlugin:_,getClassroomGuideAppLink:M.W.getClassroomGuideAppLink,getInteractiveGuidanceAppLink:M.W.getInteractiveGuidanceAppLink,getResourceGuidanceAppLink:M.W.getResourceGuidanceAppLink}),(le||ce)&&r.createElement(u._,{isFetching:ce,fetchNext:re})):r.createElement(U,null):r.createElement(m.S,null)))}},26323:(e,t,n)=>{n.d(t,{B:()=>l});var r=n(20354),a=n(63419);function o(e){return function(e){if(Array.isArray(e))return i(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function l(e){var t,n,i,l,c,s,u,d,m,f=r.a.useBasicFetch(e&&a.P.getFavouritesVideosCount(e)),v=r.a.useBasicFetch(e&&a.P.getFavouritesClipsCount(e)),h=r.a.useBasicFetch(e&&a.P.getFavouritesInteractivesCount(e));return{count:(null===(t=f.data)||void 0===t?void 0:t.count)+(null===(n=h.data)||void 0===n?void 0:n.count)+(null===(i=v.data)||void 0===i?void 0:i.count),favourites:[].concat(o((null===(l=f.data)||void 0===l?void 0:l.data)||[]),o((null===(c=v.data)||void 0===c?void 0:c.data)||[]),o((null===(s=h.data)||void 0===s?void 0:s.data)||[])),isLoading:!(null===(u=f.data)||void 0===u?void 0:u.data)||!(null===(d=v.data)||void 0===d?void 0:d.data)||!(null===(m=h.data)||void 0===m?void 0:m.data)}}},68050:(e,t,n)=>{n.d(t,{Z:()=>s});var r=n(95685),a=n.n(r),o=n(32735),i=n(46304),l=n(74512);const c=o.forwardRef((({bsPrefix:e,className:t,as:n="div",...r},o)=>{const c=(0,i.vE)(e,"row"),s=(0,i.pi)(),u=(0,i.zG)(),d=`${c}-cols`,m=[];return s.forEach((e=>{const t=r[e];let n;delete r[e],null!=t&&"object"==typeof t?({cols:n}=t):n=t;const a=e!==u?`-${e}`:"";null!=n&&m.push(`${d}${a}-${n}`)})),(0,l.jsx)(n,{ref:o,...r,className:a()(t,c,...m)})}));c.displayName="Row";const s=c}}]);
|
|
2
|
-
//# sourceMappingURL=229-900e650427-lite.chunk.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scripts/229-900e650427-lite.chunk.js","mappings":"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","sources":["file:///app/packages/libs/common/src/react/utils/PortalHelper.ts","file:///app/packages/libs/shared/src/apps/calendar/components/coming-soon-tag/coming-soon-tag.scss","file:///app/packages/libs/shared/src/apps/calendar/components/coming-soon-tag/ComingSoonTag.tsx","file:///app/packages/libs/shared/src/apps/calendar/components/generic-calendar-date/generic-calendar-date.scss","file:///app/packages/libs/shared/src/apps/calendar/components/generic-calendar-date/GenericCalendarDate.tsx","file:///app/packages/libs/shared/src/components/back-button/BackButton.tsx","file:///app/packages/libs/shared/src/components/banner-header/banner-header.scss","file:///app/packages/libs/shared/src/components/banner-header/BannerHeader.tsx","file:///app/packages/libs/shared/src/components/breadcrumbs/Breadcrumbs.tsx","file:///app/packages/libs/shared/src/components/infinite-scroll-footer/infinite-scroll-footer.scss","file:///app/packages/libs/shared/src/components/infinite-scroll-footer/InfiniteScrollFooter.tsx","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseInfiniteScroll.ts","file:///app/packages/libs/shared/src/hooks/UseInfiniteList.ts","file:///app/packages/libs/shared/src/hooks/useBreadcrumbs.ts","file:///app/packages/libs/shared/src/utils/PartialLoadingHelper.ts","file:///app/packages/projects/lite/src/shared/hooks/usePresentationAudiences.ts","file:///app/packages/projects/lite/src/shared/hooks/useVideoMixin.ts","file:///app/packages/projects/lite/src/shared/views/favourites/empty-state/favourites-empty-state.scss","file:///app/packages/projects/lite/src/shared/views/favourites/empty-state/FavouritesEmptyState.tsx","file:///app/packages/projects/lite/src/shared/views/favourites/FavouritesViewUtils.ts","file:///app/packages/projects/lite/src/shared/views/favourites/favourites-view.scss","file:///app/packages/projects/lite/src/shared/views/favourites/FavouritesView.tsx","file:///app/packages/projects/lite/src/shared/views/favourites/hooks/useFavouritesCount.ts","file:///app/node_modules/react-bootstrap/esm/Row.js"],"sourcesContent":["import React from 'react';\nimport { createPortal } from 'react-dom';\n\nexport const PortalHelper = {\n renderInPortalIfExists(component: React.ReactElement, portalContainer: Element | null): React.ReactElement {\n if (portalContainer)\n return createPortal(component, portalContainer);\n\n return component;\n }\n};","// extracted by mini-css-extract-plugin\nexport default {\"tag\":\"XRj8d\",\"tooltip\":\"X6mLk\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { SvgContainer } from 'libs/shared/components/svg-container/SvgContainer';\nimport { Tooltip } from 'libs/shared/components/tooltip/Tooltip';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './coming-soon-tag.scss';\n\nconst namespace = 'specialEventCalendar.comingSoonTag';\n\ninterface ComingSoonProps {\n className?: string;\n onlyIcon?: boolean;\n}\n\nexport function ComingSoonTag(props: ComingSoonProps): JSX.Element {\n return (\n <Tooltip title={LanguageService.getPhrase(namespace, 'tooltip')} spanHackClassName={`d-block ${styles.tooltip}`} spanHack>\n <div className={`d-flex text-dark align-items-center ${styles.tag} ${props.className}`}>\n <SvgContainer svgName={cvSvgLibrary.Timer} />\n {!props.onlyIcon && LanguageService.getPhrase(namespace, 'comingSoon')}\n </div>\n </Tooltip>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"dateItem\":\"I3SBm\",\"label\":\"PRORs\",\"body\":\"RfiM_\",\"bodyDay\":\"ZOVny\",\"bodyRange\":\"vYhXN\",\"bodyMonth\":\"mYslO\",\"month\":\"EPkkQ\"};","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { HashObject } from 'libs/common/react/interfaces';\n\nimport { AnalyticsOptions } from 'libs/analytics/interfaces';\n\nimport { CalendarTheme } from 'libs/shared/apps/calendar/interfaces/CalendarTheme';\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\n\nimport styles from './generic-calendar-date.scss';\n\nexport interface GenericCalendarDateProps {\n label?: string;\n body: {\n type: 'month' | 'range' | 'day';\n text: string;\n };\n month?: string;\n getAppLink?: () => Core.AppLink;\n analyticsData?: HashObject;\n analyticsOptions?: AnalyticsOptions;\n className?: string;\n theme?: CalendarTheme;\n}\n\nexport function GenericCalendarDate(props: GenericCalendarDateProps): JSX.Element {\n function getBodyClass(): string {\n switch (props.body.type) {\n case 'range':\n return styles.bodyRange;\n case 'day':\n return styles.bodyDay;\n case 'month':\n return styles.bodyMonth;\n }\n }\n\n return (\n <AppLink\n appLink={props.getAppLink?.()}\n className={`text-decoration-none text-center bg-white text-dark border border-3 ${props.theme?.border} rounded-3 d-block fw-semibold ${props.className}`}\n analyticsData={props.analyticsData}\n analyticsOptions={props.analyticsOptions}\n >\n <div className={`position-relative ${styles.dateItem}`}>\n <div className={`${props.theme?.background} py-1 ${styles.label} d-flex align-items-center justify-content-center`}>\n {props.label ? props.label : <> </>}\n </div>\n <div className={`${getBodyClass()} ${styles.body} my-2`}>\n {props.body.text}\n </div>\n <div className={`mb-0 ${styles.month}`}>\n {props.month}\n </div>\n </div>\n </AppLink>\n );\n}","import * as React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nconst namespace = 'shared.backButton';\n\ninterface BackButtonProps {\n appLink: Core.AppLink;\n backToName?: string;\n color?: 'black' | 'white';\n extraClasses?: string;\n /**\n * Whether or not the button text has a text shadow. Defaults to true\n */\n textShadow?: boolean;\n}\n\nBackButton.defaultProps = {\n color: 'black',\n extraClasses: ''\n};\n\nexport function BackButton(props: BackButtonProps): React.ReactElement {\n const { backToName, appLink, color, extraClasses, textShadow } = {\n textShadow: true,\n ...props\n };\n\n const backPhrase = backToName\n ? LanguageService.getPhrase(namespace, 'backTo', { backToName })\n : LanguageService.getPhrase(namespace, 'back');\n\n const colorClass = color === 'black' ? '' : 'text-white';\n const textShadowClass = textShadow ? 'text-shadow' : '';\n\n return (\n <AppLink\n appLink={appLink}\n className={`d-inline-flex align-items-center h5 mb-0 ${extraClasses} ${colorClass} ${textShadowClass}`}\n >\n <SvgContainer svgName={cvSvgLibrary.ChevronLeft} size={SvgContainerSize.Medium} />\n <span className='ms-1'>{backPhrase}</span>\n </AppLink>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"bannerContent\":\"sSCTB\",\"actionsContainer\":\"Z5WI2\",\"bannerContentWithLogo\":\"rgs7Q\",\"container\":\"M51HJ\",\"logoContainer\":\"vkeJk\",\"logoContainerLeft\":\"M3U9B\",\"logoHeading\":\"EtRwC\",\"specialEventContainer\":\"rOxDc\",\"headingLarge\":\"_8pnV\",\"heading\":\"JXVBH\"};","import * as React from 'react';\n\nimport { Core } from 'libs/common/core';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\nimport { PortalHelper } from 'libs/common/react/utils/PortalHelper';\n\nimport { ComingSoonTag } from 'libs/shared/apps/calendar/components/coming-soon-tag/ComingSoonTag';\nimport { GenericCalendarDate } from 'libs/shared/apps/calendar/components/generic-calendar-date/GenericCalendarDate';\nimport { CalendarTheme } from 'libs/shared/apps/calendar/interfaces/CalendarTheme';\nimport { ActionOptions, Actions } from 'libs/shared/components/actions/Actions';\nimport { BackButton } from 'libs/shared/components/back-button/BackButton';\nimport { LazyImage } from 'libs/shared/components/lazy-image/LazyImage';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { ImageMinDimensions } from 'libs/shared/constants/ImageSizes';\nimport { BannerPortalContext } from 'libs/shared/context/BannerPortalContext';\nimport { ImageSize, ImageType, ResizeType } from 'libs/shared/enums/Images';\nimport { useBreakpoints } from 'libs/shared/hooks/useBreakpoints';\nimport { Banner, CalendarEvent, Logo } from 'libs/shared/interfaces';\nimport { ImageHelper, ImageOptions } from 'libs/shared/utils/ImageHelper';\n\nimport styles from './banner-header.scss';\n\nconst RATIO = `${ImageMinDimensions[ImageType.Banners].width}:${ImageMinDimensions[ImageType.Banners].height}`;\nconst DEFAULT_WIDTH = 1200; // This is ImageSize.Large for a Banner.\nconst LARGE_SCREEN_WIDTH = 1920;\n\nfunction useGetImageWidth(): number {\n const breakpoints = useBreakpoints();\n\n if (breakpoints.xxl)\n return LARGE_SCREEN_WIDTH;\n\n return DEFAULT_WIDTH;\n}\n\nfunction getSizeClass(heading: string): string {\n if (heading.length < 160)\n return 'h1';\n\n return styles.headingLarge;\n}\n\ninterface BannerHeaderProps {\n heading: string;\n banner?: Banner;\n bannerClassName?: string;\n imageCdnUrl?: string;\n logo?: Logo;\n actions?: ActionOptions[];\n specialEvent?: CalendarEvent;\n backButtonAppLink?: Core.AppLink;\n backButtonText?: string;\n backButtonClasses?: string;\n sortComponent?: JSX.Element;\n blockColourClass?: string;\n actionsDropdownClassName?: string;\n detailsComponent?: () => React.ReactElement;\n imageOptions?: ImageOptions;\n showComingSoon?: boolean;\n alignLogoLeft?: boolean;\n calendarTheme?: CalendarTheme;\n}\n\nconst namespace = 'shared.bannerHeader';\n\nexport const BannerHeader = React.memo(function(props: React.PropsWithChildren<BannerHeaderProps>): React.ReactElement {\n const { heading, banner, imageCdnUrl, actions, sortComponent, blockColourClass, specialEvent } = props;\n\n const portalContainerContext = React.useContext(BannerPortalContext);\n\n const imageWidth = useGetImageWidth();\n\n const specialEventIsToday = React.useMemo(() => {\n if (!specialEvent || props.showComingSoon)\n return false;\n\n const today = DateHelper.format(new Date(), 'YYYY-MM-DD');\n\n if (!specialEvent.endDate)\n return specialEvent.startDate === today;\n\n return specialEvent.startDate <= today && specialEvent.endDate >= today;\n }, [specialEvent]);\n\n function getSpecialEventMonthText(specialEvent: CalendarEvent): string {\n if (!specialEvent.endDate)\n return DateHelper.format(specialEvent.startDate, 'MMMM');\n\n if (DateHelper.isSame(specialEvent.startDate, specialEvent.endDate, 'month'))\n return DateHelper.format(specialEvent.startDate, 'MMMM');\n\n return `${DateHelper.format(specialEvent.startDate, 'MMM')} - ${DateHelper.format(specialEvent.endDate, 'MMM')}`;\n }\n\n const imageOptions = props.imageOptions || {\n width: imageWidth,\n ratio: RATIO,\n resizeType: ResizeType.Cover\n };\n\n const url = !!banner && !!imageCdnUrl && ImageHelper.createBannerUrl(banner, {\n fallbackBaseUrl: imageCdnUrl,\n fallbackCategoryName: heading,\n type: ImageType.Banners\n }, imageOptions);\n\n const containerProps: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> = {\n className: `banner banner-header ${props.bannerClassName}`,\n style: url ? { backgroundImage: `url('${url}')` } : {}\n };\n\n if (!banner && blockColourClass) {\n delete containerProps.style;\n containerProps.className += ` ${blockColourClass}`;\n }\n\n const DetailsComponent = props.detailsComponent;\n\n return PortalHelper.renderInPortalIfExists(\n // \"banner\" is used in playlists in Online. banner-header is used by all other projects\n <header {...containerProps}>\n <div className={`container ${styles.container} position-relative inner-banner`}>\n {props.backButtonAppLink && (\n <div className='pt-3'>\n <BackButton\n appLink={props.backButtonAppLink}\n backToName={props.backButtonText}\n extraClasses={props.backButtonClasses}\n color='white'\n />\n </div>\n )}\n \n <div className={`${props.alignLogoLeft ? 'position-absolute top-50 start-0 translate-middle-y w-100 ps-4' : `${styles.bannerContent} px-2 ${props.logo?.url ? styles.bannerContentWithLogo : ''}`}`}>\n {!!specialEvent && (\n <div className={`position-relative ${styles.specialEventContainer}`}>\n <GenericCalendarDate\n body={{\n type: specialEvent.endDate ? 'range' : 'day',\n text: specialEvent.endDate\n ? `${DateHelper.format(specialEvent.startDate, 'DD')}-${DateHelper.format(specialEvent.endDate, 'DD')}`\n : DateHelper.format(specialEvent.startDate, 'DD')\n }}\n month={getSpecialEventMonthText(specialEvent)}\n theme={props.calendarTheme}\n />\n </div>\n )}\n <div>\n {specialEventIsToday && (\n <div className='rounded-pill py-1 px-2 my-1 me-1 fw-semibold bg-light-blue lh-1 d-inline-block'>\n <Text namespace={namespace} phrase='onToday' />\n </div>\n )}\n {props.showComingSoon && (\n <ComingSoonTag className='pe-2 fw-semibold mb-1 rounded-pill justify-content-start text-nowrap' />\n )}\n <div className='d-flex align-items-center'>\n {props.alignLogoLeft &&\n <div className={`${styles.logoContainerLeft} d-none d-md-block partial-loading-background rounded-circle overflow-hidden me-3`}>\n {props.logo?.url &&\n <LazyImage src={ImageHelper.createUrl(props.logo?.url, { size: ImageSize.Medium })} />}\n </div>\n }\n <h1 className={`text-white text-shadow pe-3 position-static ${styles.heading} ${getSizeClass(heading)} ${props.alignLogoLeft ? 'w-50' : ''}`}>\n {heading}\n {DetailsComponent && <DetailsComponent />}\n </h1>\n </div>\n </div>\n {!!actions && (\n <div className={styles.actionsContainer}>\n <Actions\n actions={actions}\n sortComponent={sortComponent}\n actionsDropdownClassName={props.actionsDropdownClassName}\n />\n </div>\n )}\n </div>\n {!props.alignLogoLeft && !!props.logo?.url &&\n <div className={styles.logoContainer}>\n <img\n src={ImageHelper.createUrl(props.logo.url, { size: ImageSize.Small })}\n className='rounded-circle'\n />\n </div>\n }\n </div>\n </header>,\n portalContainerContext?.container\n );\n}, (prevProps, nextProps): boolean => (\n prevProps.actions === nextProps.actions\n && prevProps.heading === nextProps.heading\n && prevProps.logo?.url === nextProps.logo?.url\n));\n\nexport function PartialBannerHeader(): JSX.Element {\n const portalContainerContext = React.useContext(BannerPortalContext);\n\n return PortalHelper.renderInPortalIfExists(\n <div className={`partial-banner partial-loading-background ${styles.banner}`} />,\n portalContainerContext?.container\n );\n}","import * as React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Core } from 'libs/common/core';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { MediaQueryStrings } from 'libs/shared/enums/MediaQueries';\nimport { useMediaQuery } from 'libs/shared/hooks/UseMediaQuery';\nimport { PartialLoadingHelper } from 'libs/shared/utils/PartialLoadingHelper';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport { SvgContainer, SvgContainerSize } from '../svg-container/SvgContainer';\n\nconst namespace = 'shared.breadcrumbComponent';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst COLLAPSE_CHARACTER_COUNT = 64;\nconst MAX_SEGMENT_LENGTH = 48;\n\nexport interface Breadcrumb {\n name: string;\n appLink?: Core.AppLink;\n active?: boolean;\n}\n\ninterface BreadcrumbItemProps {\n breadcrumb: Breadcrumb;\n withBackIcon?: boolean;\n}\n\nexport const BreadcrumbItem = React.forwardRef((\n props: BreadcrumbItemProps,\n ref: React.ForwardedRef<HTMLElement>\n) => {\n const { breadcrumb: { name, appLink, active }, withBackIcon } = props;\n\n let trimmedName = name;\n let title: string = null;\n\n if (trimmedName.length > MAX_SEGMENT_LENGTH) {\n trimmedName = name.slice(0, MAX_SEGMENT_LENGTH) + '...';\n\n // Only setting the title when we trim, because otherwise it's really not needed - Sha\n title = name;\n }\n\n return (\n <li\n className={`breadcrumb-item${active ? ' active' : ''}`}\n title={title}\n >\n {active\n ? <strong>{trimmedName}</strong>\n : <AppLink appLink={appLink} ref={ref}>\n {withBackIcon && <SvgContainer svgName={cvSvgLibrary.ChevronLeft} size={SvgContainerSize.Small} />}\n <span className={withBackIcon ? 'ms-2' : ''}>{trimmedName}</span>\n </AppLink>\n }\n </li>\n );\n});\n\ninterface BreadcrumbsProps {\n breadcrumbs: Breadcrumb[];\n}\n\nexport const Breadcrumbs = ({ breadcrumbs }: BreadcrumbsProps) => {\n const isMobile = useMediaQuery(MediaQueryStrings.XS);\n\n const length = breadcrumbs?.length || 0;\n \n const [ collapse, setCollapse ] = React.useState(false);\n const [ shouldFocus, setShouldFocus ] = React.useState(false);\n const expandRef = React.useRef<HTMLElement>();\n\n React.useEffect(() => {\n const characterLength = breadcrumbs?.reduce((prev, next) => prev + next.name.length, 0) ?? 0;\n\n if (length > 4 && characterLength > COLLAPSE_CHARACTER_COUNT)\n setCollapse(true);\n }, [breadcrumbs?.length]);\n\n /**\n * Focus our first expanded item the first time it appears.\n */\n React.useLayoutEffect(() => {\n if (shouldFocus)\n expandRef.current?.focus();\n }, [ expandRef.current, shouldFocus ]);\n\n function onClickExpand() {\n setCollapse(false);\n setShouldFocus(true);\n }\n\n if (!length || (isMobile && length < 2))\n return <></>;\n\n if (isMobile)\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n <BreadcrumbItem breadcrumb={breadcrumbs[length - 2]} withBackIcon />\n </ol>\n </nav>\n );\n\n const first = <BreadcrumbItem breadcrumb={breadcrumbs[0]} />;\n const second = length > 2 ? <BreadcrumbItem breadcrumb={breadcrumbs[1]} /> : <></>;\n const secondLast = length > 3 ? <BreadcrumbItem breadcrumb={breadcrumbs[length - 2]} /> : <></>;\n const last = length > 1 ? <BreadcrumbItem breadcrumb={breadcrumbs[length - 1]} /> : <></>;\n const rest = breadcrumbs.slice(2, length - 2);\n\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n {first}\n {second}\n {collapse ?\n <li className='breadcrumb-item'>\n <button\n className='btn-link'\n onClick={onClickExpand}\n aria-label={getPhrase('expand')}\n >\n ...\n </button>\n </li> :\n rest.map((breadcrumb, idx) => (\n <BreadcrumbItem\n key={idx}\n breadcrumb={breadcrumb}\n ref={idx === 0 ? expandRef : null}\n />\n ))\n }\n {secondLast}\n {last}\n </ol>\n </nav>\n );\n};\n\nexport const PartialBreadcrumbs = React.memo(function({ numItems = 3 }: { numItems?: number; }) {\n const isMobile = useMediaQuery(MediaQueryStrings.XS);\n\n if (isMobile) {\n return (\n <div className='partial-loading-background' style={{ height: '1.3125rem', width: '6rem' }} />\n );\n }\n\n return (\n <nav aria-label='breadcrumb'>\n <ol className='breadcrumb m-0 p-0'>\n {PartialLoadingHelper.getPartialLoadingItems({ numItems }).map(({ width }, idx) => (\n <li key={idx} className='breadcrumb-item'>\n <span className='d-inline-block partial-loading-background' style={{ width }} dangerouslySetInnerHTML={{ __html: ' ' }} />\n </li>\n ))}\n </ol>\n </nav>\n );\n});","// extracted by mini-css-extract-plugin\nexport default {\"container\":\"VwD1b\",\"spinner\":\"eJ85e\"};","import * as React from 'react';\nimport { Spinner } from 'react-bootstrap';\nimport { useInView } from 'react-intersection-observer';\n\nimport { SvgContainer, SvgContainerSize } from 'libs/shared/components/svg-container/SvgContainer';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\n\nimport styles from './infinite-scroll-footer.scss';\n\ninterface InfiniteScrollFooterProps {\n isFetching: boolean;\n fetchNext?: (nextCursor: string) => void;\n nextCursor?: string;\n fetchOnScroll?: boolean;\n}\n\nInfiniteScrollFooter.defaultProps = {\n fetchOnScroll: false\n};\n\nexport function InfiniteScrollFooter(props: InfiniteScrollFooterProps): React.ReactElement {\n const [ ref, inView ] = useInView();\n\n React.useEffect(() => {\n if (!props.fetchOnScroll)\n return;\n\n if (!inView || props.isFetching)\n return;\n\n props.fetchNext?.(props.nextCursor);\n }, [ inView, props.isFetching ]);\n\n return (\n <div className={`p-3 text-center ${styles.container}`} ref={ref}>\n {props.isFetching\n ? <Spinner as='span' animation='border' role='status' className={styles.spinner} />\n : (\n <SvgContainer\n svgName={cvSvgLibrary.ChevronDown}\n className='svg-container cursor-pointer'\n size={SvgContainerSize.Large}\n onClick={() => props.fetchNext?.(props.nextCursor)}\n />\n )\n }\n </div>\n );\n}","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { FunctionHelper } from 'libs/common/backbone/utils/FunctionHelper';\n\nconst SCROLL_TOLERANCE = 400; // value in px\n\ninterface UseInfiniteScrollOptions {\n fetchNextPage: () => void;\n hasMore: boolean;\n isFetching: boolean;\n scrollContainer?: HTMLElement;\n}\n\nexport function useInfiniteScroll(options: UseInfiniteScrollOptions): void {\n const handleScroll = (): void => {\n if (options.isFetching)\n return;\n\n if (!options.scrollContainer) {\n const currentScrollHeight = window.innerHeight + document.documentElement.scrollTop;\n \n const totalHeight = document.documentElement.scrollHeight - SCROLL_TOLERANCE;\n \n if (currentScrollHeight < totalHeight)\n return;\n } else {\n const { scrollContainer } = options;\n const currentScrollHeight = scrollContainer.getBoundingClientRect().height + scrollContainer.scrollTop;\n \n const totalHeight = scrollContainer.scrollHeight - SCROLL_TOLERANCE;\n \n if (currentScrollHeight < totalHeight)\n return;\n }\n\n options.fetchNextPage();\n };\n\n useEffect(() => {\n const onScroll = FunctionHelper.throttle(handleScroll, 200);\n\n const scrollContainer = options.scrollContainer || window;\n\n if (options.hasMore)\n scrollContainer.addEventListener('scroll', onScroll);\n\n return () => scrollContainer.removeEventListener('scroll', onScroll);\n }, [ options.hasMore, options.fetchNextPage, options.scrollContainer ]);\n}","import { useEffect, useState } from 'react';\n\nimport { HttpStatus, HttpStatusClass } from 'libs/common/backbone/enums/HttpStatus';\nimport { FunctionHelper } from 'libs/common/backbone/utils/FunctionHelper';\nimport { Flight } from 'libs/common/flight';\n\nimport { BaseObject, BasePaginatedCollection } from 'libs/shared/interfaces';\n\nimport { useInfiniteScroll } from './UseInfiniteScroll';\nimport { useSelectAllPages } from './UseSelectAllPages';\n\nexport interface UseInfiniteListResult<T extends BaseObject> {\n items: T[];\n hasMore: boolean;\n isFetching: boolean;\n nextCursor: string;\n totalItems?: number;\n hasFirstPageCompleted: boolean;\n}\n\n/**\n * Hook to extract an infinite list from the application state,\n * save it locally in state and only update when new data\n * is fetched.\n * \n * @param getRequest - callback function to get the request for each page.\n * Can be false if the request requires data that hasn't yet been fetched - e.g. user id.\n * \n * @param fetchNext - callback function to fetch a page.\n * Can be false if the request requires data that hasn't yet been fetched - e.g. user id.\n */\nexport function useInfiniteList<TObject = BaseObject, TResponse = BasePaginatedCollection<TObject>>(\n getRequest: ((cursor?: string) => Flight.Request) | false,\n fetchNext: ((cursor?: string) => void) | false,\n onError?: (pageNumber: number, statusCode: HttpStatus) => void,\n getItems?: (responseData: TResponse) => TObject[],\n getCursor?: (responseData: TResponse) => string,\n scrollContainer?: HTMLElement\n): UseInfiniteListResult<TObject> {\n const [ pagesFetched, setPagesFetched ] = useState(0);\n\n const fetchNextFn = fetchNext as (cursor?: string) => void;\n\n function getKey(cursor?: string): string {\n if (!getRequest)\n return null;\n\n const request = getRequest(cursor);\n\n if (!request)\n return null;\n\n return request.key;\n }\n\n const response = useSelectAllPages<TObject, TResponse>(\n getKey,\n getItems,\n getCursor\n );\n\n function fetchNextPage(): void {\n if (!fetchNext || !getRequest || !response)\n return;\n\n setPagesFetched(currentVal => currentVal + 1);\n return fetchNextFn(response.nextCursor);\n }\n\n useInfiniteScroll({\n fetchNextPage,\n hasMore: !!response?.nextCursor,\n isFetching: response?.isFetching,\n scrollContainer\n });\n\n useEffect(() => {\n if (!response)\n return;\n\n if (response.shouldInitialFetch && fetchNext) {\n fetchNextFn();\n setPagesFetched(currentVal => currentVal + 1);\n }\n }, [ response?.shouldInitialFetch, fetchNext ]);\n\n useEffect(() => {\n if (!response?.statusCode || !FunctionHelper.isFunction(onError))\n return;\n\n const httpStatusClass: HttpStatusClass = +(response.statusCode?.toString()?.substr(0, 1));\n\n if (httpStatusClass !== HttpStatusClass.ClientError && httpStatusClass !== HttpStatusClass.ServerError)\n return;\n\n onError(pagesFetched, response.statusCode);\n }, [response?.statusCode]);\n\n return {\n items: response?.items,\n hasMore: !!response?.nextCursor,\n nextCursor: response?.nextCursor,\n isFetching: response?.isFetching,\n totalItems: response?.totalItems,\n hasFirstPageCompleted: response?.hasFirstPageCompleted\n };\n}","import React from 'react';\n\nimport { Breadcrumb } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { BreadcrumbService } from 'libs/shared/services/BreadcrumbService';\n\nexport function useBreadcrumbs(current: Breadcrumb): Breadcrumb[] {\n const [ match, useBuilder ] = React.useMemo(() => BreadcrumbService.getBuilder(), []);\n\n const breadcrumbs = useBuilder(match);\n\n if (!breadcrumbs || !current)\n return breadcrumbs;\n\n return [ ...breadcrumbs, { ...current, active: true }];\n}\n\n","const DEFAULT_PARTIAL_LOADING_OPTIONS: PartialLoadingOptions = {\n numItems: 5,\n minWidth: 50, // px\n maxWidth: 100 // px\n};\n\nexport interface PartialLoadingOptions {\n numItems?: number;\n minWidth?: number;\n maxWidth?: number;\n}\n\ninterface PartialLoadingItem {\n width: string;\n}\n\nexport const PartialLoadingHelper = {\n getPartialLoadingItems(options: PartialLoadingOptions = {}): PartialLoadingItem[] {\n const opts = {\n ...DEFAULT_PARTIAL_LOADING_OPTIONS,\n ...options\n };\n\n const getRandomFilterWidth = () => Math.max(Math.floor(Math.random() * opts.maxWidth), opts.minWidth);\n\n return [...Array(opts.numItems)].map(() => ({ width: `${getRandomFilterWidth()}px` }));\n }\n};","import { Flight } from 'libs/common/react/index';\n\nimport { AudienceRequests } from 'libs/shared/flight-requests/AudienceRequests';\nimport { PresentationAudience } from 'libs/shared/interfaces';\n\nimport { usePresentation } from 'shared/hooks/usePresentation';\n\nexport const usePresentationAudiences = () => {\n const { activePresentation, getFallbackPresentation } = usePresentation({ redirectOnError: true });\n\n const presentation = activePresentation || getFallbackPresentation();\n\n const audiences = Flight.useBasicFetch<PresentationAudience[]>(\n !!presentation &&\n AudienceRequests.presentationAudiences(presentation.id)\n );\n\n return audiences;\n};","import React from 'react';\n\nimport { Flight } from 'libs/common/flight';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { ClassificationRequests } from 'libs/shared/flight-requests/ClassificationRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { VideoRequests } from 'libs/shared/flight-requests/VideoRequests';\nimport { Clip, ClipCollection, CurrentUser, Video, VideoCollection } from 'libs/shared/interfaces';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nconst CHUNK_SIZE = 50;\n\ntype Types = Video[] | VideoCollection | Clip[] | ClipCollection;\n\nfunction getValidObjects(objects: Types): (Video | Clip)[] {\n if (!objects)\n return [];\n\n if (Array.isArray(objects))\n return objects.filter(o => !!o && (VideoHelper.isVideo(o) || VideoHelper.isClip(o)));\n\n if ('data' in objects)\n return objects.data.filter(o => !!o && (VideoHelper.isVideo(o) || VideoHelper.isClip(o)));\n\n return [];\n}\n\ninterface VideoMixinOptions {\n /**\n * If the videos that are having new data mixed into are sitting on an explicit Flight namespace,\n * providing that namespace here is required\n */\n flightNamespace?: string;\n}\n\nexport function useVideoMixin(objects: Types, options: VideoMixinOptions = {}): void {\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n\n const hydratedVideos = React.useRef<Set<string>>(new Set<string>());\n\n const videos = getValidObjects(objects);\n\n const videoIds = videos.map(v => v.id);\n\n const [ request, setRequest ] = React.useState<Flight.Request[]>([]);\n\n React.useEffect(() => {\n if (!videoIds?.length || !currentUser.hasCompleted)\n return;\n\n const unhydratedVideos: string[] = [];\n\n videoIds.forEach(id => {\n if (!hydratedVideos.current.has(id)) {\n unhydratedVideos.push(id);\n hydratedVideos.current.add(id);\n }\n });\n \n if (!unhydratedVideos.length)\n return;\n\n setRequest(r => {\n const newRequests = [...r] ;\n\n ArrayHelper.chunk<string>(unhydratedVideos, CHUNK_SIZE).forEach(chunk => {\n newRequests.push(VideoRequests.videoMixinAssocs(chunk, options.flightNamespace));\n\n if (currentUser.data?.isAuthenticated)\n newRequests.push(ClassificationRequests.hasCurriculumLinks(chunk, null, options.flightNamespace));\n });\n\n return newRequests;\n });\n }, [ videoIds?.length, currentUser.hasCompleted ]);\n\n Flight.useBasicFetchAll(request);\n}","// extracted by mini-css-extract-plugin\nexport default {\"image\":\"ZfpQv\"};","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EntityType, LocationContext, SignUpDescriptors, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nimport styles from './favourites-empty-state.scss';\n\nconst namespace = 'shared.favouritesEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function FavouritesEmptyState(): JSX.Element {\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image\n src={ImageUrls.EmptyStates.FAVOURITED_VIDEOS}\n altText={getPhrase('info')}\n className={styles.image}\n />\n\n <EmptyState.Heading className='h3'>\n <Text phrase='heading' />\n </EmptyState.Heading>\n\n <EmptyState.Info><Text phrase='info' /></EmptyState.Info>\n\n <EmptyState.Cta\n text={LanguageService.getPhrase(namespace, 'cta')}\n appLink={{\n application: AppChannels.DASHBOARD,\n action: Actions.Dashboard.HOME\n }}\n />\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}\n\nexport function FavouritesPublicEmptyState(): JSX.Element {\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <EmptyState>\n <EmptyState.Image src={ImageUrls.EmptyStates.FAVOURITED_VIDEOS_PUBLIC} altText={getPhrase('publicInfo')} />\n <EmptyState.Heading><Text phrase='publicHeading' /></EmptyState.Heading>\n <EmptyState.Info><Text phrase='publicInfo' /></EmptyState.Info>\n <EmptyState.Cta\n text={LanguageService.getPhrase(namespace, 'publicCta')}\n appLink={{\n application: AppChannels.SIGN_UP,\n action: Actions.SignUp.SIGN_UP\n }}\n analyticsData={{}}\n analyticsOptions={{\n actionType: UserAction.Click,\n location: LocationContext.MyFavouritesLanding,\n entity: EntityType.AppLink,\n workflowPhase: WorkflowPhase.Start,\n descriptor: SignUpDescriptors.SignUp\n }}\n />\n </EmptyState>\n </LanguageNamespaceContext.Provider>\n );\n}","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { VideoTypes } from 'libs/shared/interfaces';\nimport { cvSvgLibrary } from 'libs/shared/utils/SvgHelper';\nimport { VideoHelper } from 'libs/shared/utils/VideoHelper';\n\nimport { useVideoActions, VideoActionsLocation } from 'shared/hooks/use-video-actions/useVideoActions';\nimport { useLiteFavourites } from 'shared/hooks/useLiteFavourites';\n\nconst namespace = 'shared.favourites';\n\nexport function useFavouritesVideoActions() {\n const videoActions = useVideoActions({ location: VideoActionsLocation.VideoItem });\n const { setFavourite } = useLiteFavourites(LocationContext.VideoThumbnail);\n\n const getVideoActions = (video: VideoTypes) => {\n const { canConsume } = VideoHelper.getCanBeConsumed(video);\n\n if (!canConsume) {\n return [{\n label: LanguageService.getPhrase(namespace, 'removeFromFavourites'),\n svgName: cvSvgLibrary.Delete,\n button: false,\n className: 'btn btn-link text-danger',\n onClick: () => setFavourite(video, false)\n }];\n }\n\n return videoActions.getVideoActions(video);\n };\n\n return {\n ...videoActions,\n getVideoActions\n };\n}","// extracted by mini-css-extract-plugin\nexport default {\"banner\":\"FEWd3\"};","import * as React from 'react';\nimport { useDispatch } from 'react-redux';\n\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { LocationContext } from 'libs/analytics/interfaces';\n\nimport { BannerHeader } from 'libs/shared/components/banner-header/BannerHeader';\nimport { Breadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { InfiniteScrollFooter } from 'libs/shared/components/infinite-scroll-footer/InfiniteScrollFooter';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { PartialVideoList } from 'libs/shared/components/video-list/partial-loading/PartialVideoList';\nimport { VideoList } from 'libs/shared/components/video-list/VideoList';\nimport { VideoActionsContext } from 'libs/shared/context/VideoActionsContext';\nimport { LocalPermissionName } from 'libs/shared/enums/PermissionName';\nimport { handleHttpError } from 'libs/shared/errors/handlers/HttpErrorHandlers';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { CustomerRequests } from 'libs/shared/flight-requests/CustomerRequests';\nimport { FavouriteRequests } from 'libs/shared/flight-requests/FavouriteRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useBreadcrumbs } from 'libs/shared/hooks/useBreadcrumbs';\nimport { useInfiniteList } from 'libs/shared/hooks/UseInfiniteList';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { Config, CurrentUser, VideoTypes, YearGroup } from 'libs/shared/interfaces';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\nimport { usePluginHelper } from 'shared/hooks/use-plugin-helper/usePluginHelper';\nimport { useLiteFavourites } from 'shared/hooks/useLiteFavourites';\nimport { usePresentationAudiences } from 'shared/hooks/usePresentationAudiences';\nimport { useVideoMixin } from 'shared/hooks/useVideoMixin';\nimport { InteractiveHelpers } from 'shared/utils/InteractiveHelper';\nimport { VideoAppLinkHelper } from 'shared/utils/VideoAppLinkHelper';\n\nimport { SeriesAppLinkHelper } from 'apps/series/SeriesAppLinkHelper';\n\nimport { FavouritesEmptyState, FavouritesPublicEmptyState } from './empty-state/FavouritesEmptyState';\nimport { useFavouritesCount } from './hooks/useFavouritesCount';\nimport { useFavouritesVideoActions } from './FavouritesViewUtils';\n\nimport styles from './favourites-view.scss';\n\nconst namespace = 'shared.favourites';\n\nexport function FavouritesView(): JSX.Element {\n const dispatch = useDispatch();\n const alerts = useAlerts();\n const { setFavourite, canFavourite } = useLiteFavourites(LocationContext.VideoThumbnail);\n const { isPlugin } = usePluginHelper();\n const videoActions = useFavouritesVideoActions();\n\n useSetPageMetadata({ title: LanguageService.getPhrase(namespace, 'pageTitle') });\n const { hasLocalPermissions, hasPermissions } = usePermissions();\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const yearGroups = Flight.useBasicFetch<YearGroup[]>(\n currentUser.data?.isAuthenticated && CustomerRequests.yearGroups(currentUser.data.customerId)\n );\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n const getRequest = (cursor?: string) => {\n return FavouriteRequests.getFavourites(currentUser.data.id, cursor);\n };\n\n const fetchNext = (cursor?: string) => {\n return Flight.getFetch(dispatch)(getRequest(cursor));\n };\n\n const shouldFetch = !hasLocalPermissions(LocalPermissionName.ViewMyFavouritesLanding) && currentUser.hasCompleted;\n\n const {\n items,\n hasMore,\n isFetching\n } = useInfiniteList<VideoTypes>(shouldFetch ? getRequest : false, fetchNext, onError);\n\n useVideoMixin(items);\n \n const audiences = usePresentationAudiences();\n\n const breadcrumbs = useBreadcrumbs({ name: LanguageService.getPhrase(namespace, 'header') });\n\n function onError(pageNumber: number, httpStatus: HttpStatus): void {\n if (pageNumber === 1)\n return handleHttpError(httpStatus);\n\n alerts.error(LanguageService.getPhrase(namespace, 'error'));\n }\n\n const { count, isLoading } = useFavouritesCount(currentUser.data?.id);\n if (isLoading)\n return <></>;\n\n if (hasLocalPermissions(LocalPermissionName.ViewMyFavouritesLanding))\n return <FavouritesPublicEmptyState />;\n\n return (\n <VideoActionsContext.Provider value={videoActions}>\n <div className='p-3'>\n <BannerHeader\n heading={LanguageService.getPhrase(namespace, 'header')}\n banner={{ url: ImageUrls.FAVOURITES_PLAYLIST.FAV_PLAYLIST_BANNER }}\n bannerClassName={`${styles.banner} bg-pink`}\n imageCdnUrl={config.data?.imageCdnUrl}\n detailsComponent={() => (\n <div className='mb-n1 font-size-normal fw-normal mt-1'>\n <Text namespace={namespace} phrase='videos' options={{ smartCount: count }} />\n </div>\n )}\n />\n {breadcrumbs?.length &&\n <div className='border-bottom pb-3'>\n <Breadcrumbs breadcrumbs={breadcrumbs} />\n </div>\n }\n \n {(() => {\n if (!items)\n return <PartialVideoList />;\n\n if (!items.length)\n return <FavouritesEmptyState />;\n\n return (\n <div className='mt-2'>\n <VideoList\n videos={items}\n yearGroups={yearGroups.data}\n getVideoAppLink={VideoAppLinkHelper.getAppLink}\n hasPermissions={hasPermissions}\n getSubTextAppLink={video => SeriesAppLinkHelper.getSeriesAppLink(video.series)}\n setFavourite={setFavourite}\n canFavourite={canFavourite}\n presentationAudiences={audiences.data}\n getPreviewQuestionsAppLink={interactive => InteractiveHelpers.getPreviewQuestionsAppLink(interactive)}\n isPlugin={isPlugin}\n getClassroomGuideAppLink={VideoAppLinkHelper.getClassroomGuideAppLink}\n getInteractiveGuidanceAppLink={VideoAppLinkHelper.getInteractiveGuidanceAppLink}\n getResourceGuidanceAppLink={VideoAppLinkHelper.getResourceGuidanceAppLink}\n />\n {(hasMore || isFetching) && <InfiniteScrollFooter isFetching={isFetching} fetchNext={fetchNext} />}\n </div>\n );\n })()}\n </div>\n </VideoActionsContext.Provider>\n );\n}","\nimport { Flight } from 'libs/common/flight';\n\nimport { FavouriteRequests } from 'libs/shared/flight-requests/FavouriteRequests';\nimport { FavouritesCountResponse } from 'libs/shared/interfaces';\n\nexport function useFavouritesCount(userId?: string) {\n// todo there is a beckend bug that we cannot group fetch these three number\n const favouriteVideosCount = Flight.useBasicFetch<FavouritesCountResponse>(userId &&\n FavouriteRequests.getFavouritesVideosCount(userId));\n const favouriteClipsCount = Flight.useBasicFetch<FavouritesCountResponse>(userId &&\n FavouriteRequests.getFavouritesClipsCount(userId));\n const favouriteInteractivesCount = Flight.useBasicFetch<FavouritesCountResponse>(userId &&\n FavouriteRequests.getFavouritesInteractivesCount(userId));\n \n const totalCount = favouriteVideosCount.data?.count\n + favouriteInteractivesCount.data?.count\n + favouriteClipsCount.data?.count;\n\n const favourites = [\n ...(favouriteVideosCount.data?.data || []),\n ...(favouriteClipsCount.data?.data || []),\n ...(favouriteInteractivesCount.data?.data || [])\n ];\n\n return {\n count: totalCount,\n favourites,\n isLoading: !favouriteVideosCount.data?.data\n || !favouriteClipsCount.data?.data\n || !favouriteInteractivesCount.data?.data\n };\n}","\"use client\";\n\nimport classNames from 'classnames';\nimport * as React from 'react';\nimport { useBootstrapPrefix, useBootstrapBreakpoints, useBootstrapMinBreakpoint } from './ThemeProvider';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst Row = /*#__PURE__*/React.forwardRef(({\n bsPrefix,\n className,\n // Need to define the default \"as\" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595\n as: Component = 'div',\n ...props\n}, ref) => {\n const decoratedBsPrefix = useBootstrapPrefix(bsPrefix, 'row');\n const breakpoints = useBootstrapBreakpoints();\n const minBreakpoint = useBootstrapMinBreakpoint();\n const sizePrefix = `${decoratedBsPrefix}-cols`;\n const classes = [];\n breakpoints.forEach(brkPoint => {\n const propValue = props[brkPoint];\n delete props[brkPoint];\n let cols;\n if (propValue != null && typeof propValue === 'object') {\n ({\n cols\n } = propValue);\n } else {\n cols = propValue;\n }\n const infix = brkPoint !== minBreakpoint ? `-${brkPoint}` : '';\n if (cols != null) classes.push(`${sizePrefix}${infix}-${cols}`);\n });\n return /*#__PURE__*/_jsx(Component, {\n ref: ref,\n ...props,\n className: classNames(className, decoratedBsPrefix, ...classes)\n });\n});\nRow.displayName = 'Row';\nexport default Row;"],"names":["PortalHelper","renderInPortalIfExists","component","portalContainer","createPortal","namespace","ComingSoonTag","props","Tooltip","title","LanguageService","spanHackClassName","spanHack","className","SvgContainer","svgName","onlyIcon","GenericCalendarDate","AppLink","appLink","getAppLink","theme","border","analyticsData","analyticsOptions","background","label","body","type","getBodyClass","text","month","BackButton","textShadow","backToName","color","extraClasses","backPhrase","colorClass","textShadowClass","size","S","defaultProps","RATIO","width","height","getSizeClass","heading","length","BannerHeader","banner","imageCdnUrl","actions","sortComponent","blockColourClass","specialEvent","portalContainerContext","BannerPortalContext","imageWidth","useBreakpoints","xxl","specialEventIsToday","showComingSoon","today","DateHelper","Date","endDate","startDate","imageOptions","ratio","resizeType","url","ImageHelper","fallbackBaseUrl","fallbackCategoryName","containerProps","bannerClassName","style","backgroundImage","DetailsComponent","detailsComponent","backButtonAppLink","backButtonText","backButtonClasses","alignLogoLeft","logo","getSpecialEventMonthText","calendarTheme","Text","phrase","LazyImage","src","Actions","actionsDropdownClassName","container","prevProps","nextProps","PartialBannerHeader","getPhrase","BreadcrumbItem","ref","breadcrumb","name","active","withBackIcon","trimmedName","slice","Breadcrumbs","breadcrumbs","isMobile","collapse","setCollapse","shouldFocus","setShouldFocus","expandRef","characterLength","reduce","prev","next","current","focus","first","second","secondLast","last","rest","onClick","map","idx","key","PartialBreadcrumbs","numItems","dangerouslySetInnerHTML","__html","InfiniteScrollFooter","inView","fetchOnScroll","isFetching","fetchNext","nextCursor","Spinner","as","animation","role","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","SCROLL_TOLERANCE","useInfiniteList","getRequest","onError","getItems","getCursor","scrollContainer","options","handleScroll","useState","pagesFetched","setPagesFetched","fetchNextFn","response","cursor","request","fetchNextPage","currentVal","hasMore","getBoundingClientRect","scrollTop","scrollHeight","window","innerHeight","document","documentElement","useEffect","onScroll","FunctionHelper","addEventListener","removeEventListener","shouldInitialFetch","httpStatusClass","toString","substr","HttpStatus","items","totalItems","hasFirstPageCompleted","useBreadcrumbs","match","useBuilder","DEFAULT_PARTIAL_LOADING_OPTIONS","minWidth","maxWidth","PartialLoadingHelper","getPartialLoadingItems","opts","Array","Math","max","floor","random","usePresentationAudiences","redirectOnError","activePresentation","getFallbackPresentation","presentation","id","CHUNK_SIZE","useVideoMixin","objects","currentUser","hydratedVideos","Set","videos","isArray","filter","o","data","getValidObjects","videoIds","v","setRequest","hasCompleted","unhydratedVideos","forEach","has","push","add","r","newRequests","chunk","flightNamespace","isAuthenticated","FavouritesEmptyState","value","EmptyState","ImageUrls","altText","application","action","FavouritesPublicEmptyState","actionType","location","entity","workflowPhase","descriptor","SignUp","FavouritesView","dispatch","alerts","useLiteFavourites","u","setFavourite","canFavourite","isPlugin","usePluginHelper","videoActions","useVideoActions","getVideoActions","video","VideoHelper","canConsume","button","useFavouritesVideoActions","useSetPageMetadata","usePermissions","hasLocalPermissions","hasPermissions","UserRequests","yearGroups","CustomerRequests","customerId","config","ConfigRequests","FavouriteRequests","shouldFetch","pageNumber","httpStatus","error","audiences","useFavouritesCount","count","isLoading","VideoActionsContext","smartCount","VideoList","getVideoAppLink","VideoAppLinkHelper","getSubTextAppLink","SeriesAppLinkHelper","series","presentationAudiences","getPreviewQuestionsAppLink","interactive","InteractiveHelper","getClassroomGuideAppLink","getInteractiveGuidanceAppLink","getResourceGuidanceAppLink","PartialVideoList","userId","favouriteVideosCount","favouriteClipsCount","favouriteInteractivesCount","favourites","Row","bsPrefix","Component","decoratedBsPrefix","breakpoints","minBreakpoint","sizePrefix","classes","brkPoint","propValue","cols","infix","displayName"],"sourceRoot":""}
|