@clickview/lite 0.73.1 → 0.74.0-rc.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 (164) hide show
  1. package/dist/bundles.json +2 -2
  2. package/dist/css/{7122-lite-a094f8fe17.chunk.css → 7122-lite-e0652641e4.chunk.css} +1 -1
  3. package/dist/css/{4499-lite-c43d17524f.chunk.css → 7150-lite-60d455ba66.chunk.css} +1 -1
  4. package/dist/css/{lite-app-10d57977f3.css → lite-app-98b3200025.css} +1 -1
  5. package/dist/languages/en.json +1 -1
  6. package/dist/scripts/{1362-061cd588c0-lite.chunk.js → 1362-56810ef4c8-lite.chunk.js} +3 -3
  7. package/dist/scripts/1362-56810ef4c8-lite.chunk.js.map +1 -0
  8. package/dist/scripts/{1367-12750422b0-lite.chunk.js → 1367-e0481edee3-lite.chunk.js} +2 -2
  9. package/dist/scripts/1367-e0481edee3-lite.chunk.js.map +1 -0
  10. package/dist/scripts/{1735-c0f3f1238a-lite.chunk.js → 1735-e4cdbc46ed-lite.chunk.js} +3 -3
  11. package/dist/scripts/1735-e4cdbc46ed-lite.chunk.js.map +1 -0
  12. package/dist/scripts/{324-6d6ee95d5d-lite.chunk.js → 324-e7a99b7d52-lite.chunk.js} +2 -2
  13. package/dist/scripts/{324-6d6ee95d5d-lite.chunk.js.map → 324-e7a99b7d52-lite.chunk.js.map} +1 -1
  14. package/dist/scripts/{3252-22fac3da15-lite.chunk.js → 3252-50b5c19f19-lite.chunk.js} +1 -1
  15. package/dist/scripts/{3252-22fac3da15-lite.chunk.js.map → 3252-50b5c19f19-lite.chunk.js.map} +1 -1
  16. package/dist/scripts/3677-4904f30c6a-lite.chunk.js +2 -0
  17. package/dist/scripts/3677-4904f30c6a-lite.chunk.js.map +1 -0
  18. package/dist/scripts/{3781-7a9ddc7736-lite.chunk.js → 3781-e092f92668-lite.chunk.js} +2 -2
  19. package/dist/scripts/{3781-7a9ddc7736-lite.chunk.js.map → 3781-e092f92668-lite.chunk.js.map} +1 -1
  20. package/dist/scripts/{3823-e38a508a3c-lite.chunk.js → 3823-0dc1972eb2-lite.chunk.js} +2 -2
  21. package/dist/scripts/3823-0dc1972eb2-lite.chunk.js.map +1 -0
  22. package/dist/scripts/3915-abd9a65a08-lite.chunk.js +2 -0
  23. package/dist/scripts/3915-abd9a65a08-lite.chunk.js.map +1 -0
  24. package/dist/scripts/{3978-09fb1f250e-lite.chunk.js → 3978-a551dd2648-lite.chunk.js} +2 -2
  25. package/dist/scripts/3978-a551dd2648-lite.chunk.js.map +1 -0
  26. package/dist/scripts/{4013-d31272b42a-lite.chunk.js → 4013-6f68d7031e-lite.chunk.js} +1 -1
  27. package/dist/scripts/{4013-d31272b42a-lite.chunk.js.map → 4013-6f68d7031e-lite.chunk.js.map} +1 -1
  28. package/dist/scripts/{4014-4225ce1eb6-lite.chunk.js → 4014-3eccce2f89-lite.chunk.js} +3 -3
  29. package/dist/scripts/4014-3eccce2f89-lite.chunk.js.map +1 -0
  30. package/dist/scripts/{4050-cf35c4ec45-lite.chunk.js → 4050-ffe5b6ae6d-lite.chunk.js} +2 -2
  31. package/dist/scripts/{4050-cf35c4ec45-lite.chunk.js.map → 4050-ffe5b6ae6d-lite.chunk.js.map} +1 -1
  32. package/dist/scripts/{4061-525ef00f69-lite.chunk.js → 4061-100002abf6-lite.chunk.js} +2 -2
  33. package/dist/scripts/4061-100002abf6-lite.chunk.js.map +1 -0
  34. package/dist/scripts/4191-9a08c4b205-lite.chunk.js +2 -0
  35. package/dist/scripts/4191-9a08c4b205-lite.chunk.js.map +1 -0
  36. package/dist/scripts/{4358-b21c24f96a-lite.chunk.js → 4358-a1bbca8249-lite.chunk.js} +1 -1
  37. package/dist/scripts/{4358-b21c24f96a-lite.chunk.js.map → 4358-a1bbca8249-lite.chunk.js.map} +1 -1
  38. package/dist/scripts/{4400-8c36fb4ab5-lite.chunk.js → 4400-755a158a52-lite.chunk.js} +2 -2
  39. package/dist/scripts/4400-755a158a52-lite.chunk.js.map +1 -0
  40. package/dist/scripts/4806-13c9302b2c-lite.chunk.js +2 -0
  41. package/dist/scripts/4806-13c9302b2c-lite.chunk.js.map +1 -0
  42. package/dist/scripts/{5135-864055ab0b-lite.chunk.js → 5135-166ec46620-lite.chunk.js} +2 -2
  43. package/dist/scripts/5135-166ec46620-lite.chunk.js.map +1 -0
  44. package/dist/scripts/{5143-286c66de2b-lite.chunk.js → 5143-d6c4a357ea-lite.chunk.js} +2 -2
  45. package/dist/scripts/5143-d6c4a357ea-lite.chunk.js.map +1 -0
  46. package/dist/scripts/{5743-a764171a6d-lite.chunk.js → 5743-14700e4f76-lite.chunk.js} +2 -2
  47. package/dist/scripts/5743-14700e4f76-lite.chunk.js.map +1 -0
  48. package/dist/scripts/{6030-5db8cc1bc4-lite.chunk.js → 6030-c2e07df714-lite.chunk.js} +2 -2
  49. package/dist/scripts/6030-c2e07df714-lite.chunk.js.map +1 -0
  50. package/dist/scripts/{618-4334f9451b-lite.chunk.js → 618-996d8b560b-lite.chunk.js} +2 -2
  51. package/dist/scripts/618-996d8b560b-lite.chunk.js.map +1 -0
  52. package/dist/scripts/{6207-f444184025-lite.chunk.js → 6207-be843186e0-lite.chunk.js} +1 -1
  53. package/dist/scripts/{6207-f444184025-lite.chunk.js.map → 6207-be843186e0-lite.chunk.js.map} +1 -1
  54. package/dist/scripts/{6413-c4333e80d4-lite.chunk.js → 6413-caaae6a383-lite.chunk.js} +3 -3
  55. package/dist/scripts/{6413-c4333e80d4-lite.chunk.js.map → 6413-caaae6a383-lite.chunk.js.map} +1 -1
  56. package/dist/scripts/{6646-24a34f7d99-lite.chunk.js → 6646-c5775f6553-lite.chunk.js} +3 -3
  57. package/dist/scripts/6646-c5775f6553-lite.chunk.js.map +1 -0
  58. package/dist/scripts/{6909-8a45942b63-lite.chunk.js → 6909-6805b6a0d9-lite.chunk.js} +2 -2
  59. package/dist/scripts/6909-6805b6a0d9-lite.chunk.js.map +1 -0
  60. package/dist/scripts/7064-b3bafc599f-lite.chunk.js +2 -0
  61. package/dist/scripts/7064-b3bafc599f-lite.chunk.js.map +1 -0
  62. package/dist/scripts/7122-dbf374af58-lite.chunk.js +2 -0
  63. package/dist/scripts/7122-dbf374af58-lite.chunk.js.map +1 -0
  64. package/dist/scripts/7150-93a205975c-lite.chunk.js +2 -0
  65. package/dist/scripts/7150-93a205975c-lite.chunk.js.map +1 -0
  66. package/dist/scripts/{7234-85d4acaa33-lite.chunk.js → 7234-bcddfe2112-lite.chunk.js} +2 -2
  67. package/dist/scripts/7234-bcddfe2112-lite.chunk.js.map +1 -0
  68. package/dist/scripts/{7383-690bc234f1-lite.chunk.js → 7383-02d4956304-lite.chunk.js} +2 -2
  69. package/dist/scripts/7383-02d4956304-lite.chunk.js.map +1 -0
  70. package/dist/scripts/{7873-2e64f4eb37-lite.chunk.js → 7873-0ce0523a28-lite.chunk.js} +2 -2
  71. package/dist/scripts/{7873-2e64f4eb37-lite.chunk.js.map → 7873-0ce0523a28-lite.chunk.js.map} +1 -1
  72. package/dist/scripts/{8248-050265ed2d-lite.chunk.js → 8248-41dad9bf71-lite.chunk.js} +3 -3
  73. package/dist/scripts/8248-41dad9bf71-lite.chunk.js.map +1 -0
  74. package/dist/scripts/8385-6ef08fa319-lite.chunk.js +2 -0
  75. package/dist/scripts/8385-6ef08fa319-lite.chunk.js.map +1 -0
  76. package/dist/scripts/{8451-1cb649a3f3-lite.chunk.js → 8451-0103210a8f-lite.chunk.js} +2 -2
  77. package/dist/scripts/8451-0103210a8f-lite.chunk.js.map +1 -0
  78. package/dist/scripts/8630-80f676dcda-lite.chunk.js +2 -0
  79. package/dist/scripts/8630-80f676dcda-lite.chunk.js.map +1 -0
  80. package/dist/scripts/8891-5118c47b59-lite.chunk.js +2 -0
  81. package/dist/scripts/8891-5118c47b59-lite.chunk.js.map +1 -0
  82. package/dist/scripts/8982-b9e53e43ec-lite.chunk.js +2 -0
  83. package/dist/scripts/8982-b9e53e43ec-lite.chunk.js.map +1 -0
  84. package/dist/scripts/{9186-daf77d7174-lite.chunk.js → 9186-c1d2615458-lite.chunk.js} +2 -2
  85. package/dist/scripts/9186-c1d2615458-lite.chunk.js.map +1 -0
  86. package/dist/scripts/{9241-dbac9cb9f9-lite.chunk.js → 9241-2386134dd3-lite.chunk.js} +2 -2
  87. package/dist/scripts/9241-2386134dd3-lite.chunk.js.map +1 -0
  88. package/dist/scripts/{9345-30ccf524c5-lite.chunk.js → 9345-0a7f58bb53-lite.chunk.js} +3 -3
  89. package/dist/scripts/9345-0a7f58bb53-lite.chunk.js.map +1 -0
  90. package/dist/scripts/9352-d4b2dc16a8-lite.chunk.js +2 -0
  91. package/dist/scripts/9352-d4b2dc16a8-lite.chunk.js.map +1 -0
  92. package/dist/scripts/{9503-275c13891d-lite.chunk.js → 9503-715c46ecc1-lite.chunk.js} +2 -2
  93. package/dist/scripts/9503-715c46ecc1-lite.chunk.js.map +1 -0
  94. package/dist/scripts/9630-ca2a850260-lite.chunk.js +2 -0
  95. package/dist/scripts/9630-ca2a850260-lite.chunk.js.map +1 -0
  96. package/dist/scripts/{9767-d69fdc31b0-lite.chunk.js → 9767-1b583ceb6c-lite.chunk.js} +2 -2
  97. package/dist/scripts/9767-1b583ceb6c-lite.chunk.js.map +1 -0
  98. package/dist/scripts/9894-7c119a8fe3-lite.chunk.js +2 -0
  99. package/dist/scripts/9894-7c119a8fe3-lite.chunk.js.map +1 -0
  100. package/dist/scripts/bundle-5b65703152.min.js +3 -0
  101. package/dist/scripts/{bundle-0075afb6af.min.js.map → bundle-5b65703152.min.js.map} +1 -1
  102. package/package.json +1 -1
  103. package/dist/scripts/1362-061cd588c0-lite.chunk.js.map +0 -1
  104. package/dist/scripts/1367-12750422b0-lite.chunk.js.map +0 -1
  105. package/dist/scripts/1735-c0f3f1238a-lite.chunk.js.map +0 -1
  106. package/dist/scripts/3677-20958f59d3-lite.chunk.js +0 -2
  107. package/dist/scripts/3677-20958f59d3-lite.chunk.js.map +0 -1
  108. package/dist/scripts/3823-e38a508a3c-lite.chunk.js.map +0 -1
  109. package/dist/scripts/3915-a1f15d687a-lite.chunk.js +0 -2
  110. package/dist/scripts/3915-a1f15d687a-lite.chunk.js.map +0 -1
  111. package/dist/scripts/3978-09fb1f250e-lite.chunk.js.map +0 -1
  112. package/dist/scripts/4014-4225ce1eb6-lite.chunk.js.map +0 -1
  113. package/dist/scripts/4061-525ef00f69-lite.chunk.js.map +0 -1
  114. package/dist/scripts/4191-7612e1713c-lite.chunk.js +0 -2
  115. package/dist/scripts/4191-7612e1713c-lite.chunk.js.map +0 -1
  116. package/dist/scripts/4400-8c36fb4ab5-lite.chunk.js.map +0 -1
  117. package/dist/scripts/4499-1365934bf2-lite.chunk.js +0 -2
  118. package/dist/scripts/4499-1365934bf2-lite.chunk.js.map +0 -1
  119. package/dist/scripts/4806-384760d9c9-lite.chunk.js +0 -2
  120. package/dist/scripts/4806-384760d9c9-lite.chunk.js.map +0 -1
  121. package/dist/scripts/5135-864055ab0b-lite.chunk.js.map +0 -1
  122. package/dist/scripts/5143-286c66de2b-lite.chunk.js.map +0 -1
  123. package/dist/scripts/5743-a764171a6d-lite.chunk.js.map +0 -1
  124. package/dist/scripts/6030-5db8cc1bc4-lite.chunk.js.map +0 -1
  125. package/dist/scripts/618-4334f9451b-lite.chunk.js.map +0 -1
  126. package/dist/scripts/6646-24a34f7d99-lite.chunk.js.map +0 -1
  127. package/dist/scripts/6909-8a45942b63-lite.chunk.js.map +0 -1
  128. package/dist/scripts/7064-3ccf1b82d1-lite.chunk.js +0 -2
  129. package/dist/scripts/7064-3ccf1b82d1-lite.chunk.js.map +0 -1
  130. package/dist/scripts/7122-352fdd3516-lite.chunk.js +0 -2
  131. package/dist/scripts/7122-352fdd3516-lite.chunk.js.map +0 -1
  132. package/dist/scripts/7234-85d4acaa33-lite.chunk.js.map +0 -1
  133. package/dist/scripts/7383-690bc234f1-lite.chunk.js.map +0 -1
  134. package/dist/scripts/8248-050265ed2d-lite.chunk.js.map +0 -1
  135. package/dist/scripts/8385-083e882d77-lite.chunk.js +0 -2
  136. package/dist/scripts/8385-083e882d77-lite.chunk.js.map +0 -1
  137. package/dist/scripts/8451-1cb649a3f3-lite.chunk.js.map +0 -1
  138. package/dist/scripts/8630-0945271ea2-lite.chunk.js +0 -2
  139. package/dist/scripts/8630-0945271ea2-lite.chunk.js.map +0 -1
  140. package/dist/scripts/8891-393bb5bdaf-lite.chunk.js +0 -2
  141. package/dist/scripts/8891-393bb5bdaf-lite.chunk.js.map +0 -1
  142. package/dist/scripts/8982-8c21fab48a-lite.chunk.js +0 -2
  143. package/dist/scripts/8982-8c21fab48a-lite.chunk.js.map +0 -1
  144. package/dist/scripts/9186-daf77d7174-lite.chunk.js.map +0 -1
  145. package/dist/scripts/9241-dbac9cb9f9-lite.chunk.js.map +0 -1
  146. package/dist/scripts/9345-30ccf524c5-lite.chunk.js.map +0 -1
  147. package/dist/scripts/9352-04db4c533d-lite.chunk.js +0 -2
  148. package/dist/scripts/9352-04db4c533d-lite.chunk.js.map +0 -1
  149. package/dist/scripts/9503-275c13891d-lite.chunk.js.map +0 -1
  150. package/dist/scripts/9630-285237c980-lite.chunk.js +0 -2
  151. package/dist/scripts/9630-285237c980-lite.chunk.js.map +0 -1
  152. package/dist/scripts/9767-d69fdc31b0-lite.chunk.js.map +0 -1
  153. package/dist/scripts/9894-10943e41f7-lite.chunk.js +0 -2
  154. package/dist/scripts/9894-10943e41f7-lite.chunk.js.map +0 -1
  155. package/dist/scripts/bundle-0075afb6af.min.js +0 -3
  156. /package/dist/scripts/{1362-061cd588c0-lite.chunk.js.LICENSE.txt → 1362-56810ef4c8-lite.chunk.js.LICENSE.txt} +0 -0
  157. /package/dist/scripts/{1735-c0f3f1238a-lite.chunk.js.LICENSE.txt → 1735-e4cdbc46ed-lite.chunk.js.LICENSE.txt} +0 -0
  158. /package/dist/scripts/{4014-4225ce1eb6-lite.chunk.js.LICENSE.txt → 4014-3eccce2f89-lite.chunk.js.LICENSE.txt} +0 -0
  159. /package/dist/scripts/{4050-cf35c4ec45-lite.chunk.js.LICENSE.txt → 4050-ffe5b6ae6d-lite.chunk.js.LICENSE.txt} +0 -0
  160. /package/dist/scripts/{6413-c4333e80d4-lite.chunk.js.LICENSE.txt → 6413-caaae6a383-lite.chunk.js.LICENSE.txt} +0 -0
  161. /package/dist/scripts/{6646-24a34f7d99-lite.chunk.js.LICENSE.txt → 6646-c5775f6553-lite.chunk.js.LICENSE.txt} +0 -0
  162. /package/dist/scripts/{8248-050265ed2d-lite.chunk.js.LICENSE.txt → 8248-41dad9bf71-lite.chunk.js.LICENSE.txt} +0 -0
  163. /package/dist/scripts/{9345-30ccf524c5-lite.chunk.js.LICENSE.txt → 9345-0a7f58bb53-lite.chunk.js.LICENSE.txt} +0 -0
  164. /package/dist/scripts/{bundle-0075afb6af.min.js.LICENSE.txt → bundle-5b65703152.min.js.LICENSE.txt} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"scripts/4013-d31272b42a-lite.chunk.js","mappings":"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","sources":["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/AnalyticsFilterUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AudienceUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/generate-report/GenerateInteractiveResultsReportView.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicator.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicatorUtils.ts","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/errors/general/verified-email/VerifiedEmailRequiredError.ts","file:///app/packages/libs/shared/src/hooks/useVerifiedEmailRequiredErrorHandler.ts","file:///app/packages/libs/shared/src/utils/AnalyticsRequestUtils.ts","file:///app/packages/libs/shared/src/utils/AppRouteHelper.ts","file:///app/packages/libs/shared/src/components/percentage-indicator/percentage-indicator.scss"],"sourcesContent":["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: '/api/domain/v3/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 { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nexport const AnalyticsFilterHelper = {\n getAudienceAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { users, classrooms, classroomGroups } = params;\n\n const getParam = (key: keyof AudienceQueryParams) => {\n const param = params[key];\n\n if (!param)\n return;\n\n return Array.isArray(param) ? param : [param];\n };\n\n const audienceFilters: AudienceQueryParams = {};\n\n if (users)\n audienceFilters.users = getParam('users');\n\n if (classrooms)\n audienceFilters.classrooms = getParam('classrooms');\n\n if (classroomGroups)\n audienceFilters.classroomGroups = getParam('classroomGroups');\n\n return audienceFilters;\n },\n getDateRangeAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { from, to, rangeName } = params;\n\n const dateRangeFilters: DateRangeQueryParams = {};\n\n if (from)\n dateRangeFilters.from = from;\n\n if (to)\n dateRangeFilters.to = to;\n\n if (rangeName)\n dateRangeFilters.rangeName = rangeName;\n\n return dateRangeFilters;\n }\n};","import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { User } from 'libs/shared/interfaces';\nimport { PublicInteractiveUser } from 'libs/shared/interfaces/models/interactive-results/PublicInteractiveUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: User | PublicInteractiveUser, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'profileId' in user ? user.name : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('profileId' in user ? user.profileId : user.id));\n}\n","import { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\n\nexport const getAudienceParams = (queryParams: AudienceQueryParams) => {\n const userId: string[] = [];\n const groupId: string[] = [];\n\n if (queryParams.users)\n userId.push(...queryParams.users);\n\n if (queryParams.classrooms)\n groupId.push(...queryParams.classrooms);\n\n if (queryParams.classroomGroups)\n groupId.push(...queryParams.classroomGroups);\n return {\n userId,\n groupId\n };\n};","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresets: DateRange[]): DateRange {\n return dateRangePresets.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastTwelveMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 11, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = {\n startDate,\n endDate,\n name: initialDateRangeValid\n ? rangeName || 'custom'\n : ''\n };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import React from 'react';\n\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\nimport { Flight } from 'libs/common/react/index';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { useGetResultsTableData } from 'libs/shared/apps/analytics/components/student-results/student-results-table/StudentResultsTableUtils';\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { InteractiveResultsReport } from 'libs/shared/apps/analytics/interfaces/requests/InteractiveResultsReport';\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 { getFormattedPercentage, getPercentageToFixed } from 'libs/shared/components/percentage-indicator/PercentageIndicatorUtils';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { PopupButtons } from 'libs/shared/components/popup/PopupButtons';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useVerifiedEmailRequiredErrorHandler } from 'libs/shared/hooks/useVerifiedEmailRequiredErrorHandler';\nimport { CurrentUser, Interactive, InteractiveMetadata, PopupViewProps } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nconst namespace = 'shared.generateReport';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getReportFriendlyDate(date: string): string {\n const localDate = DateHelper.convertUTCToLocal(date).toString();\n return DateHelper.format(localDate, 'Do MMMM YYYY');\n}\n\ninterface GenerateInteractiveResultsReportViewProps extends PopupViewProps {\n interactiveId: string;\n}\n\nexport function GenerateInteractiveResultsReportView(props: GenerateInteractiveResultsReportViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n const alerts = useAlerts();\n const fetchAsync = Flight.useGetFetchAsync();\n\n const audienceAppLinkParams = AnalyticsFilterHelper.getAudienceAppLinkParams();\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n const startEndParams = getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams);\n\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n\n const { loading, handleGenerateReportError } = useVerifiedEmailRequiredErrorHandler();\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId ?\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId) : null);\n const results = useFetchInteractiveResults(props.interactiveId, {\n ...startEndParams,\n ...getAudienceParams(audienceAppLinkParams)\n });\n\n useHandleObjectError([ interactive, interactiveMetadata, results ]);\n\n const interactions = getInteractions(interactive.data);\n\n const answerData = useGetResultsTableData(interactive.data, results.data, false, anonymiseUsers);\n\n function onClickGenerate(): void {\n setShowSpinner(true);\n\n const body: InteractiveResultsReport = {\n interactiveName: interactiveMetadata.data.name,\n userId: currentUser.data.id,\n customerId: currentUser.data.customerId,\n questions: interactions.map(i => i.name),\n rows: answerData.map(answer => {\n return {\n name: UserHelper.getFullName(answer.user),\n unanswered: answer.summary.unanswered,\n percentage: getFormattedPercentage(getPercentageToFixed(answer.summary.percentCorrect)),\n correct: answer.summary.correct,\n totalQuestions: answer.summary.answered + answer.summary.unanswered,\n results: interactions.map(interaction => {\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(\n interaction,\n getStudentResult(answer)\n );\n\n switch (correctness) {\n case InteractionCorrectness.Correct:\n return getPhrase('correct');\n\n case InteractionCorrectness.Incorrect:\n return getPhrase('incorrect');\n\n case InteractionCorrectness.NotApplicable:\n return '-';\n\n case InteractionCorrectness.AwaitingMarking:\n return getPhrase('awaitingMarking');\n\n case InteractionCorrectness.UnAnswered:\n case InteractionCorrectness.Answered:\n default:\n return '';\n }\n })\n };\n })\n };\n\n fetchAsync(InteractiveResultsRequests.interactiveResultsReport(body))\n .then(() => {\n alerts.success(getPhrase('success'));\n })\n .catch((xhr: Xhr) => handleGenerateReportError(xhr, getPhrase('error'), getPhrase('noEmailError')))\n .finally(props.closePopup);\n }\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <Popup\n title={getPhrase('title')}\n showLoadingSpinner={!currentUser.hasCompleted || loading}\n closePopup={props.closePopup}\n >\n <>\n <p>\n <Text phrase='description' />\n </p>\n <p>\n <Text phrase='dateRange' options={({\n dateFrom: getReportFriendlyDate(startEndParams.start),\n dateTo: getReportFriendlyDate(startEndParams.end)\n })} />\n </p>\n <p>\n <Text phrase='emailDescription' options={({ email: currentUser.data?.email })} />\n </p>\n <PopupButtons>\n <PopupButtons.Cancel onClick={props.closePopup} />\n <PopupButtons.Submit\n variant='dark'\n onClick={onClickGenerate}\n text={getPhrase('generateReport')}\n showSpinner={showSpinner}\n />\n </PopupButtons>\n </>\n </Popup>\n </LanguageNamespaceContext.Provider>\n );\n}","import React from 'react';\n\nimport { ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport {\n getCircleClassName,\n getCircleContainerClassName,\n getCircleRadius,\n getColouredLabelClassName,\n getFormattedPercentage,\n getPercentageToFixed,\n isPending,\n ProgressCircleSize\n} from './PercentageIndicatorUtils';\n\nimport styles from './percentage-indicator.scss';\n\ninterface ProgressCircleProps {\n size: ProgressCircleSize;\n scoreThresholds?: ScoreThresholds;\n percentage?: number;\n}\n\nfunction ProgressCircle(props: ProgressCircleProps): JSX.Element {\n const ref = React.useCallback((circle: SVGCircleElement) => {\n if (!circle)\n return;\n\n const radius = circle.r.baseVal.value;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - props.percentage * circumference;\n\n circle.style.strokeDasharray = `${circumference} ${circumference}`;\n circle.style.strokeDashoffset = offset.toString();\n }, [props.percentage]);\n\n return (\n <svg>\n <circle r={getCircleRadius(props.size)} className={styles.backgroundCircle} />\n {!isPending(props.percentage) &&\n <circle\n ref={ref}\n r={getCircleRadius(props.size)}\n className={getCircleClassName(props.percentage, props.scoreThresholds)}\n />\n }\n </svg>\n );\n}\n\nexport enum PercentageIndicatorLayout {\n CircleOnly = 'circle_only',\n LabelOnly = 'label_only',\n LabelBefore = 'label_before',\n LabelInside = 'label_inside'\n}\n\ninterface PercentageIndicatorProps {\n layout: PercentageIndicatorLayout;\n percentage?: number; // Between 0 and 1 or undefined for pending\n className?: string;\n customLabel?: string;\n scoreThresholds?: ScoreThresholds;\n size?: ProgressCircleSize;\n}\n\nPercentageIndicator.defaultProps = {\n layout: PercentageIndicatorLayout.CircleOnly\n};\n\nexport function PercentageIndicator(props: PercentageIndicatorProps): JSX.Element {\n const percentageToFixed = getPercentageToFixed(props.percentage);\n\n const size = props.size ||\n (props.layout === PercentageIndicatorLayout.LabelInside\n ? ProgressCircleSize.Large\n : ProgressCircleSize.Small\n );\n\n const label = props.customLabel || getFormattedPercentage(percentageToFixed);\n\n if (props.layout === PercentageIndicatorLayout.LabelOnly)\n return (\n <span className={getColouredLabelClassName(percentageToFixed)}>\n {label}\n </span>\n );\n\n return (\n <div className={`d-flex align-items-center justify-content-between ${props.className ?? ''}`}>\n {props.layout === PercentageIndicatorLayout.LabelBefore &&\n <span className='me-2'>\n {label}\n </span>\n }\n <div className={getCircleContainerClassName(size, percentageToFixed)}>\n <ProgressCircle percentage={percentageToFixed} size={size} scoreThresholds={props.scoreThresholds} />\n {props.layout === PercentageIndicatorLayout.LabelInside &&\n <span className={styles.centredPercentageText}>\n {label}\n </span>\n }\n </div>\n </div>\n );\n}","import { ScoreThresholdDefaults, ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport styles from './percentage-indicator.scss';\n\n/**\n * Values for width and strokeWidth are taken from progress-circle.scss.\n * If either are changed, they must be updated in both places.\n */\nconst CIRCLE_WIDTH = 2; // rem\nconst CIRCLE_WIDTH_LG = 5.8; // rem\nconst CIRCLE_STROKE_WIDTH = 0.2; // rem\nconst CIRCLE_STROKE_WIDTH_LG = 0.36; // rem\n \nexport enum ProgressCircleSize {\n Small = 'small',\n Large = 'large',\n ExtraSmall = 'extraSmall'\n}\n\nconst ProgressCircleSizeMap = {\n [ProgressCircleSize.ExtraSmall]: {\n size: CIRCLE_WIDTH\n },\n [ProgressCircleSize.Small]: {\n size: CIRCLE_WIDTH\n },\n [ProgressCircleSize.Large]: {\n size: CIRCLE_WIDTH_LG\n }\n};\n\n/**\n * radius = width / 2 - strokeWidth * 2\n */\nexport function getCircleRadius(size: ProgressCircleSize): string {\n const width = ProgressCircleSizeMap[size].size;\n const strokeWidth = size === ProgressCircleSize.Large ? CIRCLE_STROKE_WIDTH_LG : CIRCLE_STROKE_WIDTH;\n return `${width / 2 - strokeWidth * 2}rem`;\n}\n \nexport function getCircleClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return styles.circleSuccess;\n \n if (percentage >= scoreThresholds.MODERATE)\n return styles.circleWarning;\n \n return styles.circleDanger;\n}\n \nexport function getColouredLabelClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return 'text-success';\n \n if (percentage >= scoreThresholds.MODERATE)\n return 'text-warning';\n \n return 'text-danger';\n}\n \nexport function getCircleContainerClassName(size: ProgressCircleSize, percentage?: number): string {\n let className = `d-inline-block ${styles.circleContainer}`;\n \n if (size === ProgressCircleSize.Large)\n className += ` ${styles.lgCircleContainer}`;\n\n if (size === ProgressCircleSize.ExtraSmall)\n className += ` ${styles.xsCircleContainer}`;\n\n if (isPending(percentage))\n className += ` ${styles.pendingCircle}`;\n \n return className;\n}\n\nexport function getPercentageToFixed(percentage?: number): number | undefined {\n if (isPending(percentage))\n return;\n \n return +percentage.toFixed(2);\n}\n \nexport function getFormattedPercentage(percentage?: number): string {\n if (isPending(percentage))\n return `--%`;\n\n return `${Math.round(percentage * 100)}%`;\n}\n\nexport function isPending(percentage?: number): boolean {\n return typeof percentage !== 'number';\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\n\nimport { DialogError } from 'libs/shared/errors/primitives/DialogError';\nimport { DialogOptions } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.verifiedEmailError';\n\nexport class VerifiedEmailRequiredError extends DialogError {\n public message: string;\n public liteUrl: string;\n public hasLite: boolean;\n\n constructor(message: string, liteUrl: string, hasLite: boolean) {\n super('VerifiedEmailRequiredError');\n\n this.message = message;\n this.liteUrl = liteUrl;\n this.hasLite = hasLite;\n }\n\n // @ts-ignore\n public get name(): string {\n return 'VerifiedEmailRequiredError';\n }\n\n // @ts-ignore\n public get dialogOptions(): DialogOptions {\n const href = UrlHelper.safeUrlConcat(this.liteUrl, 'settings/account');\n\n return {\n title: LanguageService.getPhrase(namespace, 'heading'),\n text: this.hasLite\n ? `${this.message} ${LanguageService.getPhrase(namespace, 'visitSettings', { href })}`\n : this.message,\n buttons: [{\n text: LanguageService.getPhrase(namespace, 'close'),\n className: 'btn btn-dark',\n success: true\n }]\n };\n }\n}","import { Core } from 'libs/common/backbone/index';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Flight } from 'libs/common/react/index';\n\nimport { ProductId } from 'libs/shared/enums/ProductId';\nimport { VerifiedEmailRequiredError } from 'libs/shared/errors/general/verified-email/VerifiedEmailRequiredError';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useProducts } from 'libs/shared/hooks/UseProducts';\nimport { Config } from 'libs/shared/interfaces';\n\nexport function useVerifiedEmailRequiredErrorHandler() {\n const alerts = useAlerts();\n const { hasProduct, isLoadingProducts } = useProducts();\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n function handleGenerateReportError(xhr: Xhr, message: string, noEmailError: string) {\n if (!xhr.responseJSON || xhr.responseJSON?.type !== 'no-email') {\n alerts.error(message);\n return;\n }\n\n Core.ErrorHelper.throw(\n new VerifiedEmailRequiredError(noEmailError, config.data.liteUrl, hasProduct(ProductId.Primary))\n );\n }\n\n return {\n handleGenerateReportError,\n loading: !config.hasCompleted || isLoadingProducts\n };\n}","import { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nexport function getAnalyticsRequestKey(baseKey: string, filter: AnalyticsRequestFilter, sharerId?: string): string {\n let key = `${baseKey}:${filter.start}:${filter.end}`;\n\n const userIdKey = Array.isArray(filter.userId) ? filter.userId.sort().join(':') : filter.userId;\n const groupIdKey = Array.isArray(filter.groupId) ? filter.groupId.sort().join(':') : filter.groupId;\n\n if (userIdKey)\n key += `:${userIdKey}`;\n\n if (groupIdKey)\n key += `:${groupIdKey}`;\n\n if (sharerId)\n key += `:${sharerId}`;\n\n return key;\n}","import { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { ContextService } from 'libs/shared/services/ContextService';\n\ninterface UpdateParamsOptions extends Core.AppLinkOptions {\n merge?: boolean;\n keysToRemove?: string[]\n}\n\nexport const AppRouteHelper = {\n /**\n * Utility to update the params on the current appRoute.\n * \n * This is built on top of ContextService rather than build into AppLink\n * as we will generally only want to update params on appRoutes, not appLinks.\n */\n updateParams(params: HashObject, options?: UpdateParamsOptions): void {\n const { appLink } = ContextService.getCurrentRoute();\n\n let currentParams = typeof(appLink.params) === 'string'\n ? Core.LocationUtils.DeserializeQueryParams(appLink.params)\n : appLink.params as HashObject;\n\n if (options.keysToRemove)\n currentParams = ObjectHelper.omit(currentParams, options.keysToRemove);\n\n const updatedParams = options?.merge\n ? { ...currentParams, ...params }\n : params;\n\n const updatedAppLink = {\n ...appLink,\n params: updatedParams\n };\n\n /**\n * This prevents us pointlessly re-triggering if we're already on the right applink.\n */\n if (ObjectHelper.isEqual(appLink, updatedAppLink))\n return;\n \n Core.AppLinkHelper.trigger(updatedAppLink, ObjectHelper.omit(options, [ 'merge', 'keysToRemove' ]));\n }\n};","// extracted by mini-css-extract-plugin\nexport default {\"circleContainer\":\"p8Vgz\",\"backgroundCircle\":\"asGGE\",\"circleSuccess\":\"PXLNj\",\"circleWarning\":\"ZckRN\",\"circleDanger\":\"slBRg\",\"lgCircleContainer\":\"N8KCI\",\"xsCircleContainer\":\"RPqZ2\",\"pendingCircle\":\"DKrcq\",\"centredPercentageText\":\"tpmLR\"};"],"names":["getInteractiveResultFilters","currentUser","filter","currentUserId","id","currentCustomerId","customerId","dateRange","start","end","userIds","userId","classroomsAndGroups","groupId","InteractiveResultsRequests","interactiveResultSet","interactiveId","interactiveMetadataId","includePublicResults","success","error","always","url","key","data","type","normalize","formatData","students","map","student","name","profileId","publicUser","mark","answerId","resultId","invalidationKeys","pendingReviews","interactiveResultsReport","useFetchInteractiveResults","requestFilter","interactiveMetadata","interactive","shouldFetchResults","I","AnalyticsFilterHelper","getAudienceAppLinkParams","appLink","params","users","classrooms","classroomGroups","getParam","param","Array","isArray","audienceFilters","getDateRangeAppLinkParams","from","to","rangeName","dateRangeFilters","anonymiseUserName","user","shouldAnonymise","seed","Math","floor","Date","getMinutes","dictionaries","separator","length","style","getAudienceParams","queryParams","push","getPhrase","convertDateToUtcDateTimeString","date","utc","getMinDate","getMaxDate","getDefaultDateRange","dateRangePresets","find","range","getPresetRangeByName","dateRangePresetss","p","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getRouteQueryParams","useGetDateRangeFromQueryParams","dateRangeQueryParams","presetRange","replace","merge","keysToRemove","defaultDateRange","initialDateRangeValid","getStartEndParams","filterParams","getStartDate","getEndDate","defaultRange","namespace","getReportFriendlyDate","localDate","toString","GenerateInteractiveResultsReportView","props","anonymiseUsers","alerts","fetchAsync","audienceAppLinkParams","dateRangeAppLinkParams","startEndParams","showSpinner","setShowSpinner","loading","handleGenerateReportError","results","interactions","answerData","value","title","showLoadingSpinner","hasCompleted","closePopup","phrase","options","dateFrom","dateTo","email","onClick","variant","body","interactiveName","questions","i","rows","answer","unanswered","summary","percentage","percentCorrect","correct","totalQuestions","answered","interaction","then","xhr","text","PercentageIndicatorLayout","ProgressCircle","ref","circle","radius","r","baseVal","circumference","PI","offset","strokeDasharray","strokeDashoffset","size","className","scoreThresholds","PercentageIndicator","percentageToFixed","layout","LabelInside","label","customLabel","LabelOnly","LabelBefore","defaultProps","CircleOnly","ProgressCircleSize","CIRCLE_STROKE_WIDTH","CIRCLE_STROKE_WIDTH_LG","ProgressCircleSizeMap","ExtraSmall","Small","Large","getCircleRadius","width","strokeWidth","getCircleClassName","HIGH","MODERATE","getColouredLabelClassName","getCircleContainerClassName","isPending","getPercentageToFixed","toFixed","getFormattedPercentage","round","ScoreThresholdDefaults","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","useEffect","forEach","VerifiedEmailRequiredError","message","liteUrl","hasLite","href","UrlHelper","this","LanguageService","buttons","DialogError","useVerifiedEmailRequiredErrorHandler","hasProduct","isLoadingProducts","config","ConfigRequests","noEmailError","responseJSON","ProductId","getAnalyticsRequestKey","baseKey","sharerId","userIdKey","sort","groupIdKey","AppRouteHelper","updateParams","currentParams","updatedParams","updatedAppLink"],"sourceRoot":""}
