@clickview/reports 0.90.0-rc.4 → 0.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/.vite/manifest.json +210 -210
  2. package/dist/bundles.json +1 -1
  3. package/dist/en.json +1 -1
  4. package/dist/scripts/{med1nnv82.chunk.js → B2NaDejJ2.chunk.js} +2 -2
  5. package/dist/scripts/{med1nnv82.chunk.js.map → B2NaDejJ2.chunk.js.map} +1 -1
  6. package/dist/scripts/{DATsYYMP.chunk.js → B7UvjDWk.chunk.js} +2 -2
  7. package/dist/scripts/{DATsYYMP.chunk.js.map → B7UvjDWk.chunk.js.map} +1 -1
  8. package/dist/scripts/{CGYMpd9x2.chunk.js → BBC0heb12.chunk.js} +2 -2
  9. package/dist/scripts/{CGYMpd9x2.chunk.js.map → BBC0heb12.chunk.js.map} +1 -1
  10. package/dist/scripts/{BcjF3S7y.chunk.js → BBromGRt.chunk.js} +2 -2
  11. package/dist/scripts/{BcjF3S7y.chunk.js.map → BBromGRt.chunk.js.map} +1 -1
  12. package/dist/scripts/{CEM-Xsc32.chunk.js → BM1rCX722.chunk.js} +2 -2
  13. package/dist/scripts/{CEM-Xsc32.chunk.js.map → BM1rCX722.chunk.js.map} +1 -1
  14. package/dist/scripts/{D63nJT6V.chunk.js → BT26h7xG.chunk.js} +2 -2
  15. package/dist/scripts/{D63nJT6V.chunk.js.map → BT26h7xG.chunk.js.map} +1 -1
  16. package/dist/scripts/{B9syewbL.chunk.js → BhnToJrk.chunk.js} +2 -2
  17. package/dist/scripts/{B9syewbL.chunk.js.map → BhnToJrk.chunk.js.map} +1 -1
  18. package/dist/scripts/{CXyHtApp2.chunk.js → Bq-KpJWX2.chunk.js} +2 -2
  19. package/dist/scripts/{CXyHtApp2.chunk.js.map → Bq-KpJWX2.chunk.js.map} +1 -1
  20. package/dist/scripts/{C_gBUP2y2.chunk.js → Bzfy_cw32.chunk.js} +2 -2
  21. package/dist/scripts/{C_gBUP2y2.chunk.js.map → Bzfy_cw32.chunk.js.map} +1 -1
  22. package/dist/scripts/{DGuSwgQf2.chunk.js → C3yKN7vY2.chunk.js} +2 -2
  23. package/dist/scripts/{DGuSwgQf2.chunk.js.map → C3yKN7vY2.chunk.js.map} +1 -1
  24. package/dist/scripts/{DqX2L2fn2.chunk.js → CEL9EOPh2.chunk.js} +2 -2
  25. package/dist/scripts/{DqX2L2fn2.chunk.js.map → CEL9EOPh2.chunk.js.map} +1 -1
  26. package/dist/scripts/{BHwx99h9.chunk.js → COeneeRO.chunk.js} +2 -2
  27. package/dist/scripts/{BHwx99h9.chunk.js.map → COeneeRO.chunk.js.map} +1 -1
  28. package/dist/scripts/{C5nG9HKq2.chunk.js → CiMD5u2s2.chunk.js} +2 -2
  29. package/dist/scripts/{C5nG9HKq2.chunk.js.map → CiMD5u2s2.chunk.js.map} +1 -1
  30. package/dist/scripts/{q1iKm4P4.chunk.js → Coxg-CDT.chunk.js} +2 -2
  31. package/dist/scripts/{q1iKm4P4.chunk.js.map → Coxg-CDT.chunk.js.map} +1 -1
  32. package/dist/scripts/{DKgzSSZ12.chunk.js → D5JcKzGf2.chunk.js} +2 -2
  33. package/dist/scripts/{DKgzSSZ12.chunk.js.map → D5JcKzGf2.chunk.js.map} +1 -1
  34. package/dist/scripts/{DBpZNnAI2.chunk.js → DDXdEuUF2.chunk.js} +2 -2
  35. package/dist/scripts/{DBpZNnAI2.chunk.js.map → DDXdEuUF2.chunk.js.map} +1 -1
  36. package/dist/scripts/{C_nTmCTH2.chunk.js → DLWxPapJ2.chunk.js} +2 -2
  37. package/dist/scripts/{C_nTmCTH2.chunk.js.map → DLWxPapJ2.chunk.js.map} +1 -1
  38. package/dist/scripts/{CeSe3AP62.chunk.js → Da6u6D2M2.chunk.js} +3 -3
  39. package/dist/scripts/{CeSe3AP62.chunk.js.map → Da6u6D2M2.chunk.js.map} +1 -1
  40. package/dist/scripts/{CWVwHN-C2.chunk.js → DhSEOAnJ2.chunk.js} +2 -2
  41. package/dist/scripts/{CWVwHN-C2.chunk.js.map → DhSEOAnJ2.chunk.js.map} +1 -1
  42. package/dist/scripts/{Cv7tjWWS.chunk.js → IG-rboYg.chunk.js} +2 -2
  43. package/dist/scripts/{Cv7tjWWS.chunk.js.map → IG-rboYg.chunk.js.map} +1 -1
  44. package/dist/scripts/{CDx9_B5h2.chunk.js → KkZBQL3G2.chunk.js} +2 -2
  45. package/dist/scripts/{CDx9_B5h2.chunk.js.map → KkZBQL3G2.chunk.js.map} +1 -1
  46. package/dist/scripts/{CCdxPE8F.chunk.js → TJTvGoAZ.chunk.js} +2 -2
  47. package/dist/scripts/{CCdxPE8F.chunk.js.map → TJTvGoAZ.chunk.js.map} +1 -1
  48. package/dist/scripts/{app-F8o5al1q.js → app-DW-nP8r1.js} +3 -3
  49. package/dist/scripts/{app-F8o5al1q.js.map → app-DW-nP8r1.js.map} +1 -1
  50. package/dist/scripts/{DJpo4rMq2.chunk.js → i1FSKHH62.chunk.js} +2 -2
  51. package/dist/scripts/{DJpo4rMq2.chunk.js.map → i1FSKHH62.chunk.js.map} +1 -1
  52. package/dist/scripts/{B_QHbZ3D2.chunk.js → niZatQNI2.chunk.js} +2 -2
  53. package/dist/scripts/{B_QHbZ3D2.chunk.js.map → niZatQNI2.chunk.js.map} +1 -1
  54. package/dist/scripts/{BDLgF915.chunk.js → nup2thXk.chunk.js} +2 -2
  55. package/dist/scripts/{BDLgF915.chunk.js.map → nup2thXk.chunk.js.map} +1 -1
  56. package/dist/scripts/{r68VJd6w.chunk.js → qhfEmD0O.chunk.js} +2 -2
  57. package/dist/scripts/{r68VJd6w.chunk.js.map → qhfEmD0O.chunk.js.map} +1 -1
  58. package/dist/scripts/{J0H9O8cX.chunk.js → t8ONdKoR.chunk.js} +2 -2
  59. package/dist/scripts/{J0H9O8cX.chunk.js.map → t8ONdKoR.chunk.js.map} +1 -1
  60. package/dist/scripts/{CLDXLTBe.chunk.js → v01tmPE-.chunk.js} +2 -2
  61. package/dist/scripts/{CLDXLTBe.chunk.js.map → v01tmPE-.chunk.js.map} +1 -1
  62. package/dist/scripts/{DHz5C_j8.chunk.js → xV42YE03.chunk.js} +2 -2
  63. package/dist/scripts/{DHz5C_j8.chunk.js.map → xV42YE03.chunk.js.map} +1 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CGYMpd9x2.chunk.js","names":[],"sources":["../../src/shared/flight-requests/LoginRequests.ts","../../src/apps/logins/views/cards/school-logins-by-group-card/empty-state/school-logins-by-group-card-card-empty-state.module.scss","../../src/apps/logins/views/cards/school-logins-by-group-card/empty-state/SchoolLoginsByGroupCardEmptyState.tsx","../../src/apps/logins/views/cards/school-logins-by-group-card/SchoolLoginsByGroupCardView.tsx","../../src/shared/utils/LineChartByMonthUtils.ts","../../src/apps/logins/views/cards/school-logins-by-month-card/SchoolLoginsByMonthCardView.tsx","../../src/apps/logins/views/school-login-overview/school-login-overview.module.scss","../../src/apps/logins/views/school-login-overview/SchoolLoginOverview.tsx"],"sourcesContent":["import { Xhr } from 'libs/common/backbone/interfaces/Xhr';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { AnalyticsRequestFilter } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\nexport const LoginRequests = {\n logins(\n filter: AnalyticsRequestFilter,\n success?: (data: LoginEventResponse) => void,\n error?: (xhr: Xhr) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/logins', {\n ...filter,\n timeOffset: DateHelper.getTimezoneOffset()\n }),\n key: getAnalyticsRequestKey('logins', filter),\n normalize: false,\n success,\n error,\n always\n };\n }\n};\n",":local {\n .image {\n width: 200px;\n height: auto;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\n\nimport { ImageUrls } from 'shared/constants/ReportsImageUrls';\n\nconst namespace = 'reportsShared.schoolLoginsByGroupCardEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nimport styles from './school-logins-by-group-card-card-empty-state.module.scss';\n\nexport function SchoolLoginsByGroupCardEmptyState() {\n return (\n <EmptyState className='flex-grow-1 justify-content-center'>\n <EmptyState.Image\n src={ImageUrls.EmptyStates.Shared.School}\n className={styles.image}\n />\n <EmptyState.Heading className='h6'>\n {getPhrase('heading')}\n </EmptyState.Heading>\n <EmptyState.Info className='w-100'>\n {getPhrase('description')}\n </EmptyState.Info>\n </EmptyState>\n );\n}\n","import React from 'react';\nimport { Scrollbars } from 'react-custom-scrollbars-2';\n\nimport { Flight } from 'libs/common/react/index';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { Text } from 'libs/shared/components/text/Text';\n\nimport { VerticalBarChart } from 'shared/components/vertical-bar-chart/VerticalBarChart';\nimport { LoginRequests } from 'shared/flight-requests/LoginRequests';\nimport { useGetRequestFilter } from 'shared/hooks/UseGetFilterQueryParams';\nimport { useIsTertiary } from 'shared/hooks/useIsTertiary';\nimport { getCountByGroup } from 'shared/utils/BarChartByGroupUtils';\n\nimport { SchoolLoginsByGroupCardEmptyState } from './empty-state/SchoolLoginsByGroupCardEmptyState';\n\nconst namespace = 'logins.schoolLoginsByGroupCard';\n\n// eslint-disable-next-line rulesdir/require-view-title\nexport function SchoolLoginsByGroupCardView() {\n const requestFilter = useGetRequestFilter('logins');\n\n const logins = Flight.useBasicFetch<LoginEventResponse>(LoginRequests.logins(requestFilter));\n \n const isTertiary = useIsTertiary();\n\n const mapNameToGroup = (name: string) => (name === 'Unknown' || name === null) ? 'Staff' : name;\n const totalLoginsByGroupData = getCountByGroup(\n logins.data?.yearGroupCount?.map(group => ({\n name: mapNameToGroup(group.name),\n count: group.count\n }))\n );\n const totalLoginsCount = totalLoginsByGroupData?.reduce((acc, group) => (acc + group.y), 0);\n\n return (\n <div className='d-flex flex-column h-100 bg-white overflow-hidden rounded pt-3 px-3'>\n {totalLoginsByGroupData ?\n <>\n <h2 className='h6 mb-1'>\n <Text\n namespace={namespace}\n phrase={isTertiary ? 'totalLoginsTertiary' : 'totalLogins'}\n options={{ logins: totalLoginsCount }}\n />\n </h2>\n\n {totalLoginsByGroupData.length ?\n <Scrollbars className='position-relative'>\n <div className='position-absolute w-100'>\n <VerticalBarChart data={totalLoginsByGroupData} />\n </div>\n </Scrollbars> :\n <SchoolLoginsByGroupCardEmptyState />\n }\n </> :\n <div className='partial-loading-background w-50'>&nbsp;</div>\n }\n </div>\n );\n}\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { LoginEvent } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { VideoViewEvent } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { UserGroup } from 'libs/shared/enums/UserGroup';\nimport { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nimport { mapUserTypeToChartColour, mapUserTypeToChartLabel } from 'shared/utils/UserUtils';\n\nconst GroupByThresholds = {\n MONTH: 35,\n YEAR: 365\n};\n\nconst DateFormats = {\n day: 'YYYY-MM-DD',\n month: 'YYYY-MM',\n year: 'YYYY'\n};\n\nconst DisplayFormats = {\n day: 'D MMM',\n month: 'MMM',\n year: 'YYYY'\n};\n\ntype GroupedViewData = {\n [key in UserGroup]?: {\n [date: string]: number\n }\n};\n\ntype GroupBy = 'day' | 'month' | 'year';\n\ninterface ChartData {\n categories: string[];\n data: Highcharts.SeriesLineOptions[];\n}\n\nfunction getGroupBy(requestFilter: AnalyticsRequestFilter): GroupBy {\n const range = DateHelper.diffBetween(requestFilter.end, requestFilter.start, 'day');\n\n if (range > GroupByThresholds.YEAR)\n return 'year';\n\n if (range > GroupByThresholds.MONTH)\n return 'month';\n\n return 'day';\n}\n\nfunction getFullDateRange(requestFilter: AnalyticsRequestFilter, groupBy: GroupBy): string[] {\n const range: string[] = [];\n\n const localStart = DateHelper.convertUTCToLocal(requestFilter.start);\n const localEnd = DateHelper.convertUTCToLocal(requestFilter.end);\n\n let currentDate = DateHelper.format(localStart, DateFormats[groupBy]);\n\n while (!DateHelper.isAfter(currentDate, localEnd, groupBy)) {\n range.push(currentDate);\n currentDate = DateHelper.format(DateHelper.add(currentDate, 1, groupBy), DateFormats[groupBy]);\n }\n\n return range;\n}\n\nexport function getChartData(\n events: VideoViewEvent[] | LoginEvent[],\n requestFilter: AnalyticsRequestFilter\n): ChartData {\n if (!events) return null;\n\n const groupBy = getGroupBy(requestFilter);\n const fullDateRange = getFullDateRange(requestFilter, groupBy);\n \n const grouped: GroupedViewData = {};\n\n events.forEach(ev => {\n if (!ev.userType)\n return;\n\n const eventDate = 'groupedDateWatched' in ev && ev.groupedDateWatched || 'groupedLoggedOn' in ev && ev.groupedLoggedOn;\n const eventDateFormatted = DateHelper.format(DateHelper.convertUTCToLocal(eventDate), DateFormats[groupBy]);\n\n grouped[ev.userType] = grouped[ev.userType] ?? {};\n grouped[ev.userType][eventDateFormatted] = grouped[ev.userType][eventDateFormatted] ?? 0;\n grouped[ev.userType][eventDateFormatted] += ev.count;\n });\n\n const roles = Object.keys(grouped) as UserGroup[];\n\n if (!roles.length) return {\n categories: fullDateRange.map(d => DateHelper.format(d, DisplayFormats[groupBy])),\n data: []\n };\n\n return {\n categories: fullDateRange.map(d => DateHelper.format(d, DisplayFormats[groupBy])),\n data:\n ArrayHelper.sortBy(roles.map(r => ({\n name: mapUserTypeToChartLabel(r),\n type: 'line',\n data: fullDateRange.map(d => grouped[r][d] ?? 0),\n color: mapUserTypeToChartColour(r)\n })), 'name')\n };\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/react/index';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { Text } from 'libs/shared/components/text/Text';\n\nimport { LineChart } from 'shared/components/line-chart/LineChart';\nimport { LoginRequests } from 'shared/flight-requests/LoginRequests';\nimport { useGetRequestFilter } from 'shared/hooks/UseGetFilterQueryParams';\nimport { getChartData } from 'shared/utils/LineChartByMonthUtils';\n\nconst namespace = 'logins.schoolLoginsByMonthCard';\n\n// eslint-disable-next-line rulesdir/require-view-title\nexport function SchoolLoginsByMonthCardView() {\n const requestFilter = useGetRequestFilter('logins');\n\n const logins = Flight.useBasicFetch<LoginEventResponse>(LoginRequests.logins(requestFilter));\n\n const chartData = getChartData(logins.data?.data, requestFilter);\n\n return (\n <div className='d-flex flex-column h-100 bg-white rounded p-3 position-relative'>\n {chartData ?\n <>\n <h2 className='position-absolute h6 mb-1'><Text namespace={namespace} phrase='loginActivity' /></h2>\n\n <LineChart categories={chartData.categories} data={chartData.data} />\n </> :\n <div className='partial-loading-background w-25'>&nbsp;</div>}\n </div>\n );\n}\n",":local {\n %column {\n height: 30rem;\n }\n\n .column1 {\n @extend %column;\n flex: 3 0;\n }\n \n .column2 {\n @extend %column;\n flex: 4 0;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\n\nimport { useSetHeaderActions } from 'shared/hooks/UseSetHeaderActions';\nimport { useSetHeaderTitle } from 'shared/hooks/UseSetHeaderTitle';\nimport { getLoginHeaderActions } from 'shared/utils/HeaderActionUtils';\n\nimport { SchoolLoginsByGroupCardView } from 'apps/logins/views/cards/school-logins-by-group-card/SchoolLoginsByGroupCardView';\nimport { SchoolLoginsByMonthCardView } from 'apps/logins/views/cards/school-logins-by-month-card/SchoolLoginsByMonthCardView';\n\nimport styles from './school-login-overview.module.scss';\n\nconst namespace = 'logins.schoolLoginOverview';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function SchoolLoginOverview() {\n useSetPageMetadata({ title: getPhrase('title') });\n useSetHeaderTitle(getPhrase('title'));\n useSetHeaderActions(getLoginHeaderActions());\n\n return (\n <div>\n <div className='d-flex gap-3'>\n <div className={`${styles.column1}`}>\n <SchoolLoginsByGroupCardView />\n </div>\n <div className={`${styles.column2}`}>\n <SchoolLoginsByMonthCardView />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"2hBASa,EAAgB,CAC3B,OACE,EACA,EACA,EACA,EACgB,CAChB,MAAO,CACL,IAAK,EAAU,WAAW,gCAAiC,CACzD,GAAG,EACH,WAAY,EAAW,kBAAkB,CAC3C,CAAC,EACD,IAAK,EAAuB,SAAU,CAAM,EAC5C,UAAW,GACX,UACA,QACA,QACF,CACF,CACF,mCEnBM,EAAY,EAAgB,iBAAiB,iDAAS,EAI5D,SAAgB,GAAoC,CAClD,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAY,UAAU,8CAAtB,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CACE,IAAK,EAAU,YAAY,OAAO,OAClC,UAAW,EAAO,KACnB,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAoB,UAAU,cAC3B,EAAU,SAAS,CACF,CAAA,GACpB,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAiB,UAAU,iBACxB,EAAU,aAAa,CACT,CAAA,CACP,GAEhB,CCZA,IAAM,EAAY,iCAGlB,SAAgB,GAA8B,CAC5C,IAAM,EAAgB,EAAoB,QAAQ,EAE5C,EAAS,EAAyC,EAAc,OAAO,CAAa,CAAC,EAErF,EAAa,EAAc,EAE3B,EAAkB,GAAkB,IAAS,WAAa,IAAS,KAAQ,QAAU,EACrF,EAAyB,EAC7B,EAAO,MAAM,gBAAgB,IAAI,IAAU,CACzC,KAAM,EAAe,EAAM,IAAI,EAC/B,MAAO,EAAM,KACf,EAAE,CACJ,EACM,EAAmB,GAAwB,QAAQ,EAAK,IAAW,EAAM,EAAM,EAAI,CAAC,EAE1F,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+EACZ,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,oBACZ,EAAA,EAAA,IAAA,CAAC,EAAD,CACa,UAAA,EACX,OAAQ,EAAa,sBAAwB,cAC7C,QAAS,CAAE,OAAQ,CAAiB,CACrC,CAAA,CACC,CAAA,EAEH,EAAuB,QACtB,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CAAY,UAAU,8BACpB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,KAAM,CAAyB,CAAA,CAC9C,CAAA,CACK,CAAA,GACZ,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoC,CAAA,CAEtC,CAAA,CAAA,GACF,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2CAAkC,MAAW,CAAA,CAE3D,CAAA,CAET,CClDA,IAAM,EAAoB,CACxB,MAAO,GACP,KAAM,GACR,EAEM,EAAc,CAClB,IAAK,aACL,MAAO,UACP,KAAM,MACR,EAEM,EAAiB,CACrB,IAAK,QACL,MAAO,MACP,KAAM,MACR,EAeA,SAAS,EAAW,EAAgD,CAClE,IAAM,EAAQ,EAAW,YAAY,EAAc,IAAK,EAAc,MAAO,KAAK,EAQlF,OANI,EAAQ,EAAkB,KACrB,OAEL,EAAQ,EAAkB,MACrB,QAEF,KACT,CAEA,SAAS,EAAiB,EAAuC,EAA4B,CAC3F,IAAM,EAAkB,CAAC,EAEnB,EAAa,EAAW,kBAAkB,EAAc,KAAK,EAC7D,EAAW,EAAW,kBAAkB,EAAc,GAAG,EAE3D,EAAc,EAAW,OAAO,EAAY,EAAY,EAAQ,EAEpE,KAAO,CAAC,EAAW,QAAQ,EAAa,EAAU,CAAO,GACvD,EAAM,KAAK,CAAW,EACtB,EAAc,EAAW,OAAO,EAAW,IAAI,EAAa,EAAG,CAAO,EAAG,EAAY,EAAQ,EAG/F,OAAO,CACT,CAEA,SAAgB,EACd,EACA,EACW,CACX,GAAI,CAAC,EAAQ,OAAO,KAEpB,IAAM,EAAU,EAAW,CAAa,EAClC,EAAgB,EAAiB,EAAe,CAAO,EAEvD,EAA2B,CAAC,EAElC,EAAO,QAAQ,GAAM,CACnB,GAAI,CAAC,EAAG,SACN,OAEF,IAAM,EAAY,uBAAwB,GAAM,EAAG,oBAAsB,oBAAqB,GAAM,EAAG,gBACjG,EAAqB,EAAW,OAAO,EAAW,kBAAkB,CAAS,EAAG,EAAY,EAAQ,EAE1G,EAAQ,EAAG,UAAY,EAAQ,EAAG,WAAa,CAAC,EAChD,EAAQ,EAAG,SAAS,CAAC,GAAsB,EAAQ,EAAG,SAAS,CAAC,IAAuB,EACvF,EAAQ,EAAG,SAAS,CAAC,IAAuB,EAAG,KACjD,CAAC,EAED,IAAM,EAAQ,OAAO,KAAK,CAAO,EAOjC,OALK,EAAM,OAKJ,CACL,WAAY,EAAc,IAAI,GAAK,EAAW,OAAO,EAAG,EAAe,EAAQ,CAAC,EAChF,KACE,EAAY,OAAO,EAAM,IAAI,IAAM,CACjC,KAAM,EAAwB,CAAC,EAC/B,KAAM,OACN,KAAM,EAAc,IAAI,GAAK,EAAQ,EAAE,CAAC,IAAM,CAAC,EAC/C,MAAO,EAAyB,CAAC,CACnC,EAAE,EAAG,MAAM,CACf,EAd0B,CACxB,WAAY,EAAc,IAAI,GAAK,EAAW,OAAO,EAAG,EAAe,EAAQ,CAAC,EAChF,KAAM,CAAC,CACT,CAYF,CChGA,IAAM,EAAY,iCAGlB,SAAgB,GAA8B,CAC5C,IAAM,EAAgB,EAAoB,QAAQ,EAI5C,EAAY,EAFH,EAAyC,EAAc,OAAO,CAAa,CAE3D,CAAA,CAAO,MAAM,KAAM,CAAa,EAE/D,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2EACZ,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,sCAA4B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,YAAW,OAAO,eAAiB,CAAA,CAAK,CAAA,GAEnG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,WAAY,EAAU,WAAY,KAAM,EAAU,IAAO,CAAA,CACpE,CAAA,CAAA,GACF,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2CAAkC,MAAW,CAAA,CAC3D,CAAA,CAET,+DEjBM,EAAY,EAAgB,iBAAiB,4BAAS,EAE5D,SAAgB,GAAsB,CAKpC,OAJA,EAAmB,CAAE,MAAO,EAAU,OAAO,CAAE,CAAC,EAChD,EAAkB,EAAU,OAAO,CAAC,EACpC,EAAoB,EAAsB,CAAC,GAGzC,EAAA,EAAA,IAAA,CAAC,MAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wBAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,oBACxB,EAAA,EAAA,IAAA,CAAC,EAAD,CAA8B,CAAA,CAC3B,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,oBACxB,EAAA,EAAA,IAAA,CAAC,EAAD,CAA8B,CAAA,CAC3B,CAAA,CACF,GACF,CAAA,CAET"}
1
+ {"version":3,"file":"BBC0heb12.chunk.js","names":[],"sources":["../../src/shared/flight-requests/LoginRequests.ts","../../src/apps/logins/views/cards/school-logins-by-group-card/empty-state/school-logins-by-group-card-card-empty-state.module.scss","../../src/apps/logins/views/cards/school-logins-by-group-card/empty-state/SchoolLoginsByGroupCardEmptyState.tsx","../../src/apps/logins/views/cards/school-logins-by-group-card/SchoolLoginsByGroupCardView.tsx","../../src/shared/utils/LineChartByMonthUtils.ts","../../src/apps/logins/views/cards/school-logins-by-month-card/SchoolLoginsByMonthCardView.tsx","../../src/apps/logins/views/school-login-overview/school-login-overview.module.scss","../../src/apps/logins/views/school-login-overview/SchoolLoginOverview.tsx"],"sourcesContent":["import { Xhr } from 'libs/common/backbone/interfaces/Xhr';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { AnalyticsRequestFilter } from 'libs/shared/interfaces';\nimport { getAnalyticsRequestKey } from 'libs/shared/utils/AnalyticsRequestUtils';\n\nexport const LoginRequests = {\n logins(\n filter: AnalyticsRequestFilter,\n success?: (data: LoginEventResponse) => void,\n error?: (xhr: Xhr) => void,\n always?: () => void\n ): Flight.Request {\n return {\n url: UrlHelper.urlBuilder('{gateway}/v1/analytics/logins', {\n ...filter,\n timeOffset: DateHelper.getTimezoneOffset()\n }),\n key: getAnalyticsRequestKey('logins', filter),\n normalize: false,\n success,\n error,\n always\n };\n }\n};\n",":local {\n .image {\n width: 200px;\n height: auto;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { EmptyState } from 'libs/shared/components/empty-states/EmptyState';\n\nimport { ImageUrls } from 'shared/constants/ReportsImageUrls';\n\nconst namespace = 'reportsShared.schoolLoginsByGroupCardEmptyState';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nimport styles from './school-logins-by-group-card-card-empty-state.module.scss';\n\nexport function SchoolLoginsByGroupCardEmptyState() {\n return (\n <EmptyState className='flex-grow-1 justify-content-center'>\n <EmptyState.Image\n src={ImageUrls.EmptyStates.Shared.School}\n className={styles.image}\n />\n <EmptyState.Heading className='h6'>\n {getPhrase('heading')}\n </EmptyState.Heading>\n <EmptyState.Info className='w-100'>\n {getPhrase('description')}\n </EmptyState.Info>\n </EmptyState>\n );\n}\n","import React from 'react';\nimport { Scrollbars } from 'react-custom-scrollbars-2';\n\nimport { Flight } from 'libs/common/react/index';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { Text } from 'libs/shared/components/text/Text';\n\nimport { VerticalBarChart } from 'shared/components/vertical-bar-chart/VerticalBarChart';\nimport { LoginRequests } from 'shared/flight-requests/LoginRequests';\nimport { useGetRequestFilter } from 'shared/hooks/UseGetFilterQueryParams';\nimport { useIsTertiary } from 'shared/hooks/useIsTertiary';\nimport { getCountByGroup } from 'shared/utils/BarChartByGroupUtils';\n\nimport { SchoolLoginsByGroupCardEmptyState } from './empty-state/SchoolLoginsByGroupCardEmptyState';\n\nconst namespace = 'logins.schoolLoginsByGroupCard';\n\n// eslint-disable-next-line rulesdir/require-view-title\nexport function SchoolLoginsByGroupCardView() {\n const requestFilter = useGetRequestFilter('logins');\n\n const logins = Flight.useBasicFetch<LoginEventResponse>(LoginRequests.logins(requestFilter));\n \n const isTertiary = useIsTertiary();\n\n const mapNameToGroup = (name: string) => (name === 'Unknown' || name === null) ? 'Staff' : name;\n const totalLoginsByGroupData = getCountByGroup(\n logins.data?.yearGroupCount?.map(group => ({\n name: mapNameToGroup(group.name),\n count: group.count\n }))\n );\n const totalLoginsCount = totalLoginsByGroupData?.reduce((acc, group) => (acc + group.y), 0);\n\n return (\n <div className='d-flex flex-column h-100 bg-white overflow-hidden rounded pt-3 px-3'>\n {totalLoginsByGroupData ?\n <>\n <h2 className='h6 mb-1'>\n <Text\n namespace={namespace}\n phrase={isTertiary ? 'totalLoginsTertiary' : 'totalLogins'}\n options={{ logins: totalLoginsCount }}\n />\n </h2>\n\n {totalLoginsByGroupData.length ?\n <Scrollbars className='position-relative'>\n <div className='position-absolute w-100'>\n <VerticalBarChart data={totalLoginsByGroupData} />\n </div>\n </Scrollbars> :\n <SchoolLoginsByGroupCardEmptyState />\n }\n </> :\n <div className='partial-loading-background w-50'>&nbsp;</div>\n }\n </div>\n );\n}\n","import { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { LoginEvent } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { VideoViewEvent } from 'libs/shared/apps/analytics/interfaces/VideoViewEvent';\nimport { UserGroup } from 'libs/shared/enums/UserGroup';\nimport { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nimport { mapUserTypeToChartColour, mapUserTypeToChartLabel } from 'shared/utils/UserUtils';\n\nconst GroupByThresholds = {\n MONTH: 35,\n YEAR: 365\n};\n\nconst DateFormats = {\n day: 'YYYY-MM-DD',\n month: 'YYYY-MM',\n year: 'YYYY'\n};\n\nconst DisplayFormats = {\n day: 'D MMM',\n month: 'MMM',\n year: 'YYYY'\n};\n\ntype GroupedViewData = {\n [key in UserGroup]?: {\n [date: string]: number\n }\n};\n\ntype GroupBy = 'day' | 'month' | 'year';\n\ninterface ChartData {\n categories: string[];\n data: Highcharts.SeriesLineOptions[];\n}\n\nfunction getGroupBy(requestFilter: AnalyticsRequestFilter): GroupBy {\n const range = DateHelper.diffBetween(requestFilter.end, requestFilter.start, 'day');\n\n if (range > GroupByThresholds.YEAR)\n return 'year';\n\n if (range > GroupByThresholds.MONTH)\n return 'month';\n\n return 'day';\n}\n\nfunction getFullDateRange(requestFilter: AnalyticsRequestFilter, groupBy: GroupBy): string[] {\n const range: string[] = [];\n\n const localStart = DateHelper.convertUTCToLocal(requestFilter.start);\n const localEnd = DateHelper.convertUTCToLocal(requestFilter.end);\n\n let currentDate = DateHelper.format(localStart, DateFormats[groupBy]);\n\n while (!DateHelper.isAfter(currentDate, localEnd, groupBy)) {\n range.push(currentDate);\n currentDate = DateHelper.format(DateHelper.add(currentDate, 1, groupBy), DateFormats[groupBy]);\n }\n\n return range;\n}\n\nexport function getChartData(\n events: VideoViewEvent[] | LoginEvent[],\n requestFilter: AnalyticsRequestFilter\n): ChartData {\n if (!events) return null;\n\n const groupBy = getGroupBy(requestFilter);\n const fullDateRange = getFullDateRange(requestFilter, groupBy);\n \n const grouped: GroupedViewData = {};\n\n events.forEach(ev => {\n if (!ev.userType)\n return;\n\n const eventDate = 'groupedDateWatched' in ev && ev.groupedDateWatched || 'groupedLoggedOn' in ev && ev.groupedLoggedOn;\n const eventDateFormatted = DateHelper.format(DateHelper.convertUTCToLocal(eventDate), DateFormats[groupBy]);\n\n grouped[ev.userType] = grouped[ev.userType] ?? {};\n grouped[ev.userType][eventDateFormatted] = grouped[ev.userType][eventDateFormatted] ?? 0;\n grouped[ev.userType][eventDateFormatted] += ev.count;\n });\n\n const roles = Object.keys(grouped) as UserGroup[];\n\n if (!roles.length) return {\n categories: fullDateRange.map(d => DateHelper.format(d, DisplayFormats[groupBy])),\n data: []\n };\n\n return {\n categories: fullDateRange.map(d => DateHelper.format(d, DisplayFormats[groupBy])),\n data:\n ArrayHelper.sortBy(roles.map(r => ({\n name: mapUserTypeToChartLabel(r),\n type: 'line',\n data: fullDateRange.map(d => grouped[r][d] ?? 0),\n color: mapUserTypeToChartColour(r)\n })), 'name')\n };\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/react/index';\n\nimport { LoginEventResponse } from 'libs/shared/apps/analytics/interfaces/LoginEvent';\nimport { Text } from 'libs/shared/components/text/Text';\n\nimport { LineChart } from 'shared/components/line-chart/LineChart';\nimport { LoginRequests } from 'shared/flight-requests/LoginRequests';\nimport { useGetRequestFilter } from 'shared/hooks/UseGetFilterQueryParams';\nimport { getChartData } from 'shared/utils/LineChartByMonthUtils';\n\nconst namespace = 'logins.schoolLoginsByMonthCard';\n\n// eslint-disable-next-line rulesdir/require-view-title\nexport function SchoolLoginsByMonthCardView() {\n const requestFilter = useGetRequestFilter('logins');\n\n const logins = Flight.useBasicFetch<LoginEventResponse>(LoginRequests.logins(requestFilter));\n\n const chartData = getChartData(logins.data?.data, requestFilter);\n\n return (\n <div className='d-flex flex-column h-100 bg-white rounded p-3 position-relative'>\n {chartData ?\n <>\n <h2 className='position-absolute h6 mb-1'><Text namespace={namespace} phrase='loginActivity' /></h2>\n\n <LineChart categories={chartData.categories} data={chartData.data} />\n </> :\n <div className='partial-loading-background w-25'>&nbsp;</div>}\n </div>\n );\n}\n",":local {\n %column {\n height: 30rem;\n }\n\n .column1 {\n @extend %column;\n flex: 3 0;\n }\n \n .column2 {\n @extend %column;\n flex: 4 0;\n }\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\n\nimport { useSetHeaderActions } from 'shared/hooks/UseSetHeaderActions';\nimport { useSetHeaderTitle } from 'shared/hooks/UseSetHeaderTitle';\nimport { getLoginHeaderActions } from 'shared/utils/HeaderActionUtils';\n\nimport { SchoolLoginsByGroupCardView } from 'apps/logins/views/cards/school-logins-by-group-card/SchoolLoginsByGroupCardView';\nimport { SchoolLoginsByMonthCardView } from 'apps/logins/views/cards/school-logins-by-month-card/SchoolLoginsByMonthCardView';\n\nimport styles from './school-login-overview.module.scss';\n\nconst namespace = 'logins.schoolLoginOverview';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function SchoolLoginOverview() {\n useSetPageMetadata({ title: getPhrase('title') });\n useSetHeaderTitle(getPhrase('title'));\n useSetHeaderActions(getLoginHeaderActions());\n\n return (\n <div>\n <div className='d-flex gap-3'>\n <div className={`${styles.column1}`}>\n <SchoolLoginsByGroupCardView />\n </div>\n <div className={`${styles.column2}`}>\n <SchoolLoginsByMonthCardView />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"2hBASa,EAAgB,CAC3B,OACE,EACA,EACA,EACA,EACgB,CAChB,MAAO,CACL,IAAK,EAAU,WAAW,gCAAiC,CACzD,GAAG,EACH,WAAY,EAAW,kBAAkB,CAC3C,CAAC,EACD,IAAK,EAAuB,SAAU,CAAM,EAC5C,UAAW,GACX,UACA,QACA,QACF,CACF,CACF,mCEnBM,EAAY,EAAgB,iBAAiB,iDAAS,EAI5D,SAAgB,GAAoC,CAClD,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAY,UAAU,8CAAtB,EACE,EAAA,EAAA,IAAA,CAAC,EAAW,MAAZ,CACE,IAAK,EAAU,YAAY,OAAO,OAClC,UAAW,EAAO,KACnB,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAW,QAAZ,CAAoB,UAAU,cAC3B,EAAU,SAAS,CACF,CAAA,GACpB,EAAA,EAAA,IAAA,CAAC,EAAW,KAAZ,CAAiB,UAAU,iBACxB,EAAU,aAAa,CACT,CAAA,CACP,GAEhB,CCZA,IAAM,EAAY,iCAGlB,SAAgB,GAA8B,CAC5C,IAAM,EAAgB,EAAoB,QAAQ,EAE5C,EAAS,EAAyC,EAAc,OAAO,CAAa,CAAC,EAErF,EAAa,EAAc,EAE3B,EAAkB,GAAkB,IAAS,WAAa,IAAS,KAAQ,QAAU,EACrF,EAAyB,EAC7B,EAAO,MAAM,gBAAgB,IAAI,IAAU,CACzC,KAAM,EAAe,EAAM,IAAI,EAC/B,MAAO,EAAM,KACf,EAAE,CACJ,EACM,EAAmB,GAAwB,QAAQ,EAAK,IAAW,EAAM,EAAM,EAAI,CAAC,EAE1F,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+EACZ,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,oBACZ,EAAA,EAAA,IAAA,CAAC,EAAD,CACa,UAAA,EACX,OAAQ,EAAa,sBAAwB,cAC7C,QAAS,CAAE,OAAQ,CAAiB,CACrC,CAAA,CACC,CAAA,EAEH,EAAuB,QACtB,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CAAY,UAAU,8BACpB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,KAAM,CAAyB,CAAA,CAC9C,CAAA,CACK,CAAA,GACZ,EAAA,EAAA,IAAA,CAAC,EAAD,CAAoC,CAAA,CAEtC,CAAA,CAAA,GACF,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2CAAkC,MAAW,CAAA,CAE3D,CAAA,CAET,CClDA,IAAM,EAAoB,CACxB,MAAO,GACP,KAAM,GACR,EAEM,EAAc,CAClB,IAAK,aACL,MAAO,UACP,KAAM,MACR,EAEM,EAAiB,CACrB,IAAK,QACL,MAAO,MACP,KAAM,MACR,EAeA,SAAS,EAAW,EAAgD,CAClE,IAAM,EAAQ,EAAW,YAAY,EAAc,IAAK,EAAc,MAAO,KAAK,EAQlF,OANI,EAAQ,EAAkB,KACrB,OAEL,EAAQ,EAAkB,MACrB,QAEF,KACT,CAEA,SAAS,EAAiB,EAAuC,EAA4B,CAC3F,IAAM,EAAkB,CAAC,EAEnB,EAAa,EAAW,kBAAkB,EAAc,KAAK,EAC7D,EAAW,EAAW,kBAAkB,EAAc,GAAG,EAE3D,EAAc,EAAW,OAAO,EAAY,EAAY,EAAQ,EAEpE,KAAO,CAAC,EAAW,QAAQ,EAAa,EAAU,CAAO,GACvD,EAAM,KAAK,CAAW,EACtB,EAAc,EAAW,OAAO,EAAW,IAAI,EAAa,EAAG,CAAO,EAAG,EAAY,EAAQ,EAG/F,OAAO,CACT,CAEA,SAAgB,EACd,EACA,EACW,CACX,GAAI,CAAC,EAAQ,OAAO,KAEpB,IAAM,EAAU,EAAW,CAAa,EAClC,EAAgB,EAAiB,EAAe,CAAO,EAEvD,EAA2B,CAAC,EAElC,EAAO,QAAQ,GAAM,CACnB,GAAI,CAAC,EAAG,SACN,OAEF,IAAM,EAAY,uBAAwB,GAAM,EAAG,oBAAsB,oBAAqB,GAAM,EAAG,gBACjG,EAAqB,EAAW,OAAO,EAAW,kBAAkB,CAAS,EAAG,EAAY,EAAQ,EAE1G,EAAQ,EAAG,UAAY,EAAQ,EAAG,WAAa,CAAC,EAChD,EAAQ,EAAG,SAAS,CAAC,GAAsB,EAAQ,EAAG,SAAS,CAAC,IAAuB,EACvF,EAAQ,EAAG,SAAS,CAAC,IAAuB,EAAG,KACjD,CAAC,EAED,IAAM,EAAQ,OAAO,KAAK,CAAO,EAOjC,OALK,EAAM,OAKJ,CACL,WAAY,EAAc,IAAI,GAAK,EAAW,OAAO,EAAG,EAAe,EAAQ,CAAC,EAChF,KACE,EAAY,OAAO,EAAM,IAAI,IAAM,CACjC,KAAM,EAAwB,CAAC,EAC/B,KAAM,OACN,KAAM,EAAc,IAAI,GAAK,EAAQ,EAAE,CAAC,IAAM,CAAC,EAC/C,MAAO,EAAyB,CAAC,CACnC,EAAE,EAAG,MAAM,CACf,EAd0B,CACxB,WAAY,EAAc,IAAI,GAAK,EAAW,OAAO,EAAG,EAAe,EAAQ,CAAC,EAChF,KAAM,CAAC,CACT,CAYF,CChGA,IAAM,EAAY,iCAGlB,SAAgB,GAA8B,CAC5C,IAAM,EAAgB,EAAoB,QAAQ,EAI5C,EAAY,EAFH,EAAyC,EAAc,OAAO,CAAa,CAE3D,CAAA,CAAO,MAAM,KAAM,CAAa,EAE/D,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2EACZ,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,sCAA4B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,YAAW,OAAO,eAAiB,CAAA,CAAK,CAAA,GAEnG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,WAAY,EAAU,WAAY,KAAM,EAAU,IAAO,CAAA,CACpE,CAAA,CAAA,GACF,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2CAAkC,MAAW,CAAA,CAC3D,CAAA,CAET,+DEjBM,EAAY,EAAgB,iBAAiB,4BAAS,EAE5D,SAAgB,GAAsB,CAKpC,OAJA,EAAmB,CAAE,MAAO,EAAU,OAAO,CAAE,CAAC,EAChD,EAAkB,EAAU,OAAO,CAAC,EACpC,EAAoB,EAAsB,CAAC,GAGzC,EAAA,EAAA,IAAA,CAAC,MAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wBAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,oBACxB,EAAA,EAAA,IAAA,CAAC,EAAD,CAA8B,CAAA,CAC3B,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,oBACxB,EAAA,EAAA,IAAA,CAAC,EAAD,CAA8B,CAAA,CAC3B,CAAA,CACF,GACF,CAAA,CAET"}
@@ -1,2 +1,2 @@
1
- import{Dr as e,N as t,at as n,it as r}from"./CrTgNROp.chunk.js";import{h as i}from"./Dwe-4MVf.chunk.js";import{t as a}from"./o2slFZEB.chunk.js";import"./HeoWyBUD.chunk.js";import"./app-F8o5al1q.js";var o=e(n()),s=e(r()),c=(function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},e(t,n)};return function(t,n){e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}})(),l=`html`,u=`svg`,d=`http://www.w3.org/2000/svg`,f=function(e,t){if(t===l)return e instanceof HTMLElement;if(t===u)return e instanceof SVGElement;throw Error(`Unrecognized element type "`+t+`" for validateElementType.`)},p=function(e,t){var n={},r,i,a;if(e===l)a=document.createElement(`div`);else if(e===u)a=document.createElementNS(d,`g`);else throw Error(`Invalid element type "`+e+`" for createPortalNode: must be "html" or "svg".`);if(t&&typeof t==`object`)for(var o=0,s=Object.entries(t.attributes);o<s.length;o++){var c=s[o],p=c[0],m=c[1];a.setAttribute(p,m)}var h={element:a,elementType:e,setPortalProps:function(e){n=e},getInitialPortalProps:function(){return n},mount:function(t,n){if(n!==i){if(h.unmount(),t!==r&&!f(t,e))throw Error(`Invalid element type for portal: "`+e+`" portalNodes must be used with `+e+` elements, but OutPortal is within <`+t.tagName+`>.`);t.replaceChild(h.element,n),r=t,i=n}},unmount:function(e){e&&e!==i||r&&i&&(r.replaceChild(i,h.element),r=void 0,i=void 0)}};return h},m=function(e){c(t,e);function t(t){var n=e.call(this,t)||this;return n.addPropsChannel=function(){Object.assign(n.props.node,{setPortalProps:function(e){n.setState({nodeProps:e})}})},n.state={nodeProps:n.props.node.getInitialPortalProps()},n}return t.prototype.componentDidMount=function(){this.addPropsChannel()},t.prototype.componentDidUpdate=function(){this.addPropsChannel()},t.prototype.render=function(){var e=this,t=this.props,n=t.children,r=t.node;return s.createPortal(o.Children.map(n,function(t){return o.isValidElement(t)?o.cloneElement(t,e.state.nodeProps):t}),r.element)},t}(o.PureComponent),h=function(e){c(t,e);function t(t){var n=e.call(this,t)||this;return n.placeholderNode=o.createRef(),n.passPropsThroughPortal(),n}return t.prototype.passPropsThroughPortal=function(){var e=Object.assign({},this.props,{node:void 0});this.props.node.setPortalProps(e)},t.prototype.componentDidMount=function(){var e=this.props.node;this.currentPortalNode=e;var t=this.placeholderNode.current,n=t.parentNode;e.mount(n,t),this.passPropsThroughPortal()},t.prototype.componentDidUpdate=function(){var e=this.props.node;this.currentPortalNode&&e!==this.currentPortalNode&&(this.currentPortalNode.unmount(this.placeholderNode.current),this.currentPortalNode.setPortalProps({}),this.currentPortalNode=e);var t=this.placeholderNode.current,n=t.parentNode;e.mount(n,t),this.passPropsThroughPortal()},t.prototype.componentWillUnmount=function(){var e=this.props.node;e.unmount(this.placeholderNode.current),e.setPortalProps({})},t.prototype.render=function(){return o.createElement(`div`,{ref:this.placeholderNode})},t}(o.PureComponent),g=p.bind(null,l);p.bind(null,u),t();var _=o.createContext({hasProvider:!1});function v(){return o.useContext(_)}var y=50;function b(e,t){let n=i(a.chunk(e,y).map(e=>t(a.uniq(e)))),r=a.flatten(n.data);return{itemsArr:r,items:n.data.length?r.reduce((e,t)=>({...e,[t.id]:t}),{}):null,isFetching:n.isFetching,hasCompleted:n.hasCompleted}}function x(e,t,n){let r=n??(e=>typeof e==`object`?e.id:e),{fetchItems:i,...a}=S({getRequest:t,_getKey:n});return o.useEffect(()=>{e?.length&&i(e)},[e?.map(r).join(`,`)]),a}function S(e){let t=e._getKey??(e=>typeof e==`object`?e.id:e),n=o.useRef(new Set),[r,s]=o.useState([]);function c(r){if(!r?.length)return;let i=[];r.forEach(e=>{let r=t(e);n.current.has(r)||(i.push(e),n.current.add(r))}),i.length&&s(t=>[...t,...a.chunk(i,y).map(e.getRequest)])}let l=i(r),u=a.flatten(l.data),d=l.data.length?u.reduce((e,n)=>({...e,[t(n)]:n}),{}):null;return{hasFirstRequestCompleted:!!l.responses?.[0]?.hasCompleted,itemsArr:u,items:d,isFetching:l.isFetching,fetchItems:c}}export{h as a,m as i,x as n,g as o,v as r,b as t};
2
- //# sourceMappingURL=BcjF3S7y.chunk.js.map
1
+ import{Dr as e,N as t,at as n,it as r}from"./CrTgNROp.chunk.js";import{h as i}from"./Dwe-4MVf.chunk.js";import{t as a}from"./o2slFZEB.chunk.js";import"./HeoWyBUD.chunk.js";import"./app-DW-nP8r1.js";var o=e(n()),s=e(r()),c=(function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},e(t,n)};return function(t,n){e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}})(),l=`html`,u=`svg`,d=`http://www.w3.org/2000/svg`,f=function(e,t){if(t===l)return e instanceof HTMLElement;if(t===u)return e instanceof SVGElement;throw Error(`Unrecognized element type "`+t+`" for validateElementType.`)},p=function(e,t){var n={},r,i,a;if(e===l)a=document.createElement(`div`);else if(e===u)a=document.createElementNS(d,`g`);else throw Error(`Invalid element type "`+e+`" for createPortalNode: must be "html" or "svg".`);if(t&&typeof t==`object`)for(var o=0,s=Object.entries(t.attributes);o<s.length;o++){var c=s[o],p=c[0],m=c[1];a.setAttribute(p,m)}var h={element:a,elementType:e,setPortalProps:function(e){n=e},getInitialPortalProps:function(){return n},mount:function(t,n){if(n!==i){if(h.unmount(),t!==r&&!f(t,e))throw Error(`Invalid element type for portal: "`+e+`" portalNodes must be used with `+e+` elements, but OutPortal is within <`+t.tagName+`>.`);t.replaceChild(h.element,n),r=t,i=n}},unmount:function(e){e&&e!==i||r&&i&&(r.replaceChild(i,h.element),r=void 0,i=void 0)}};return h},m=function(e){c(t,e);function t(t){var n=e.call(this,t)||this;return n.addPropsChannel=function(){Object.assign(n.props.node,{setPortalProps:function(e){n.setState({nodeProps:e})}})},n.state={nodeProps:n.props.node.getInitialPortalProps()},n}return t.prototype.componentDidMount=function(){this.addPropsChannel()},t.prototype.componentDidUpdate=function(){this.addPropsChannel()},t.prototype.render=function(){var e=this,t=this.props,n=t.children,r=t.node;return s.createPortal(o.Children.map(n,function(t){return o.isValidElement(t)?o.cloneElement(t,e.state.nodeProps):t}),r.element)},t}(o.PureComponent),h=function(e){c(t,e);function t(t){var n=e.call(this,t)||this;return n.placeholderNode=o.createRef(),n.passPropsThroughPortal(),n}return t.prototype.passPropsThroughPortal=function(){var e=Object.assign({},this.props,{node:void 0});this.props.node.setPortalProps(e)},t.prototype.componentDidMount=function(){var e=this.props.node;this.currentPortalNode=e;var t=this.placeholderNode.current,n=t.parentNode;e.mount(n,t),this.passPropsThroughPortal()},t.prototype.componentDidUpdate=function(){var e=this.props.node;this.currentPortalNode&&e!==this.currentPortalNode&&(this.currentPortalNode.unmount(this.placeholderNode.current),this.currentPortalNode.setPortalProps({}),this.currentPortalNode=e);var t=this.placeholderNode.current,n=t.parentNode;e.mount(n,t),this.passPropsThroughPortal()},t.prototype.componentWillUnmount=function(){var e=this.props.node;e.unmount(this.placeholderNode.current),e.setPortalProps({})},t.prototype.render=function(){return o.createElement(`div`,{ref:this.placeholderNode})},t}(o.PureComponent),g=p.bind(null,l);p.bind(null,u),t();var _=o.createContext({hasProvider:!1});function v(){return o.useContext(_)}var y=50;function b(e,t){let n=i(a.chunk(e,y).map(e=>t(a.uniq(e)))),r=a.flatten(n.data);return{itemsArr:r,items:n.data.length?r.reduce((e,t)=>({...e,[t.id]:t}),{}):null,isFetching:n.isFetching,hasCompleted:n.hasCompleted}}function x(e,t,n){let r=n??(e=>typeof e==`object`?e.id:e),{fetchItems:i,...a}=S({getRequest:t,_getKey:n});return o.useEffect(()=>{e?.length&&i(e)},[e?.map(r).join(`,`)]),a}function S(e){let t=e._getKey??(e=>typeof e==`object`?e.id:e),n=o.useRef(new Set),[r,s]=o.useState([]);function c(r){if(!r?.length)return;let i=[];r.forEach(e=>{let r=t(e);n.current.has(r)||(i.push(e),n.current.add(r))}),i.length&&s(t=>[...t,...a.chunk(i,y).map(e.getRequest)])}let l=i(r),u=a.flatten(l.data),d=l.data.length?u.reduce((e,n)=>({...e,[t(n)]:n}),{}):null;return{hasFirstRequestCompleted:!!l.responses?.[0]?.hasCompleted,itemsArr:u,items:d,isFetching:l.isFetching,fetchItems:c}}export{h as a,m as i,x as n,g as o,v as r,b as t};
2
+ //# sourceMappingURL=BBromGRt.chunk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BcjF3S7y.chunk.js","names":[],"sources":["../../../../../node_modules/react-reverse-portal/dist/web/index.js","../../../../libs/shared/src/context/player-context/PlayerContext.tsx","../../../../libs/shared/src/hooks/UseBatchFetch.ts"],"sourcesContent":["var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nimport * as React from 'react';\nimport * as ReactDOM from 'react-dom';\n// Internally, the portalNode must be for either HTML or SVG elements\nvar ELEMENT_TYPE_HTML = 'html';\nvar ELEMENT_TYPE_SVG = 'svg';\n// ReactDOM can handle several different namespaces, but they're not exported publicly\n// https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/shared/DOMNamespaces.js#L8-L10\nvar SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\nvar validateElementType = function (domElement, elementType) {\n if (elementType === ELEMENT_TYPE_HTML) {\n return domElement instanceof HTMLElement;\n }\n if (elementType === ELEMENT_TYPE_SVG) {\n return domElement instanceof SVGElement;\n }\n throw new Error(\"Unrecognized element type \\\"\" + elementType + \"\\\" for validateElementType.\");\n};\n// This is the internal implementation: the public entry points set elementType to an appropriate value\nvar createPortalNode = function (elementType, options) {\n var initialProps = {};\n var parent;\n var lastPlaceholder;\n var element;\n if (elementType === ELEMENT_TYPE_HTML) {\n element = document.createElement('div');\n }\n else if (elementType === ELEMENT_TYPE_SVG) {\n element = document.createElementNS(SVG_NAMESPACE, 'g');\n }\n else {\n throw new Error(\"Invalid element type \\\"\" + elementType + \"\\\" for createPortalNode: must be \\\"html\\\" or \\\"svg\\\".\");\n }\n if (options && typeof options === \"object\") {\n for (var _i = 0, _a = Object.entries(options.attributes); _i < _a.length; _i++) {\n var _b = _a[_i], key = _b[0], value = _b[1];\n element.setAttribute(key, value);\n }\n }\n var portalNode = {\n element: element,\n elementType: elementType,\n setPortalProps: function (props) {\n initialProps = props;\n },\n getInitialPortalProps: function () {\n return initialProps;\n },\n mount: function (newParent, newPlaceholder) {\n if (newPlaceholder === lastPlaceholder) {\n // Already mounted - noop.\n return;\n }\n portalNode.unmount();\n // To support SVG and other non-html elements, the portalNode's elementType needs to match\n // the elementType it's being rendered into\n if (newParent !== parent) {\n if (!validateElementType(newParent, elementType)) {\n throw new Error(\"Invalid element type for portal: \\\"\" + elementType + \"\\\" portalNodes must be used with \" + elementType + \" elements, but OutPortal is within <\" + newParent.tagName + \">.\");\n }\n }\n newParent.replaceChild(portalNode.element, newPlaceholder);\n parent = newParent;\n lastPlaceholder = newPlaceholder;\n },\n unmount: function (expectedPlaceholder) {\n if (expectedPlaceholder && expectedPlaceholder !== lastPlaceholder) {\n // Skip unmounts for placeholders that aren't currently mounted\n // They will have been automatically unmounted already by a subsequent mount()\n return;\n }\n if (parent && lastPlaceholder) {\n parent.replaceChild(lastPlaceholder, portalNode.element);\n parent = undefined;\n lastPlaceholder = undefined;\n }\n }\n };\n return portalNode;\n};\nvar InPortal = /** @class */ (function (_super) {\n __extends(InPortal, _super);\n function InPortal(props) {\n var _this = _super.call(this, props) || this;\n _this.addPropsChannel = function () {\n Object.assign(_this.props.node, {\n setPortalProps: function (props) {\n // Rerender the child node here if/when the out portal props change\n _this.setState({ nodeProps: props });\n }\n });\n };\n _this.state = {\n nodeProps: _this.props.node.getInitialPortalProps(),\n };\n return _this;\n }\n InPortal.prototype.componentDidMount = function () {\n this.addPropsChannel();\n };\n InPortal.prototype.componentDidUpdate = function () {\n this.addPropsChannel();\n };\n InPortal.prototype.render = function () {\n var _this = this;\n var _a = this.props, children = _a.children, node = _a.node;\n return ReactDOM.createPortal(React.Children.map(children, function (child) {\n if (!React.isValidElement(child))\n return child;\n return React.cloneElement(child, _this.state.nodeProps);\n }), node.element);\n };\n return InPortal;\n}(React.PureComponent));\nvar OutPortal = /** @class */ (function (_super) {\n __extends(OutPortal, _super);\n function OutPortal(props) {\n var _this = _super.call(this, props) || this;\n _this.placeholderNode = React.createRef();\n _this.passPropsThroughPortal();\n return _this;\n }\n OutPortal.prototype.passPropsThroughPortal = function () {\n var propsForTarget = Object.assign({}, this.props, { node: undefined });\n this.props.node.setPortalProps(propsForTarget);\n };\n OutPortal.prototype.componentDidMount = function () {\n var node = this.props.node;\n this.currentPortalNode = node;\n var placeholder = this.placeholderNode.current;\n var parent = placeholder.parentNode;\n node.mount(parent, placeholder);\n this.passPropsThroughPortal();\n };\n OutPortal.prototype.componentDidUpdate = function () {\n // We re-mount on update, just in case we were unmounted (e.g. by\n // a second OutPortal, which has now been removed)\n var node = this.props.node;\n // If we're switching portal nodes, we need to clean up the current one first.\n if (this.currentPortalNode && node !== this.currentPortalNode) {\n this.currentPortalNode.unmount(this.placeholderNode.current);\n this.currentPortalNode.setPortalProps({});\n this.currentPortalNode = node;\n }\n var placeholder = this.placeholderNode.current;\n var parent = placeholder.parentNode;\n node.mount(parent, placeholder);\n this.passPropsThroughPortal();\n };\n OutPortal.prototype.componentWillUnmount = function () {\n var node = this.props.node;\n node.unmount(this.placeholderNode.current);\n node.setPortalProps({});\n };\n OutPortal.prototype.render = function () {\n // Render a placeholder to the DOM, so we can get a reference into\n // our location in the DOM, and swap it out for the portaled node.\n // A <div> placeholder works fine even for SVG.\n return React.createElement(\"div\", { ref: this.placeholderNode });\n };\n return OutPortal;\n}(React.PureComponent));\nvar createHtmlPortalNode = createPortalNode.bind(null, ELEMENT_TYPE_HTML);\nvar createSvgPortalNode = createPortalNode.bind(null, ELEMENT_TYPE_SVG);\nexport { createHtmlPortalNode, createSvgPortalNode, InPortal, OutPortal, };\n//# sourceMappingURL=index.js.map","import React from 'react';\nimport { createHtmlPortalNode, HtmlPortalNode } from 'react-reverse-portal';\n\nimport { LocalStorageHelper } from 'libs/common/backbone/utils/LocalStorageHelper';\n\nimport { DefaultDisplayMode, PlayerInitializationData } from 'libs/shared/context/player-context/interfaces/PlayerContextAction';\nimport { PlayerContextState } from 'libs/shared/context/player-context/interfaces/PlayerContextState';\nimport { PlayerMode } from 'libs/shared/context/player-context/interfaces/PlayerMode';\nimport { PlayerReference } from 'libs/shared/context/player-context/interfaces/PlayerReference';\nimport { playerContextReducer } from 'libs/shared/context/player-context/reducer/PlayerContextReducer';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\n\nconst _THEATRE_MODE = 'play-page-theatre-mode';\n\nexport interface PlayerContextValues extends PlayerContextState {\n playerRef?: React.MutableRefObject<PlayerReference>;\n portalNode?: HtmlPortalNode;\n questionListPortalNode?: HtmlPortalNode;\n\n useInitialize?: (initializeData: PlayerInitializationData) => void;\n dispose?: () => void;\n setPlayerRef?: (player: any) => void;\n setPlayerMode?: (mode: PlayerMode) => void;\n setDefaultDisplayMode?: (displayMode: DefaultDisplayMode) => void;\n setStarted?: (started: boolean) => void;\n setPersist?: () => void;\n\n /**\n * Tells components if an instance of <PlayerContextProvider /> exists\n * above them in the tree. I.e. When this is used in curator.\n */\n hasProvider: boolean;\n}\n\nconst PlayerContext = React.createContext<PlayerContextValues>({ hasProvider: false });\n\nexport function usePlayerContext() {\n return React.useContext(PlayerContext);\n}\n\nfunction getInitialState(): PlayerContextState {\n const hasSavedTheatreMode = LocalStorageHelper.get(_THEATRE_MODE);\n\n return {\n defaultDisplayMode: hasSavedTheatreMode ? 'theatre' : 'normal'\n };\n}\n\nexport function PlayerContextProvider(props: React.PropsWithChildren) {\n const [ state, dispatch ] = React.useReducer(playerContextReducer, getInitialState());\n const { hasPreviewVideos } = useSettings(null);\n\n const playerRef = React.useRef<any>(null);\n\n const portalNode = React.useMemo(() => createHtmlPortalNode(\n { attributes: { class: 'cv-theatre-mode-video-container' } }\n ), []);\n\n const questionListPortalNode = React.useMemo(createHtmlPortalNode, []);\n\n function setPlayerRef(player: PlayerReference) {\n playerRef.current = player;\n }\n\n function useInitialize(initializeData: PlayerInitializationData) {\n const enabled = hasPreviewVideos || initializeData.mode !== 'hover';\n\n React.useEffect(() => {\n if (!enabled)\n return;\n\n /**\n * Cannot initialize a hover player if we already have a player elsewhere.\n */\n if (initializeData.mode === 'hover' && state.mode)\n return;\n\n /**\n * No hover to play on interactives. This feature is ComingSoon™️ - Sha\n */\n if (initializeData.mode === 'hover' && initializeData.objectTypeId === MasterType.Interactive)\n return;\n\n dispatch({\n type: 'initialize',\n data: initializeData\n });\n\n return disposeInternal;\n }, []);\n }\n\n function setPlayerMode(mode: PlayerMode) {\n dispatch({ type: 'mode', data: { mode } });\n }\n\n function setDefaultDisplayMode(defaultDisplayMode: DefaultDisplayMode) {\n LocalStorageHelper.set(_THEATRE_MODE, defaultDisplayMode === 'theatre');\n\n dispatch({ type: 'defaultDisplayMode', data: { defaultDisplayMode } });\n }\n\n function setStarted(): void {\n dispatch({ type: 'started' });\n }\n\n function disposeInternal(force: boolean = false): void {\n if (force) {\n playerRef.current = null;\n }\n\n dispatch({ type: 'dispose', data: { force: force } });\n }\n\n function setPersist(): void {\n dispatch({ type: 'persist' });\n }\n\n /**\n * If anything external calls dispose, we ignore the persist flag and force a disposal\n */\n function dispose(): void {\n disposeInternal(true);\n }\n\n const playerContextValues: PlayerContextValues = {\n ...state,\n playerRef,\n setPlayerRef,\n portalNode,\n questionListPortalNode,\n useInitialize,\n setPlayerMode,\n setDefaultDisplayMode,\n setStarted,\n dispose,\n setPersist,\n hasProvider: true\n };\n\n return (\n <PlayerContext.Provider value={playerContextValues}>\n {props.children}\n </PlayerContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/flight';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { BaseObject } from 'libs/shared/interfaces';\n\nconst CHUNK_SIZE = 50;\n\nexport interface UseBatchFetchResult<T extends BaseObject> {\n itemsArr: T[];\n items: {[key: string]: T } | null;\n isFetching: boolean;\n hasCompleted: boolean;\n}\n\n/**\n * Used to fetch multiple items by id with Flight. Will fetch 25 items at a time firing off multiple\n * requests if there are more than 25 items.\n * This will return items as null until we have all our items. Items will be returned as an object with\n * their ids as they key for easy mapping\n * \n * @param itemIds \n * @param getRequest \n */\nexport function useBatchFetch<T extends BaseObject>(\n itemIds: string[],\n getRequest: (ids: string[]) => Flight.Request\n): UseBatchFetchResult<T> {\n const chunks = ArrayHelper.chunk<string>(itemIds, CHUNK_SIZE);\n\n const requests = chunks.map(chunk => getRequest(ArrayHelper.uniq(chunk)));\n\n const responses = Flight.useBasicFetchAll<T[]>(requests);\n\n const itemsArr = ArrayHelper.flatten(responses.data);\n const items = responses.data.length ?\n itemsArr.reduce((acc, item) => ({ ...acc, [item.id]: item }), {}) :\n null;\n\n return {\n itemsArr,\n items,\n isFetching: responses.isFetching,\n hasCompleted: responses.hasCompleted\n };\n}\n\n/**\n * When you need the useBatchFetch() behavior, but your list of objects to hydrate\n * will grow, such as on a scrolling page. useGrowingBatchFetch() will use local state\n * to determine what we've already built a request for and what items are new\n * as to not re-fetch items - Sha\n */\nexport function useGrowingBatchFetch<TResponse, TObjects = string>(\n objs: TObjects[],\n getRequest: (items: TObjects[]) => Flight.Request,\n _getKey?: (obj: TObjects) => string\n) {\n const getKey = _getKey ?? ((obj: any) => {\n if (typeof obj === 'object')\n return obj.id;\n\n return obj;\n });\n\n const { fetchItems, ...data } = useGrowingBatchFetchFunc<TResponse, TObjects>({ getRequest, _getKey });\n\n React.useEffect(() => {\n if (!objs?.length)\n return;\n\n fetchItems(objs);\n }, [objs?.map(getKey).join(',')]);\n\n return data;\n}\n\ninterface UseGrowingBatchFetchFuncOptions<TObjects> {\n getRequest: (items: TObjects[]) => Flight.Request;\n _getKey?: (obj: TObjects) => string;\n}\n\n/**\n * When you need the useGrowingBatchFetch() behaviour, but need to trigger the\n * fetch manually and update the objects - Nish \n */\nexport function useGrowingBatchFetchFunc<TResponse, TObjects = string>(\n options: UseGrowingBatchFetchFuncOptions<TObjects>\n) {\n const getKey = options._getKey ?? ((obj: any) => {\n if (typeof obj === 'object')\n return obj.id;\n\n return obj;\n });\n\n const fetchedItems = React.useRef<Set<string>>(new Set<string>());\n const [ requests, setRequests ] = React.useState<Flight.Request[]>([]);\n\n function fetchItems(objs: TObjects[]) {\n if (!objs?.length)\n return;\n\n const unfetchedItems: TObjects[] = [];\n \n objs.forEach(obj => {\n const key = getKey(obj);\n\n if (fetchedItems.current.has(key))\n return;\n\n unfetchedItems.push(obj);\n fetchedItems.current.add(key);\n });\n \n if (!unfetchedItems.length)\n return;\n \n setRequests(r => ([ ...r, ...ArrayHelper.chunk<TObjects>(unfetchedItems, CHUNK_SIZE).map(options.getRequest) ]));\n }\n\n const responses = Flight.useBasicFetchAll<TResponse[]>(requests);\n const itemsArr = ArrayHelper.flatten(responses.data);\n const items = responses.data.length ?\n itemsArr.reduce<Record<string, TResponse>>((acc, item) => ({ ...acc, [getKey(item)]: item }), {}) :\n null;\n\n return {\n hasFirstRequestCompleted: !!responses.responses?.[0]?.hasCompleted,\n itemsArr,\n items,\n isFetching: responses.isFetching,\n fetchItems\n };\n}\n"],"x_google_ignoreList":[0],"mappings":"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"}
1
+ {"version":3,"file":"BBromGRt.chunk.js","names":[],"sources":["../../../../../node_modules/react-reverse-portal/dist/web/index.js","../../../../libs/shared/src/context/player-context/PlayerContext.tsx","../../../../libs/shared/src/hooks/UseBatchFetch.ts"],"sourcesContent":["var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nimport * as React from 'react';\nimport * as ReactDOM from 'react-dom';\n// Internally, the portalNode must be for either HTML or SVG elements\nvar ELEMENT_TYPE_HTML = 'html';\nvar ELEMENT_TYPE_SVG = 'svg';\n// ReactDOM can handle several different namespaces, but they're not exported publicly\n// https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/shared/DOMNamespaces.js#L8-L10\nvar SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\nvar validateElementType = function (domElement, elementType) {\n if (elementType === ELEMENT_TYPE_HTML) {\n return domElement instanceof HTMLElement;\n }\n if (elementType === ELEMENT_TYPE_SVG) {\n return domElement instanceof SVGElement;\n }\n throw new Error(\"Unrecognized element type \\\"\" + elementType + \"\\\" for validateElementType.\");\n};\n// This is the internal implementation: the public entry points set elementType to an appropriate value\nvar createPortalNode = function (elementType, options) {\n var initialProps = {};\n var parent;\n var lastPlaceholder;\n var element;\n if (elementType === ELEMENT_TYPE_HTML) {\n element = document.createElement('div');\n }\n else if (elementType === ELEMENT_TYPE_SVG) {\n element = document.createElementNS(SVG_NAMESPACE, 'g');\n }\n else {\n throw new Error(\"Invalid element type \\\"\" + elementType + \"\\\" for createPortalNode: must be \\\"html\\\" or \\\"svg\\\".\");\n }\n if (options && typeof options === \"object\") {\n for (var _i = 0, _a = Object.entries(options.attributes); _i < _a.length; _i++) {\n var _b = _a[_i], key = _b[0], value = _b[1];\n element.setAttribute(key, value);\n }\n }\n var portalNode = {\n element: element,\n elementType: elementType,\n setPortalProps: function (props) {\n initialProps = props;\n },\n getInitialPortalProps: function () {\n return initialProps;\n },\n mount: function (newParent, newPlaceholder) {\n if (newPlaceholder === lastPlaceholder) {\n // Already mounted - noop.\n return;\n }\n portalNode.unmount();\n // To support SVG and other non-html elements, the portalNode's elementType needs to match\n // the elementType it's being rendered into\n if (newParent !== parent) {\n if (!validateElementType(newParent, elementType)) {\n throw new Error(\"Invalid element type for portal: \\\"\" + elementType + \"\\\" portalNodes must be used with \" + elementType + \" elements, but OutPortal is within <\" + newParent.tagName + \">.\");\n }\n }\n newParent.replaceChild(portalNode.element, newPlaceholder);\n parent = newParent;\n lastPlaceholder = newPlaceholder;\n },\n unmount: function (expectedPlaceholder) {\n if (expectedPlaceholder && expectedPlaceholder !== lastPlaceholder) {\n // Skip unmounts for placeholders that aren't currently mounted\n // They will have been automatically unmounted already by a subsequent mount()\n return;\n }\n if (parent && lastPlaceholder) {\n parent.replaceChild(lastPlaceholder, portalNode.element);\n parent = undefined;\n lastPlaceholder = undefined;\n }\n }\n };\n return portalNode;\n};\nvar InPortal = /** @class */ (function (_super) {\n __extends(InPortal, _super);\n function InPortal(props) {\n var _this = _super.call(this, props) || this;\n _this.addPropsChannel = function () {\n Object.assign(_this.props.node, {\n setPortalProps: function (props) {\n // Rerender the child node here if/when the out portal props change\n _this.setState({ nodeProps: props });\n }\n });\n };\n _this.state = {\n nodeProps: _this.props.node.getInitialPortalProps(),\n };\n return _this;\n }\n InPortal.prototype.componentDidMount = function () {\n this.addPropsChannel();\n };\n InPortal.prototype.componentDidUpdate = function () {\n this.addPropsChannel();\n };\n InPortal.prototype.render = function () {\n var _this = this;\n var _a = this.props, children = _a.children, node = _a.node;\n return ReactDOM.createPortal(React.Children.map(children, function (child) {\n if (!React.isValidElement(child))\n return child;\n return React.cloneElement(child, _this.state.nodeProps);\n }), node.element);\n };\n return InPortal;\n}(React.PureComponent));\nvar OutPortal = /** @class */ (function (_super) {\n __extends(OutPortal, _super);\n function OutPortal(props) {\n var _this = _super.call(this, props) || this;\n _this.placeholderNode = React.createRef();\n _this.passPropsThroughPortal();\n return _this;\n }\n OutPortal.prototype.passPropsThroughPortal = function () {\n var propsForTarget = Object.assign({}, this.props, { node: undefined });\n this.props.node.setPortalProps(propsForTarget);\n };\n OutPortal.prototype.componentDidMount = function () {\n var node = this.props.node;\n this.currentPortalNode = node;\n var placeholder = this.placeholderNode.current;\n var parent = placeholder.parentNode;\n node.mount(parent, placeholder);\n this.passPropsThroughPortal();\n };\n OutPortal.prototype.componentDidUpdate = function () {\n // We re-mount on update, just in case we were unmounted (e.g. by\n // a second OutPortal, which has now been removed)\n var node = this.props.node;\n // If we're switching portal nodes, we need to clean up the current one first.\n if (this.currentPortalNode && node !== this.currentPortalNode) {\n this.currentPortalNode.unmount(this.placeholderNode.current);\n this.currentPortalNode.setPortalProps({});\n this.currentPortalNode = node;\n }\n var placeholder = this.placeholderNode.current;\n var parent = placeholder.parentNode;\n node.mount(parent, placeholder);\n this.passPropsThroughPortal();\n };\n OutPortal.prototype.componentWillUnmount = function () {\n var node = this.props.node;\n node.unmount(this.placeholderNode.current);\n node.setPortalProps({});\n };\n OutPortal.prototype.render = function () {\n // Render a placeholder to the DOM, so we can get a reference into\n // our location in the DOM, and swap it out for the portaled node.\n // A <div> placeholder works fine even for SVG.\n return React.createElement(\"div\", { ref: this.placeholderNode });\n };\n return OutPortal;\n}(React.PureComponent));\nvar createHtmlPortalNode = createPortalNode.bind(null, ELEMENT_TYPE_HTML);\nvar createSvgPortalNode = createPortalNode.bind(null, ELEMENT_TYPE_SVG);\nexport { createHtmlPortalNode, createSvgPortalNode, InPortal, OutPortal, };\n//# sourceMappingURL=index.js.map","import React from 'react';\nimport { createHtmlPortalNode, HtmlPortalNode } from 'react-reverse-portal';\n\nimport { LocalStorageHelper } from 'libs/common/backbone/utils/LocalStorageHelper';\n\nimport { DefaultDisplayMode, PlayerInitializationData } from 'libs/shared/context/player-context/interfaces/PlayerContextAction';\nimport { PlayerContextState } from 'libs/shared/context/player-context/interfaces/PlayerContextState';\nimport { PlayerMode } from 'libs/shared/context/player-context/interfaces/PlayerMode';\nimport { PlayerReference } from 'libs/shared/context/player-context/interfaces/PlayerReference';\nimport { playerContextReducer } from 'libs/shared/context/player-context/reducer/PlayerContextReducer';\nimport { MasterType } from 'libs/shared/enums/MasterType';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\n\nconst _THEATRE_MODE = 'play-page-theatre-mode';\n\nexport interface PlayerContextValues extends PlayerContextState {\n playerRef?: React.MutableRefObject<PlayerReference>;\n portalNode?: HtmlPortalNode;\n questionListPortalNode?: HtmlPortalNode;\n\n useInitialize?: (initializeData: PlayerInitializationData) => void;\n dispose?: () => void;\n setPlayerRef?: (player: any) => void;\n setPlayerMode?: (mode: PlayerMode) => void;\n setDefaultDisplayMode?: (displayMode: DefaultDisplayMode) => void;\n setStarted?: (started: boolean) => void;\n setPersist?: () => void;\n\n /**\n * Tells components if an instance of <PlayerContextProvider /> exists\n * above them in the tree. I.e. When this is used in curator.\n */\n hasProvider: boolean;\n}\n\nconst PlayerContext = React.createContext<PlayerContextValues>({ hasProvider: false });\n\nexport function usePlayerContext() {\n return React.useContext(PlayerContext);\n}\n\nfunction getInitialState(): PlayerContextState {\n const hasSavedTheatreMode = LocalStorageHelper.get(_THEATRE_MODE);\n\n return {\n defaultDisplayMode: hasSavedTheatreMode ? 'theatre' : 'normal'\n };\n}\n\nexport function PlayerContextProvider(props: React.PropsWithChildren) {\n const [ state, dispatch ] = React.useReducer(playerContextReducer, getInitialState());\n const { hasPreviewVideos } = useSettings(null);\n\n const playerRef = React.useRef<any>(null);\n\n const portalNode = React.useMemo(() => createHtmlPortalNode(\n { attributes: { class: 'cv-theatre-mode-video-container' } }\n ), []);\n\n const questionListPortalNode = React.useMemo(createHtmlPortalNode, []);\n\n function setPlayerRef(player: PlayerReference) {\n playerRef.current = player;\n }\n\n function useInitialize(initializeData: PlayerInitializationData) {\n const enabled = hasPreviewVideos || initializeData.mode !== 'hover';\n\n React.useEffect(() => {\n if (!enabled)\n return;\n\n /**\n * Cannot initialize a hover player if we already have a player elsewhere.\n */\n if (initializeData.mode === 'hover' && state.mode)\n return;\n\n /**\n * No hover to play on interactives. This feature is ComingSoon™️ - Sha\n */\n if (initializeData.mode === 'hover' && initializeData.objectTypeId === MasterType.Interactive)\n return;\n\n dispatch({\n type: 'initialize',\n data: initializeData\n });\n\n return disposeInternal;\n }, []);\n }\n\n function setPlayerMode(mode: PlayerMode) {\n dispatch({ type: 'mode', data: { mode } });\n }\n\n function setDefaultDisplayMode(defaultDisplayMode: DefaultDisplayMode) {\n LocalStorageHelper.set(_THEATRE_MODE, defaultDisplayMode === 'theatre');\n\n dispatch({ type: 'defaultDisplayMode', data: { defaultDisplayMode } });\n }\n\n function setStarted(): void {\n dispatch({ type: 'started' });\n }\n\n function disposeInternal(force: boolean = false): void {\n if (force) {\n playerRef.current = null;\n }\n\n dispatch({ type: 'dispose', data: { force: force } });\n }\n\n function setPersist(): void {\n dispatch({ type: 'persist' });\n }\n\n /**\n * If anything external calls dispose, we ignore the persist flag and force a disposal\n */\n function dispose(): void {\n disposeInternal(true);\n }\n\n const playerContextValues: PlayerContextValues = {\n ...state,\n playerRef,\n setPlayerRef,\n portalNode,\n questionListPortalNode,\n useInitialize,\n setPlayerMode,\n setDefaultDisplayMode,\n setStarted,\n dispose,\n setPersist,\n hasProvider: true\n };\n\n return (\n <PlayerContext.Provider value={playerContextValues}>\n {props.children}\n </PlayerContext.Provider>\n );\n}\n","import React from 'react';\n\nimport { Flight } from 'libs/common/flight';\nimport { ArrayHelper } from 'libs/common/react/utils/ArrayHelper';\n\nimport { BaseObject } from 'libs/shared/interfaces';\n\nconst CHUNK_SIZE = 50;\n\nexport interface UseBatchFetchResult<T extends BaseObject> {\n itemsArr: T[];\n items: {[key: string]: T } | null;\n isFetching: boolean;\n hasCompleted: boolean;\n}\n\n/**\n * Used to fetch multiple items by id with Flight. Will fetch 25 items at a time firing off multiple\n * requests if there are more than 25 items.\n * This will return items as null until we have all our items. Items will be returned as an object with\n * their ids as they key for easy mapping\n * \n * @param itemIds \n * @param getRequest \n */\nexport function useBatchFetch<T extends BaseObject>(\n itemIds: string[],\n getRequest: (ids: string[]) => Flight.Request\n): UseBatchFetchResult<T> {\n const chunks = ArrayHelper.chunk<string>(itemIds, CHUNK_SIZE);\n\n const requests = chunks.map(chunk => getRequest(ArrayHelper.uniq(chunk)));\n\n const responses = Flight.useBasicFetchAll<T[]>(requests);\n\n const itemsArr = ArrayHelper.flatten(responses.data);\n const items = responses.data.length ?\n itemsArr.reduce((acc, item) => ({ ...acc, [item.id]: item }), {}) :\n null;\n\n return {\n itemsArr,\n items,\n isFetching: responses.isFetching,\n hasCompleted: responses.hasCompleted\n };\n}\n\n/**\n * When you need the useBatchFetch() behavior, but your list of objects to hydrate\n * will grow, such as on a scrolling page. useGrowingBatchFetch() will use local state\n * to determine what we've already built a request for and what items are new\n * as to not re-fetch items - Sha\n */\nexport function useGrowingBatchFetch<TResponse, TObjects = string>(\n objs: TObjects[],\n getRequest: (items: TObjects[]) => Flight.Request,\n _getKey?: (obj: TObjects) => string\n) {\n const getKey = _getKey ?? ((obj: any) => {\n if (typeof obj === 'object')\n return obj.id;\n\n return obj;\n });\n\n const { fetchItems, ...data } = useGrowingBatchFetchFunc<TResponse, TObjects>({ getRequest, _getKey });\n\n React.useEffect(() => {\n if (!objs?.length)\n return;\n\n fetchItems(objs);\n }, [objs?.map(getKey).join(',')]);\n\n return data;\n}\n\ninterface UseGrowingBatchFetchFuncOptions<TObjects> {\n getRequest: (items: TObjects[]) => Flight.Request;\n _getKey?: (obj: TObjects) => string;\n}\n\n/**\n * When you need the useGrowingBatchFetch() behaviour, but need to trigger the\n * fetch manually and update the objects - Nish \n */\nexport function useGrowingBatchFetchFunc<TResponse, TObjects = string>(\n options: UseGrowingBatchFetchFuncOptions<TObjects>\n) {\n const getKey = options._getKey ?? ((obj: any) => {\n if (typeof obj === 'object')\n return obj.id;\n\n return obj;\n });\n\n const fetchedItems = React.useRef<Set<string>>(new Set<string>());\n const [ requests, setRequests ] = React.useState<Flight.Request[]>([]);\n\n function fetchItems(objs: TObjects[]) {\n if (!objs?.length)\n return;\n\n const unfetchedItems: TObjects[] = [];\n \n objs.forEach(obj => {\n const key = getKey(obj);\n\n if (fetchedItems.current.has(key))\n return;\n\n unfetchedItems.push(obj);\n fetchedItems.current.add(key);\n });\n \n if (!unfetchedItems.length)\n return;\n \n setRequests(r => ([ ...r, ...ArrayHelper.chunk<TObjects>(unfetchedItems, CHUNK_SIZE).map(options.getRequest) ]));\n }\n\n const responses = Flight.useBasicFetchAll<TResponse[]>(requests);\n const itemsArr = ArrayHelper.flatten(responses.data);\n const items = responses.data.length ?\n itemsArr.reduce<Record<string, TResponse>>((acc, item) => ({ ...acc, [getKey(item)]: item }), {}) :\n null;\n\n return {\n hasFirstRequestCompleted: !!responses.responses?.[0]?.hasCompleted,\n itemsArr,\n items,\n isFetching: responses.isFetching,\n fetchItems\n };\n}\n"],"x_google_ignoreList":[0],"mappings":"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"}