1
+ {"version":3,"file":"scripts/4013-6f68d7031e-lite.chunk.js","mappings":"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","sources":["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/AnalyticsFilterUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AnonymiseUserUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/AudienceUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/utils/DateRangeUtils.ts","file:///app/packages/libs/shared/src/apps/analytics/views/generate-report/GenerateInteractiveResultsReportView.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicator.tsx","file:///app/packages/libs/shared/src/components/percentage-indicator/PercentageIndicatorUtils.ts","file:///app/packages/libs/shared/src/constants/ScoreThresholds.ts","file:///app/packages/libs/shared/src/errors/handlers/HttpErrorHandlers.ts","file:///app/packages/libs/shared/src/hooks/UseHandleObjectError.ts","file:///app/packages/libs/shared/src/errors/general/verified-email/VerifiedEmailRequiredError.ts","file:///app/packages/libs/shared/src/hooks/useVerifiedEmailRequiredErrorHandler.ts","file:///app/packages/libs/shared/src/utils/AnalyticsRequestUtils.ts","file:///app/packages/libs/shared/src/utils/AppRouteHelper.ts","file:///app/packages/libs/shared/src/components/percentage-indicator/percentage-indicator.scss"],"sourcesContent":["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: '/api/domain/v3/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 { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { ContextService } from 'libs/shared/services/ContextService';\n\nexport const AnalyticsFilterHelper = {\n getAudienceAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { users, classrooms, classroomGroups } = params;\n\n const getParam = (key: keyof AudienceQueryParams) => {\n const param = params[key];\n\n if (!param)\n return;\n\n return Array.isArray(param) ? param : [param];\n };\n\n const audienceFilters: AudienceQueryParams = {};\n\n if (users)\n audienceFilters.users = getParam('users');\n\n if (classrooms)\n audienceFilters.classrooms = getParam('classrooms');\n\n if (classroomGroups)\n audienceFilters.classroomGroups = getParam('classroomGroups');\n\n return audienceFilters;\n },\n getDateRangeAppLinkParams: () => {\n const { appLink } = ContextService.getCurrentRoute();\n const params = ObjectHelper.isObject(appLink.params) ? appLink.params as HashObject : {};\n const { from, to, rangeName } = params;\n\n const dateRangeFilters: DateRangeQueryParams = {};\n\n if (from)\n dateRangeFilters.from = from;\n\n if (to)\n dateRangeFilters.to = to;\n\n if (rangeName)\n dateRangeFilters.rangeName = rangeName;\n\n return dateRangeFilters;\n }\n};","import { animals, colors, Config as UniqueNamesConfig, uniqueNamesGenerator } from 'unique-names-generator';\n\nimport { User } from 'libs/shared/interfaces';\nimport { PublicInteractiveUser } from 'libs/shared/interfaces/models/interactive-results/PublicInteractiveUser';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\n\nfunction getUniqueNamesConfig(id: string): UniqueNamesConfig {\n /**\n * Generate a seed that is unique to each user but changes every 5 minutes.\n * \n * We use a seed so that if the same user's name is anonymised multiple times\n * in quick succession (e.g. multiple renders), the same name will be returned each time.\n * \n * We change the seed every 5 minutes so that students don't always have the same name.\n */\n const seed = +`${id}${Math.floor((new Date()).getMinutes() / 5)}`;\n\n return {\n dictionaries: [ colors, animals ],\n separator: ' ',\n length: 2,\n style: 'capital',\n seed\n };\n}\n\nexport function anonymiseUserName(user: User | PublicInteractiveUser, shouldAnonymise: boolean): string {\n if (!user)\n return '';\n\n if (!shouldAnonymise)\n return 'profileId' in user ? user.name : UserHelper.getFullName(user);\n\n return uniqueNamesGenerator(getUniqueNamesConfig('profileId' in user ? user.profileId : user.id));\n}\n","import { AudienceQueryParams } from 'libs/shared/apps/analytics/interfaces/AudienceQueryParams';\n\nexport const getAudienceParams = (queryParams: AudienceQueryParams) => {\n const userId: string[] = [];\n const groupId: string[] = [];\n\n if (queryParams.users)\n userId.push(...queryParams.users);\n\n if (queryParams.classrooms)\n groupId.push(...queryParams.classrooms);\n\n if (queryParams.classroomGroups)\n groupId.push(...queryParams.classroomGroups);\n return {\n userId,\n groupId\n };\n};","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { DateRangeQueryParams } from 'libs/shared/apps/analytics/interfaces/DateRangeQueryParams';\nimport { FilterQueryParams } from 'libs/shared/apps/analytics/interfaces/FilterQueryParams';\nimport { DateRange } from 'libs/shared/interfaces';\nimport { AppRouteHelper } from 'libs/shared/utils/AppRouteHelper';\n\nconst namespace = 'shared.analyticsUtils';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function convertDateToUtcDateTimeString(date: Date): string {\n const utc = DateHelper.convertDateToUTC(date);\n return DateHelper.format(utc, 'YYYY-MM-DDTHH:mm:ss');\n}\n\nexport function getMinDate(): Date {\n return new Date(2021, 0, 1);\n}\n\nexport function getMaxDate(): Date {\n return new Date();\n}\n\nexport function getDefaultDateRange(dateRangePresets: DateRange[]): DateRange {\n return dateRangePresets.find(range => !!range.default);\n}\n\nexport function getPresetRangeByName(dateRangePresetss: DateRange[], rangeName: string): DateRange | undefined {\n if (!rangeName)\n return;\n\n const presets = dateRangePresetss;\n \n return presets.find(p => p.name === rangeName);\n}\n\nexport function getGenericDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastTwelveMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 11, 1),\n endDate: new Date(),\n default: true\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n }\n ];\n}\n\nexport function getInsightsDateRangePresets(): DateRange[] {\n const minDate = getMinDate();\n const currentYear = (new Date()).getFullYear();\n\n const isMinDateThisYear = currentYear === minDate.getFullYear();\n\n return [\n {\n name: getPhrase('today'),\n startDate: new Date(),\n endDate: new Date()\n },\n {\n name: getPhrase('thisMonth'),\n startDate: new Date(currentYear, new Date().getMonth(), 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastThreeMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 2, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastSixMonths'),\n startDate: new Date(currentYear, new Date().getMonth() - 5, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('thisYear'),\n startDate: new Date(currentYear, 0, 1),\n endDate: new Date()\n },\n {\n name: getPhrase('lastYear'),\n startDate: new Date(currentYear - 1, 0, 1),\n endDate: new Date(currentYear, 0, 0),\n disabled: isMinDateThisYear,\n tooltip: isMinDateThisYear ? getPhrase('lastYearDisabled') : ''\n },\n {\n name: getPhrase('allTime'),\n startDate: DateHelper.subtract(new Date(), 5, 'years'),\n endDate: new Date(),\n default: true\n }\n ];\n}\n\nexport function formatDateQueryParam(date: Date): string {\n return DateHelper.format(date, 'YYYY-MM-DD');\n}\n\nexport function getRouteQueryParams(dateRange: DateRange): DateRangeQueryParams {\n if (dateRange.name)\n return { rangeName: dateRange.name };\n\n return {\n from: formatDateQueryParam(dateRange.startDate),\n to: formatDateQueryParam(dateRange.endDate)\n };\n}\n\nexport function useGetDateRangeFromQueryParams(\n dateRangePresets: DateRange[],\n dateRangeQueryParams: DateRangeQueryParams\n): DateRange | null {\n const { to, from, rangeName } = dateRangeQueryParams;\n \n const presetRange = getPresetRangeByName(dateRangePresets, rangeName);\n\n if (presetRange) {\n if (!from && !to)\n return presetRange;\n\n /**\n * If a rangeName has been set, we don't use to and from so we remove them from the url params.\n */\n AppRouteHelper.updateParams(\n getRouteQueryParams(presetRange),\n { replace: true, merge: true, keysToRemove: [ 'from', 'to' ]}\n );\n return;\n }\n\n const defaultDateRange = getDefaultDateRange(dateRangePresets);\n\n /**\n * If a param is missing, or one of them isn't a valid date, short-circuit the logic below.\n */\n if (!from || !to || !DateHelper.isValid(from) || !DateHelper.isValid(to)) {\n AppRouteHelper.updateParams(\n getRouteQueryParams(defaultDateRange),\n { replace: true, merge: true, keysToRemove: ['rangeName']}\n );\n return;\n }\n\n let initialDateRangeValid = true;\n\n let startDate = DateHelper.convertDateToUTC(new Date(from));\n let endDate = DateHelper.convertDateToUTC(new Date(to));\n\n if (DateHelper.isBefore(startDate, getMinDate(), 'day')) {\n startDate = getMinDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(endDate, getMaxDate(), 'day')) {\n endDate = getMaxDate();\n initialDateRangeValid = false;\n }\n\n if (DateHelper.isAfter(startDate, endDate)) {\n startDate = defaultDateRange.startDate;\n endDate = defaultDateRange.endDate;\n initialDateRangeValid = false;\n }\n\n const dateRange: DateRange = {\n startDate,\n endDate,\n name: initialDateRangeValid\n ? rangeName || 'custom'\n : ''\n };\n\n if (initialDateRangeValid)\n return dateRange;\n\n /**\n * If one or both of the date params were invalid, we trigger a route update.\n */\n AppRouteHelper.updateParams(getRouteQueryParams(dateRange), { replace: true, merge: true, keysToRemove: ['rangeName']});\n}\n\nexport function getStartEndParams(\n dateRangePresetss: DateRange[],\n filterParams: FilterQueryParams\n): { start: string; end: string } {\n const getStartDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.startOf(date, 'day'));\n const getEndDate = (date: string) => convertDateToUtcDateTimeString(DateHelper.endOf(date, 'day'));\n\n const presetRange = getPresetRangeByName(dateRangePresetss, filterParams.rangeName);\n\n /**\n * If the user has chosen a preset range, lookup the start and end dates as they won't be\n * in the query params.\n */\n if (presetRange)\n return {\n start: getStartDate(formatDateQueryParam(presetRange.startDate)),\n end: getEndDate(formatDateQueryParam(presetRange.endDate))\n };\n\n /**\n * If they have chosen a custom date range, use their chosen start and end dates.\n */\n if (filterParams.from && filterParams.to)\n return {\n start: getStartDate(filterParams.from),\n end: getEndDate(filterParams.to)\n };\n\n /**\n * The below should never be hit\n */\n const defaultRange = getDefaultDateRange(dateRangePresetss);\n\n return {\n start: getStartDate(formatDateQueryParam(defaultRange.startDate)),\n end: getEndDate(formatDateQueryParam(defaultRange.endDate))\n };\n}","import React from 'react';\n\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { useViewModel } from 'libs/common/react/hooks/UseViewModel';\nimport { Flight } from 'libs/common/react/index';\nimport { DateHelper } from 'libs/common/react/utils/DateHelper';\n\nimport { useGetResultsTableData } from 'libs/shared/apps/analytics/components/student-results/student-results-table/StudentResultsTableUtils';\nimport { InteractiveResultsRequests } from 'libs/shared/apps/analytics/flight-requests/InteractiveResultsRequests';\nimport { useFetchInteractiveResults } from 'libs/shared/apps/analytics/hooks/UseFetchInteractiveResults';\nimport { InteractiveResultsReport } from 'libs/shared/apps/analytics/interfaces/requests/InteractiveResultsReport';\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 { getFormattedPercentage, getPercentageToFixed } from 'libs/shared/components/percentage-indicator/PercentageIndicatorUtils';\nimport { Popup } from 'libs/shared/components/popup/Popup';\nimport { PopupButtons } from 'libs/shared/components/popup/PopupButtons';\nimport { LanguageNamespaceContext, Text } from 'libs/shared/components/text/Text';\nimport { SharedViewModelKeys } from 'libs/shared/constants/SharedViewModelKeys';\nimport { InteractionCorrectness } from 'libs/shared/enums/InteractionCorrectness';\nimport { InteractiveRequests } from 'libs/shared/flight-requests/InteractiveRequests';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useHandleObjectError } from 'libs/shared/hooks/UseHandleObjectError';\nimport { useVerifiedEmailRequiredErrorHandler } from 'libs/shared/hooks/useVerifiedEmailRequiredErrorHandler';\nimport { CurrentUser, Interactive, InteractiveMetadata, PopupViewProps } from 'libs/shared/interfaces';\nimport { InteractiveCorrectnessHelper } from 'libs/shared/utils/InteractiveCorrectnessHelper';\nimport { getInteractions, getStudentResult } from 'libs/shared/utils/InteractiveHelper';\nimport { UserHelper } from 'libs/shared/utils/UserHelper';\n\nconst namespace = 'shared.generateReport';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nfunction getReportFriendlyDate(date: string): string {\n const localDate = DateHelper.convertUTCToLocal(date).toString();\n return DateHelper.format(localDate, 'Do MMMM YYYY');\n}\n\ninterface GenerateInteractiveResultsReportViewProps extends PopupViewProps {\n interactiveId: string;\n}\n\nexport function GenerateInteractiveResultsReportView(props: GenerateInteractiveResultsReportViewProps): JSX.Element {\n const [anonymiseUsers] = useViewModel<boolean>(SharedViewModelKeys.ANONYMISE_USERS);\n\n const alerts = useAlerts();\n const fetchAsync = Flight.useGetFetchAsync();\n\n const audienceAppLinkParams = AnalyticsFilterHelper.getAudienceAppLinkParams();\n const dateRangeAppLinkParams = AnalyticsFilterHelper.getDateRangeAppLinkParams();\n const startEndParams = getStartEndParams(getInsightsDateRangePresets(), dateRangeAppLinkParams);\n\n const [ showSpinner, setShowSpinner ] = React.useState(false);\n\n const { loading, handleGenerateReportError } = useVerifiedEmailRequiredErrorHandler();\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const interactiveMetadata = Flight.useBasicFetch<InteractiveMetadata>(\n InteractiveRequests.interactiveMetadata(props.interactiveId)\n );\n const interactive = Flight.useBasicFetch<Interactive>(interactiveMetadata.data?.interactiveId ?\n InteractiveRequests.interactive(interactiveMetadata.data.interactiveId) : null);\n const results = useFetchInteractiveResults(props.interactiveId, {\n ...startEndParams,\n ...getAudienceParams(audienceAppLinkParams)\n });\n\n useHandleObjectError([ interactive, interactiveMetadata, results ]);\n\n const interactions = getInteractions(interactive.data);\n\n const answerData = useGetResultsTableData(interactive.data, results.data, false, anonymiseUsers);\n\n function onClickGenerate(): void {\n setShowSpinner(true);\n\n const body: InteractiveResultsReport = {\n interactiveName: interactiveMetadata.data.name,\n userId: currentUser.data.id,\n customerId: currentUser.data.customerId,\n questions: interactions.map(i => i.name),\n rows: answerData.map(answer => {\n return {\n name: UserHelper.getFullName(answer.user),\n unanswered: answer.summary.unanswered,\n percentage: getFormattedPercentage(getPercentageToFixed(answer.summary.percentCorrect)),\n correct: answer.summary.correct,\n totalQuestions: answer.summary.answered + answer.summary.unanswered,\n results: interactions.map(interaction => {\n const correctness = InteractiveCorrectnessHelper.isInteractionCorrect(\n interaction,\n getStudentResult(answer)\n );\n\n switch (correctness) {\n case InteractionCorrectness.Correct:\n return getPhrase('correct');\n\n case InteractionCorrectness.Incorrect:\n return getPhrase('incorrect');\n\n case InteractionCorrectness.NotApplicable:\n return '-';\n\n case InteractionCorrectness.AwaitingMarking:\n return getPhrase('awaitingMarking');\n\n case InteractionCorrectness.UnAnswered:\n case InteractionCorrectness.Answered:\n default:\n return '';\n }\n })\n };\n })\n };\n\n fetchAsync(InteractiveResultsRequests.interactiveResultsReport(body))\n .then(() => {\n alerts.success(getPhrase('success'));\n })\n .catch((xhr: Xhr) => handleGenerateReportError(xhr, getPhrase('error'), getPhrase('noEmailError')))\n .finally(props.closePopup);\n }\n\n return (\n <LanguageNamespaceContext.Provider value={namespace}>\n <Popup\n title={getPhrase('title')}\n showLoadingSpinner={!currentUser.hasCompleted || loading}\n closePopup={props.closePopup}\n >\n <>\n <p>\n <Text phrase='description' />\n </p>\n <p>\n <Text phrase='dateRange' options={({\n dateFrom: getReportFriendlyDate(startEndParams.start),\n dateTo: getReportFriendlyDate(startEndParams.end)\n })} />\n </p>\n <p>\n <Text phrase='emailDescription' options={({ email: currentUser.data?.email })} />\n </p>\n <PopupButtons>\n <PopupButtons.Cancel onClick={props.closePopup} />\n <PopupButtons.Submit\n variant='dark'\n onClick={onClickGenerate}\n text={getPhrase('generateReport')}\n showSpinner={showSpinner}\n />\n </PopupButtons>\n </>\n </Popup>\n </LanguageNamespaceContext.Provider>\n );\n}","import React from 'react';\n\nimport { ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport {\n getCircleClassName,\n getCircleContainerClassName,\n getCircleRadius,\n getColouredLabelClassName,\n getFormattedPercentage,\n getPercentageToFixed,\n isPending,\n ProgressCircleSize\n} from './PercentageIndicatorUtils';\n\nimport styles from './percentage-indicator.scss';\n\ninterface ProgressCircleProps {\n size: ProgressCircleSize;\n scoreThresholds?: ScoreThresholds;\n percentage?: number;\n}\n\nfunction ProgressCircle(props: ProgressCircleProps): JSX.Element {\n const ref = React.useCallback((circle: SVGCircleElement) => {\n if (!circle)\n return;\n\n const radius = circle.r.baseVal.value;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - props.percentage * circumference;\n\n circle.style.strokeDasharray = `${circumference} ${circumference}`;\n circle.style.strokeDashoffset = offset.toString();\n }, [props.percentage]);\n\n return (\n <svg>\n <circle r={getCircleRadius(props.size)} className={styles.backgroundCircle} />\n {!isPending(props.percentage) &&\n <circle\n ref={ref}\n r={getCircleRadius(props.size)}\n className={getCircleClassName(props.percentage, props.scoreThresholds)}\n />\n }\n </svg>\n );\n}\n\nexport enum PercentageIndicatorLayout {\n CircleOnly = 'circle_only',\n LabelOnly = 'label_only',\n LabelBefore = 'label_before',\n LabelInside = 'label_inside'\n}\n\ninterface PercentageIndicatorProps {\n layout: PercentageIndicatorLayout;\n percentage?: number; // Between 0 and 1 or undefined for pending\n className?: string;\n customLabel?: string;\n scoreThresholds?: ScoreThresholds;\n size?: ProgressCircleSize;\n}\n\nPercentageIndicator.defaultProps = {\n layout: PercentageIndicatorLayout.CircleOnly\n};\n\nexport function PercentageIndicator(props: PercentageIndicatorProps): JSX.Element {\n const percentageToFixed = getPercentageToFixed(props.percentage);\n\n const size = props.size ||\n (props.layout === PercentageIndicatorLayout.LabelInside\n ? ProgressCircleSize.Large\n : ProgressCircleSize.Small\n );\n\n const label = props.customLabel || getFormattedPercentage(percentageToFixed);\n\n if (props.layout === PercentageIndicatorLayout.LabelOnly)\n return (\n <span className={getColouredLabelClassName(percentageToFixed)}>\n {label}\n </span>\n );\n\n return (\n <div className={`d-flex align-items-center justify-content-between ${props.className ?? ''}`}>\n {props.layout === PercentageIndicatorLayout.LabelBefore &&\n <span className='me-2'>\n {label}\n </span>\n }\n <div className={getCircleContainerClassName(size, percentageToFixed)}>\n <ProgressCircle percentage={percentageToFixed} size={size} scoreThresholds={props.scoreThresholds} />\n {props.layout === PercentageIndicatorLayout.LabelInside &&\n <span className={styles.centredPercentageText}>\n {label}\n </span>\n }\n </div>\n </div>\n );\n}","import { ScoreThresholdDefaults, ScoreThresholds } from 'libs/shared/constants/ScoreThresholds';\n\nimport styles from './percentage-indicator.scss';\n\n/**\n * Values for width and strokeWidth are taken from progress-circle.scss.\n * If either are changed, they must be updated in both places.\n */\nconst CIRCLE_WIDTH = 2; // rem\nconst CIRCLE_WIDTH_LG = 5.8; // rem\nconst CIRCLE_STROKE_WIDTH = 0.2; // rem\nconst CIRCLE_STROKE_WIDTH_LG = 0.36; // rem\n \nexport enum ProgressCircleSize {\n Small = 'small',\n Large = 'large',\n ExtraSmall = 'extraSmall'\n}\n\nconst ProgressCircleSizeMap = {\n [ProgressCircleSize.ExtraSmall]: {\n size: CIRCLE_WIDTH\n },\n [ProgressCircleSize.Small]: {\n size: CIRCLE_WIDTH\n },\n [ProgressCircleSize.Large]: {\n size: CIRCLE_WIDTH_LG\n }\n};\n\n/**\n * radius = width / 2 - strokeWidth * 2\n */\nexport function getCircleRadius(size: ProgressCircleSize): string {\n const width = ProgressCircleSizeMap[size].size;\n const strokeWidth = size === ProgressCircleSize.Large ? CIRCLE_STROKE_WIDTH_LG : CIRCLE_STROKE_WIDTH;\n return `${width / 2 - strokeWidth * 2}rem`;\n}\n \nexport function getCircleClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return styles.circleSuccess;\n \n if (percentage >= scoreThresholds.MODERATE)\n return styles.circleWarning;\n \n return styles.circleDanger;\n}\n \nexport function getColouredLabelClassName(\n percentage: number,\n scoreThresholds: ScoreThresholds = ScoreThresholdDefaults\n): string {\n if (percentage >= scoreThresholds.HIGH)\n return 'text-success';\n \n if (percentage >= scoreThresholds.MODERATE)\n return 'text-warning';\n \n return 'text-danger';\n}\n \nexport function getCircleContainerClassName(size: ProgressCircleSize, percentage?: number): string {\n let className = `d-inline-block ${styles.circleContainer}`;\n \n if (size === ProgressCircleSize.Large)\n className += ` ${styles.lgCircleContainer}`;\n\n if (size === ProgressCircleSize.ExtraSmall)\n className += ` ${styles.xsCircleContainer}`;\n\n if (isPending(percentage))\n className += ` ${styles.pendingCircle}`;\n \n return className;\n}\n\nexport function getPercentageToFixed(percentage?: number): number | undefined {\n if (isPending(percentage))\n return;\n \n return +percentage.toFixed(2);\n}\n \nexport function getFormattedPercentage(percentage?: number): string {\n if (isPending(percentage))\n return `--%`;\n\n return `${Math.round(percentage * 100)}%`;\n}\n\nexport function isPending(percentage?: number): boolean {\n return typeof percentage !== 'number';\n}","export interface ScoreThresholds {\n HIGH: number;\n MODERATE: number;\n}\n\nexport const ScoreThresholdDefaults: ScoreThresholds = {\n HIGH: 0.75,\n MODERATE: 0.5\n};\n\nexport const ScoreThresholdInsights: ScoreThresholds = {\n HIGH: 0.7,\n MODERATE: 0.7\n};","import { BaseError } from 'libs/common/backbone/core/BaseError';\nimport { HttpStatus } from 'libs/common/backbone/enums/HttpStatus';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Core } from 'libs/common/core';\n\nimport { NotFoundError } from 'libs/shared/errors/general/not-found/NotFoundError';\nimport { PrivateResourceError } from 'libs/shared/errors/general/private-resource/PrivateResourceError';\nimport { RegionLockedResourceError } from 'libs/shared/errors/general/region-locked-resource/RegionLockedResourceError';\nimport { UnspecifiedError } from 'libs/shared/errors/general/unspecified-error/UnspecifiedError';\nimport { VideoTypes } from 'libs/shared/interfaces';\n\nexport interface HttpErrorMap {\n notFound?: new () => BaseError;\n forbidden?: {\n rating?: new (description: string) => BaseError;\n yearLevel?: new (description: string) => BaseError;\n region?: new () => BaseError;\n privacy?: new (video?: VideoTypes) => BaseError;\n };\n badRequest?: new () => BaseError;\n internalServerError?: new () => BaseError;\n}\n\nexport type IgnoreHttpErrorMap = {\n [key in keyof HttpErrorMap]: boolean;\n};\n\nconst defaultErrors: HttpErrorMap = {\n notFound: NotFoundError,\n forbidden: {\n rating: PrivateResourceError,\n yearLevel: PrivateResourceError,\n region: RegionLockedResourceError,\n privacy: PrivateResourceError\n },\n badRequest: UnspecifiedError,\n internalServerError: UnspecifiedError\n};\n\nexport function handleHttpError(\n info: HttpStatus | Xhr,\n customErrorMap: HttpErrorMap = {},\n /**\n * Prevent certain errors in the errorMap from being thrown\n * so that you may implement your own handler\n */\n ignoreMap: IgnoreHttpErrorMap = {}\n): void {\n if (!info)\n return;\n\n let statusCode: HttpStatus;\n\n if (typeof(info) === 'number') {\n statusCode = info;\n } else {\n statusCode = info.status;\n }\n\n const errorMap = {\n ...defaultErrors,\n ...customErrorMap\n };\n\n if (!statusCode)\n return;\n\n if (!Core.ErrorHelper.isStatusCodeError(statusCode))\n return;\n\n if (statusCode === HttpStatus.InternalServer) {\n if (!ignoreMap.internalServerError)\n Core.ErrorHelper.throw(new UnspecifiedError());\n return;\n }\n\n if (statusCode === HttpStatus.NotFound) {\n if (!ignoreMap.notFound)\n Core.ErrorHelper.throw(new errorMap.notFound());\n return;\n }\n\n if (statusCode === HttpStatus.Forbidden) {\n /**\n * TODO: Work out how to go about handling all forbidden errors, such as region locking, year levels,\n * ratings, and privacy.\n */\n if (!ignoreMap.forbidden)\n Core.ErrorHelper.throw(new errorMap.forbidden.privacy());\n return;\n }\n\n if (!ignoreMap.badRequest)\n Core.ErrorHelper.throw(new errorMap.badRequest());\n}\n\nexport function handleXhrError(xhr: Xhr, customErrorMap?: HttpErrorMap): void {\n handleHttpError(xhr.status, customErrorMap);\n}","import { useEffect } from 'react';\n\nimport { Flight } from 'libs/common/flight';\n\nimport { handleHttpError, HttpErrorMap, IgnoreHttpErrorMap } from 'libs/shared/errors/handlers/HttpErrorHandlers';\n\nfunction generateCacheKey(flightObjs: Array<Flight.Response<any>>): string {\n return flightObjs.map(obj => obj.statusCode).join(':');\n}\n\n// TODO: Change this to just `useHandleHttpError` and only accept a status code.\nexport function useHandleObjectError(\n _flightObjs: Flight.Response<any> | Array<Flight.Response<any>>,\n customErrors?: HttpErrorMap,\n ignoreErrors?: IgnoreHttpErrorMap\n): void {\n const flightObjs = Array.isArray(_flightObjs) ? _flightObjs : [_flightObjs];\n\n useEffect(() => {\n flightObjs.forEach(obj => {\n handleHttpError(obj.statusCode, customErrors, ignoreErrors);\n });\n }, [ generateCacheKey(flightObjs), customErrors, ignoreErrors ]);\n}","import { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\n\nimport { DialogError } from 'libs/shared/errors/primitives/DialogError';\nimport { DialogOptions } from 'libs/shared/interfaces';\n\nconst namespace = 'shared.verifiedEmailError';\n\nexport class VerifiedEmailRequiredError extends DialogError {\n public message: string;\n public liteUrl: string;\n public hasLite: boolean;\n\n constructor(message: string, liteUrl: string, hasLite: boolean) {\n super('VerifiedEmailRequiredError');\n\n this.message = message;\n this.liteUrl = liteUrl;\n this.hasLite = hasLite;\n }\n\n // @ts-ignore\n public get name(): string {\n return 'VerifiedEmailRequiredError';\n }\n\n // @ts-ignore\n public get dialogOptions(): DialogOptions {\n const href = UrlHelper.safeUrlConcat(this.liteUrl, 'settings/account');\n\n return {\n title: LanguageService.getPhrase(namespace, 'heading'),\n text: this.hasLite\n ? `${this.message} ${LanguageService.getPhrase(namespace, 'visitSettings', { href })}`\n : this.message,\n buttons: [{\n text: LanguageService.getPhrase(namespace, 'close'),\n className: 'btn btn-dark',\n success: true\n }]\n };\n }\n}","import { Core } from 'libs/common/backbone/index';\nimport { Xhr } from 'libs/common/backbone/interfaces';\nimport { Flight } from 'libs/common/react/index';\n\nimport { ProductId } from 'libs/shared/enums/ProductId';\nimport { VerifiedEmailRequiredError } from 'libs/shared/errors/general/verified-email/VerifiedEmailRequiredError';\nimport { ConfigRequests } from 'libs/shared/flight-requests/ConfigRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { useProducts } from 'libs/shared/hooks/UseProducts';\nimport { Config } from 'libs/shared/interfaces';\n\nexport function useVerifiedEmailRequiredErrorHandler() {\n const alerts = useAlerts();\n const { hasProduct, isLoadingProducts } = useProducts();\n const config = Flight.useBasicFetch<Config>(ConfigRequests.config());\n\n function handleGenerateReportError(xhr: Xhr, message: string, noEmailError: string) {\n if (!xhr.responseJSON || xhr.responseJSON?.type !== 'no-email') {\n alerts.error(message);\n return;\n }\n\n Core.ErrorHelper.throw(\n new VerifiedEmailRequiredError(noEmailError, config.data.liteUrl, hasProduct(ProductId.Primary))\n );\n }\n\n return {\n handleGenerateReportError,\n loading: !config.hasCompleted || isLoadingProducts\n };\n}","import { AnalyticsRequestFilter } from 'libs/shared/interfaces';\n\nexport function getAnalyticsRequestKey(baseKey: string, filter: AnalyticsRequestFilter, sharerId?: string): string {\n let key = `${baseKey}:${filter.start}:${filter.end}`;\n\n const userIdKey = Array.isArray(filter.userId) ? filter.userId.sort().join(':') : filter.userId;\n const groupIdKey = Array.isArray(filter.groupId) ? filter.groupId.sort().join(':') : filter.groupId;\n\n if (userIdKey)\n key += `:${userIdKey}`;\n\n if (groupIdKey)\n key += `:${groupIdKey}`;\n\n if (sharerId)\n key += `:${sharerId}`;\n\n return key;\n}","import { Core } from 'libs/common/core';\nimport { HashObject } from 'libs/common/react/interfaces';\nimport { ObjectHelper } from 'libs/common/react/utils/ObjectHelper';\n\nimport { ContextService } from 'libs/shared/services/ContextService';\n\ninterface UpdateParamsOptions extends Core.AppLinkOptions {\n merge?: boolean;\n keysToRemove?: string[]\n}\n\nexport const AppRouteHelper = {\n /**\n * Utility to update the params on the current appRoute.\n * \n * This is built on top of ContextService rather than build into AppLink\n * as we will generally only want to update params on appRoutes, not appLinks.\n */\n updateParams(params: HashObject, options?: UpdateParamsOptions): void {\n const { appLink } = ContextService.getCurrentRoute();\n\n let currentParams = typeof(appLink.params) === 'string'\n ? Core.LocationUtils.DeserializeQueryParams(appLink.params)\n : appLink.params as HashObject;\n\n if (options.keysToRemove)\n currentParams = ObjectHelper.omit(currentParams, options.keysToRemove);\n\n const updatedParams = options?.merge\n ? { ...currentParams, ...params }\n : params;\n\n const updatedAppLink = {\n ...appLink,\n params: updatedParams\n };\n\n /**\n * This prevents us pointlessly re-triggering if we're already on the right applink.\n */\n if (ObjectHelper.isEqual(appLink, updatedAppLink))\n return;\n \n Core.AppLinkHelper.trigger(updatedAppLink, ObjectHelper.omit(options, [ 'merge', 'keysToRemove' ]));\n }\n};","// extracted by mini-css-extract-plugin\nexport default {\"circleContainer\":\"p8Vgz\",\"backgroundCircle\":\"asGGE\",\"circleSuccess\":\"PXLNj\",\"circleWarning\":\"ZckRN\",\"circleDanger\":\"slBRg\",\"lgCircleContainer\":\"N8KCI\",\"xsCircleContainer\":\"RPqZ2\",\"pendingCircle\":\"DKrcq\",\"centredPercentageText\":\"tpmLR\"};"],"names":["getInteractiveResultFilters","currentUser","filter","currentUserId","id","currentCustomerId","customerId","dateRange","start","end","userIds","userId","classroomsAndGroups","groupId","InteractiveResultsRequests","interactiveResultSet","interactiveId","interactiveMetadataId","includePublicResults","success","error","always","url","key","data","type","normalize","formatData","students","map","student","name","profileId","publicUser","mark","answerId","resultId","invalidationKeys","pendingReviews","interactiveResultsReport","useFetchInteractiveResults","requestFilter","interactiveMetadata","interactive","shouldFetchResults","I","AnalyticsFilterHelper","getAudienceAppLinkParams","appLink","params","users","classrooms","classroomGroups","getParam","param","Array","isArray","audienceFilters","getDateRangeAppLinkParams","from","to","rangeName","dateRangeFilters","anonymiseUserName","user","shouldAnonymise","seed","Math","floor","Date","getMinutes","dictionaries","separator","length","style","getAudienceParams","queryParams","push","getPhrase","convertDateToUtcDateTimeString","date","utc","getMinDate","getMaxDate","getDefaultDateRange","dateRangePresets","find","range","getPresetRangeByName","dateRangePresetss","p","getInsightsDateRangePresets","minDate","currentYear","getFullYear","isMinDateThisYear","startDate","endDate","getMonth","disabled","tooltip","default","formatDateQueryParam","getRouteQueryParams","useGetDateRangeFromQueryParams","dateRangeQueryParams","presetRange","replace","merge","keysToRemove","defaultDateRange","initialDateRangeValid","getStartEndParams","filterParams","getStartDate","getEndDate","defaultRange","namespace","getReportFriendlyDate","localDate","toString","GenerateInteractiveResultsReportView","props","anonymiseUsers","alerts","fetchAsync","audienceAppLinkParams","dateRangeAppLinkParams","startEndParams","showSpinner","setShowSpinner","loading","handleGenerateReportError","results","interactions","answerData","value","title","showLoadingSpinner","hasCompleted","closePopup","phrase","options","dateFrom","dateTo","email","onClick","variant","body","interactiveName","questions","i","rows","answer","unanswered","summary","percentage","percentCorrect","correct","totalQuestions","answered","interaction","then","xhr","text","PercentageIndicatorLayout","ProgressCircle","ref","circle","radius","r","baseVal","circumference","PI","offset","strokeDasharray","strokeDashoffset","size","className","scoreThresholds","PercentageIndicator","percentageToFixed","layout","LabelInside","label","customLabel","LabelOnly","LabelBefore","defaultProps","CircleOnly","ProgressCircleSize","CIRCLE_STROKE_WIDTH","CIRCLE_STROKE_WIDTH_LG","ProgressCircleSizeMap","ExtraSmall","Small","Large","getCircleRadius","width","strokeWidth","getCircleClassName","HIGH","MODERATE","getColouredLabelClassName","getCircleContainerClassName","isPending","getPercentageToFixed","toFixed","getFormattedPercentage","round","ScoreThresholdDefaults","ScoreThresholdInsights","defaultErrors","notFound","forbidden","rating","yearLevel","region","privacy","badRequest","internalServerError","handleHttpError","info","customErrorMap","ignoreMap","statusCode","status","errorMap","generateCacheKey","flightObjs","obj","join","useHandleObjectError","_flightObjs","customErrors","ignoreErrors","useEffect","forEach","VerifiedEmailRequiredError","message","liteUrl","hasLite","href","UrlHelper","this","LanguageService","buttons","DialogError","useVerifiedEmailRequiredErrorHandler","hasProduct","isLoadingProducts","config","ConfigRequests","noEmailError","responseJSON","ProductId","getAnalyticsRequestKey","baseKey","sharerId","userIdKey","sort","groupIdKey","AppRouteHelper","updateParams","currentParams","updatedParams","updatedAppLink"],"sourceRoot":""}
@@ -1,3 +1,3 @@
1
- /*! For license information please see 4014-4225ce1eb6-lite.chunk.js.LICENSE.txt */
2
- "use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[4014],{81803:(t,e,r)=>{r.d(e,{d:()=>m});var n=r(32735),o=r(81886),i=r(23481),a=r(49935),c=r(22902),l=r(14070),u=r(97291),s=r(96368);function f(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var p="settings.settingsLayout",d=function(t){var e=(0,c.T)().hasPermissions,r=(0,s.e)();if(t)return e(t);var n=o.Q.C$.getCurrentAppLink();return n.application!==u.O.SETTINGS||r.some((function(t){return t.modules.some((function(t){return"appLink"in t&&t.appLink.action===n.action}))}))};function m(t){var e,r=d(t.requiredPermissions);if(n.useEffect((function(){r||o.Q.C$.trigger({application:u.O.SETTINGS,action:l.e.Settings.HOME},{replace:!0})}),[r]),!r)return n.createElement(n.Fragment,null);var c,s=t.breadcrumbs.map((function(e,r){return{name:e,appLink:{application:u.O.SETTINGS,action:l.e.Settings.HOME},active:r===t.breadcrumbs.length-1}}));return n.createElement("div",{className:"px-3"},n.createElement("div",{className:"d-flex align-items-center justify-content-between"},n.createElement("h1",{className:"h2"},t.heading),null===(e=t.headingButton)||void 0===e?void 0:e.call(t)),n.createElement("div",{className:"pb-3"},n.createElement(a.Oo,{breadcrumbs:[{name:i.T.getPhrase(p,"settingsBreadcrumb"),appLink:{application:u.O.SETTINGS,action:l.e.Settings.HOME}}].concat((c=s,function(t){if(Array.isArray(t))return f(t)}(c)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(c)||function(t,e){if(t){if("string"==typeof t)return f(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?f(t,e):void 0}}(c)||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.description&&n.createElement(n.Fragment,null,n.createElement("p",null,t.description),n.createElement("hr",null)),t.children)}},24014:(t,e,r)=>{r.r(e),r.d(e,{NotificationSettingsView:()=>$});var n=r(32735),o=r(81886),i=r(23481),a=r(20354),c=r(49985),l=r(65858),u=r(74254),s=r(15611),f=r(83345),p=r(16714),d=r(77963),m=r(65728),h=r(31949),y=r(69883),g=r(22902),v=r(79612),b=r(37802),E=r(14070),w=r(97291);const S={images:"lgrLY",group:"oDj7s",groupContainer:"uAqY0",description:"fDHV0",title:"Z91M9",content:"KvFr1",pill:"_Nl44"};function N(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var x=["anytime","weekly","monthly","snooze"],T="settings.messageFrequency",O=i.T.encloseNamespace(T);function _(t){var e,r,o=t.currentFrequency||"anytime",i=(e=n.useState(o),r=2,function(t){if(Array.isArray(t))return t}(e)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,c=[],l=!0,u=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);l=!0);}catch(t){u=!0,o=t}finally{try{if(!l&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,r)||function(t,e){if(t){if("string"==typeof t)return N(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?N(t,e):void 0}}(e,r)||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.")}()),a=i[0],c=i[1];return n.createElement(n.Fragment,null,n.createElement("h4",{className:"mt-3"},O("messageFrequency")),n.createElement(f.x,{namespace:T,phrase:"messageFrequencyDescription"}),n.createElement("div",{className:"py-3 text-center d-flex justify-content-start"},n.createElement("div",{className:"btn-group mb-1 d-flex flex-wrap ".concat(S.pill)},x.map((function(e){return n.createElement("button",{key:e,className:(r=e,o="btn border",(o+=r===a?" btn-dark":" btn-outline-dark")+" px-5 col-12 col-md-3"),onClick:function(r){return function(e,r){e.preventDefault(),c(r),t.updateMessageFrequency(r.toLowerCase())}(r,e)},type:"button"},O(e));var r,o})))))}var L=r(83523),k=r(99742);function A(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var j=i.T.encloseNamespace("settings.notificationSettings"),C={"account-updates":{title:j("accountUpdates"),description:j("accountUpdatesDescription"),note:j("accountUpdatesNote"),tooltip:j("tooltip"),imageUrl:k.W.Notifications.ACCOUNT_UPDATES,colour:"bg-light-orange",disabled:!0,active:!0},core_product_cv_product_news:{title:j("productNews"),description:j("productNewsDescription"),imageUrl:k.W.Notifications.PRODUCT_NEWS,colour:"bg-light-purple",disabled:!1},core_product_cv_content_updates:{title:j("contentUpdates"),description:j("contentUpdatesDescription"),imageUrl:k.W.Notifications.CONTENT_UPDATES,colour:"bg-light-teal",disabled:!1},core_product_cv_recommendations:{title:j("recommendations"),description:j("recommendationsDescription"),imageUrl:k.W.Notifications.RECOMMENDATIONS,colour:"bg-light-orange",disabled:!1},core_product_cv_product_tips:{title:j("productTips"),description:j("productTipsDescription"),imageUrl:k.W.Notifications.PRODUCT_TIPS,colour:"bg-light-pink",disabled:!1}};function F(t){var e,r,o=C[t.type],i=(e=n.useState(t.toggled),r=2,function(t){if(Array.isArray(t))return t}(e)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,c=[],l=!0,u=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);l=!0);}catch(t){u=!0,o=t}finally{try{if(!l&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,r)||function(t,e){if(t){if("string"==typeof t)return A(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?A(t,e):void 0}}(e,r)||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.")}()),a=i[0],c=i[1];return o?n.createElement("div",{className:"col-md-6 p-0"},n.createElement("div",{className:"".concat(S.groupContainer," d-flex flex-row h-100")},n.createElement("div",{className:"row border m-0 w-100 rounded-3"},n.createElement("div",{className:"col-3 d-flex justify-content-center align-items-center h-100 rounded-start-3 ".concat(o.colour)},n.createElement("img",{src:o.imageUrl,alt:o.title,role:"presentation",className:"img-fluid ".concat(S.images," w-50")})),n.createElement("div",{className:"py-3 ".concat(S.content),style:{width:"64%"}},n.createElement("p",{className:"fw-medium ".concat(S.title)},o.title),n.createElement("p",{className:"".concat(S.description)},o.description),o.note&&n.createElement("small",null,o.note)),n.createElement("div",{className:"py-3 d-flex justify-content-end align-items-start",style:{width:"11%"}},n.createElement(L.Z,{onClick:function(){return function(e){c(!a),t.setToggle(e,!a)}(o.title)},disabled:o.disabled,on:a||o.active,showStateWhenDisabled:!0,tooltipText:o.tooltip}))))):n.createElement(n.Fragment,null)}var P=r(81803),U=r(99940),I=r(97395),G={getSubscriptionPreferences:function(){return{key:"current:subscriptions",url:I._.urlBuilder("{gateway}/v1/users/me/subscription-groups",{productId:"lite"}),type:U.k.GET}},setSubscriptionPreference:function(t){return{key:"set:subscriptions",url:"{gateway}/v1/users/me/subscription-groups",data:t,type:U.k.PUT,invalidationKeys:["current:subscriptions"]}}};function D(t){return D="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},D(t)}function M(){M=function(){return e};var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",l=i.toStringTag||"@@toStringTag";function u(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{u({},"")}catch(t){u=function(t,e,r){return t[e]=r}}function s(t,e,r,n){var i=e&&e.prototype instanceof g?e:g,a=Object.create(i.prototype),c=new A(n||[]);return o(a,"_invoke",{value:O(t,r,c)}),a}function f(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=s;var p="suspendedStart",d="suspendedYield",m="executing",h="completed",y={};function g(){}function v(){}function b(){}var E={};u(E,a,(function(){return this}));var w=Object.getPrototypeOf,S=w&&w(w(j([])));S&&S!==r&&n.call(S,a)&&(E=S);var N=b.prototype=g.prototype=Object.create(E);function x(t){["next","throw","return"].forEach((function(e){u(t,e,(function(t){return this._invoke(e,t)}))}))}function T(t,e){function r(o,i,a,c){var l=f(t[o],t,i);if("throw"!==l.type){var u=l.arg,s=u.value;return s&&"object"==D(s)&&n.call(s,"__await")?e.resolve(s.__await).then((function(t){r("next",t,a,c)}),(function(t){r("throw",t,a,c)})):e.resolve(s).then((function(t){u.value=t,a(u)}),(function(t){return r("throw",t,a,c)}))}c(l.arg)}var i;o(this,"_invoke",{value:function(t,n){function o(){return new e((function(e,o){r(t,n,e,o)}))}return i=i?i.then(o,o):o()}})}function O(e,r,n){var o=p;return function(i,a){if(o===m)throw Error("Generator is already running");if(o===h){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var l=_(c,n);if(l){if(l===y)continue;return l}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===p)throw o=h,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=m;var u=f(e,r,n);if("normal"===u.type){if(o=n.done?h:d,u.arg===y)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(o=h,n.method="throw",n.arg=u.arg)}}}function _(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator.return&&(r.method="return",r.arg=t,_(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=f(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function L(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function k(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(L,this),this.reset(!0)}function j(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function r(){for(;++o<e.length;)if(n.call(e,o))return r.value=e[o],r.done=!1,r;return r.value=t,r.done=!0,r};return i.next=i}}throw new TypeError(D(e)+" is not iterable")}return v.prototype=b,o(N,"constructor",{value:b,configurable:!0}),o(b,"constructor",{value:v,configurable:!0}),v.displayName=u(b,l,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===v||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,u(t,l,"GeneratorFunction")),t.prototype=Object.create(N),t},e.awrap=function(t){return{__await:t}},x(T.prototype),u(T.prototype,c,(function(){return this})),e.AsyncIterator=T,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new T(s(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},x(N),u(N,l,"Generator"),u(N,a,(function(){return this})),u(N,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},e.values=j,A.prototype={constructor:A,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(k),!e)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=t)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var r=this;function o(n,o){return c.type="throw",c.arg=e,r.next=n,o&&(r.method="next",r.arg=t),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var l=n.call(a,"catchLoc"),u=n.call(a,"finallyLoc");if(l&&u){if(this.prev<a.catchLoc)return o(a.catchLoc,!0);if(this.prev<a.finallyLoc)return o(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return o(a.catchLoc,!0)}else{if(!u)throw Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return o(a.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,y):this.complete(a)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),y},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),k(r),y}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;k(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function(e,r,n){return this.delegate={iterator:j(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}var q=function(t,e,r,n){return new(r||(r=Promise))((function(o,i){function a(t){try{l(n.next(t))}catch(t){i(t)}}function c(t){try{l(n.throw(t))}catch(t){i(t)}}function l(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,c)}l((n=n.apply(t,e||[])).next())}))},W="settings.notificationSettings",H=i.T.encloseNamespace(W);function $(){var t,e=(0,g.T)().hasPermissions,r=a.a.useBasicFetch(h.N.currentUser()),i=(0,b.r)(l.LZ.Settings),S=i.messageFrequencyOption,N=i.updateSetting,x=(0,y.Z)();(0,v.M)({title:"Notification Settings"});var T=a.a.useBasicFetch(G.getSubscriptionPreferences()),O=a.a.useGetFetchAsync();return e(p.C.StudentExperience)&&o.Q.C$.trigger({application:w.O.SETTINGS,action:E.e.Settings.HOME},{replace:!0}),(null===(t=T.data)||void 0===t?void 0:t.length)&&r.data?n.createElement(P.d,{heading:H("heading"),breadcrumbs:[H("heading")]},n.createElement("div",{className:"w-100 d-flex justify-content-center flex-column"},n.createElement("h4",null,H("label")),n.createElement("p",null,H("description")),n.createElement("p",null,n.createElement(f.x,{namespace:W,phrase:"updateEmailStart"})," ",n.createElement(s.F,{appLink:{application:w.O.SETTINGS,action:E.e.Settings.ACCOUNT},className:"text-decoration-underline"},H("updateEmailHref"))," ",n.createElement(f.x,{namespace:W,phrase:"updateEmailEnding"}))),n.createElement("div",{className:"row"},n.createElement(F,{type:"account-updates"}),T.data.map((function(t){return n.createElement(F,{key:t.id,type:t.type,toggled:t.subscribed,setToggle:function(e,r){return function(t,e,r){return q(this,void 0,void 0,M().mark((function n(){return M().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,O(G.setSubscriptionPreference({subscriptionGroupId:t,subscribed:r})).then((function(){var n=e.toLowerCase().trim();x.success(H(r?"alert-subscribed":"alert-unsubscribed",{name:n})),c.k.logUserAction({id:t,name:n.replace(" ","_"),value:r},{location:l.LZ.NotificationSettings,entity:u.py.NotificationSetting,descriptor:u.MK.Email,actionType:u.Vw.Edit})})).catch((function(){x.error("Could not update subscription preference")}));case 2:case"end":return n.stop()}}),n)})))}(t.id,e,r)}})}))),n.createElement(_,{updateMessageFrequency:function(t){if(t!==S){var e={name:m.E.MessageFrequencyOption,value:t,kind:d.g.Permanent};N(r.data.id,e)}},currentFrequency:S})):n.createElement(n.Fragment,null)}}}]);
3
- //# sourceMappingURL=4014-4225ce1eb6-lite.chunk.js.map
1
+ /*! For license information please see 4014-3eccce2f89-lite.chunk.js.LICENSE.txt */
2
+ "use strict";(self.webpackChunk_clickview_lite=self.webpackChunk_clickview_lite||[]).push([[4014],{81803:(t,e,r)=>{r.d(e,{d:()=>m});var n=r(32735),o=r(81886),i=r(23481),a=r(49935),c=r(22902),l=r(14070),u=r(97291),s=r(96368);function f(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var p="settings.settingsLayout",d=function(t){var e=(0,c.T)().hasPermissions,r=(0,s.e)();if(t)return e(t);var n=o.Q.C$.getCurrentAppLink();return n.application!==u.O.SETTINGS||r.some((function(t){return t.modules.some((function(t){return"appLink"in t&&t.appLink.action===n.action}))}))};function m(t){var e,r=d(t.requiredPermissions);if(n.useEffect((function(){r||o.Q.C$.trigger({application:u.O.SETTINGS,action:l.e.Settings.HOME},{replace:!0})}),[r]),!r)return n.createElement(n.Fragment,null);var c,s=t.breadcrumbs.map((function(e,r){return{name:e,appLink:{application:u.O.SETTINGS,action:l.e.Settings.HOME},active:r===t.breadcrumbs.length-1}}));return n.createElement("div",{className:"px-3"},n.createElement("div",{className:"d-flex align-items-center justify-content-between"},n.createElement("h1",{className:"h2"},t.heading),null===(e=t.headingButton)||void 0===e?void 0:e.call(t)),n.createElement("div",{className:"pb-3"},n.createElement(a.Oo,{breadcrumbs:[{name:i.T.getPhrase(p,"settingsBreadcrumb"),appLink:{application:u.O.SETTINGS,action:l.e.Settings.HOME}}].concat((c=s,function(t){if(Array.isArray(t))return f(t)}(c)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(c)||function(t,e){if(t){if("string"==typeof t)return f(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?f(t,e):void 0}}(c)||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.description&&n.createElement(n.Fragment,null,n.createElement("p",null,t.description),n.createElement("hr",null)),t.children)}},24014:(t,e,r)=>{r.r(e),r.d(e,{NotificationSettingsView:()=>$});var n=r(32735),o=r(81886),i=r(23481),a=r(20354),c=r(49985),l=r(65858),u=r(74254),s=r(15611),f=r(83345),p=r(16714),d=r(77963),m=r(65728),h=r(31949),y=r(69883),g=r(22902),v=r(79612),b=r(37802),E=r(14070),w=r(97291);const S={images:"lgrLY",group:"oDj7s",groupContainer:"uAqY0",description:"fDHV0",title:"Z91M9",content:"KvFr1",pill:"_Nl44"};function N(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var x=["anytime","weekly","monthly","snooze"],T="settings.messageFrequency",O=i.T.encloseNamespace(T);function _(t){var e,r,o=t.currentFrequency||"anytime",i=(e=n.useState(o),r=2,function(t){if(Array.isArray(t))return t}(e)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,c=[],l=!0,u=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);l=!0);}catch(t){u=!0,o=t}finally{try{if(!l&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,r)||function(t,e){if(t){if("string"==typeof t)return N(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?N(t,e):void 0}}(e,r)||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.")}()),a=i[0],c=i[1];return n.createElement(n.Fragment,null,n.createElement("h4",{className:"mt-3"},O("messageFrequency")),n.createElement(f.x,{namespace:T,phrase:"messageFrequencyDescription"}),n.createElement("div",{className:"py-3 text-center d-flex justify-content-start"},n.createElement("div",{className:"btn-group mb-1 d-flex flex-wrap ".concat(S.pill)},x.map((function(e){return n.createElement("button",{key:e,className:(r=e,o="btn border",(o+=r===a?" btn-dark":" btn-outline-dark")+" px-5 col-12 col-md-3"),onClick:function(r){return function(e,r){e.preventDefault(),c(r),t.updateMessageFrequency(r.toLowerCase())}(r,e)},type:"button"},O(e));var r,o})))))}var L=r(83523),k=r(99742);function A(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}var j=i.T.encloseNamespace("settings.notificationSettings"),C={"account-updates":{title:j("accountUpdates"),description:j("accountUpdatesDescription"),note:j("accountUpdatesNote"),tooltip:j("tooltip"),imageUrl:k.W.Notifications.ACCOUNT_UPDATES,colour:"bg-light-orange",disabled:!0,active:!0},core_product_cv_product_news:{title:j("productNews"),description:j("productNewsDescription"),imageUrl:k.W.Notifications.PRODUCT_NEWS,colour:"bg-light-purple",disabled:!1},core_product_cv_content_updates:{title:j("contentUpdates"),description:j("contentUpdatesDescription"),imageUrl:k.W.Notifications.CONTENT_UPDATES,colour:"bg-light-teal",disabled:!1},core_product_cv_recommendations:{title:j("recommendations"),description:j("recommendationsDescription"),imageUrl:k.W.Notifications.RECOMMENDATIONS,colour:"bg-light-orange",disabled:!1},core_product_cv_product_tips:{title:j("productTips"),description:j("productTipsDescription"),imageUrl:k.W.Notifications.PRODUCT_TIPS,colour:"bg-light-pink",disabled:!1}};function F(t){var e,r,o=C[t.type],i=(e=n.useState(t.toggled),r=2,function(t){if(Array.isArray(t))return t}(e)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,c=[],l=!0,u=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);l=!0);}catch(t){u=!0,o=t}finally{try{if(!l&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,r)||function(t,e){if(t){if("string"==typeof t)return A(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?A(t,e):void 0}}(e,r)||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.")}()),a=i[0],c=i[1];return o?n.createElement("div",{className:"col-md-6 p-0"},n.createElement("div",{className:"".concat(S.groupContainer," d-flex flex-row h-100")},n.createElement("div",{className:"row border m-0 w-100 rounded-3"},n.createElement("div",{className:"col-3 d-flex justify-content-center align-items-center h-100 rounded-start-3 ".concat(o.colour)},n.createElement("img",{src:o.imageUrl,alt:o.title,role:"presentation",className:"img-fluid ".concat(S.images," w-50")})),n.createElement("div",{className:"py-3 ".concat(S.content),style:{width:"64%"}},n.createElement("p",{className:"fw-medium ".concat(S.title)},o.title),n.createElement("p",{className:"".concat(S.description)},o.description),o.note&&n.createElement("small",null,o.note)),n.createElement("div",{className:"py-3 d-flex justify-content-end align-items-start",style:{width:"11%"}},n.createElement(L.Z,{onClick:function(){return function(e){c(!a),t.setToggle(e,!a)}(o.title)},disabled:o.disabled,on:a||o.active,showStateWhenDisabled:!0,tooltipText:o.tooltip}))))):n.createElement(n.Fragment,null)}var U=r(81803),I=r(99940),P=r(97395),G={getSubscriptionPreferences:function(){return{key:"current:subscriptions",url:P._.urlBuilder("{gateway}/v1/users/me/subscription-groups",{productId:"lite"}),type:I.k.GET}},setSubscriptionPreference:function(t){return{key:"set:subscriptions",url:"{gateway}/v1/users/me/subscription-groups",data:t,type:I.k.PUT,invalidationKeys:["current:subscriptions"]}}};function D(t){return D="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},D(t)}function M(){M=function(){return e};var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",l=i.toStringTag||"@@toStringTag";function u(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{u({},"")}catch(t){u=function(t,e,r){return t[e]=r}}function s(t,e,r,n){var i=e&&e.prototype instanceof g?e:g,a=Object.create(i.prototype),c=new A(n||[]);return o(a,"_invoke",{value:O(t,r,c)}),a}function f(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=s;var p="suspendedStart",d="suspendedYield",m="executing",h="completed",y={};function g(){}function v(){}function b(){}var E={};u(E,a,(function(){return this}));var w=Object.getPrototypeOf,S=w&&w(w(j([])));S&&S!==r&&n.call(S,a)&&(E=S);var N=b.prototype=g.prototype=Object.create(E);function x(t){["next","throw","return"].forEach((function(e){u(t,e,(function(t){return this._invoke(e,t)}))}))}function T(t,e){function r(o,i,a,c){var l=f(t[o],t,i);if("throw"!==l.type){var u=l.arg,s=u.value;return s&&"object"==D(s)&&n.call(s,"__await")?e.resolve(s.__await).then((function(t){r("next",t,a,c)}),(function(t){r("throw",t,a,c)})):e.resolve(s).then((function(t){u.value=t,a(u)}),(function(t){return r("throw",t,a,c)}))}c(l.arg)}var i;o(this,"_invoke",{value:function(t,n){function o(){return new e((function(e,o){r(t,n,e,o)}))}return i=i?i.then(o,o):o()}})}function O(e,r,n){var o=p;return function(i,a){if(o===m)throw Error("Generator is already running");if(o===h){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var l=_(c,n);if(l){if(l===y)continue;return l}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===p)throw o=h,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=m;var u=f(e,r,n);if("normal"===u.type){if(o=n.done?h:d,u.arg===y)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(o=h,n.method="throw",n.arg=u.arg)}}}function _(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator.return&&(r.method="return",r.arg=t,_(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=f(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function L(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function k(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(L,this),this.reset(!0)}function j(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function r(){for(;++o<e.length;)if(n.call(e,o))return r.value=e[o],r.done=!1,r;return r.value=t,r.done=!0,r};return i.next=i}}throw new TypeError(D(e)+" is not iterable")}return v.prototype=b,o(N,"constructor",{value:b,configurable:!0}),o(b,"constructor",{value:v,configurable:!0}),v.displayName=u(b,l,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===v||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,u(t,l,"GeneratorFunction")),t.prototype=Object.create(N),t},e.awrap=function(t){return{__await:t}},x(T.prototype),u(T.prototype,c,(function(){return this})),e.AsyncIterator=T,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new T(s(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},x(N),u(N,l,"Generator"),u(N,a,(function(){return this})),u(N,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},e.values=j,A.prototype={constructor:A,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(k),!e)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=t)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var r=this;function o(n,o){return c.type="throw",c.arg=e,r.next=n,o&&(r.method="next",r.arg=t),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var l=n.call(a,"catchLoc"),u=n.call(a,"finallyLoc");if(l&&u){if(this.prev<a.catchLoc)return o(a.catchLoc,!0);if(this.prev<a.finallyLoc)return o(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return o(a.catchLoc,!0)}else{if(!u)throw Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return o(a.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,y):this.complete(a)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),y},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),k(r),y}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;k(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function(e,r,n){return this.delegate={iterator:j(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}var q=function(t,e,r,n){return new(r||(r=Promise))((function(o,i){function a(t){try{l(n.next(t))}catch(t){i(t)}}function c(t){try{l(n.throw(t))}catch(t){i(t)}}function l(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,c)}l((n=n.apply(t,e||[])).next())}))},W="settings.notificationSettings",H=i.T.encloseNamespace(W);function $(){var t,e=(0,g.T)().hasPermissions,r=a.a.useBasicFetch(h.N.currentUser()),i=(0,b.r)(l.LZ.Settings),S=i.messageFrequencyOption,N=i.updateSetting,x=(0,y.Z)();(0,v.M)({title:"Notification Settings"});var T=a.a.useBasicFetch(G.getSubscriptionPreferences()),O=a.a.useGetFetchAsync();return e(p.C.StudentExperience)&&o.Q.C$.trigger({application:w.O.SETTINGS,action:E.e.Settings.HOME},{replace:!0}),(null===(t=T.data)||void 0===t?void 0:t.length)&&r.data?n.createElement(U.d,{heading:H("heading"),breadcrumbs:[H("heading")]},n.createElement("div",{className:"w-100 d-flex justify-content-center flex-column"},n.createElement("h4",null,H("label")),n.createElement("p",null,H("description")),n.createElement("p",null,n.createElement(f.x,{namespace:W,phrase:"updateEmailStart"})," ",n.createElement(s.F,{appLink:{application:w.O.SETTINGS,action:E.e.Settings.ACCOUNT},className:"text-decoration-underline"},H("updateEmailHref"))," ",n.createElement(f.x,{namespace:W,phrase:"updateEmailEnding"}))),n.createElement("div",{className:"row"},n.createElement(F,{type:"account-updates"}),T.data.map((function(t){return n.createElement(F,{key:t.id,type:t.type,toggled:t.subscribed,setToggle:function(e,r){return function(t,e,r){return q(this,void 0,void 0,M().mark((function n(){return M().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,O(G.setSubscriptionPreference({subscriptionGroupId:t,subscribed:r})).then((function(){var n=e.toLowerCase().trim();x.success(H(r?"alert-subscribed":"alert-unsubscribed",{name:n})),c.k.logUserAction({id:t,name:n.replace(" ","_"),value:r},{location:l.LZ.NotificationSettings,entity:u.py.NotificationSetting,descriptor:u.MK.Email,actionType:u.Vw.Edit})})).catch((function(){x.error("Could not update subscription preference")}));case 2:case"end":return n.stop()}}),n)})))}(t.id,e,r)}})}))),n.createElement(_,{updateMessageFrequency:function(t){if(t!==S){var e={name:m.E.MessageFrequencyOption,value:t,kind:d.g.Setting};N(r.data.id,e)}},currentFrequency:S})):n.createElement(n.Fragment,null)}}}]);
3
+ //# sourceMappingURL=4014-3eccce2f89-lite.chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripts/4014-3eccce2f89-lite.chunk.js","mappings":";sUAcA,IAAMA,EAAY,0BAKLC,EAAuB,SAACC,GACnC,IAAQC,GAAmB,SAAnBA,eACFC,GAAiB,SAOvB,GAAIF,EACF,OAAOC,EAAeD,GAExB,IAAMG,EAAe,2BAOrB,OAAIA,EAAaC,cAAgB,cAG1BF,EAAeG,MAAK,SAAAC,GACzB,OAAOA,EAAMC,QAAQF,MAAK,SAAAG,GACxB,MAAI,YAAaA,GACRA,EAAeC,QAAQC,SAAWP,EAAaO,MAI1D,GACF,GACF,EAUM,SAAUC,EAAeC,SACvBC,EAAYd,EAAqBa,EAAMZ,qBAW7C,GATA,aAAgB,WACTa,GACH,eAA2B,CACzBT,YAAa,aACbM,OAAQ,mBACP,CAAEI,SAAS,GAElB,GAAG,CAACD,KAECA,EACH,OAAO,iCAET,MAAME,EAAcH,EAAMG,YAAYC,KAAI,SAACC,EAAMC,GAAC,MAAM,CACtDD,KAAAA,EACAR,QAAS,CACPL,YAAa,aACbM,OAAQ,mBAEVS,OAAQD,IAAMN,EAAMG,YAAYK,OAAS,EAC1C,IAED,OACE,uBAAKC,UAAU,QACb,uBAAKA,UAAU,qDACb,sBAAIA,UAAU,MAAMT,EAAMU,SACN,QAAnB,EAAAV,EAAMW,qBAAa,wBAEtB,uBAAKF,UAAU,QACb,gBAAC,KAAW,CACVN,YAAW,CACT,CACEE,KAAM,cAA0BnB,EAAW,sBAC3CW,QAAS,CACPL,YAAa,aACbM,OAAQ,qBAEX,UACEK,0mBAIRH,EAAMY,aACL,gCACE,yBAAIZ,EAAMY,aACV,4BAIHZ,EAAMa,SAGb,uRCjHA,SAAgB,OAAS,QAAQ,MAAQ,QAAQ,eAAiB,QAAQ,YAAc,QAAQ,MAAQ,QAAQ,QAAU,QAAQ,KAAO,+GCSzI,IAAMC,EAA+C,CAAE,UAAW,SAAU,UAAW,UAOjF5B,EAAY,4BACZ6B,EAAYC,EAAA,mBAAiC9B,GAErC,SAAU+B,EAAiBjB,GACvC,QAAMkB,EAA2BlB,EAAMmB,kBAAoB,UACW,KAAhC,WAAeD,KAAiB,s4BAA9DE,EAAU,KAAEC,EAAa,KAmBjC,OACE,gCACE,sBAAIZ,UAAU,QAAQM,EAAU,qBAChC,gBAACO,EAAA,EAAI,CAACpC,UAAWA,EAAWqC,OAAO,gCACnC,uBAAKd,UAAU,iDACb,uBAAKA,UAAS,0CAAqC,SAChDK,EAAmBV,KAAI,SAACoB,GAAiC,OACxD,0BACEC,IAAKD,EACLf,WApBgBiB,EAoBcF,EAnBpCf,EAAY,cAGdA,GADEiB,IAAWN,EACA,YAEA,qBAEI,yBAaTO,QAAS,SAAAC,GAAC,OA3BtB,SAAiBA,EAAqBJ,GACpCI,EAAEC,iBACFR,EAAcG,GACdxB,EAAM8B,uBAAuBN,EAAUO,cACzC,CAuB0B,CAAQH,EAAGJ,EAAU,EACnCQ,KAAK,UAEJjB,EAAUS,IAxBvB,IAA4BE,EACtBjB,CAwBa,MAMrB,iICtCA,IACM,EAAYO,EAAA,mBADA,iCAGZiB,EAA0B,CAC9B,kBAAmB,CACjBC,MAAO,EAAU,kBACjBtB,YAAa,EAAU,6BACvBuB,KAAM,EAAU,sBAChBC,QAAS,EAAU,WACnBC,SAAUC,EAAA,gCACVC,OAAQ,kBACRC,UAAU,EACVjC,QAAQ,GAEV,6BAAgC,CAC9B2B,MAAO,EAAU,eACjBtB,YAAa,EAAU,0BACvByB,SAAUC,EAAA,6BACVC,OAAQ,kBACRC,UAAU,GAEZ,gCAAmC,CACjCN,MAAO,EAAU,kBACjBtB,YAAa,EAAU,6BACvByB,SAAUC,EAAA,gCACVC,OAAQ,gBACRC,UAAU,GAEZ,gCAAmC,CACjCN,MAAO,EAAU,mBACjBtB,YAAa,EAAU,8BACvByB,SAAUC,EAAA,gCACVC,OAAQ,kBACRC,UAAU,GAEZ,6BAAgC,CAC9BN,MAAO,EAAU,eACjBtB,YAAa,EAAU,0BACvByB,SAAUC,EAAA,6BACVC,OAAQ,gBACRC,UAAU,IAUR,SAAUC,EAAiBzC,GAC/B,QAAM0C,EAA6BT,EAAwBjC,EAAMgC,MAEL,KAA7B,WAAehC,EAAM2C,WAAQ,s4BAApDA,EAAO,KAAEC,EAAS,KAO1B,OAAKF,EAIH,uBAAKjC,UAAU,gBACb,uBAAKA,UAAS,UAAK,iBAAqB,2BACtC,uBAAKA,UAAS,kCAEZ,uBAAKA,UAAS,uFAAkFiC,EAAaH,SAC3G,uBACEM,IAAKH,EAAaL,SAClBS,IAAKJ,EAAaR,MAClBa,KAAK,eACLtC,UAAS,oBAAe,SAAa,YAIzC,uBAAKA,UAAS,eAAU,WAAkBuC,MAAO,CAAEC,MAAO,QACxD,qBAAGxC,UAAS,oBAAe,UAAiBiC,EAAaR,OACzD,qBAAGzB,UAAS,UAAK,gBAAuBiC,EAAa9B,aACpD8B,EAAaP,MAAQ,6BAAQO,EAAaP,OAG7C,uBAAK1B,UAAU,oDAAoDuC,MAAO,CAAEC,MAAO,QACjF,gBAACC,EAAA,EAAY,CACXvB,QAAS,WAAF,OA9BnB,SAAgBe,GACdE,GAAWD,GACX3C,EAAM4C,UAAUF,GAAeC,EACjC,CA2B2BQ,CAAOT,EAAaR,MAAM,EACzCM,SAAUE,EAAaF,SACvBY,GAAIT,GAAWD,EAAanC,OAC5B8C,uBAAqB,EACrBC,YAAaZ,EAAaN,cA5B7B,gCAoCX,sCCpHamB,EAAuB,CAClCC,2BAA0B,WACxB,MAAO,CACL/B,IAAK,wBACLgC,IAAKC,EAAA,aAAqB,4CAA6C,CACrEC,UAAW,SAEb3B,KAAM4B,EAAA,MAEV,EAEAC,0BAAyB,SAACC,GACxB,MAAO,CACLrC,IAAK,oBACLgC,IAAK,4CACLK,KAAMA,EACN9B,KAAM4B,EAAA,MACNG,iBAAkB,CAChB,yBAGN,i3NCOI,EAAY,gCACZ,EAAY/C,EAAA,mBAAiC,GAE7C,SAAUgD,UACN3E,GAAmB,EAAA4E,EAAA,KAAnB5E,eAEF6E,EAAc,kBAAkCC,EAAA,iBACtD,GAAkD,EAAAC,EAAA,GAAY,eAAtDC,EAAsB,EAAtBA,uBAAwBC,EAAa,EAAbA,cAE1BC,GAAS,UACf,EAAAC,EAAA,GAAmB,CAAEtC,MAAO,0BAE5B,IAAMuC,EAAgB,kBAA0ClB,EAAqBC,8BAC/EkB,EAAa,uBA+CnB,OA7CIrF,EAAesF,EAAA,sBACjB,eAA2B,CACzBnF,YAAa,aACbM,OAAQ,mBACP,CAAEI,SAAS,KAyCO,QAAlB,EAAAuE,EAAcX,YAAI,eAAEtD,SAAW0D,EAAYJ,KAI9C,gBAAC/D,EAAA,EAAc,CACbW,QAAS,EAAU,WACnBP,YAAa,CAAC,EAAU,aAExB,uBAAKM,UAAU,mDACb,0BAAK,EAAU,UACf,yBAAI,EAAU,gBACd,yBACE,gBAACa,EAAA,EAAI,CAACpC,UAAW,EAAWqC,OAAO,qBAAqB,IACxD,gBAACqD,EAAA,EAAO,CACN/E,QAAS,CACPL,YAAa,aACbM,OAAQ,sBAEVW,UAAU,6BAET,EAAU,oBACH,IACJ,gBAACa,EAAA,EAAI,CAACpC,UAAW,EAAWqC,OAAO,wBAI7C,uBAAKd,UAAU,OAEb,gBAACgC,EAAgB,CACfT,KAAM,oBAEPyC,EAAcX,KAAK1D,KAAI,SAAAsC,GACtB,OACE,gBAACD,EAAgB,CACfhB,IAAKiB,EAAamC,GAClB7C,KAAMU,EAAaV,KACnBW,QAASD,EAAaoC,WACtBlC,UACE,SAACmC,EAAkBC,GAAY,OA5E7C,SAA4CH,EAAYE,EAA0BC,uHAChF,gBAAMN,EAAWnB,EAAqBM,0BAA0B,CAC9DoB,oBAAqBJ,EACrBC,WAAYE,KACVE,MAAK,WACP,IAAM7E,EAAO0E,EAAiBhD,cAAcoD,OAC5CZ,EAAOa,QAAQ,EAAUJ,EAAe,mBAAqB,qBAAsB,CAAE3E,KAAAA,KACrFgF,EAAA,gBAA8B,CAC5BR,GAAAA,EACAxE,KAAMA,EAAKH,QAAQ,IAAK,KACxBoF,MAAON,GACN,CACDO,SAAU,0BACVC,OAAQ,yBACRC,WAAY,WACZC,WAAY,WAEhB,IAAE,OAAO,WACPnB,EAAOoB,MAAM,2CACf,IAAE,0CACH,CAyDeC,CAA6BlD,EAAamC,GAAIE,EAAkBC,EAAa,GAIvF,KAGF,gBAAC/D,EAAgB,CACfa,uBA/DN,SAA+BN,GAC7B,GAAIA,IAAc6C,EAAlB,CAGA,IAAMwB,EAAa,CACjBxF,KAAMyF,EAAA,yBACNR,MAAO9D,EACPuE,KAAMC,EAAA,EAAAC,SAGR3B,EACEJ,EAAYJ,KAAKe,GACjBgB,EAVM,CAYV,EAkDM1E,iBAAkBkD,KA/Cf,gCAoDX","sources":["file:///app/packages/projects/lite/src/apps/settings/components/settings-layout/SettingsLayout.tsx","file:///app/packages/projects/lite/src/apps/settings/components/notification-settings/notification-settings.scss","file:///app/packages/projects/lite/src/apps/settings/components/notification-settings/MessageFrequency.tsx","file:///app/packages/projects/lite/src/apps/settings/components/notification-settings/SubscriptionCard.tsx","file:///app/packages/projects/lite/src/apps/settings/flight-requests/SubscriptionRequests.ts","file:///app/packages/projects/lite/src/apps/settings/views/notification-settings/NotificationSettingsView.tsx"],"sourcesContent":["import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { Breadcrumbs } from 'libs/shared/components/breadcrumbs/Breadcrumbs';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nimport { useGetSettingsGroups } from 'apps/settings/hooks/useGetSettingsGroups';\n\nconst namespace = 'settings.settingsLayout';\n\n/**\n * Checks if the current user has permission to access the settings module\n */\nexport const useCanAccessSettings = (requiredPermissions: PermissionName | PermissionName[]): boolean => {\n const { hasPermissions } = usePermissions();\n const settingsGroups = useGetSettingsGroups();\n\n /**\n * TODO: Update all settings pages to pasas required permissions, because checking the \n * `useGetSettingsGroups()` values clearly doesnt work for settings pages with multiple\n * applinks inside of them. - Sha\n */\n if (requiredPermissions)\n return hasPermissions(requiredPermissions);\n\n const currentRoute = Core.AppLinkHelper.getCurrentAppLink();\n\n /**\n * Allows us to have popups sitting in other locations be used\n * by our settings pages. For example the manage video access popup\n * in the \"videos with restricted access\" page - Sha\n */\n if (currentRoute.application !== AppChannels.SETTINGS)\n return true;\n\n return settingsGroups.some(group => {\n return group.modules.some(settingsModule => {\n if ('appLink' in settingsModule) {\n return settingsModule.appLink.action === currentRoute.action;\n }\n\n return false;\n });\n });\n};\n\ninterface SettingsLayoutProps {\n heading: string;\n breadcrumbs: string[];\n description?: string;\n requiredPermissions?: PermissionName | PermissionName[];\n headingButton?: () => JSX.Element;\n}\n\nexport function SettingsLayout(props: React.PropsWithChildren<SettingsLayoutProps>): JSX.Element {\n const canAccess = useCanAccessSettings(props.requiredPermissions);\n\n React.useEffect(() => {\n if (!canAccess) {\n Core.AppLinkHelper.trigger({\n application: AppChannels.SETTINGS,\n action: Actions.Settings.HOME\n }, { replace: true });\n }\n }, [canAccess]);\n\n if (!canAccess)\n return <></>;\n\n const breadcrumbs = props.breadcrumbs.map((name, i) => ({\n name,\n appLink: {\n application: AppChannels.SETTINGS,\n action: Actions.Settings.HOME\n },\n active: i === props.breadcrumbs.length - 1\n }));\n\n return (\n <div className='px-3'>\n <div className='d-flex align-items-center justify-content-between'>\n <h1 className='h2'>{props.heading}</h1>\n {props.headingButton?.()}\n </div>\n <div className='pb-3'>\n <Breadcrumbs\n breadcrumbs={[\n {\n name: LanguageService.getPhrase(namespace, 'settingsBreadcrumb'),\n appLink: {\n application: AppChannels.SETTINGS,\n action: Actions.Settings.HOME\n }\n },\n ...breadcrumbs\n ]}\n />\n </div>\n {props.description &&\n <>\n <p>{props.description}</p>\n <hr />\n </>\n }\n\n {props.children}\n </div>\n );\n}","// extracted by mini-css-extract-plugin\nexport default {\"images\":\"lgrLY\",\"group\":\"oDj7s\",\"groupContainer\":\"uAqY0\",\"description\":\"fDHV0\",\"title\":\"Z91M9\",\"content\":\"KvFr1\",\"pill\":\"_Nl44\"};","\nimport React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { Text } from 'libs/shared/components/text/Text';\nimport { MessageFrequencyOption } from 'libs/shared/interfaces/models/MessageFrequencyOption';\n\nimport styles from './notification-settings.scss';\n\nconst messageFrequencies: MessageFrequencyOption[] = [ 'anytime', 'weekly', 'monthly', 'snooze' ];\n\ninterface MessageFrequencyProps {\n updateMessageFrequency: (frequency: string) => void;\n currentFrequency: MessageFrequencyOption\n}\n\nconst namespace = 'settings.messageFrequency';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport default function MessageFrequency(props: MessageFrequencyProps) {\n const defaultFrequency: string = props.currentFrequency || 'anytime';\n const [ activePill, setActivePill ] = React.useState(defaultFrequency);\n\n function onClick(e: React.MouseEvent, frequency: MessageFrequencyOption): void {\n e.preventDefault();\n setActivePill(frequency);\n props.updateMessageFrequency(frequency.toLowerCase());\n }\n\n function getButtonClassName(option: string): string {\n let className = 'btn border';\n \n if (option === activePill)\n className += ' btn-dark';\n else\n className += ' btn-outline-dark';\n \n return className + ' px-5 col-12 col-md-3';\n }\n\n return (\n <>\n <h4 className='mt-3'>{getPhrase('messageFrequency')}</h4>\n <Text namespace={namespace} phrase='messageFrequencyDescription' />\n <div className='py-3 text-center d-flex justify-content-start'>\n <div className={`btn-group mb-1 d-flex flex-wrap ${styles.pill}`}>\n {messageFrequencies.map((frequency: MessageFrequencyOption) => (\n <button\n key={frequency}\n className={getButtonClassName(frequency)}\n onClick={e => onClick(e, frequency)}\n type='button'\n >\n {getPhrase(frequency)}\n </button>\n ))}\n </div>\n </div>\n </>\n );\n}","import React from 'react';\n\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\n\nimport { ToggleSwitch } from 'libs/shared/components/toggle-switch/ToggleSwitch';\n\nimport { ImageUrls } from 'shared/constants/ImageUrls';\n\nimport { Subscriptions } from 'apps/settings/interfaces/SubscriptionGroups';\n\nimport styles from './notification-settings.scss';\n\ninterface Subscription {\n title: string,\n description: string,\n note?: string,\n tooltip?: string,\n disabled?: boolean,\n imageUrl: string,\n colour: string,\n active?: boolean\n}\n\nconst namespace = 'settings.notificationSettings';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nconst subscriptionGroupLookup = {\n 'account-updates': {\n title: getPhrase('accountUpdates'),\n description: getPhrase('accountUpdatesDescription'),\n note: getPhrase('accountUpdatesNote'),\n tooltip: getPhrase('tooltip'),\n imageUrl: ImageUrls.Notifications.ACCOUNT_UPDATES,\n colour: 'bg-light-orange',\n disabled: true,\n active: true\n },\n 'core_product_cv_product_news': {\n title: getPhrase('productNews'),\n description: getPhrase('productNewsDescription'),\n imageUrl: ImageUrls.Notifications.PRODUCT_NEWS,\n colour: 'bg-light-purple',\n disabled: false\n },\n 'core_product_cv_content_updates': {\n title: getPhrase('contentUpdates'),\n description: getPhrase('contentUpdatesDescription'),\n imageUrl: ImageUrls.Notifications.CONTENT_UPDATES,\n colour: 'bg-light-teal',\n disabled: false\n },\n 'core_product_cv_recommendations': {\n title: getPhrase('recommendations'),\n description: getPhrase('recommendationsDescription'),\n imageUrl: ImageUrls.Notifications.RECOMMENDATIONS,\n colour: 'bg-light-orange',\n disabled: false\n },\n 'core_product_cv_product_tips': {\n title: getPhrase('productTips'),\n description: getPhrase('productTipsDescription'),\n imageUrl: ImageUrls.Notifications.PRODUCT_TIPS,\n colour: 'bg-light-pink',\n disabled: false\n }\n};\n\ninterface SubscriptionPreferencesProps {\n type: Subscriptions;\n setToggle?: (subscription: string, value: boolean) => void;\n toggled?: boolean;\n}\n\nexport function SubscriptionCard(props: SubscriptionPreferencesProps): JSX.Element {\n const subscription: Subscription = subscriptionGroupLookup[props.type];\n\n const [ toggled, setToggle ] = React.useState(props.toggled);\n\n function toggle(subscription: string): void {\n setToggle(!toggled);\n props.setToggle(subscription, !toggled);\n }\n\n if (!subscription)\n return <></>;\n\n return (\n <div className='col-md-6 p-0'>\n <div className={`${styles.groupContainer} d-flex flex-row h-100`}>\n <div className={`row border m-0 w-100 rounded-3`}>\n\n <div className={`col-3 d-flex justify-content-center align-items-center h-100 rounded-start-3 ${subscription.colour}`}>\n <img\n src={subscription.imageUrl}\n alt={subscription.title}\n role='presentation'\n className={`img-fluid ${styles.images} w-50`}\n />\n </div>\n\n <div className={`py-3 ${styles.content}`} style={{ width: '64%' }}>\n <p className={`fw-medium ${styles.title}`}>{subscription.title}</p>\n <p className={`${styles.description}`}>{subscription.description}</p>\n {subscription.note && <small>{subscription.note}</small>}\n </div>\n\n <div className='py-3 d-flex justify-content-end align-items-start' style={{ width: '11%' }}>\n <ToggleSwitch\n onClick={() => toggle(subscription.title)}\n disabled={subscription.disabled}\n on={toggled || subscription.active}\n showStateWhenDisabled\n tooltipText={subscription.tooltip}\n />\n </div>\n\n </div>\n </div>\n </div>\n );\n}","import { HttpVerbs } from 'libs/common/backbone/enums/HttpVerbs';\nimport { UrlHelper } from 'libs/common/backbone/utils/UrlHelper';\nimport { Flight } from 'libs/common/flight';\n\nexport const SubscriptionRequests = {\n getSubscriptionPreferences(): Flight.Request {\n return {\n key: 'current:subscriptions',\n url: UrlHelper.urlBuilder(`{gateway}/v1/users/me/subscription-groups`, {\n productId: `lite`\n }),\n type: HttpVerbs.GET\n };\n },\n\n setSubscriptionPreference(data: { subscriptionGroupId: string; subscribed: boolean }): Flight.Request {\n return {\n key: 'set:subscriptions',\n url: '{gateway}/v1/users/me/subscription-groups',\n data: data,\n type: HttpVerbs.PUT,\n invalidationKeys: [\n 'current:subscriptions'\n ]\n };\n }\n};","import React from 'react';\n\nimport { Core } from 'libs/common/backbone/index';\nimport { LanguageService } from 'libs/common/backbone/services/LanguageService';\nimport { Flight } from 'libs/common/flight';\n\nimport { AnalyticsHelper } from 'libs/analytics/AnalyticsHelper';\nimport { LocationContext } from 'libs/analytics/interfaces';\nimport { EntityType, NotificationDescriptor, UserAction } from 'libs/analytics/interfaces/AnalyticsTypes';\n\nimport { AppLink } from 'libs/shared/components/app-link/AppLink';\nimport { Text } from 'libs/shared/components/text/Text';\nimport { PermissionName } from 'libs/shared/enums/PermissionName';\nimport { SettingKind } from 'libs/shared/enums/SettingKind';\nimport { SettingName } from 'libs/shared/enums/SettingName';\nimport { UserRequests } from 'libs/shared/flight-requests/UserRequests';\nimport { useAlerts } from 'libs/shared/hooks/UseAlerts';\nimport { usePermissions } from 'libs/shared/hooks/usePermissions';\nimport { useSetPageMetadata } from 'libs/shared/hooks/useSetPageMetadata';\nimport { useSettings } from 'libs/shared/hooks/useSettings';\nimport { CurrentUser } from 'libs/shared/interfaces';\nimport { MessageFrequencyOption } from 'libs/shared/interfaces/models/MessageFrequencyOption';\n\nimport { Actions } from 'shared/constants/LiteActions';\nimport { AppChannels } from 'shared/constants/LiteRadioChannels';\n\nimport MessageFrequency from 'apps/settings/components/notification-settings/MessageFrequency';\nimport { SubscriptionCard } from 'apps/settings/components/notification-settings/SubscriptionCard';\nimport { SettingsLayout } from 'apps/settings/components/settings-layout/SettingsLayout';\nimport { SubscriptionRequests } from 'apps/settings/flight-requests/SubscriptionRequests';\nimport { SubscriptionGroup } from 'apps/settings/interfaces/SubscriptionGroups';\n\nconst namespace = 'settings.notificationSettings';\nconst getPhrase = LanguageService.encloseNamespace(namespace);\n\nexport function NotificationSettingsView(): React.ReactElement {\n const { hasPermissions } = usePermissions();\n\n const currentUser = Flight.useBasicFetch<CurrentUser>(UserRequests.currentUser());\n const { messageFrequencyOption, updateSetting } = useSettings(LocationContext.Settings);\n\n const alerts = useAlerts();\n useSetPageMetadata({ title: 'Notification Settings' });\n\n const subscriptions = Flight.useBasicFetch<SubscriptionGroup[]>(SubscriptionRequests.getSubscriptionPreferences());\n const fetchAsync = Flight.useGetFetchAsync();\n\n if (hasPermissions(PermissionName.StudentExperience)) {\n Core.AppLinkHelper.trigger({\n application: AppChannels.SETTINGS,\n action: Actions.Settings.HOME\n }, { replace: true });\n }\n\n async function updateSubscriptionPreference(id: string, subscriptionName: string, isSubscribed: boolean) {\n await fetchAsync(SubscriptionRequests.setSubscriptionPreference({\n subscriptionGroupId: id,\n subscribed: isSubscribed\n })).then(() => {\n const name = subscriptionName.toLowerCase().trim();\n alerts.success(getPhrase(isSubscribed ? 'alert-subscribed' : 'alert-unsubscribed', { name }));\n AnalyticsHelper.logUserAction({\n id,\n name: name.replace(' ', '_'),\n value: isSubscribed\n }, {\n location: LocationContext.NotificationSettings,\n entity: EntityType.NotificationSetting,\n descriptor: NotificationDescriptor.Email,\n actionType: UserAction.Edit\n });\n }).catch(() => {\n alerts.error('Could not update subscription preference');\n });\n }\n\n function updateMessgeFrequency(frequency: MessageFrequencyOption) {\n if (frequency === messageFrequencyOption)\n return;\n\n const newSetting = {\n name: SettingName.MessageFrequencyOption,\n value: frequency,\n kind: SettingKind.Setting\n };\n\n updateSetting(\n currentUser.data.id,\n newSetting\n );\n }\n\n if (!subscriptions.data?.length || !currentUser.data)\n return <></>;\n\n return (\n <SettingsLayout\n heading={getPhrase('heading')}\n breadcrumbs={[getPhrase('heading')]}\n >\n <div className='w-100 d-flex justify-content-center flex-column'>\n <h4>{getPhrase('label')}</h4>\n <p>{getPhrase('description')}</p>\n <p>\n <Text namespace={namespace} phrase='updateEmailStart' />&nbsp;\n <AppLink\n appLink={{\n application: AppChannels.SETTINGS,\n action: Actions.Settings.ACCOUNT\n }}\n className='text-decoration-underline'\n >\n {getPhrase('updateEmailHref')}\n </AppLink>\n &nbsp;<Text namespace={namespace} phrase='updateEmailEnding' />\n </p>\n </div>\n\n <div className='row'>\n {/* Account updates is the only one that cannot be toggled and does not have an ID passed in by the backend so render it seperately */}\n <SubscriptionCard\n type={'account-updates'}\n />\n {subscriptions.data.map(subscription => {\n return (\n <SubscriptionCard\n key={subscription.id}\n type={subscription.type}\n toggled={subscription.subscribed}\n setToggle={\n (subscriptionName, isSubscribed) =>\n updateSubscriptionPreference(subscription.id, subscriptionName, isSubscribed)\n }\n />\n );\n })}\n </div>\n \n <MessageFrequency\n updateMessageFrequency={updateMessgeFrequency}\n currentFrequency={messageFrequencyOption}\n />\n \n </SettingsLayout>\n );\n}"],"names":["namespace","useCanAccessSettings","requiredPermissions","hasPermissions","settingsGroups","currentRoute","application","some","group","modules","settingsModule","appLink","action","SettingsLayout","props","canAccess","replace","breadcrumbs","map","name","i","active","length","className","heading","headingButton","description","children","messageFrequencies","getPhrase","LanguageService","MessageFrequency","defaultFrequency","currentFrequency","activePill","setActivePill","Text","phrase","frequency","key","option","onClick","e","preventDefault","updateMessageFrequency","toLowerCase","type","subscriptionGroupLookup","title","note","tooltip","imageUrl","ImageUrls","colour","disabled","SubscriptionCard","subscription","toggled","setToggle","src","alt","role","style","width","ToggleSwitch","toggle","on","showStateWhenDisabled","tooltipText","SubscriptionRequests","getSubscriptionPreferences","url","UrlHelper","productId","HttpVerbs","setSubscriptionPreference","data","invalidationKeys","NotificationSettingsView","usePermissions","currentUser","UserRequests","useSettings","messageFrequencyOption","updateSetting","alerts","useSetPageMetadata","subscriptions","fetchAsync","PermissionName","AppLink","id","subscribed","subscriptionName","isSubscribed","subscriptionGroupId","then","trim","success","AnalyticsHelper","value","location","entity","descriptor","actionType","error","updateSubscriptionPreference","newSetting","SettingName","kind","SettingKind","Setting"],"sourceRoot":""}