@gen-epix/ui-client-casedb 4.0.0 → 4.0.2

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 (393) hide show
  1. package/dist/@types/mui.d.ts +1 -1
  2. package/dist/@types/{ui-casedb.d.ts → ui-client-casedb.d.ts} +1 -1
  3. package/dist/_chunks/AddCasesToEventDialog.js +74 -74
  4. package/dist/_chunks/AddCasesToEventDialog.js.map +1 -1
  5. package/dist/_chunks/CaseContentForm.js +2 -2
  6. package/dist/_chunks/CaseContentForm.js.map +1 -1
  7. package/dist/_chunks/CaseDbDownloadUtil.js +40 -35
  8. package/dist/_chunks/CaseDbDownloadUtil.js.map +1 -1
  9. package/dist/_chunks/CaseInfoDialog.js +195 -195
  10. package/dist/_chunks/CaseInfoDialog.js.map +1 -1
  11. package/dist/_chunks/CaseSetInfoDialog.js +131 -131
  12. package/dist/_chunks/CaseSetInfoDialog.js.map +1 -1
  13. package/dist/_chunks/CaseTypeInfoDialog.js +63 -61
  14. package/dist/_chunks/CaseTypeInfoDialog.js.map +1 -1
  15. package/dist/_chunks/CasesAlreadyInCaseSetWarning.js +6 -6
  16. package/dist/_chunks/CasesAlreadyInCaseSetWarning.js.map +1 -1
  17. package/dist/_chunks/CompletCaseTypeLoader.js +3 -3
  18. package/dist/_chunks/CompletCaseTypeLoader.js.map +1 -1
  19. package/dist/_chunks/CreateEventDialogSuccessNotificationMessage.js +1 -1
  20. package/dist/_chunks/CreateEventDialogSuccessNotificationMessage.js.map +1 -1
  21. package/dist/_chunks/CustomTabPanel.js.map +1 -1
  22. package/dist/_chunks/Dashboard.js +399 -386
  23. package/dist/_chunks/Dashboard.js.map +1 -1
  24. package/dist/_chunks/DashboardStoreLoader.js +5 -5
  25. package/dist/_chunks/DashboardStoreLoader.js.map +1 -1
  26. package/dist/_chunks/DataCollectionAccessInfo.js +21 -21
  27. package/dist/_chunks/DataCollectionAccessInfo.js.map +1 -1
  28. package/dist/_chunks/EpiCurveUtil.js +4 -4
  29. package/dist/_chunks/EpiCurveUtil.js.map +1 -1
  30. package/dist/_chunks/EpiCurveWidget.js +189 -183
  31. package/dist/_chunks/EpiCurveWidget.js.map +1 -1
  32. package/dist/_chunks/FilterUtil.js +103 -101
  33. package/dist/_chunks/FilterUtil.js.map +1 -1
  34. package/dist/_chunks/FindSimilarCasesDialog.js +16 -16
  35. package/dist/_chunks/FindSimilarCasesDialog.js.map +1 -1
  36. package/dist/_chunks/FindSimilarCasesUtil.js +9 -9
  37. package/dist/_chunks/FindSimilarCasesUtil.js.map +1 -1
  38. package/dist/_chunks/HomePageTrends.js +8 -8
  39. package/dist/_chunks/HomePageTrends.js.map +1 -1
  40. package/dist/_chunks/LegendaItem.js +3 -3
  41. package/dist/_chunks/LegendaItem.js.map +1 -1
  42. package/dist/_chunks/LineListWidget.js +23 -21
  43. package/dist/_chunks/LineListWidget.js.map +1 -1
  44. package/dist/_chunks/PanelSeparator.js +374 -384
  45. package/dist/_chunks/PanelSeparator.js.map +1 -1
  46. package/dist/_chunks/Upload.js +222 -207
  47. package/dist/_chunks/Upload.js.map +1 -1
  48. package/dist/_chunks/UploadUtil.js +1970 -841
  49. package/dist/_chunks/UploadUtil.js.map +1 -1
  50. package/dist/_chunks/UserRightsDialog.js +12 -12
  51. package/dist/_chunks/UserRightsDialog.js.map +1 -1
  52. package/dist/_chunks/_MapCache.js +2 -2
  53. package/dist/_chunks/_baseGet.js +1 -1
  54. package/dist/_chunks/_baseGet.js.map +1 -1
  55. package/dist/_chunks/_baseIteratee.js +1 -1
  56. package/dist/_chunks/_baseIteratee.js.map +1 -1
  57. package/dist/_chunks/_setToString.js.map +1 -1
  58. package/dist/_chunks/{chunk-KS7C4IRE.js → chunk-BV7QT456.js} +330 -495
  59. package/dist/_chunks/chunk-BV7QT456.js.map +1 -0
  60. package/dist/_chunks/cloneDeep.js +11 -9
  61. package/dist/_chunks/cloneDeep.js.map +1 -1
  62. package/dist/_chunks/dashboardStore.js +259 -261
  63. package/dist/_chunks/dashboardStore.js.map +1 -1
  64. package/dist/_chunks/esm.js +2900 -2868
  65. package/dist/_chunks/esm.js.map +1 -1
  66. package/dist/_chunks/format.js +8 -8
  67. package/dist/_chunks/format.js.map +1 -1
  68. package/dist/_chunks/index.esm.js +919 -796
  69. package/dist/_chunks/index.esm.js.map +1 -1
  70. package/dist/_chunks/index.module.js +1 -1
  71. package/dist/_chunks/index.module.js.map +1 -1
  72. package/dist/_chunks/protectedTokens.js +79 -81
  73. package/dist/_chunks/protectedTokens.js.map +1 -1
  74. package/dist/_chunks/react.js +1 -1
  75. package/dist/_chunks/react.js.map +1 -1
  76. package/dist/_chunks/round.js +1 -1
  77. package/dist/_chunks/round.js.map +1 -1
  78. package/dist/_chunks/shallow.js +2 -2
  79. package/dist/_chunks/shallow.js.map +1 -1
  80. package/dist/_chunks/sync.js +198 -161
  81. package/dist/_chunks/sync.js.map +1 -1
  82. package/dist/_chunks/toDate.js +1 -1
  83. package/dist/_chunks/toDate.js.map +1 -1
  84. package/dist/_chunks/toString.js +1 -1
  85. package/dist/_chunks/toString.js.map +1 -1
  86. package/dist/_chunks/useUnit.js.map +1 -1
  87. package/dist/_chunks/vanilla.js +1 -1
  88. package/dist/_chunks/vanilla.js.map +1 -1
  89. package/dist/_chunks/yup.js +5 -5
  90. package/dist/_chunks/yup.js.map +1 -1
  91. package/dist/classes/filters/SelectionFilter.d.ts +2 -2
  92. package/dist/classes/filters/TreeFilter.d.ts +2 -2
  93. package/dist/classes/services/DataService/index.js +3 -3
  94. package/dist/classes/services/DataService/index.js.map +1 -1
  95. package/dist/classes/services/EventBusService/EventBusService.d.ts +1 -1
  96. package/dist/classes/services/EventBusService/index.js.map +1 -1
  97. package/dist/classes/services/LineListService/LineListServiceAbstract/index.js +1 -1
  98. package/dist/classes/services/LineListService/LineListServiceAbstract/index.js.map +1 -1
  99. package/dist/components/app/CaseDbApp/index.js +8 -5
  100. package/dist/components/app/CaseDbApp/index.js.map +1 -1
  101. package/dist/components/form/fields/ArrangementEditor/index.js +83 -83
  102. package/dist/components/form/fields/ArrangementEditor/index.js.map +1 -1
  103. package/dist/components/ui/AddCasesToEventDialog/AddCasesToEventDialog.d.ts +2 -2
  104. package/dist/components/ui/CaseContentFormDialog/CaseContentFormDialog.d.ts +2 -2
  105. package/dist/components/ui/CaseContentFormDialog/index.js +1 -1
  106. package/dist/components/ui/CaseContentFormDialog/index.js.map +1 -1
  107. package/dist/components/ui/CaseInfoDialog/CaseInfoDialog.d.ts +2 -2
  108. package/dist/components/ui/CaseSetInfoDialog/CaseSetInfoDialog.d.ts +2 -2
  109. package/dist/components/ui/CaseSummary/index.js +1 -1
  110. package/dist/components/ui/CaseSummary/index.js.map +1 -1
  111. package/dist/components/ui/CaseTypeInfoDialog/CaseTypeInfoDialog.d.ts +2 -2
  112. package/dist/components/ui/CaseTypeInfoDialog/CaseTypeInfoDialogContent.d.ts +1 -1
  113. package/dist/components/ui/CaseTypeInfoDialog/CaseTypeInfoDialogWithLoader.d.ts +2 -2
  114. package/dist/components/ui/ContextMenu/index.js.map +1 -1
  115. package/dist/components/ui/CreateEventDialog/CreateEventDialog.d.ts +2 -2
  116. package/dist/components/ui/CreateEventDialog/index.js +9 -9
  117. package/dist/components/ui/CreateEventDialog/index.js.map +1 -1
  118. package/dist/components/ui/Dashboard/DashboardDownloadSidebarItem.d.ts +1 -1
  119. package/dist/components/ui/Dashboard/DashboardSettingsSidebarItem.d.ts +1 -1
  120. package/dist/components/ui/Dashboard/DashboardWidget.d.ts +1 -1
  121. package/dist/components/ui/DashboardEditCases/index.js +1 -1
  122. package/dist/components/ui/DashboardEditCases/index.js.map +1 -1
  123. package/dist/components/ui/FileSelector/index.js +46 -46
  124. package/dist/components/ui/FileSelector/index.js.map +1 -1
  125. package/dist/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialog.d.ts +2 -2
  126. package/dist/components/ui/Grouping/index.js +50 -50
  127. package/dist/components/ui/Grouping/index.js.map +1 -1
  128. package/dist/components/ui/HistogramWidget/index.js +1 -1
  129. package/dist/components/ui/HistogramWidget/index.js.map +1 -1
  130. package/dist/components/ui/MapWidget/index.js +7 -3
  131. package/dist/components/ui/MapWidget/index.js.map +1 -1
  132. package/dist/components/ui/RemoveCasesFromEventDialog/RemoveCasesFromEventDialog.d.ts +2 -2
  133. package/dist/components/ui/RemoveCasesFromEventDialog/index.js +6 -6
  134. package/dist/components/ui/RemoveCasesFromEventDialog/index.js.map +1 -1
  135. package/dist/components/ui/RemoveFindSimilarCasesResultDialog/RemoveFindSimilarCasesResultDialog.d.ts +2 -2
  136. package/dist/components/ui/SequenceDownloadDialog/SequenceDownloadDialog.d.ts +2 -2
  137. package/dist/components/ui/SequenceDownloadDialog/index.js +22 -22
  138. package/dist/components/ui/SequenceDownloadDialog/index.js.map +1 -1
  139. package/dist/components/ui/TreeDescription/index.js.map +1 -1
  140. package/dist/components/ui/TreeWidget/index.js +11 -11
  141. package/dist/components/ui/TreeWidget/index.js.map +1 -1
  142. package/dist/components/ui/Upload/UploadCaseResultTable.d.ts +2 -2
  143. package/dist/components/ui/Upload/UploadEditColumnValuesDialog.d.ts +2 -2
  144. package/dist/components/ui/UserRightsDialog/UserRightsDialog.d.ts +2 -2
  145. package/dist/components/ui/UsersEffectiveRightsDetailsDialog/UsersEffectiveRightsDetailsDialog.d.ts +2 -2
  146. package/dist/components/ui/UsersEffectiveRightsDetailsDialog/index.js +25 -11
  147. package/dist/components/ui/UsersEffectiveRightsDetailsDialog/index.js.map +1 -1
  148. package/dist/components/ui/Warning/index.js.map +1 -1
  149. package/dist/components/ui/WidgetHeaderIconButton/index.js.map +1 -1
  150. package/dist/components/ui/WidgetMenu/WidgetMenu.d.ts +1 -1
  151. package/dist/components/ui/WidgetMenu/index.js +2 -2
  152. package/dist/components/ui/WidgetMenu/index.js.map +1 -1
  153. package/dist/components/ui/WidgetUnavailable/index.js.map +1 -1
  154. package/dist/constants/query.d.ts +1 -1
  155. package/dist/constants/query.js +1 -1
  156. package/dist/constants/query.js.map +1 -1
  157. package/dist/context/caseAbac/CaseAbacContext.d.ts +1 -1
  158. package/dist/dataHooks/useAssemblyProtocolsQuery/index.js +3 -3
  159. package/dist/dataHooks/useAssemblyProtocolsQuery/index.js.map +1 -1
  160. package/dist/dataHooks/useAssemblyProtocolsQuery/useAssemblyProtocolsQuery.d.ts +1 -1
  161. package/dist/dataHooks/useCaseRightsQuery/index.js +2 -2
  162. package/dist/dataHooks/useCaseRightsQuery/index.js.map +1 -1
  163. package/dist/dataHooks/useCaseSetCategoriesQuery/index.js +3 -3
  164. package/dist/dataHooks/useCaseSetCategoriesQuery/index.js.map +1 -1
  165. package/dist/dataHooks/useCaseSetCategoriesQuery/useCaseSetCategoriesQuery.d.ts +1 -1
  166. package/dist/dataHooks/useCaseSetRightsQuery/index.js +2 -2
  167. package/dist/dataHooks/useCaseSetRightsQuery/index.js.map +1 -1
  168. package/dist/dataHooks/useCaseSetStatsQuery/index.js +3 -3
  169. package/dist/dataHooks/useCaseSetStatsQuery/index.js.map +1 -1
  170. package/dist/dataHooks/useCaseSetStatsQuery/useCaseSetStatsQuery.d.ts +1 -1
  171. package/dist/dataHooks/useCaseSetStatusesQuery/index.js +3 -3
  172. package/dist/dataHooks/useCaseSetStatusesQuery/index.js.map +1 -1
  173. package/dist/dataHooks/useCaseSetStatusesQuery/useCaseSetStatusesQuery.d.ts +1 -1
  174. package/dist/dataHooks/useCaseSetsQuery/index.js +3 -3
  175. package/dist/dataHooks/useCaseSetsQuery/index.js.map +1 -1
  176. package/dist/dataHooks/useCaseSetsQuery/useCaseSetsQuery.d.ts +1 -1
  177. package/dist/dataHooks/useCaseTypeSetCategoriesQuery/index.js +3 -3
  178. package/dist/dataHooks/useCaseTypeSetCategoriesQuery/index.js.map +1 -1
  179. package/dist/dataHooks/useCaseTypeSetCategoriesQuery/useCaseTypeSetCategoriesQuery.d.ts +1 -1
  180. package/dist/dataHooks/useCaseTypeSetCategoryPurposeQuery/index.js.map +1 -1
  181. package/dist/dataHooks/useCaseTypeSetCategoryPurposeQuery/useCaseTypeSetCategoryPurposeQuery.d.ts +1 -1
  182. package/dist/dataHooks/useCaseTypeSetMembersQuery/index.js +2 -2
  183. package/dist/dataHooks/useCaseTypeSetMembersQuery/index.js.map +1 -1
  184. package/dist/dataHooks/useCaseTypeSetsQuery/index.js +3 -3
  185. package/dist/dataHooks/useCaseTypeSetsQuery/index.js.map +1 -1
  186. package/dist/dataHooks/useCaseTypeSetsQuery/useCaseTypeSetsQuery.d.ts +1 -1
  187. package/dist/dataHooks/useCaseTypeStatsQuery/index.js +2 -2
  188. package/dist/dataHooks/useCaseTypeStatsQuery/index.js.map +1 -1
  189. package/dist/dataHooks/useCaseTypesQuery/index.js +3 -3
  190. package/dist/dataHooks/useCaseTypesQuery/index.js.map +1 -1
  191. package/dist/dataHooks/useCaseTypesQuery/useCaseTypesQuery.d.ts +1 -1
  192. package/dist/dataHooks/useColSetMembersQuery/index.js +2 -2
  193. package/dist/dataHooks/useColSetMembersQuery/index.js.map +1 -1
  194. package/dist/dataHooks/useColSetsQuery/index.js +3 -3
  195. package/dist/dataHooks/useColSetsQuery/index.js.map +1 -1
  196. package/dist/dataHooks/useColSetsQuery/useColSetsQuery.d.ts +1 -1
  197. package/dist/dataHooks/useColTypesQuery/index.js.map +1 -1
  198. package/dist/dataHooks/useColTypesQuery/useColTypesQuery.d.ts +1 -1
  199. package/dist/dataHooks/useColsQuery/index.js +3 -3
  200. package/dist/dataHooks/useColsQuery/index.js.map +1 -1
  201. package/dist/dataHooks/useColsQuery/useColsQuery.d.ts +1 -1
  202. package/dist/dataHooks/useConceptQuery/index.js +3 -3
  203. package/dist/dataHooks/useConceptQuery/index.js.map +1 -1
  204. package/dist/dataHooks/useConceptQuery/useConceptQuery.d.ts +1 -1
  205. package/dist/dataHooks/useConceptRelationTypeQuery/index.js.map +1 -1
  206. package/dist/dataHooks/useConceptRelationTypeQuery/useConceptRelationTypeQuery.d.ts +1 -1
  207. package/dist/dataHooks/useConceptSetTypeQuery/index.js.map +1 -1
  208. package/dist/dataHooks/useConceptSetTypeQuery/useConceptSetTypeQuery.d.ts +1 -1
  209. package/dist/dataHooks/useConceptSetsQuery/index.js +3 -3
  210. package/dist/dataHooks/useConceptSetsQuery/index.js.map +1 -1
  211. package/dist/dataHooks/useConceptSetsQuery/useConceptSetsQuery.d.ts +1 -1
  212. package/dist/dataHooks/useDataCollectionSetMembersQuery/index.js +2 -2
  213. package/dist/dataHooks/useDataCollectionSetMembersQuery/index.js.map +1 -1
  214. package/dist/dataHooks/useDataCollectionsQuery/index.js +3 -3
  215. package/dist/dataHooks/useDataCollectionsQuery/index.js.map +1 -1
  216. package/dist/dataHooks/useDataCollectionsQuery/useDataCollectionsQuery.d.ts +1 -1
  217. package/dist/dataHooks/useDimTypesQuery/index.js.map +1 -1
  218. package/dist/dataHooks/useDimTypesQuery/useDimTypesQuery.d.ts +1 -1
  219. package/dist/dataHooks/useDimsQuery/index.js +3 -3
  220. package/dist/dataHooks/useDimsQuery/index.js.map +1 -1
  221. package/dist/dataHooks/useDimsQuery/useDimsQuery.d.ts +1 -1
  222. package/dist/dataHooks/useDiseasesQuery/index.js +3 -3
  223. package/dist/dataHooks/useDiseasesQuery/index.js.map +1 -1
  224. package/dist/dataHooks/useDiseasesQuery/useDiseasesQuery.d.ts +1 -1
  225. package/dist/dataHooks/useEtiologicalAgentsQuery/index.js +3 -3
  226. package/dist/dataHooks/useEtiologicalAgentsQuery/index.js.map +1 -1
  227. package/dist/dataHooks/useEtiologicalAgentsQuery/useEtiologicalAgentsQuery.d.ts +1 -1
  228. package/dist/dataHooks/useGeneticDistanceProtocolsQuery/index.js +3 -3
  229. package/dist/dataHooks/useGeneticDistanceProtocolsQuery/index.js.map +1 -1
  230. package/dist/dataHooks/useGeneticDistanceProtocolsQuery/useGeneticDistanceProtocolsQuery.d.ts +1 -1
  231. package/dist/dataHooks/useOrganizationAccessCasePoliciesQuery/index.js +2 -2
  232. package/dist/dataHooks/useOrganizationAccessCasePoliciesQuery/index.js.map +1 -1
  233. package/dist/dataHooks/useOrganizationShareCasePoliciesQuery/index.js +2 -2
  234. package/dist/dataHooks/useOrganizationShareCasePoliciesQuery/index.js.map +1 -1
  235. package/dist/dataHooks/useRefColsQuery/index.js +3 -3
  236. package/dist/dataHooks/useRefColsQuery/index.js.map +1 -1
  237. package/dist/dataHooks/useRefColsQuery/useRefColsQuery.d.ts +1 -1
  238. package/dist/dataHooks/useRefColsValidationRulesQuery/index.js +2 -2
  239. package/dist/dataHooks/useRefColsValidationRulesQuery/index.js.map +1 -1
  240. package/dist/dataHooks/useRefDimsQuery/index.js +3 -3
  241. package/dist/dataHooks/useRefDimsQuery/index.js.map +1 -1
  242. package/dist/dataHooks/useRefDimsQuery/useRefDimsQuery.d.ts +1 -1
  243. package/dist/dataHooks/useRegionQuery/index.js +3 -3
  244. package/dist/dataHooks/useRegionQuery/index.js.map +1 -1
  245. package/dist/dataHooks/useRegionQuery/useRegionQuery.d.ts +1 -1
  246. package/dist/dataHooks/useRegionRelationTypeQuery/index.js.map +1 -1
  247. package/dist/dataHooks/useRegionRelationTypeQuery/useRegionRelationTypeQuery.d.ts +1 -1
  248. package/dist/dataHooks/useRegionSetsQuery/index.js +3 -3
  249. package/dist/dataHooks/useRegionSetsQuery/index.js.map +1 -1
  250. package/dist/dataHooks/useRegionSetsQuery/useRegionSetsQuery.d.ts +1 -1
  251. package/dist/dataHooks/useSequencingProtocolsQuery/index.js +3 -3
  252. package/dist/dataHooks/useSequencingProtocolsQuery/index.js.map +1 -1
  253. package/dist/dataHooks/useSequencingProtocolsQuery/useSequencingProtocolsQuery.d.ts +1 -1
  254. package/dist/dataHooks/useTreeAlgorithmCodesQuery/index.js.map +1 -1
  255. package/dist/dataHooks/useTreeAlgorithmCodesQuery/useTreeAlgorithmCodesQuery.d.ts +1 -1
  256. package/dist/dataHooks/useUnitQuery/useUnit.d.ts +1 -1
  257. package/dist/dataHooks/useUserAccessCasePoliciesQuery/index.js +2 -2
  258. package/dist/dataHooks/useUserAccessCasePoliciesQuery/index.js.map +1 -1
  259. package/dist/dataHooks/useUserEffectiveRightsQuery/index.js +3 -3
  260. package/dist/dataHooks/useUserEffectiveRightsQuery/index.js.map +1 -1
  261. package/dist/dataHooks/useUserEffectiveRightsQuery/useUserEffectiveRightsQuery.d.ts +1 -1
  262. package/dist/dataHooks/useUserShareCasePoliciesQuery/index.js +2 -2
  263. package/dist/dataHooks/useUserShareCasePoliciesQuery/index.js.map +1 -1
  264. package/dist/hooks/useOrganizationCasePolicyNameFactory/index.js +2 -2
  265. package/dist/hooks/useOrganizationCasePolicyNameFactory/index.js.map +1 -1
  266. package/dist/hooks/useOrganizationCasePolicyNameFactory/useOrganizationCasePolicyNameFactory.d.ts +1 -1
  267. package/dist/hooks/useUserCasePolicyNameFactory/index.js +3 -3
  268. package/dist/hooks/useUserCasePolicyNameFactory/index.js.map +1 -1
  269. package/dist/hooks/useUserCasePolicyNameFactory/useUserCasePolicyNameFactory.d.ts +1 -1
  270. package/dist/locale/nl.json +1 -1
  271. package/dist/models/config.d.ts +1 -1
  272. package/dist/models/dashboard.d.ts +1 -1
  273. package/dist/models/dashboard.js.map +1 -1
  274. package/dist/models/theme.d.ts +2 -2
  275. package/dist/pages/CaseDbUsersAdminPage/index.js +5 -5
  276. package/dist/pages/CaseDbUsersAdminPage/index.js.map +1 -1
  277. package/dist/pages/CaseSetCategoryAdminPage/index.js +4 -4
  278. package/dist/pages/CaseSetCategoryAdminPage/index.js.map +1 -1
  279. package/dist/pages/CaseSetStatusAdminPage/index.js +4 -4
  280. package/dist/pages/CaseSetStatusAdminPage/index.js.map +1 -1
  281. package/dist/pages/CaseTypeSetCategoriesAdminPage/index.js +4 -4
  282. package/dist/pages/CaseTypeSetCategoriesAdminPage/index.js.map +1 -1
  283. package/dist/pages/CaseTypeSetsAdminPage/index.js +6 -6
  284. package/dist/pages/CaseTypeSetsAdminPage/index.js.map +1 -1
  285. package/dist/pages/CaseTypesAdminPage/index.js +5 -5
  286. package/dist/pages/CaseTypesAdminPage/index.js.map +1 -1
  287. package/dist/pages/CasesDetailPage/index.js +5 -5
  288. package/dist/pages/CasesDetailPage/index.js.map +1 -1
  289. package/dist/pages/CasesPage/index.js +10 -10
  290. package/dist/pages/CasesPage/index.js.map +1 -1
  291. package/dist/pages/ColSetsAdminPage/index.js +6 -6
  292. package/dist/pages/ColSetsAdminPage/index.js.map +1 -1
  293. package/dist/pages/ColsAdminPage/index.js +5 -5
  294. package/dist/pages/ColsAdminPage/index.js.map +1 -1
  295. package/dist/pages/ConceptRelationsAdminPage/index.js +19 -19
  296. package/dist/pages/ConceptRelationsAdminPage/index.js.map +1 -1
  297. package/dist/pages/ConceptSetsAdminPage/index.js +5 -5
  298. package/dist/pages/ConceptSetsAdminPage/index.js.map +1 -1
  299. package/dist/pages/ConceptsAdminPage/index.js +5 -5
  300. package/dist/pages/ConceptsAdminPage/index.js.map +1 -1
  301. package/dist/pages/DataCollectionSetsAdminPage/index.js +12 -12
  302. package/dist/pages/DataCollectionSetsAdminPage/index.js.map +1 -1
  303. package/dist/pages/DataCollectionVisualizationPage/index.js +4 -4
  304. package/dist/pages/DataCollectionVisualizationPage/index.js.map +1 -1
  305. package/dist/pages/DataCollectionsAdminPage/index.js +4 -4
  306. package/dist/pages/DataCollectionsAdminPage/index.js.map +1 -1
  307. package/dist/pages/DimsAdminPage/index.js +6 -6
  308. package/dist/pages/DimsAdminPage/index.js.map +1 -1
  309. package/dist/pages/DiseasesAdminPage/index.js +4 -4
  310. package/dist/pages/DiseasesAdminPage/index.js.map +1 -1
  311. package/dist/pages/EtiologicalAgentsAdminPage/index.js +4 -4
  312. package/dist/pages/EtiologicalAgentsAdminPage/index.js.map +1 -1
  313. package/dist/pages/EtiologiesAdminPage/index.js +3 -3
  314. package/dist/pages/EtiologiesAdminPage/index.js.map +1 -1
  315. package/dist/pages/EventsDetailPage/index.js +5 -5
  316. package/dist/pages/EventsDetailPage/index.js.map +1 -1
  317. package/dist/pages/EventsPage/index.js +11 -11
  318. package/dist/pages/EventsPage/index.js.map +1 -1
  319. package/dist/pages/HomePage/index.js +2 -2
  320. package/dist/pages/HomePage/index.js.map +1 -1
  321. package/dist/pages/OrganizationAccessCasePoliciesAdminPage/index.js +4 -4
  322. package/dist/pages/OrganizationAccessCasePoliciesAdminPage/index.js.map +1 -1
  323. package/dist/pages/OrganizationShareCasePoliciesAdminPage/index.js +4 -4
  324. package/dist/pages/OrganizationShareCasePoliciesAdminPage/index.js.map +1 -1
  325. package/dist/pages/RefColsAdminPage/index.js +7 -7
  326. package/dist/pages/RefColsAdminPage/index.js.map +1 -1
  327. package/dist/pages/RefDimsAdminPage/index.js +5 -5
  328. package/dist/pages/RefDimsAdminPage/index.js.map +1 -1
  329. package/dist/pages/RegionRelationsAdminPage/index.js +3 -3
  330. package/dist/pages/RegionRelationsAdminPage/index.js.map +1 -1
  331. package/dist/pages/RegionSetShapesAdminPage/index.js +4 -4
  332. package/dist/pages/RegionSetShapesAdminPage/index.js.map +1 -1
  333. package/dist/pages/RegionSetsAdminPage/index.js +5 -5
  334. package/dist/pages/RegionSetsAdminPage/index.js.map +1 -1
  335. package/dist/pages/RegionsAdminPage/index.js +5 -5
  336. package/dist/pages/RegionsAdminPage/index.js.map +1 -1
  337. package/dist/pages/TrendsPage/index.js +1 -1
  338. package/dist/pages/TrendsPage/index.js.map +1 -1
  339. package/dist/pages/UploadPage/index.js +1 -1
  340. package/dist/pages/UploadPage/index.js.map +1 -1
  341. package/dist/pages/UserAccessCasePoliciesAdminPage/index.js +4 -4
  342. package/dist/pages/UserAccessCasePoliciesAdminPage/index.js.map +1 -1
  343. package/dist/pages/UserEffectiveRightsAdminPage/index.js +12 -12
  344. package/dist/pages/UserEffectiveRightsAdminPage/index.js.map +1 -1
  345. package/dist/pages/UserEffectiveRightsTesterAdminPage/index.js +8 -8
  346. package/dist/pages/UserEffectiveRightsTesterAdminPage/index.js.map +1 -1
  347. package/dist/pages/UserShareCasePoliciesAdminPage/index.js +4 -4
  348. package/dist/pages/UserShareCasePoliciesAdminPage/index.js.map +1 -1
  349. package/dist/routes/adminRoutes.d.ts +1 -1
  350. package/dist/routes/index.js +11 -8
  351. package/dist/routes/index.js.map +1 -1
  352. package/dist/routes/routes.d.ts +1 -1
  353. package/dist/setup/setup.js +5 -5
  354. package/dist/setup/setup.js.map +1 -1
  355. package/dist/stores/dashboardStore/dashboardStore.d.ts +1 -1
  356. package/dist/stores/uploadStore/index.js +2 -2
  357. package/dist/stores/uploadStore/index.js.map +1 -1
  358. package/dist/stores/uploadStore/uploadStore.d.ts +1 -1
  359. package/dist/stores/userProfileStore/index.js +2 -2
  360. package/dist/stores/userProfileStore/index.js.map +1 -1
  361. package/dist/theme/demoTheme/index.js +2 -2
  362. package/dist/theme/demoTheme/index.js.map +1 -1
  363. package/dist/utils/CaseDbDataUtil/CaseDbDataUtil.d.ts +1 -1
  364. package/dist/utils/CaseDbDataUtil/index.js +1 -1
  365. package/dist/utils/CaseDbDataUtil/index.js.map +1 -1
  366. package/dist/utils/CaseDbStandardConfigUtil/index.js +2488 -1408
  367. package/dist/utils/CaseDbStandardConfigUtil/index.js.map +1 -1
  368. package/dist/utils/CaseDbTableUtil/CaseDbTableUtil.d.ts +1 -1
  369. package/dist/utils/CaseDbTableUtil/index.js +1 -1
  370. package/dist/utils/CaseDbTableUtil/index.js.map +1 -1
  371. package/dist/utils/CaseSelectionUtil/index.js.map +1 -1
  372. package/dist/utils/CaseTypeFormUtil/CaseTypeFormUtil.d.ts +1 -1
  373. package/dist/utils/CaseTypeFormUtil/index.js +7 -10
  374. package/dist/utils/CaseTypeFormUtil/index.js.map +1 -1
  375. package/dist/utils/CaseTypeUtil/index.js +1 -1
  376. package/dist/utils/CaseTypeUtil/index.js.map +1 -1
  377. package/dist/utils/CaseUtil/index.js +3 -3
  378. package/dist/utils/CaseUtil/index.js.map +1 -1
  379. package/dist/utils/DashboardUtil/index.js +1 -1
  380. package/dist/utils/DashboardUtil/index.js.map +1 -1
  381. package/dist/utils/DataSetUtil/index.js.map +1 -1
  382. package/dist/utils/FileUtil/index.js +1 -1
  383. package/dist/utils/FileUtil/index.js.map +1 -1
  384. package/dist/utils/FilterUtil/FilterUtil.d.ts +2 -2
  385. package/dist/utils/HistogramUtil/index.js +1 -1
  386. package/dist/utils/HistogramUtil/index.js.map +1 -1
  387. package/dist/utils/MapUtil/index.js +1 -1
  388. package/dist/utils/MapUtil/index.js.map +1 -1
  389. package/dist/utils/StratificationUtil/index.js +3 -2
  390. package/dist/utils/StratificationUtil/index.js.map +1 -1
  391. package/dist/utils/UploadUtil/UploadUtil.d.ts +1 -1
  392. package/package.json +19 -11
  393. package/dist/_chunks/chunk-KS7C4IRE.js.map +0 -1
@@ -11,20 +11,20 @@ import { c as ee, o as te, t as x } from "./index.esm.js";
11
11
  import { t as ne } from "./yup.js";
12
12
  import { mixed as re, object as ie, string as S } from "yup";
13
13
  import { CaseDbCaseApi as C } from "@gen-epix/api-casedb";
14
- import { QueryClientService as w } from "@gen-epix/ui/classes/services/QueryClientService";
15
- import { FORM_FIELD_DEFINITION_TYPE as T } from "@gen-epix/ui-form/models/form";
14
+ import { QueryClientService as w } from "@gen-epix/ui-client-common/classes/services/QueryClientService";
15
+ import { FORM_FIELD_DEFINITION_TYPE as T } from "@gen-epix/ui-core-form/models/form";
16
16
  import { DATE_FORMAT as E } from "@gen-epix/ui-core/constants/date";
17
- import { ConfigService as D } from "@gen-epix/ui/classes/services/ConfigService";
17
+ import { ConfigService as D } from "@gen-epix/ui-client-common/classes/services/ConfigService";
18
18
  import { Alert as O, AlertTitle as k, Box as A, Button as ae, Divider as oe, Typography as se, useTheme as j } from "@mui/material";
19
19
  import { use as M, useCallback as N, useEffect as P, useId as F, useMemo as I, useRef as L, useState as R } from "react";
20
20
  import { useTranslation as z } from "react-i18next";
21
21
  import { Fragment as B, jsx as V, jsxs as H } from "react/jsx-runtime";
22
- import { ResponseHandler as ce } from "@gen-epix/ui/components/ui/ResponseHandler";
23
- import { GenericForm as le } from "@gen-epix/ui-form/components/helpers/GenericForm";
24
- import { useQueryMemo as ue } from "@gen-epix/ui/hooks/useQueryMemo";
25
- import { withDialog as U } from "@gen-epix/ui/hoc/withDialog";
22
+ import { ResponseHandler as ce } from "@gen-epix/ui-client-common/components/ui/ResponseHandler";
23
+ import { GenericForm as le } from "@gen-epix/ui-core-form/components/helpers/GenericForm";
24
+ import { useQueryMemo as ue } from "@gen-epix/ui-client-common/hooks/useQueryMemo";
25
+ import { withDialog as U } from "@gen-epix/ui-core-components/hoc/withDialog";
26
26
  import { TestIdUtil as W } from "@gen-epix/ui-core/utils/TestIdUtil";
27
- import { SchemaUtil as de } from "@gen-epix/ui-form/utils/SchemaUtil";
27
+ import { SchemaUtil as de } from "@gen-epix/ui-core-form/utils/SchemaUtil";
28
28
  //#region src/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialogDateRangeChart.tsx
29
29
  l([
30
30
  o,
@@ -173,17 +173,17 @@ var G = {
173
173
  y: n.clientY + 12
174
174
  });
175
175
  }
176
- }), [h, v]);
176
+ }), [h, v]), b = N(({ field: { onChange: e } }) => (m.current = e, /* @__PURE__ */ V(_, {
177
+ echarts: G,
178
+ notMerge: !0,
179
+ onEvents: y,
180
+ option: g,
181
+ style: { height: 400 }
182
+ })), [y, g]);
177
183
  return /* @__PURE__ */ H(B, { children: [/* @__PURE__ */ V(x, {
178
184
  control: e,
179
185
  name: r,
180
- render: N(({ field: { onChange: e } }) => (m.current = e, /* @__PURE__ */ V(_, {
181
- echarts: G,
182
- notMerge: !0,
183
- onEvents: y,
184
- option: g,
185
- style: { height: 400 }
186
- })), [y, g])
186
+ render: b
187
187
  }), l && /* @__PURE__ */ V(A, {
188
188
  sx: {
189
189
  bgcolor: "background.paper",
@@ -1 +1 @@
1
- {"version":3,"file":"FindSimilarCasesDialog.js","names":[],"sources":["../../src/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialogDateRangeChart.tsx","../../src/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialog.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { ReactElement } from 'react';\nimport {\n dispose,\n getInstanceByDom,\n init,\n use as registerECharts,\n} from 'echarts/core';\nimport {\n DataZoomComponent,\n GridComponent,\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport {\n BarChart,\n LineChart,\n} from 'echarts/charts';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport EChartsReact from 'echarts-for-react';\nimport type {\n Control,\n FieldValues,\n Path,\n} from 'react-hook-form';\nimport { Controller } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport {\n Box,\n useTheme,\n} from '@mui/material';\nimport { ConfigService } from '@gen-epix/ui/classes/services/ConfigService';\n\nimport { FindSimilarCasesUtil } from '../../../utils/FindSimilarCasesUtil';\nimport type {\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesOrganizationFilter,\n} from '../../../models/caseDb';\nimport type { CaseDbConfig } from '../../../models/config';\n\nregisterECharts([BarChart, LineChart, GridComponent, LegendComponent, TooltipComponent, DataZoomComponent, CanvasRenderer]);\n\nconst echartsCore = {\n dispose,\n getInstanceByDom,\n init,\n};\n\nexport interface FindSimilarCasesDialogDateRangeChartProps<\n TFieldValues extends FieldValues,\n TName extends Path<TFieldValues> = Path<TFieldValues>,\n> {\n control: Control<TFieldValues>;\n data: FindSimilarCasesChartDataPoint[];\n name: TName;\n onOrganizationFilterChange: (organizationFilter: FindSimilarCasesOrganizationFilter) => void;\n organizationFilter: FindSimilarCasesOrganizationFilter;\n}\n\nexport const FindSimilarCasesDialogDateRangeChart = <\n TFieldValues extends FieldValues,\n TName extends Path<TFieldValues> = Path<TFieldValues>,\n>({\n control,\n data,\n name,\n onOrganizationFilterChange,\n organizationFilter,\n}: FindSimilarCasesDialogDateRangeChartProps<TFieldValues, TName>): ReactElement => {\n const { t } = useTranslation();\n const intervals = useMemo(() => FindSimilarCasesUtil.buildChartIntervals(data), [data]);\n const theme = useTheme();\n const [tooltipState, setTooltipState] = useState<{ content: string; x: number; y: number } | null>(null);\n const ownCasesLabel = t`Own cases`;\n const otherOrganizationCasesLabel = t`Cases from other organizations`;\n\n const intervalsRef = useRef(intervals);\n useEffect(() => {\n intervalsRef.current = intervals;\n }, [intervals]);\n\n // Keeps a stable reference to the latest onChange so onDataZoom never goes stale.\n const onChangeRef = useRef<((value: [string, string] | null) => void) | null>(null);\n\n const onDataZoom = useCallback((params: unknown) => {\n type ZoomPayload = { end?: number; endValue?: number; start?: number; startValue?: number };\n const event = params as { batch?: ZoomPayload[] } & ZoomPayload;\n const base = event.batch?.[0] ?? event;\n\n const n = intervalsRef.current.length - 1;\n let startIndex: number;\n let endIndex: number;\n\n if (base.startValue !== undefined && base.endValue !== undefined) {\n // index-based (e.g. inside/wheel zoom)\n startIndex = Math.round(base.startValue);\n endIndex = Math.round(base.endValue);\n } else if (base.start !== undefined && base.end !== undefined) {\n // percentage-based (slider drag)\n startIndex = Math.round((base.start / 100) * n);\n endIndex = Math.round((base.end / 100) * n);\n } else {\n onChangeRef.current?.(null);\n return;\n }\n\n const startInterval = intervalsRef.current[startIndex];\n const endInterval = intervalsRef.current[endIndex];\n if (startInterval && endInterval) {\n onChangeRef.current?.([startInterval.startDate, endInterval.endDate]);\n return;\n }\n onChangeRef.current?.(null);\n }, []);\n\n const option = useMemo(() => {\n const { BASE_COLORS } = ConfigService.getInstance<CaseDbConfig>().config.epi.STRATIFICATION;\n return {\n color: BASE_COLORS,\n dataZoom: [{\n borderColor: theme.palette.primary.light,\n bottom: 0,\n fillerColor: `${theme.palette.primary.main}33`,\n handleStyle: { borderColor: theme.palette.primary.main, color: theme.palette.primary.main },\n height: 50,\n left: 80,\n right: 80,\n selectedDataBackground: { areaStyle: { color: theme.palette.primary.light }, lineStyle: { color: theme.palette.primary.main } },\n type: 'slider',\n }],\n grid: { bottom: 110, left: 80, right: 80, top: 40 },\n legend: {\n data: [ownCasesLabel, otherOrganizationCasesLabel],\n selected: {\n [otherOrganizationCasesLabel]: organizationFilter !== 'own',\n [ownCasesLabel]: organizationFilter !== 'otherOrganization',\n },\n top: 0,\n },\n series: [\n {\n data: intervals.map(i => i.count),\n lineStyle: { opacity: 0 },\n name: 'dataZoomShadow',\n silent: true,\n symbol: 'none',\n type: 'line',\n },\n { data: intervals.map(i => i.ownCaseCount), itemStyle: { color: BASE_COLORS[0] }, name: ownCasesLabel, stack: 'similarCases', type: 'bar' },\n { data: intervals.map(i => i.otherOrganizationCaseCount), itemStyle: { color: BASE_COLORS[1] }, name: otherOrganizationCasesLabel, stack: 'similarCases', type: 'bar' },\n ],\n tooltip: { show: false },\n xAxis: { axisLabel: {\n height: 100,\n rotate: 45,\n }, axisTick: {\n alignWithLabel: true,\n show: true,\n }, data: intervals.map(i => i.label),\n type: 'category' },\n yAxis: { max: Math.max(...intervals.map(i => i.count), 1), minInterval: 1, type: 'value' },\n };\n }, [intervals, organizationFilter, otherOrganizationCasesLabel, ownCasesLabel, theme]);\n\n const onLegendSelectChanged = useCallback((params: unknown) => {\n const { selected } = params as { selected?: Record<string, boolean> };\n if (!selected) {\n return;\n }\n const ownCasesSelected = selected[ownCasesLabel] ?? true;\n const otherOrganizationCasesSelected = selected[otherOrganizationCasesLabel] ?? true;\n if (ownCasesSelected && !otherOrganizationCasesSelected) {\n onOrganizationFilterChange('own');\n return;\n }\n if (!ownCasesSelected && otherOrganizationCasesSelected) {\n onOrganizationFilterChange('otherOrganization');\n return;\n }\n onOrganizationFilterChange('all');\n }, [onOrganizationFilterChange, otherOrganizationCasesLabel, ownCasesLabel]);\n\n const onEvents = useMemo(() => ({\n datazoom: onDataZoom,\n legendselectchanged: onLegendSelectChanged,\n mouseout: () => {\n setTooltipState(null);\n },\n mouseover: (event: unknown) => {\n const e = event as { event?: { event?: MouseEvent }; name?: string; value?: number };\n const mouseEvent = e.event?.event;\n if (mouseEvent && e.name !== null && e.name !== undefined) {\n setTooltipState({ content: `${e.name} (n=${e.value ?? 0})`, x: mouseEvent.clientX + 12, y: mouseEvent.clientY + 12 });\n }\n },\n }), [onDataZoom, onLegendSelectChanged]);\n\n const renderChart = useCallback(({ field: { onChange } }: { field: { onChange: (value: [string, string] | null) => void } }) => {\n onChangeRef.current = onChange;\n return (\n <EChartsReact\n echarts={echartsCore}\n notMerge\n onEvents={onEvents}\n option={option}\n style={{ height: 400 }}\n />\n );\n }, [onEvents, option]);\n\n return (\n <>\n <Controller\n control={control}\n name={name}\n render={renderChart}\n />\n {tooltipState && (\n <Box\n sx={{\n bgcolor: 'background.paper',\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: 1,\n fontSize: 12,\n left: tooltipState.x,\n pointerEvents: 'none',\n position: 'fixed',\n px: 1,\n py: 0.5,\n top: tooltipState.y,\n zIndex: 'tooltip',\n }}\n >\n {tooltipState.content}\n </Box>\n )}\n </>\n );\n};\n","import {\n use,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n mixed,\n object,\n string,\n} from 'yup';\nimport { yupResolver } from '@hookform/resolvers/yup';\nimport type { Resolver } from 'react-hook-form';\nimport {\n useForm,\n useWatch,\n} from 'react-hook-form';\nimport {\n Alert,\n AlertTitle,\n Box,\n Button,\n Divider,\n Typography,\n} from '@mui/material';\nimport { useStore } from 'zustand';\nimport { produce } from 'immer';\nimport {\n format,\n parseISO,\n} from 'date-fns';\nimport type {\n CaseDbCase,\n CaseDbCol,\n CaseDbCompleteCaseType,\n} from '@gen-epix/api-casedb';\nimport { CaseDbCaseApi } from '@gen-epix/api-casedb';\nimport type { DialogAction } from '@gen-epix/ui/components/ui/Dialog';\nimport type {\n WithDialogRefMethods,\n WithDialogRenderProps,\n} from '@gen-epix/ui/hoc/withDialog';\nimport { ConfigService } from '@gen-epix/ui/classes/services/ConfigService';\nimport { QueryClientService } from '@gen-epix/ui/classes/services/QueryClientService';\nimport { ResponseHandler } from '@gen-epix/ui/components/ui/ResponseHandler';\nimport { useQueryMemo } from '@gen-epix/ui/hooks/useQueryMemo';\nimport { withDialog } from '@gen-epix/ui/hoc/withDialog';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport { GenericForm } from '@gen-epix/ui-form/components/helpers/GenericForm';\nimport type {\n AutoCompleteOption,\n FormFieldDefinition,\n} from '@gen-epix/ui-form/models/form';\nimport { FORM_FIELD_DEFINITION_TYPE } from '@gen-epix/ui-form/models/form';\nimport { SchemaUtil } from '@gen-epix/ui-form/utils/SchemaUtil';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport { CASEDB_QUERY_KEY } from '../../../constants/query';\nimport type { CaseDbConfig } from '../../../models/config';\nimport { DashboardStoreContext } from '../../../stores/dashboardStore';\nimport { TreeWidgetUtil } from '../../../utils/TreeWidgetUtil';\nimport type {\n CaseDbSimilarCaseWithIsOwnCase,\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesOrganizationFilter,\n} from '../../../models/caseDb';\nimport type { TreeWidgetDataPersistable } from '../../../models/dashboard';\nimport { DASHBOARD_COMPONENT_NAME } from '../../../constants/dashboard';\n\nimport { FindSimilarCasesDialogDateRangeChart } from './FindSimilarCasesDialogDateRangeChart';\n\nexport interface FindSimilarCasesDialogOpenProps {\n allRows: CaseDbCase[];\n completeCaseType: CaseDbCompleteCaseType;\n selectedRows: CaseDbCase[];\n}\n\nexport interface FindSimilarCasesDialogProps extends WithDialogRenderProps<FindSimilarCasesDialogOpenProps> {\n //\n}\n\nexport type FindSimilarCasesDialogRefMethods = WithDialogRefMethods<FindSimilarCasesDialogProps, FindSimilarCasesDialogOpenProps>;\n\ntype FormFields = {\n dateRange: [string, string] | null;\n maxDistance: number;\n organizationFilter: FindSimilarCasesOrganizationFilter;\n treeColId: string;\n};\n\nexport const FindSimilarCasesDialog = withDialog<FindSimilarCasesDialogProps, FindSimilarCasesDialogOpenProps>((\n {\n onActionsChange,\n onClose,\n onTitleChange,\n openProps,\n }: FindSimilarCasesDialogProps,\n): ReactElement => {\n const { t } = useTranslation();\n const searchFormId = useId();\n const dashboardStore = use(DashboardStoreContext);\n const treeConfiguration = dashboardStore.getState().getWidgetDataPersistable<TreeWidgetDataPersistable>(DASHBOARD_COMPONENT_NAME.TREE).treeConfiguration;\n const setFindSimilarCasesResults = useStore(dashboardStore, (state) => state.setFindSimilarCasesResults);\n const findSimilarCasesResults = useStore(dashboardStore, (state) => state.findSimilarCasesResults);\n const treeConfigurations = useMemo(() => TreeWidgetUtil.getTreeConfigurations(openProps.completeCaseType), [openProps.completeCaseType]);\n const [formData, setFormData] = useState<FormFields>(null);\n\n const schema = useMemo(() => object<FormFields>().shape({\n dateRange: mixed<[string, string] | null>().nullable().default(null),\n maxDistance: SchemaUtil.number.required().positive().when('treeColId', ([treeColId], s) => {\n const currentTreeConfiguration = treeConfigurations.find(x => x.col.id === treeColId);\n if (!currentTreeConfiguration) {\n return s;\n }\n const sWithIntegerCheck = s.integer(t`Max distance must be an integer`);\n return sWithIntegerCheck.max(currentTreeConfiguration.geneticDistanceProtocol.seqdb_max_stored_distance || ConfigService.getInstance<CaseDbConfig>().config.epi.SEQDB_MAX_STORED_DISTANCE_FALLBACK);\n }),\n organizationFilter: string<FindSimilarCasesOrganizationFilter>().required().oneOf(['all', 'own', 'otherOrganization']),\n treeColId: string().required(),\n }), [t, treeConfigurations]);\n\n const treeOptions = useMemo<AutoCompleteOption<string>[]>(() => {\n const cols = new Set<CaseDbCol>();\n treeConfigurations.forEach(x => {\n cols.add(x.col);\n });\n return Array.from(cols).map(x => {\n return {\n label: x.label,\n value: x.id,\n } satisfies AutoCompleteOption<string>;\n });\n\n }, [treeConfigurations]);\n\n const formMethods = useForm<FormFields>({\n defaultValues: {\n dateRange: null,\n maxDistance: 0,\n organizationFilter: 'all',\n treeColId: treeConfiguration ? treeConfiguration.col.id : null,\n },\n resolver: yupResolver(schema, undefined, { raw: true }) as Resolver<FormFields>,\n });\n const { control, handleSubmit } = formMethods;\n\n const formValues = useWatch({ control });\n\n const searchFormFieldDefinitions = useMemo(() => {\n const currentTreeConfiguration = treeConfigurations.find(x => x.col.id === formValues.treeColId);\n return [\n {\n definition: FORM_FIELD_DEFINITION_TYPE.SELECT,\n label: t`Tree`,\n name: 'treeColId',\n options: treeOptions,\n } as const satisfies FormFieldDefinition<FormFields>,\n {\n definition: FORM_FIELD_DEFINITION_TYPE.NUMBER,\n label: t`Max distance`,\n max: currentTreeConfiguration?.geneticDistanceProtocol?.seqdb_max_stored_distance || ConfigService.getInstance<CaseDbConfig>().config.epi.SEQDB_MAX_STORED_DISTANCE_FALLBACK,\n min: 0,\n name: 'maxDistance',\n showSlider: true,\n step: 1,\n } as const satisfies FormFieldDefinition<FormFields>,\n ];\n }, [formValues.treeColId, t, treeConfigurations, treeOptions]);\n\n useEffect(() => {\n onTitleChange(t`Find similar cases`);\n }, [t, onTitleChange]);\n\n const onFormSubmit = useCallback((data: FormFields) => {\n formMethods.setValue('dateRange', null);\n setFormData({ ...data, dateRange: null });\n }, [formMethods]);\n\n const onOrganizationFilterChange = useCallback((organizationFilter: FindSimilarCasesOrganizationFilter) => {\n formMethods.setValue('organizationFilter', organizationFilter);\n }, [formMethods]);\n\n const query = useQueryMemo({\n enabled: !!formData,\n queryFn: async ({ signal }) => {\n const retrieveSimilarCasesResponse = await CaseDbCaseApi.getInstance().retrieveSimilarCases({\n case_ids: openProps.selectedRows.map(x => x.id),\n case_type_id: openProps.completeCaseType.id,\n genetic_distance_col_id: formData?.treeColId,\n max_distance: formData?.maxDistance,\n }, { signal });\n const retrieveIsOwnCasesResponse = await CaseDbCaseApi.getInstance().retrieveIsOwnCases({\n case_ids: retrieveSimilarCasesResponse.data.cases.map(x => x.id),\n case_type_id: openProps.completeCaseType.id,\n }, { signal });\n\n return retrieveSimilarCasesResponse.data.cases.map(caseDbCase => {\n return {\n ...caseDbCase,\n is_own_case: retrieveIsOwnCasesResponse.data[caseDbCase.id] || false,\n } satisfies CaseDbSimilarCaseWithIsOwnCase;\n });\n },\n queryKey: [QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.SIMILAR_CASES), JSON.stringify({ formData, rowIds: openProps.selectedRows.map(row => row.id) })],\n });\n\n const organizationFilteredCases = useMemo<CaseDbSimilarCaseWithIsOwnCase[]>(() => {\n if (!query.data) {\n return [];\n }\n return query.data.filter(c => {\n switch (formValues.organizationFilter) {\n case 'all': return true;\n case 'otherOrganization': return !c.is_own_case;\n case 'own': return c.is_own_case;\n default: return true;\n }\n });\n }, [query.data, formValues.organizationFilter]);\n\n const chartData = useMemo<FindSimilarCasesChartDataPoint[]>(() => {\n const counts = new Map<string, FindSimilarCasesChartDataPoint>();\n for (const { case_date, is_own_case } of query.data ?? []) {\n if (case_date) {\n const currentCount = counts.get(case_date) ?? {\n count: 0,\n date: case_date,\n otherOrganizationCaseCount: 0,\n ownCaseCount: 0,\n };\n currentCount.count += 1;\n if (is_own_case) {\n currentCount.ownCaseCount += 1;\n } else {\n currentCount.otherOrganizationCaseCount += 1;\n }\n counts.set(case_date, currentCount);\n }\n }\n return Array.from(counts.values())\n .sort((a, b) => a.date.localeCompare(b.date));\n }, [query.data]);\n\n const filteredCases = useMemo<CaseDbSimilarCaseWithIsOwnCase[]>(() => {\n const dateRange = formValues.dateRange;\n if (!dateRange) {\n return organizationFilteredCases;\n }\n const [startDate, endDate] = dateRange;\n return organizationFilteredCases.filter(c => {\n if (!c.case_date) {\n return false;\n }\n const caseDateOnly = format(parseISO(c.case_date), DATE_FORMAT.DATE);\n return caseDateOnly >= startDate && caseDateOnly <= endDate;\n });\n }, [formValues.dateRange, organizationFilteredCases]);\n\n const similarCaseIdsNotInLineListWithDateFilter = useMemo<string[]>(() => {\n const allRowIds = openProps.allRows.map(x => x.id);\n return filteredCases.reduce<string[]>((acc, caseIdAndDate) => {\n const caseId = caseIdAndDate.id;\n if (!allRowIds.includes(caseId)) {\n acc.push(caseId);\n }\n return acc;\n }, []);\n }, [filteredCases, openProps.allRows]);\n\n const similarCaseIdsAlreadyInLineListWithDateFilter = useMemo<string[]>(() => {\n const allRowIds = openProps.allRows.map(x => x.id);\n return filteredCases.reduce<string[]>((acc, caseIdAndDate) => {\n const caseId = caseIdAndDate.id;\n if (allRowIds.includes(caseId)) {\n acc.push(caseId);\n }\n return acc;\n }, []);\n }, [filteredCases, openProps.allRows]);\n\n const onAddToLineListButtonClick = useCallback(async () => {\n\n await setFindSimilarCasesResults(produce(findSimilarCasesResults, draft => {\n draft.push({\n colId: formData?.treeColId,\n distance: formData?.maxDistance,\n key: findSimilarCasesResults.length.toString(),\n originalCaseIds: openProps.allRows.map(x => x.id),\n similarCaseIds: similarCaseIdsNotInLineListWithDateFilter,\n });\n return draft;\n }));\n\n onClose();\n }, [setFindSimilarCasesResults, findSimilarCasesResults, onClose, similarCaseIdsNotInLineListWithDateFilter, formData?.maxDistance, formData?.treeColId, openProps.allRows]);\n\n useEffect(() => {\n const actions: DialogAction[] = [];\n actions.push({\n ...TestIdUtil.createAttributes('FindSimilarCasesDialog-closeButton'),\n color: 'primary',\n label: t`Close`,\n onClick: onClose,\n variant: 'outlined',\n });\n actions.push({\n ...TestIdUtil.createAttributes('FindSimilarCasesDialog-addSimilarCasesButton'),\n color: 'secondary',\n disabled: similarCaseIdsNotInLineListWithDateFilter.length === 0,\n label: t('Add {{count}} similar cases to line list', { count: similarCaseIdsNotInLineListWithDateFilter.length }),\n onClick: onAddToLineListButtonClick,\n variant: 'contained',\n });\n onActionsChange(actions);\n }, [onActionsChange, onAddToLineListButtonClick, onClose, similarCaseIdsNotInLineListWithDateFilter.length, t]);\n\n return (\n <Box>\n <Box\n sx={{\n marginBottom: 2,\n }}\n >\n <Typography>\n {t('Select a tree and maximum distance to find similar cases for the {{count}} selected cases.', { count: openProps.selectedRows.length })}\n </Typography>\n </Box>\n <Box>\n <GenericForm<FormFields>\n formFieldDefinitions={searchFormFieldDefinitions}\n formId={searchFormId}\n formMethods={formMethods}\n onSubmit={handleSubmit(onFormSubmit)}\n schema={schema}\n />\n </Box>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n marginTop: 2,\n }}\n >\n <Button\n color={'secondary'}\n form={searchFormId}\n type={'submit'}\n variant={'contained'}\n >\n {formData ? t`Search again` : t`Search`}\n </Button>\n </Box>\n <Divider sx={{ marginY: 2 }} />\n <ResponseHandler\n inlineSpinner\n loadables={query}\n >\n {query.data && (\n <>\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Alert\n severity={query.data.length > 0 ? 'success' : 'warning'}\n >\n <AlertTitle>\n {t('Found {{count}} similar cases with a distance of {{distance}}.', { count: query.data.length, distance: formData?.maxDistance })}\n </AlertTitle>\n </Alert>\n </Box>\n {chartData.length > 0 && (\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <FindSimilarCasesDialogDateRangeChart<FormFields>\n control={control}\n data={chartData}\n name={'dateRange'}\n onOrganizationFilterChange={onOrganizationFilterChange}\n organizationFilter={formValues.organizationFilter}\n />\n </Box>\n )}\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Alert\n severity={'info'}\n >\n <AlertTitle>\n {t('{{count}} similar cases can be added to the line list.', { count: similarCaseIdsNotInLineListWithDateFilter.length })}\n </AlertTitle>\n </Alert>\n </Box>\n {similarCaseIdsAlreadyInLineListWithDateFilter.length > 0 && (\n <Alert\n severity={'warning'}\n >\n <AlertTitle>\n {t('{{count}} similar cases found that are already in the line list.', { count: similarCaseIdsAlreadyInLineListWithDateFilter.length })}\n </AlertTitle>\n </Alert>\n )}\n </>\n )}\n </ResponseHandler>\n </Box>\n );\n}, {\n defaultTitle: '',\n fullWidth: true,\n maxWidth: 'md',\n testId: 'FindSimilarCasesDialog',\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"FindSimilarCasesDialog.js","names":[],"sources":["../../src/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialogDateRangeChart.tsx","../../src/components/ui/FindSimilarCasesDialog/FindSimilarCasesDialog.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { ReactElement } from 'react';\nimport {\n dispose,\n getInstanceByDom,\n init,\n use as registerECharts,\n} from 'echarts/core';\nimport {\n DataZoomComponent,\n GridComponent,\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport {\n BarChart,\n LineChart,\n} from 'echarts/charts';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport EChartsReact from 'echarts-for-react';\nimport type {\n Control,\n FieldValues,\n Path,\n} from 'react-hook-form';\nimport { Controller } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport {\n Box,\n useTheme,\n} from '@mui/material';\nimport { ConfigService } from '@gen-epix/ui-client-common/classes/services/ConfigService';\n\nimport { FindSimilarCasesUtil } from '../../../utils/FindSimilarCasesUtil';\nimport type {\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesOrganizationFilter,\n} from '../../../models/caseDb';\nimport type { CaseDbConfig } from '../../../models/config';\n\nregisterECharts([BarChart, LineChart, GridComponent, LegendComponent, TooltipComponent, DataZoomComponent, CanvasRenderer]);\n\nconst echartsCore = {\n dispose,\n getInstanceByDom,\n init,\n};\n\nexport interface FindSimilarCasesDialogDateRangeChartProps<\n TFieldValues extends FieldValues,\n TName extends Path<TFieldValues> = Path<TFieldValues>,\n> {\n control: Control<TFieldValues>;\n data: FindSimilarCasesChartDataPoint[];\n name: TName;\n onOrganizationFilterChange: (organizationFilter: FindSimilarCasesOrganizationFilter) => void;\n organizationFilter: FindSimilarCasesOrganizationFilter;\n}\n\nexport const FindSimilarCasesDialogDateRangeChart = <\n TFieldValues extends FieldValues,\n TName extends Path<TFieldValues> = Path<TFieldValues>,\n>({\n control,\n data,\n name,\n onOrganizationFilterChange,\n organizationFilter,\n}: FindSimilarCasesDialogDateRangeChartProps<TFieldValues, TName>): ReactElement => {\n const { t } = useTranslation();\n const intervals = useMemo(() => FindSimilarCasesUtil.buildChartIntervals(data), [data]);\n const theme = useTheme();\n const [tooltipState, setTooltipState] = useState<{ content: string; x: number; y: number } | null>(null);\n const ownCasesLabel = t`Own cases`;\n const otherOrganizationCasesLabel = t`Cases from other organizations`;\n\n const intervalsRef = useRef(intervals);\n useEffect(() => {\n intervalsRef.current = intervals;\n }, [intervals]);\n\n // Keeps a stable reference to the latest onChange so onDataZoom never goes stale.\n const onChangeRef = useRef<((value: [string, string] | null) => void) | null>(null);\n\n const onDataZoom = useCallback((params: unknown) => {\n type ZoomPayload = { end?: number; endValue?: number; start?: number; startValue?: number };\n const event = params as { batch?: ZoomPayload[] } & ZoomPayload;\n const base = event.batch?.[0] ?? event;\n\n const n = intervalsRef.current.length - 1;\n let startIndex: number;\n let endIndex: number;\n\n if (base.startValue !== undefined && base.endValue !== undefined) {\n // index-based (e.g. inside/wheel zoom)\n startIndex = Math.round(base.startValue);\n endIndex = Math.round(base.endValue);\n } else if (base.start !== undefined && base.end !== undefined) {\n // percentage-based (slider drag)\n startIndex = Math.round((base.start / 100) * n);\n endIndex = Math.round((base.end / 100) * n);\n } else {\n onChangeRef.current?.(null);\n return;\n }\n\n const startInterval = intervalsRef.current[startIndex];\n const endInterval = intervalsRef.current[endIndex];\n if (startInterval && endInterval) {\n onChangeRef.current?.([startInterval.startDate, endInterval.endDate]);\n return;\n }\n onChangeRef.current?.(null);\n }, []);\n\n const option = useMemo(() => {\n const { BASE_COLORS } = ConfigService.getInstance<CaseDbConfig>().config.epi.STRATIFICATION;\n return {\n color: BASE_COLORS,\n dataZoom: [{\n borderColor: theme.palette.primary.light,\n bottom: 0,\n fillerColor: `${theme.palette.primary.main}33`,\n handleStyle: { borderColor: theme.palette.primary.main, color: theme.palette.primary.main },\n height: 50,\n left: 80,\n right: 80,\n selectedDataBackground: { areaStyle: { color: theme.palette.primary.light }, lineStyle: { color: theme.palette.primary.main } },\n type: 'slider',\n }],\n grid: { bottom: 110, left: 80, right: 80, top: 40 },\n legend: {\n data: [ownCasesLabel, otherOrganizationCasesLabel],\n selected: {\n [otherOrganizationCasesLabel]: organizationFilter !== 'own',\n [ownCasesLabel]: organizationFilter !== 'otherOrganization',\n },\n top: 0,\n },\n series: [\n {\n data: intervals.map(i => i.count),\n lineStyle: { opacity: 0 },\n name: 'dataZoomShadow',\n silent: true,\n symbol: 'none',\n type: 'line',\n },\n { data: intervals.map(i => i.ownCaseCount), itemStyle: { color: BASE_COLORS[0] }, name: ownCasesLabel, stack: 'similarCases', type: 'bar' },\n { data: intervals.map(i => i.otherOrganizationCaseCount), itemStyle: { color: BASE_COLORS[1] }, name: otherOrganizationCasesLabel, stack: 'similarCases', type: 'bar' },\n ],\n tooltip: { show: false },\n xAxis: { axisLabel: {\n height: 100,\n rotate: 45,\n }, axisTick: {\n alignWithLabel: true,\n show: true,\n }, data: intervals.map(i => i.label),\n type: 'category' },\n yAxis: { max: Math.max(...intervals.map(i => i.count), 1), minInterval: 1, type: 'value' },\n };\n }, [intervals, organizationFilter, otherOrganizationCasesLabel, ownCasesLabel, theme]);\n\n const onLegendSelectChanged = useCallback((params: unknown) => {\n const { selected } = params as { selected?: Record<string, boolean> };\n if (!selected) {\n return;\n }\n const ownCasesSelected = selected[ownCasesLabel] ?? true;\n const otherOrganizationCasesSelected = selected[otherOrganizationCasesLabel] ?? true;\n if (ownCasesSelected && !otherOrganizationCasesSelected) {\n onOrganizationFilterChange('own');\n return;\n }\n if (!ownCasesSelected && otherOrganizationCasesSelected) {\n onOrganizationFilterChange('otherOrganization');\n return;\n }\n onOrganizationFilterChange('all');\n }, [onOrganizationFilterChange, otherOrganizationCasesLabel, ownCasesLabel]);\n\n const onEvents = useMemo(() => ({\n datazoom: onDataZoom,\n legendselectchanged: onLegendSelectChanged,\n mouseout: () => {\n setTooltipState(null);\n },\n mouseover: (event: unknown) => {\n const e = event as { event?: { event?: MouseEvent }; name?: string; value?: number };\n const mouseEvent = e.event?.event;\n if (mouseEvent && e.name !== null && e.name !== undefined) {\n setTooltipState({ content: `${e.name} (n=${e.value ?? 0})`, x: mouseEvent.clientX + 12, y: mouseEvent.clientY + 12 });\n }\n },\n }), [onDataZoom, onLegendSelectChanged]);\n\n const renderChart = useCallback(({ field: { onChange } }: { field: { onChange: (value: [string, string] | null) => void } }) => {\n onChangeRef.current = onChange;\n return (\n <EChartsReact\n echarts={echartsCore}\n notMerge\n onEvents={onEvents}\n option={option}\n style={{ height: 400 }}\n />\n );\n }, [onEvents, option]);\n\n return (\n <>\n <Controller\n control={control}\n name={name}\n render={renderChart}\n />\n {tooltipState && (\n <Box\n sx={{\n bgcolor: 'background.paper',\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: 1,\n fontSize: 12,\n left: tooltipState.x,\n pointerEvents: 'none',\n position: 'fixed',\n px: 1,\n py: 0.5,\n top: tooltipState.y,\n zIndex: 'tooltip',\n }}\n >\n {tooltipState.content}\n </Box>\n )}\n </>\n );\n};\n","import {\n use,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n mixed,\n object,\n string,\n} from 'yup';\nimport { yupResolver } from '@hookform/resolvers/yup';\nimport type { Resolver } from 'react-hook-form';\nimport {\n useForm,\n useWatch,\n} from 'react-hook-form';\nimport {\n Alert,\n AlertTitle,\n Box,\n Button,\n Divider,\n Typography,\n} from '@mui/material';\nimport { useStore } from 'zustand';\nimport { produce } from 'immer';\nimport {\n format,\n parseISO,\n} from 'date-fns';\nimport type {\n CaseDbCase,\n CaseDbCol,\n CaseDbCompleteCaseType,\n} from '@gen-epix/api-casedb';\nimport { CaseDbCaseApi } from '@gen-epix/api-casedb';\nimport type { DialogAction } from '@gen-epix/ui-core-components/components/Dialog';\nimport type {\n WithDialogRefMethods,\n WithDialogRenderProps,\n} from '@gen-epix/ui-core-components/hoc/withDialog';\nimport { ConfigService } from '@gen-epix/ui-client-common/classes/services/ConfigService';\nimport { QueryClientService } from '@gen-epix/ui-client-common/classes/services/QueryClientService';\nimport { ResponseHandler } from '@gen-epix/ui-client-common/components/ui/ResponseHandler';\nimport { useQueryMemo } from '@gen-epix/ui-client-common/hooks/useQueryMemo';\nimport { withDialog } from '@gen-epix/ui-core-components/hoc/withDialog';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport { GenericForm } from '@gen-epix/ui-core-form/components/helpers/GenericForm';\nimport type {\n AutoCompleteOption,\n FormFieldDefinition,\n} from '@gen-epix/ui-core-form/models/form';\nimport { FORM_FIELD_DEFINITION_TYPE } from '@gen-epix/ui-core-form/models/form';\nimport { SchemaUtil } from '@gen-epix/ui-core-form/utils/SchemaUtil';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport { CASEDB_QUERY_KEY } from '../../../constants/query';\nimport type { CaseDbConfig } from '../../../models/config';\nimport { DashboardStoreContext } from '../../../stores/dashboardStore';\nimport { TreeWidgetUtil } from '../../../utils/TreeWidgetUtil';\nimport type {\n CaseDbSimilarCaseWithIsOwnCase,\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesOrganizationFilter,\n} from '../../../models/caseDb';\nimport type { TreeWidgetDataPersistable } from '../../../models/dashboard';\nimport { DASHBOARD_COMPONENT_NAME } from '../../../constants/dashboard';\n\nimport { FindSimilarCasesDialogDateRangeChart } from './FindSimilarCasesDialogDateRangeChart';\n\nexport interface FindSimilarCasesDialogOpenProps {\n allRows: CaseDbCase[];\n completeCaseType: CaseDbCompleteCaseType;\n selectedRows: CaseDbCase[];\n}\n\nexport interface FindSimilarCasesDialogProps extends WithDialogRenderProps<FindSimilarCasesDialogOpenProps> {\n //\n}\n\nexport type FindSimilarCasesDialogRefMethods = WithDialogRefMethods<FindSimilarCasesDialogProps, FindSimilarCasesDialogOpenProps>;\n\ntype FormFields = {\n dateRange: [string, string] | null;\n maxDistance: number;\n organizationFilter: FindSimilarCasesOrganizationFilter;\n treeColId: string;\n};\n\nexport const FindSimilarCasesDialog = withDialog<FindSimilarCasesDialogProps, FindSimilarCasesDialogOpenProps>((\n {\n onActionsChange,\n onClose,\n onTitleChange,\n openProps,\n }: FindSimilarCasesDialogProps,\n): ReactElement => {\n const { t } = useTranslation();\n const searchFormId = useId();\n const dashboardStore = use(DashboardStoreContext);\n const treeConfiguration = dashboardStore.getState().getWidgetDataPersistable<TreeWidgetDataPersistable>(DASHBOARD_COMPONENT_NAME.TREE).treeConfiguration;\n const setFindSimilarCasesResults = useStore(dashboardStore, (state) => state.setFindSimilarCasesResults);\n const findSimilarCasesResults = useStore(dashboardStore, (state) => state.findSimilarCasesResults);\n const treeConfigurations = useMemo(() => TreeWidgetUtil.getTreeConfigurations(openProps.completeCaseType), [openProps.completeCaseType]);\n const [formData, setFormData] = useState<FormFields>(null);\n\n const schema = useMemo(() => object<FormFields>().shape({\n dateRange: mixed<[string, string] | null>().nullable().default(null),\n maxDistance: SchemaUtil.number.required().positive().when('treeColId', ([treeColId], s) => {\n const currentTreeConfiguration = treeConfigurations.find(x => x.col.id === treeColId);\n if (!currentTreeConfiguration) {\n return s;\n }\n const sWithIntegerCheck = s.integer(t`Max distance must be an integer`);\n return sWithIntegerCheck.max(currentTreeConfiguration.geneticDistanceProtocol.seqdb_max_stored_distance || ConfigService.getInstance<CaseDbConfig>().config.epi.SEQDB_MAX_STORED_DISTANCE_FALLBACK);\n }),\n organizationFilter: string<FindSimilarCasesOrganizationFilter>().required().oneOf(['all', 'own', 'otherOrganization']),\n treeColId: string().required(),\n }), [t, treeConfigurations]);\n\n const treeOptions = useMemo<AutoCompleteOption<string>[]>(() => {\n const cols = new Set<CaseDbCol>();\n treeConfigurations.forEach(x => {\n cols.add(x.col);\n });\n return Array.from(cols).map(x => {\n return {\n label: x.label,\n value: x.id,\n } satisfies AutoCompleteOption<string>;\n });\n\n }, [treeConfigurations]);\n\n const formMethods = useForm<FormFields>({\n defaultValues: {\n dateRange: null,\n maxDistance: 0,\n organizationFilter: 'all',\n treeColId: treeConfiguration ? treeConfiguration.col.id : null,\n },\n resolver: yupResolver(schema, undefined, { raw: true }) as Resolver<FormFields>,\n });\n const { control, handleSubmit } = formMethods;\n\n const formValues = useWatch({ control });\n\n const searchFormFieldDefinitions = useMemo(() => {\n const currentTreeConfiguration = treeConfigurations.find(x => x.col.id === formValues.treeColId);\n return [\n {\n definition: FORM_FIELD_DEFINITION_TYPE.SELECT,\n label: t`Tree`,\n name: 'treeColId',\n options: treeOptions,\n } as const satisfies FormFieldDefinition<FormFields>,\n {\n definition: FORM_FIELD_DEFINITION_TYPE.NUMBER,\n label: t`Max distance`,\n max: currentTreeConfiguration?.geneticDistanceProtocol?.seqdb_max_stored_distance || ConfigService.getInstance<CaseDbConfig>().config.epi.SEQDB_MAX_STORED_DISTANCE_FALLBACK,\n min: 0,\n name: 'maxDistance',\n showSlider: true,\n step: 1,\n } as const satisfies FormFieldDefinition<FormFields>,\n ];\n }, [formValues.treeColId, t, treeConfigurations, treeOptions]);\n\n useEffect(() => {\n onTitleChange(t`Find similar cases`);\n }, [t, onTitleChange]);\n\n const onFormSubmit = useCallback((data: FormFields) => {\n formMethods.setValue('dateRange', null);\n setFormData({ ...data, dateRange: null });\n }, [formMethods]);\n\n const onOrganizationFilterChange = useCallback((organizationFilter: FindSimilarCasesOrganizationFilter) => {\n formMethods.setValue('organizationFilter', organizationFilter);\n }, [formMethods]);\n\n const query = useQueryMemo({\n enabled: !!formData,\n queryFn: async ({ signal }) => {\n const retrieveSimilarCasesResponse = await CaseDbCaseApi.getInstance().retrieveSimilarCases({\n case_ids: openProps.selectedRows.map(x => x.id),\n case_type_id: openProps.completeCaseType.id,\n genetic_distance_col_id: formData?.treeColId,\n max_distance: formData?.maxDistance,\n }, { signal });\n const retrieveIsOwnCasesResponse = await CaseDbCaseApi.getInstance().retrieveIsOwnCases({\n case_ids: retrieveSimilarCasesResponse.data.cases.map(x => x.id),\n case_type_id: openProps.completeCaseType.id,\n }, { signal });\n\n return retrieveSimilarCasesResponse.data.cases.map(caseDbCase => {\n return {\n ...caseDbCase,\n is_own_case: retrieveIsOwnCasesResponse.data[caseDbCase.id] || false,\n } satisfies CaseDbSimilarCaseWithIsOwnCase;\n });\n },\n queryKey: [QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.SIMILAR_CASES), JSON.stringify({ formData, rowIds: openProps.selectedRows.map(row => row.id) })],\n });\n\n const organizationFilteredCases = useMemo<CaseDbSimilarCaseWithIsOwnCase[]>(() => {\n if (!query.data) {\n return [];\n }\n return query.data.filter(c => {\n switch (formValues.organizationFilter) {\n case 'all': return true;\n case 'otherOrganization': return !c.is_own_case;\n case 'own': return c.is_own_case;\n default: return true;\n }\n });\n }, [query.data, formValues.organizationFilter]);\n\n const chartData = useMemo<FindSimilarCasesChartDataPoint[]>(() => {\n const counts = new Map<string, FindSimilarCasesChartDataPoint>();\n for (const { case_date, is_own_case } of query.data ?? []) {\n if (case_date) {\n const currentCount = counts.get(case_date) ?? {\n count: 0,\n date: case_date,\n otherOrganizationCaseCount: 0,\n ownCaseCount: 0,\n };\n currentCount.count += 1;\n if (is_own_case) {\n currentCount.ownCaseCount += 1;\n } else {\n currentCount.otherOrganizationCaseCount += 1;\n }\n counts.set(case_date, currentCount);\n }\n }\n return Array.from(counts.values())\n .sort((a, b) => a.date.localeCompare(b.date));\n }, [query.data]);\n\n const filteredCases = useMemo<CaseDbSimilarCaseWithIsOwnCase[]>(() => {\n const dateRange = formValues.dateRange;\n if (!dateRange) {\n return organizationFilteredCases;\n }\n const [startDate, endDate] = dateRange;\n return organizationFilteredCases.filter(c => {\n if (!c.case_date) {\n return false;\n }\n const caseDateOnly = format(parseISO(c.case_date), DATE_FORMAT.DATE);\n return caseDateOnly >= startDate && caseDateOnly <= endDate;\n });\n }, [formValues.dateRange, organizationFilteredCases]);\n\n const similarCaseIdsNotInLineListWithDateFilter = useMemo<string[]>(() => {\n const allRowIds = openProps.allRows.map(x => x.id);\n return filteredCases.reduce<string[]>((acc, caseIdAndDate) => {\n const caseId = caseIdAndDate.id;\n if (!allRowIds.includes(caseId)) {\n acc.push(caseId);\n }\n return acc;\n }, []);\n }, [filteredCases, openProps.allRows]);\n\n const similarCaseIdsAlreadyInLineListWithDateFilter = useMemo<string[]>(() => {\n const allRowIds = openProps.allRows.map(x => x.id);\n return filteredCases.reduce<string[]>((acc, caseIdAndDate) => {\n const caseId = caseIdAndDate.id;\n if (allRowIds.includes(caseId)) {\n acc.push(caseId);\n }\n return acc;\n }, []);\n }, [filteredCases, openProps.allRows]);\n\n const onAddToLineListButtonClick = useCallback(async () => {\n\n await setFindSimilarCasesResults(produce(findSimilarCasesResults, draft => {\n draft.push({\n colId: formData?.treeColId,\n distance: formData?.maxDistance,\n key: findSimilarCasesResults.length.toString(),\n originalCaseIds: openProps.allRows.map(x => x.id),\n similarCaseIds: similarCaseIdsNotInLineListWithDateFilter,\n });\n return draft;\n }));\n\n onClose();\n }, [setFindSimilarCasesResults, findSimilarCasesResults, onClose, similarCaseIdsNotInLineListWithDateFilter, formData?.maxDistance, formData?.treeColId, openProps.allRows]);\n\n useEffect(() => {\n const actions: DialogAction[] = [];\n actions.push({\n ...TestIdUtil.createAttributes('FindSimilarCasesDialog-closeButton'),\n color: 'primary',\n label: t`Close`,\n onClick: onClose,\n variant: 'outlined',\n });\n actions.push({\n ...TestIdUtil.createAttributes('FindSimilarCasesDialog-addSimilarCasesButton'),\n color: 'secondary',\n disabled: similarCaseIdsNotInLineListWithDateFilter.length === 0,\n label: t('Add {{count}} similar cases to line list', { count: similarCaseIdsNotInLineListWithDateFilter.length }),\n onClick: onAddToLineListButtonClick,\n variant: 'contained',\n });\n onActionsChange(actions);\n }, [onActionsChange, onAddToLineListButtonClick, onClose, similarCaseIdsNotInLineListWithDateFilter.length, t]);\n\n return (\n <Box>\n <Box\n sx={{\n marginBottom: 2,\n }}\n >\n <Typography>\n {t('Select a tree and maximum distance to find similar cases for the {{count}} selected cases.', { count: openProps.selectedRows.length })}\n </Typography>\n </Box>\n <Box>\n <GenericForm<FormFields>\n formFieldDefinitions={searchFormFieldDefinitions}\n formId={searchFormId}\n formMethods={formMethods}\n onSubmit={handleSubmit(onFormSubmit)}\n schema={schema}\n />\n </Box>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n marginTop: 2,\n }}\n >\n <Button\n color={'secondary'}\n form={searchFormId}\n type={'submit'}\n variant={'contained'}\n >\n {formData ? t`Search again` : t`Search`}\n </Button>\n </Box>\n <Divider sx={{ marginY: 2 }} />\n <ResponseHandler\n inlineSpinner\n loadables={query}\n >\n {query.data && (\n <>\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Alert\n severity={query.data.length > 0 ? 'success' : 'warning'}\n >\n <AlertTitle>\n {t('Found {{count}} similar cases with a distance of {{distance}}.', { count: query.data.length, distance: formData?.maxDistance })}\n </AlertTitle>\n </Alert>\n </Box>\n {chartData.length > 0 && (\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <FindSimilarCasesDialogDateRangeChart<FormFields>\n control={control}\n data={chartData}\n name={'dateRange'}\n onOrganizationFilterChange={onOrganizationFilterChange}\n organizationFilter={formValues.organizationFilter}\n />\n </Box>\n )}\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Alert\n severity={'info'}\n >\n <AlertTitle>\n {t('{{count}} similar cases can be added to the line list.', { count: similarCaseIdsNotInLineListWithDateFilter.length })}\n </AlertTitle>\n </Alert>\n </Box>\n {similarCaseIdsAlreadyInLineListWithDateFilter.length > 0 && (\n <Alert\n severity={'warning'}\n >\n <AlertTitle>\n {t('{{count}} similar cases found that are already in the line list.', { count: similarCaseIdsAlreadyInLineListWithDateFilter.length })}\n </AlertTitle>\n </Alert>\n )}\n </>\n )}\n </ResponseHandler>\n </Box>\n );\n}, {\n defaultTitle: '',\n fullWidth: true,\n maxWidth: 'md',\n testId: 'FindSimilarCasesDialog',\n});\n"],"mappings":"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"}
@@ -3,10 +3,10 @@ import { a as t, c as n, i as r, l as i, n as a, r as o, s, t as c } from "./eac
3
3
  import { i as l, n as u, t as d } from "./format.js";
4
4
  import { t as f } from "./parseISO.js";
5
5
  import { DATE_FORMAT as p } from "@gen-epix/ui-core/constants/date";
6
- //#region ../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfQuarter.js
6
+ //#region ../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/startOfMonth.js
7
7
  function m(t, n) {
8
- let r = e(t, n?.in), i = r.getMonth(), a = i - i % 3 + 3;
9
- return r.setMonth(a, 0), r.setHours(23, 59, 59, 999), r;
8
+ let r = e(t, n?.in);
9
+ return r.setDate(1), r.setHours(0, 0, 0, 0), r;
10
10
  }
11
11
  //#endregion
12
12
  //#region ../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfYear.js
@@ -15,10 +15,10 @@ function h(t, n) {
15
15
  return r.setFullYear(i + 1, 0, 0), r.setHours(23, 59, 59, 999), r;
16
16
  }
17
17
  //#endregion
18
- //#region ../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/startOfMonth.js
18
+ //#region ../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfQuarter.js
19
19
  function g(t, n) {
20
- let r = e(t, n?.in);
21
- return r.setDate(1), r.setHours(0, 0, 0, 0), r;
20
+ let r = e(t, n?.in), i = r.getMonth(), a = i - i % 3 + 3;
21
+ return r.setMonth(a, 0), r.setHours(23, 59, 59, 999), r;
22
22
  }
23
23
  //#endregion
24
24
  //#region src/utils/FindSimilarCasesUtil/FindSimilarCasesUtil.ts
@@ -73,11 +73,11 @@ var _ = class e {
73
73
  };
74
74
  case "month": return {
75
75
  end: s(e),
76
- label: d(g(e), p.YEAR_MONTH),
77
- start: g(e)
76
+ label: d(m(e), p.YEAR_MONTH),
77
+ start: m(e)
78
78
  };
79
79
  case "quarter": return {
80
- end: m(e),
80
+ end: g(e),
81
81
  label: d(o(e), p.YEAR_QUARTER),
82
82
  start: o(e)
83
83
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FindSimilarCasesUtil.js","names":[],"sources":["../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfQuarter.js","../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfYear.js","../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/startOfMonth.js","../../src/utils/FindSimilarCasesUtil/FindSimilarCasesUtil.ts"],"sourcesContent":["import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link endOfQuarter} function options.\n */\n\n/**\n * @name endOfQuarter\n * @category Quarter Helpers\n * @summary Return the end of a year quarter for the given date.\n *\n * @description\n * Return the end of a year quarter for the given date.\n * The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - An object with options\n *\n * @returns The end of a quarter\n *\n * @example\n * // The end of a quarter for 2 September 2014 11:55:00:\n * const result = endOfQuarter(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 30 2014 23:59:59.999\n */\nexport function endOfQuarter(date, options) {\n const _date = toDate(date, options?.in);\n const currentMonth = _date.getMonth();\n const month = currentMonth - (currentMonth % 3) + 3;\n _date.setMonth(month, 0);\n _date.setHours(23, 59, 59, 999);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default endOfQuarter;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link endOfYear} function options.\n */\n\n/**\n * @name endOfYear\n * @category Year Helpers\n * @summary Return the end of a year for the given date.\n *\n * @description\n * Return the end of a year for the given date.\n * The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - The options\n *\n * @returns The end of a year\n *\n * @example\n * // The end of a year for 2 September 2014 11:55:00:\n * const result = endOfYear(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Wed Dec 31 2014 23:59:59.999\n */\nexport function endOfYear(date, options) {\n const _date = toDate(date, options?.in);\n const year = _date.getFullYear();\n _date.setFullYear(year + 1, 0, 0);\n _date.setHours(23, 59, 59, 999);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default endOfYear;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link startOfMonth} function options.\n */\n\n/**\n * @name startOfMonth\n * @category Month Helpers\n * @summary Return the start of a month for the given date.\n *\n * @description\n * Return the start of a month for the given date. The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.\n * Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed,\n * or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - An object with options\n *\n * @returns The start of a month\n *\n * @example\n * // The start of a month for 2 September 2014 11:55:00:\n * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Mon Sep 01 2014 00:00:00\n */\nexport function startOfMonth(date, options) {\n const _date = toDate(date, options?.in);\n _date.setDate(1);\n _date.setHours(0, 0, 0, 0);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default startOfMonth;\n","import {\n differenceInDays,\n eachDayOfInterval,\n eachMonthOfInterval,\n eachQuarterOfInterval,\n eachYearOfInterval,\n endOfDay,\n endOfMonth,\n endOfQuarter,\n endOfYear,\n format,\n parseISO,\n startOfDay,\n startOfMonth,\n startOfQuarter,\n startOfYear,\n} from 'date-fns';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport type {\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesChartGranularity,\n FindSimilarCasesChartInterval,\n} from '../../models/caseDb';\n\nexport class FindSimilarCasesUtil {\n public static buildChartIntervals(data: FindSimilarCasesChartDataPoint[]): FindSimilarCasesChartInterval[] {\n if (data.length === 0) {\n return [];\n }\n\n const minDate = parseISO(data[0].date);\n const maxDate = parseISO(data[data.length - 1].date);\n const granularity = FindSimilarCasesUtil.pickGranularity(minDate, maxDate);\n\n const countsMap = new Map<string, number>();\n const ownCaseCountsMap = new Map<string, number>();\n const otherOrganizationCaseCountsMap = new Map<string, number>();\n for (const { count, date, otherOrganizationCaseCount, ownCaseCount } of data) {\n const { label } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(parseISO(date), granularity);\n countsMap.set(label, (countsMap.get(label) ?? 0) + count);\n ownCaseCountsMap.set(label, (ownCaseCountsMap.get(label) ?? 0) + ownCaseCount);\n otherOrganizationCaseCountsMap.set(label, (otherOrganizationCaseCountsMap.get(label) ?? 0) + otherOrganizationCaseCount);\n }\n\n const { start: rangeStart } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(minDate, granularity);\n const { start: rangeEnd } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(maxDate, granularity);\n const intervalDates = FindSimilarCasesUtil.generateIntervalStartDates(rangeStart, rangeEnd, granularity);\n\n return intervalDates.map(d => {\n const { end, label, start } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(d, granularity);\n return {\n count: countsMap.get(label) ?? 0,\n endDate: format(end, DATE_FORMAT.DATE),\n label,\n otherOrganizationCaseCount: otherOrganizationCaseCountsMap.get(label) ?? 0,\n ownCaseCount: ownCaseCountsMap.get(label) ?? 0,\n startDate: format(start, DATE_FORMAT.DATE),\n };\n });\n }\n\n private static generateIntervalStartDates(rangeStart: Date, rangeEnd: Date, granularity: FindSimilarCasesChartGranularity): Date[] {\n switch (granularity) {\n case 'day': return eachDayOfInterval({ end: rangeEnd, start: rangeStart });\n case 'month': return eachMonthOfInterval({ end: rangeEnd, start: rangeStart });\n case 'quarter': return eachQuarterOfInterval({ end: rangeEnd, start: rangeStart });\n case 'year': return eachYearOfInterval({ end: rangeEnd, start: rangeStart });\n default: throw new Error(`Unhandled granularity: ${String(granularity)}`);\n }\n }\n\n private static getIntervalBoundsAndLabel(d: Date, granularity: FindSimilarCasesChartGranularity): { end: Date; label: string; start: Date } {\n switch (granularity) {\n case 'day': return { end: endOfDay(d), label: format(startOfDay(d), DATE_FORMAT.DATE), start: startOfDay(d) };\n case 'month': return { end: endOfMonth(d), label: format(startOfMonth(d), DATE_FORMAT.YEAR_MONTH), start: startOfMonth(d) };\n case 'quarter': return { end: endOfQuarter(d), label: format(startOfQuarter(d), DATE_FORMAT.YEAR_QUARTER), start: startOfQuarter(d) };\n case 'year': return { end: endOfYear(d), label: format(startOfYear(d), DATE_FORMAT.YEAR), start: startOfYear(d) };\n default: throw new Error(`Unhandled granularity: ${String(granularity)}`);\n }\n }\n\n private static pickGranularity(minDate: Date, maxDate: Date): FindSimilarCasesChartGranularity {\n const days = differenceInDays(maxDate, minDate);\n if (days <= 90) {\n return 'day';\n }\n if (days <= 730) {\n return 'month';\n }\n if (days <= 2920) {\n return 'quarter';\n }\n return 'year';\n }\n}\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
1
+ {"version":3,"file":"FindSimilarCasesUtil.js","names":[],"sources":["../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/startOfMonth.js","../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfYear.js","../../../../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/endOfQuarter.js","../../src/utils/FindSimilarCasesUtil/FindSimilarCasesUtil.ts"],"sourcesContent":["import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link startOfMonth} function options.\n */\n\n/**\n * @name startOfMonth\n * @category Month Helpers\n * @summary Return the start of a month for the given date.\n *\n * @description\n * Return the start of a month for the given date. The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.\n * Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed,\n * or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - An object with options\n *\n * @returns The start of a month\n *\n * @example\n * // The start of a month for 2 September 2014 11:55:00:\n * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Mon Sep 01 2014 00:00:00\n */\nexport function startOfMonth(date, options) {\n const _date = toDate(date, options?.in);\n _date.setDate(1);\n _date.setHours(0, 0, 0, 0);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default startOfMonth;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link endOfYear} function options.\n */\n\n/**\n * @name endOfYear\n * @category Year Helpers\n * @summary Return the end of a year for the given date.\n *\n * @description\n * Return the end of a year for the given date.\n * The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - The options\n *\n * @returns The end of a year\n *\n * @example\n * // The end of a year for 2 September 2014 11:55:00:\n * const result = endOfYear(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Wed Dec 31 2014 23:59:59.999\n */\nexport function endOfYear(date, options) {\n const _date = toDate(date, options?.in);\n const year = _date.getFullYear();\n _date.setFullYear(year + 1, 0, 0);\n _date.setHours(23, 59, 59, 999);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default endOfYear;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link endOfQuarter} function options.\n */\n\n/**\n * @name endOfQuarter\n * @category Quarter Helpers\n * @summary Return the end of a year quarter for the given date.\n *\n * @description\n * Return the end of a year quarter for the given date.\n * The result will be in the local timezone.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The original date\n * @param options - An object with options\n *\n * @returns The end of a quarter\n *\n * @example\n * // The end of a quarter for 2 September 2014 11:55:00:\n * const result = endOfQuarter(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 30 2014 23:59:59.999\n */\nexport function endOfQuarter(date, options) {\n const _date = toDate(date, options?.in);\n const currentMonth = _date.getMonth();\n const month = currentMonth - (currentMonth % 3) + 3;\n _date.setMonth(month, 0);\n _date.setHours(23, 59, 59, 999);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default endOfQuarter;\n","import {\n differenceInDays,\n eachDayOfInterval,\n eachMonthOfInterval,\n eachQuarterOfInterval,\n eachYearOfInterval,\n endOfDay,\n endOfMonth,\n endOfQuarter,\n endOfYear,\n format,\n parseISO,\n startOfDay,\n startOfMonth,\n startOfQuarter,\n startOfYear,\n} from 'date-fns';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport type {\n FindSimilarCasesChartDataPoint,\n FindSimilarCasesChartGranularity,\n FindSimilarCasesChartInterval,\n} from '../../models/caseDb';\n\nexport class FindSimilarCasesUtil {\n public static buildChartIntervals(data: FindSimilarCasesChartDataPoint[]): FindSimilarCasesChartInterval[] {\n if (data.length === 0) {\n return [];\n }\n\n const minDate = parseISO(data[0].date);\n const maxDate = parseISO(data[data.length - 1].date);\n const granularity = FindSimilarCasesUtil.pickGranularity(minDate, maxDate);\n\n const countsMap = new Map<string, number>();\n const ownCaseCountsMap = new Map<string, number>();\n const otherOrganizationCaseCountsMap = new Map<string, number>();\n for (const { count, date, otherOrganizationCaseCount, ownCaseCount } of data) {\n const { label } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(parseISO(date), granularity);\n countsMap.set(label, (countsMap.get(label) ?? 0) + count);\n ownCaseCountsMap.set(label, (ownCaseCountsMap.get(label) ?? 0) + ownCaseCount);\n otherOrganizationCaseCountsMap.set(label, (otherOrganizationCaseCountsMap.get(label) ?? 0) + otherOrganizationCaseCount);\n }\n\n const { start: rangeStart } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(minDate, granularity);\n const { start: rangeEnd } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(maxDate, granularity);\n const intervalDates = FindSimilarCasesUtil.generateIntervalStartDates(rangeStart, rangeEnd, granularity);\n\n return intervalDates.map(d => {\n const { end, label, start } = FindSimilarCasesUtil.getIntervalBoundsAndLabel(d, granularity);\n return {\n count: countsMap.get(label) ?? 0,\n endDate: format(end, DATE_FORMAT.DATE),\n label,\n otherOrganizationCaseCount: otherOrganizationCaseCountsMap.get(label) ?? 0,\n ownCaseCount: ownCaseCountsMap.get(label) ?? 0,\n startDate: format(start, DATE_FORMAT.DATE),\n };\n });\n }\n\n private static generateIntervalStartDates(rangeStart: Date, rangeEnd: Date, granularity: FindSimilarCasesChartGranularity): Date[] {\n switch (granularity) {\n case 'day': return eachDayOfInterval({ end: rangeEnd, start: rangeStart });\n case 'month': return eachMonthOfInterval({ end: rangeEnd, start: rangeStart });\n case 'quarter': return eachQuarterOfInterval({ end: rangeEnd, start: rangeStart });\n case 'year': return eachYearOfInterval({ end: rangeEnd, start: rangeStart });\n default: throw new Error(`Unhandled granularity: ${String(granularity)}`);\n }\n }\n\n private static getIntervalBoundsAndLabel(d: Date, granularity: FindSimilarCasesChartGranularity): { end: Date; label: string; start: Date } {\n switch (granularity) {\n case 'day': return { end: endOfDay(d), label: format(startOfDay(d), DATE_FORMAT.DATE), start: startOfDay(d) };\n case 'month': return { end: endOfMonth(d), label: format(startOfMonth(d), DATE_FORMAT.YEAR_MONTH), start: startOfMonth(d) };\n case 'quarter': return { end: endOfQuarter(d), label: format(startOfQuarter(d), DATE_FORMAT.YEAR_QUARTER), start: startOfQuarter(d) };\n case 'year': return { end: endOfYear(d), label: format(startOfYear(d), DATE_FORMAT.YEAR), start: startOfYear(d) };\n default: throw new Error(`Unhandled granularity: ${String(granularity)}`);\n }\n }\n\n private static pickGranularity(minDate: Date, maxDate: Date): FindSimilarCasesChartGranularity {\n const days = differenceInDays(maxDate, minDate);\n if (days <= 90) {\n return 'day';\n }\n if (days <= 730) {\n return 'month';\n }\n if (days <= 2920) {\n return 'quarter';\n }\n return 'year';\n }\n}\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
@@ -6,20 +6,20 @@ import { useCaseTypeMapQuery as i } from "../dataHooks/useCaseTypesQuery/index.j
6
6
  import { useCaseSetsQuery as a } from "../dataHooks/useCaseSetsQuery/index.js";
7
7
  import { t as o } from "i18next";
8
8
  import { CaseDbCaseApi as s, CaseDbCommandName as c, CaseDbPermissionType as l } from "@gen-epix/api-casedb";
9
- import { QueryClientService as u } from "@gen-epix/ui/classes/services/QueryClientService";
10
- import { ConfigService as d } from "@gen-epix/ui/classes/services/ConfigService";
9
+ import { QueryClientService as u } from "@gen-epix/ui-client-common/classes/services/QueryClientService";
10
+ import { ConfigService as d } from "@gen-epix/ui-client-common/classes/services/ConfigService";
11
11
  import { Box as f, Button as p, Card as m, CardActions as h, CardContent as g, Skeleton as _, Typography as v, darken as y, useTheme as b } from "@mui/material";
12
12
  import { useCallback as x, useMemo as S } from "react";
13
13
  import { useTranslation as C } from "react-i18next";
14
- import { AxiosUtil as w } from "@gen-epix/ui/utils/AxiosUtil";
14
+ import { AxiosUtil as w } from "@gen-epix/ui-client-common/utils/AxiosUtil";
15
15
  import { jsx as T, jsxs as E } from "react/jsx-runtime";
16
- import { ResponseHandler as D } from "@gen-epix/ui/components/ui/ResponseHandler";
16
+ import { ResponseHandler as D } from "@gen-epix/ui-client-common/components/ui/ResponseHandler";
17
17
  import { useArray as O } from "@gen-epix/ui-core/hooks/useArray";
18
- import { useQueryMemo as k } from "@gen-epix/ui/hooks/useQueryMemo";
18
+ import { useQueryMemo as k } from "@gen-epix/ui-client-common/hooks/useQueryMemo";
19
19
  import { TestIdUtil as A } from "@gen-epix/ui-core/utils/TestIdUtil";
20
- import { RouterService as j } from "@gen-epix/ui/classes/services/RouterService";
21
- import { LoadableUtil as M } from "@gen-epix/ui/utils/LoadableUtil";
22
- import { withPermissions as N } from "@gen-epix/ui/hoc/withPermissions";
20
+ import { RouterService as j } from "@gen-epix/ui-client-common/classes/services/RouterService";
21
+ import { LoadableUtil as M } from "@gen-epix/ui-client-common/utils/LoadableUtil";
22
+ import { withPermissions as N } from "@gen-epix/ui-client-common/hoc/withPermissions";
23
23
  //#region src/components/ui/HomePageTrends/HomePageTrendCard.tsx
24
24
  var P = /* @__PURE__ */ e(r(), 1), F = ({ callback: e, callbackLabel: t, diffPercentage: n, header: r, sinceLabel: i, value: a }) => {
25
25
  let s = b(), c = x(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"HomePageTrends.js","names":[],"sources":["../../src/components/ui/HomePageTrends/HomePageTrendCard.tsx","../../src/components/ui/HomePageTrends/HomePageTrends.tsx"],"sourcesContent":["import { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport {\n Box,\n Button,\n Card,\n CardActions,\n CardContent,\n darken,\n Typography,\n useTheme,\n} from '@mui/material';\nimport { t } from 'i18next';\nimport { useCallback } from 'react';\n\n\nexport type HomagePageTrendCardProps = {\n readonly callback?: () => void;\n readonly callbackLabel?: string;\n readonly diffPercentage: number;\n readonly header: string;\n readonly sinceLabel: string;\n readonly value: number;\n};\n\nexport const HomePageTrendCard = ({ callback, callbackLabel, diffPercentage, header, sinceLabel, value }: HomagePageTrendCardProps) => {\n const theme = useTheme();\n\n const onCallbackButtonClick = useCallback(() => {\n callback();\n }, [callback]);\n\n return (\n <Card\n {...TestIdUtil.createAttributes('HomePageTrendCard', { header })}\n elevation={1}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }}\n >\n <CardContent\n sx={{\n paddingBottom: 0,\n }}\n >\n <Typography\n component={'h3'}\n sx={{\n display: 'block',\n fontSize: '1rem',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {header}\n </Typography>\n <Typography\n {...TestIdUtil.createAttributes('HomePageTrendCard-value')}\n sx={{ fontSize: '1.8rem' }}\n >\n {value.toLocaleString()}\n </Typography>\n </CardContent>\n {callback && callbackLabel && (\n <CardActions\n sx={{\n justifyContent: 'flex-end',\n }}\n >\n <Button\n {...TestIdUtil.createAttributes('HomePageTrendCard-button')}\n onClick={onCallbackButtonClick}\n size={'small'}\n variant={'outlined'}\n >\n {callbackLabel}\n </Button>\n </CardActions>\n )}\n <Box\n sx={{\n background: theme.palette.grey['100'],\n justifyContent: 'flex-end',\n padding: 1,\n }}\n >\n <Box\n sx={{\n marginX: 1,\n }}\n >\n {diffPercentage === 0 && (\n <Typography>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage-label')}\n component={'span'}\n sx={{\n color: theme.palette.text.secondary,\n fontWeight: 'bold',\n }}\n >\n {t('No change')}\n </Box>\n </Typography>\n )}\n {diffPercentage !== 0 && (\n <Typography>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage')}\n component={'span'}\n sx={{\n color: diffPercentage > 0 ? darken(theme.palette.success.main, 0.4) : theme.palette.error.main,\n fontWeight: 'bold',\n }}\n >\n {diffPercentage > 0 ? '+' : ''}\n {diffPercentage.toLocaleString()}\n {'%'}\n\n </Box>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage-label')}\n component={'span'}\n >\n {' '}\n {sinceLabel}\n </Box>\n </Typography>\n )}\n </Box>\n </Box>\n </Card>\n );\n};\n","import {\n Box,\n Button,\n Skeleton,\n Typography,\n useTheme,\n} from '@mui/material';\nimport {\n useCallback,\n useMemo,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport round from 'lodash/round';\nimport type {\n CaseDbApiPermission,\n CaseDbCaseStats,\n CaseDbEpiFilter,\n CaseDbRetrieveCaseTypeStatsRequestBody,\n CaseDbTypedDatetimeRangeFilter,\n} from '@gen-epix/api-casedb';\nimport {\n CaseDbCaseApi,\n CaseDbCommandName,\n CaseDbPermissionType,\n} from '@gen-epix/api-casedb';\nimport { AxiosUtil } from '@gen-epix/ui/utils/AxiosUtil';\nimport { ConfigService } from '@gen-epix/ui/classes/services/ConfigService';\nimport { LoadableUtil } from '@gen-epix/ui/utils/LoadableUtil';\nimport { QueryClientService } from '@gen-epix/ui/classes/services/QueryClientService';\nimport { ResponseHandler } from '@gen-epix/ui/components/ui/ResponseHandler';\nimport { RouterService } from '@gen-epix/ui/classes/services/RouterService';\nimport { useQueryMemo } from '@gen-epix/ui/hooks/useQueryMemo';\nimport { withPermissions } from '@gen-epix/ui/hoc/withPermissions';\nimport { useArray } from '@gen-epix/ui-core/hooks/useArray';\n\nimport { useCaseSetsQuery } from '../../../dataHooks/useCaseSetsQuery';\nimport { useCaseTypeMapQuery } from '../../../dataHooks/useCaseTypesQuery';\nimport { CaseTypeUtil } from '../../../utils/CaseTypeUtil';\nimport type { CaseDbConfig } from '../../../models/config';\nimport { CASEDB_QUERY_KEY } from '../../../constants/query';\n\nimport { HomePageTrendCard } from './HomePageTrendCard';\n\ntype CaseStatsWithDiff = {\n diffPercentage: number;\n} & CaseDbCaseStats;\n\ntype Statistic = {\n callback?: () => void;\n callbackLabel?: string;\n diffPercentage: number;\n header: string;\n value: number;\n};\n\nexport const HomePageTrends = withPermissions<CaseDbApiPermission>(() => {\n const theme = useTheme();\n const { t } = useTranslation();\n\n const dateTimeRangeFilter = useMemo<CaseDbTypedDatetimeRangeFilter>(() => ({\n type: 'DATETIME_RANGE',\n upper_bound: ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceDate(),\n upper_bound_censor: '<=',\n } satisfies CaseDbTypedDatetimeRangeFilter), []);\n\n const caseSetQueryFilter = useMemo<CaseDbEpiFilter>(() => ({\n key: 'case_set_date',\n type: 'DATETIME_RANGE',\n upper_bound: ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceDate(),\n upper_bound_censor: '<=',\n } satisfies CaseDbEpiFilter), []);\n\n const caseTypeStatsQueryNow = useQueryMemo({\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().retrieveCaseTypeStats({}, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_TYPE_STATS),\n });\n\n const retrieveTypeCaseStatsRequestBody = useMemo<CaseDbRetrieveCaseTypeStatsRequestBody>(() => {\n if (!caseTypeStatsQueryNow.data) {\n return undefined;\n }\n return {\n case_type_ids: caseTypeStatsQueryNow.data?.filter(stat => stat.n_cases > 0).map(stat => stat.case_type_id),\n datetime_range_filter: dateTimeRangeFilter,\n };\n }, [dateTimeRangeFilter, caseTypeStatsQueryNow.data]);\n\n const caseTypeStatsQueryPast = useQueryMemo({\n enabled: !!retrieveTypeCaseStatsRequestBody,\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().retrieveCaseTypeStats(retrieveTypeCaseStatsRequestBody ?? {}, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_TYPE_STATS, retrieveTypeCaseStatsRequestBody ?? {}),\n });\n const caseSetsNowQuery = useCaseSetsQuery();\n const caseTypeMapQuery = useCaseTypeMapQuery();\n\n const { data: caseSetsThenData, ...caseSetsThenQuery } = useQueryMemo({\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().caseSetsPostQuery(caseSetQueryFilter, null, null, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_SETS, caseSetQueryFilter),\n });\n\n const loadables = useArray([\n caseTypeStatsQueryNow,\n caseTypeStatsQueryPast,\n caseTypeMapQuery,\n caseSetsNowQuery,\n caseSetsThenQuery,\n ]);\n\n const statistics = useMemo<Statistic[]>(() => {\n const s: Statistic[] = [];\n\n if (LoadableUtil.isSomeLoading(loadables) || LoadableUtil.hasSomeError(loadables) || !caseTypeStatsQueryNow.data?.length || !caseTypeStatsQueryPast.data?.length) {\n return s;\n }\n\n const nowTotalCases = caseTypeStatsQueryNow.data?.reduce((acc, stat) => acc + stat.n_cases, 0) ?? 0;\n const thenTotalCases = caseTypeStatsQueryPast.data?.reduce((acc, stat) => acc + stat.n_cases, 0) ?? 0;\n\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate('/cases');\n },\n callbackLabel: t`View all cases`,\n diffPercentage: round((nowTotalCases - thenTotalCases) / (thenTotalCases || 1) * 100, 2),\n header: 'Cases',\n value: nowTotalCases,\n },\n );\n\n const numberOfCaseSetsNow = caseSetsNowQuery.data.length;\n const numberOfCaseSetsThen = caseSetsThenData.length;\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate('/events');\n },\n callbackLabel: t`View all events`,\n diffPercentage: round((numberOfCaseSetsNow - numberOfCaseSetsThen) / (numberOfCaseSetsThen || 1) * 100, 2),\n header: 'Events',\n value: numberOfCaseSetsNow,\n },\n );\n\n const caseStatsThenByCaseTypeId = new Map<string, CaseDbCaseStats>(caseTypeStatsQueryPast.data?.map(stat => [stat.case_type_id, stat]));\n const sortedStats = caseTypeStatsQueryNow?.data?.map<CaseStatsWithDiff>(stat => {\n const nowNCases = stat.n_cases;\n const thenNCases = caseStatsThenByCaseTypeId.get(stat.case_type_id)?.n_cases ?? 0;\n const diff = nowNCases - thenNCases;\n let diffPercentage: number;\n if (thenNCases > 0) {\n diffPercentage = round((diff / thenNCases) * 100, 2);\n } else {\n diffPercentage = 0;\n }\n return ({\n ...stat,\n diffPercentage,\n });\n }).sort((a, b) => b.diffPercentage - a.diffPercentage);\n\n for (let i = 0; i < 6; i += 1) {\n if (sortedStats?.[i]) {\n const caseType = caseTypeMapQuery.map?.get(sortedStats?.[i].case_type_id ?? '');\n const caseTypeName = caseType?.name;\n if (caseTypeName) {\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate(CaseTypeUtil.createCaseTypeLink(caseType));\n },\n callbackLabel: t`View cases`,\n diffPercentage: sortedStats[i].diffPercentage,\n header: t('{{caseTypeName}} cases', { caseTypeName, number: i + 1 }),\n value: sortedStats[i].n_cases,\n },\n );\n }\n }\n }\n\n return s;\n }, [caseSetsNowQuery.data?.length, caseSetsThenData?.length, caseTypeMapQuery.map, caseTypeStatsQueryNow.data, caseTypeStatsQueryPast.data, loadables, t]);\n\n const onViewMoreTrendsButtonClick = useCallback(async () => {\n await RouterService.getInstance().router.navigate('/trends');\n }, []);\n\n if (AxiosUtil.isAxiosForbiddenError(LoadableUtil.findFirstError(loadables))) {\n return null;\n }\n\n return (\n <Box>\n <Box\n sx={{\n marginBottom: 1,\n }}\n >\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'space-between',\n }}\n >\n <Box>\n <Typography\n variant={'h2'}\n >\n {t`Trends summary`}\n </Typography>\n </Box>\n <Box>\n <Button\n color={'primary'}\n disabled\n onClick={onViewMoreTrendsButtonClick}\n variant={'outlined'}\n >\n {t`View more trends`}\n </Button>\n </Box>\n </Box>\n </Box>\n <ResponseHandler\n inlineSpinner\n loadables={loadables}\n loadingContent={(\n <Box\n sx={{\n display: 'grid',\n gap: 2,\n gridTemplateColumns: 'repeat(1, 1fr)',\n marginBottom: 2,\n [theme.breakpoints.up('md')]: {\n gridTemplateColumns: 'repeat(4, 1fr)',\n },\n [theme.breakpoints.up('sm')]: {\n gridTemplateColumns: 'repeat(2, 1fr)',\n },\n }}\n >\n {[...Array<string>(8)].map((_, index) => (\n <Box\n // eslint-disable-next-line @eslint-react/no-array-index-key\n key={index}\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: 165.75,\n justifyContent: 'center',\n }}\n >\n <Skeleton\n animation={'pulse'}\n height={'100%'}\n variant={'rounded'}\n width={'100%'}\n />\n </Box>\n ))}\n </Box>\n )}\n shouldHideActionButtons\n >\n {statistics.length === 0 && (\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Typography>\n {t`No trends available.`}\n </Typography>\n </Box>\n )}\n {statistics.length > 0 && (\n <Box\n sx={{\n display: 'grid',\n gap: 2,\n gridTemplateColumns: 'repeat(1, 1fr)',\n marginBottom: 2,\n [theme.breakpoints.up('md')]: {\n gridTemplateColumns: 'repeat(4, 1fr)',\n },\n [theme.breakpoints.up('sm')]: {\n gridTemplateColumns: 'repeat(2, 1fr)',\n },\n }}\n >\n {statistics.map(statistic => (\n <HomePageTrendCard\n callback={statistic.callback}\n callbackLabel={statistic.callbackLabel}\n diffPercentage={statistic.diffPercentage}\n header={statistic.header}\n key={statistic.header}\n sinceLabel={ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceLabel(t)}\n value={statistic.value}\n />\n ))}\n </Box>\n )}\n </ResponseHandler>\n </Box>\n );\n}, {\n requiredPermissions: [\n { command_name: CaseDbCommandName.RetrieveCaseTypeStatsCommand, permission_type: CaseDbPermissionType.EXECUTE },\n { command_name: CaseDbCommandName.CaseSetCrudCommand, permission_type: CaseDbPermissionType.READ },\n { command_name: CaseDbCommandName.CaseTypeCrudCommand, permission_type: CaseDbPermissionType.READ },\n ],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"HomePageTrends.js","names":[],"sources":["../../src/components/ui/HomePageTrends/HomePageTrendCard.tsx","../../src/components/ui/HomePageTrends/HomePageTrends.tsx"],"sourcesContent":["import { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport {\n Box,\n Button,\n Card,\n CardActions,\n CardContent,\n darken,\n Typography,\n useTheme,\n} from '@mui/material';\nimport { t } from 'i18next';\nimport { useCallback } from 'react';\n\n\nexport type HomagePageTrendCardProps = {\n readonly callback?: () => void;\n readonly callbackLabel?: string;\n readonly diffPercentage: number;\n readonly header: string;\n readonly sinceLabel: string;\n readonly value: number;\n};\n\nexport const HomePageTrendCard = ({ callback, callbackLabel, diffPercentage, header, sinceLabel, value }: HomagePageTrendCardProps) => {\n const theme = useTheme();\n\n const onCallbackButtonClick = useCallback(() => {\n callback();\n }, [callback]);\n\n return (\n <Card\n {...TestIdUtil.createAttributes('HomePageTrendCard', { header })}\n elevation={1}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n }}\n >\n <CardContent\n sx={{\n paddingBottom: 0,\n }}\n >\n <Typography\n component={'h3'}\n sx={{\n display: 'block',\n fontSize: '1rem',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {header}\n </Typography>\n <Typography\n {...TestIdUtil.createAttributes('HomePageTrendCard-value')}\n sx={{ fontSize: '1.8rem' }}\n >\n {value.toLocaleString()}\n </Typography>\n </CardContent>\n {callback && callbackLabel && (\n <CardActions\n sx={{\n justifyContent: 'flex-end',\n }}\n >\n <Button\n {...TestIdUtil.createAttributes('HomePageTrendCard-button')}\n onClick={onCallbackButtonClick}\n size={'small'}\n variant={'outlined'}\n >\n {callbackLabel}\n </Button>\n </CardActions>\n )}\n <Box\n sx={{\n background: theme.palette.grey['100'],\n justifyContent: 'flex-end',\n padding: 1,\n }}\n >\n <Box\n sx={{\n marginX: 1,\n }}\n >\n {diffPercentage === 0 && (\n <Typography>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage-label')}\n component={'span'}\n sx={{\n color: theme.palette.text.secondary,\n fontWeight: 'bold',\n }}\n >\n {t('No change')}\n </Box>\n </Typography>\n )}\n {diffPercentage !== 0 && (\n <Typography>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage')}\n component={'span'}\n sx={{\n color: diffPercentage > 0 ? darken(theme.palette.success.main, 0.4) : theme.palette.error.main,\n fontWeight: 'bold',\n }}\n >\n {diffPercentage > 0 ? '+' : ''}\n {diffPercentage.toLocaleString()}\n {'%'}\n\n </Box>\n <Box\n {...TestIdUtil.createAttributes('HomePageTrendCard-diffPercentage-label')}\n component={'span'}\n >\n {' '}\n {sinceLabel}\n </Box>\n </Typography>\n )}\n </Box>\n </Box>\n </Card>\n );\n};\n","import {\n Box,\n Button,\n Skeleton,\n Typography,\n useTheme,\n} from '@mui/material';\nimport {\n useCallback,\n useMemo,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport round from 'lodash/round';\nimport type {\n CaseDbApiPermission,\n CaseDbCaseStats,\n CaseDbEpiFilter,\n CaseDbRetrieveCaseTypeStatsRequestBody,\n CaseDbTypedDatetimeRangeFilter,\n} from '@gen-epix/api-casedb';\nimport {\n CaseDbCaseApi,\n CaseDbCommandName,\n CaseDbPermissionType,\n} from '@gen-epix/api-casedb';\nimport { AxiosUtil } from '@gen-epix/ui-client-common/utils/AxiosUtil';\nimport { ConfigService } from '@gen-epix/ui-client-common/classes/services/ConfigService';\nimport { LoadableUtil } from '@gen-epix/ui-client-common/utils/LoadableUtil';\nimport { QueryClientService } from '@gen-epix/ui-client-common/classes/services/QueryClientService';\nimport { ResponseHandler } from '@gen-epix/ui-client-common/components/ui/ResponseHandler';\nimport { RouterService } from '@gen-epix/ui-client-common/classes/services/RouterService';\nimport { useQueryMemo } from '@gen-epix/ui-client-common/hooks/useQueryMemo';\nimport { withPermissions } from '@gen-epix/ui-client-common/hoc/withPermissions';\nimport { useArray } from '@gen-epix/ui-core/hooks/useArray';\n\nimport { useCaseSetsQuery } from '../../../dataHooks/useCaseSetsQuery';\nimport { useCaseTypeMapQuery } from '../../../dataHooks/useCaseTypesQuery';\nimport { CaseTypeUtil } from '../../../utils/CaseTypeUtil';\nimport type { CaseDbConfig } from '../../../models/config';\nimport { CASEDB_QUERY_KEY } from '../../../constants/query';\n\nimport { HomePageTrendCard } from './HomePageTrendCard';\n\ntype CaseStatsWithDiff = {\n diffPercentage: number;\n} & CaseDbCaseStats;\n\ntype Statistic = {\n callback?: () => void;\n callbackLabel?: string;\n diffPercentage: number;\n header: string;\n value: number;\n};\n\nexport const HomePageTrends = withPermissions<CaseDbApiPermission>(() => {\n const theme = useTheme();\n const { t } = useTranslation();\n\n const dateTimeRangeFilter = useMemo<CaseDbTypedDatetimeRangeFilter>(() => ({\n type: 'DATETIME_RANGE',\n upper_bound: ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceDate(),\n upper_bound_censor: '<=',\n } satisfies CaseDbTypedDatetimeRangeFilter), []);\n\n const caseSetQueryFilter = useMemo<CaseDbEpiFilter>(() => ({\n key: 'case_set_date',\n type: 'DATETIME_RANGE',\n upper_bound: ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceDate(),\n upper_bound_censor: '<=',\n } satisfies CaseDbEpiFilter), []);\n\n const caseTypeStatsQueryNow = useQueryMemo({\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().retrieveCaseTypeStats({}, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_TYPE_STATS),\n });\n\n const retrieveTypeCaseStatsRequestBody = useMemo<CaseDbRetrieveCaseTypeStatsRequestBody>(() => {\n if (!caseTypeStatsQueryNow.data) {\n return undefined;\n }\n return {\n case_type_ids: caseTypeStatsQueryNow.data?.filter(stat => stat.n_cases > 0).map(stat => stat.case_type_id),\n datetime_range_filter: dateTimeRangeFilter,\n };\n }, [dateTimeRangeFilter, caseTypeStatsQueryNow.data]);\n\n const caseTypeStatsQueryPast = useQueryMemo({\n enabled: !!retrieveTypeCaseStatsRequestBody,\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().retrieveCaseTypeStats(retrieveTypeCaseStatsRequestBody ?? {}, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_TYPE_STATS, retrieveTypeCaseStatsRequestBody ?? {}),\n });\n const caseSetsNowQuery = useCaseSetsQuery();\n const caseTypeMapQuery = useCaseTypeMapQuery();\n\n const { data: caseSetsThenData, ...caseSetsThenQuery } = useQueryMemo({\n queryFn: async ({ signal }) => {\n const response = await CaseDbCaseApi.getInstance().caseSetsPostQuery(caseSetQueryFilter, null, null, { signal });\n return response.data;\n },\n queryKey: QueryClientService.getInstance().getGenericKey(CASEDB_QUERY_KEY.CASE_SETS, caseSetQueryFilter),\n });\n\n const loadables = useArray([\n caseTypeStatsQueryNow,\n caseTypeStatsQueryPast,\n caseTypeMapQuery,\n caseSetsNowQuery,\n caseSetsThenQuery,\n ]);\n\n const statistics = useMemo<Statistic[]>(() => {\n const s: Statistic[] = [];\n\n if (LoadableUtil.isSomeLoading(loadables) || LoadableUtil.hasSomeError(loadables) || !caseTypeStatsQueryNow.data?.length || !caseTypeStatsQueryPast.data?.length) {\n return s;\n }\n\n const nowTotalCases = caseTypeStatsQueryNow.data?.reduce((acc, stat) => acc + stat.n_cases, 0) ?? 0;\n const thenTotalCases = caseTypeStatsQueryPast.data?.reduce((acc, stat) => acc + stat.n_cases, 0) ?? 0;\n\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate('/cases');\n },\n callbackLabel: t`View all cases`,\n diffPercentage: round((nowTotalCases - thenTotalCases) / (thenTotalCases || 1) * 100, 2),\n header: 'Cases',\n value: nowTotalCases,\n },\n );\n\n const numberOfCaseSetsNow = caseSetsNowQuery.data.length;\n const numberOfCaseSetsThen = caseSetsThenData.length;\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate('/events');\n },\n callbackLabel: t`View all events`,\n diffPercentage: round((numberOfCaseSetsNow - numberOfCaseSetsThen) / (numberOfCaseSetsThen || 1) * 100, 2),\n header: 'Events',\n value: numberOfCaseSetsNow,\n },\n );\n\n const caseStatsThenByCaseTypeId = new Map<string, CaseDbCaseStats>(caseTypeStatsQueryPast.data?.map(stat => [stat.case_type_id, stat]));\n const sortedStats = caseTypeStatsQueryNow?.data?.map<CaseStatsWithDiff>(stat => {\n const nowNCases = stat.n_cases;\n const thenNCases = caseStatsThenByCaseTypeId.get(stat.case_type_id)?.n_cases ?? 0;\n const diff = nowNCases - thenNCases;\n let diffPercentage: number;\n if (thenNCases > 0) {\n diffPercentage = round((diff / thenNCases) * 100, 2);\n } else {\n diffPercentage = 0;\n }\n return ({\n ...stat,\n diffPercentage,\n });\n }).sort((a, b) => b.diffPercentage - a.diffPercentage);\n\n for (let i = 0; i < 6; i += 1) {\n if (sortedStats?.[i]) {\n const caseType = caseTypeMapQuery.map?.get(sortedStats?.[i].case_type_id ?? '');\n const caseTypeName = caseType?.name;\n if (caseTypeName) {\n s.push(\n {\n callback: async () => {\n await RouterService.getInstance().router.navigate(CaseTypeUtil.createCaseTypeLink(caseType));\n },\n callbackLabel: t`View cases`,\n diffPercentage: sortedStats[i].diffPercentage,\n header: t('{{caseTypeName}} cases', { caseTypeName, number: i + 1 }),\n value: sortedStats[i].n_cases,\n },\n );\n }\n }\n }\n\n return s;\n }, [caseSetsNowQuery.data?.length, caseSetsThenData?.length, caseTypeMapQuery.map, caseTypeStatsQueryNow.data, caseTypeStatsQueryPast.data, loadables, t]);\n\n const onViewMoreTrendsButtonClick = useCallback(async () => {\n await RouterService.getInstance().router.navigate('/trends');\n }, []);\n\n if (AxiosUtil.isAxiosForbiddenError(LoadableUtil.findFirstError(loadables))) {\n return null;\n }\n\n return (\n <Box>\n <Box\n sx={{\n marginBottom: 1,\n }}\n >\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'space-between',\n }}\n >\n <Box>\n <Typography\n variant={'h2'}\n >\n {t`Trends summary`}\n </Typography>\n </Box>\n <Box>\n <Button\n color={'primary'}\n disabled\n onClick={onViewMoreTrendsButtonClick}\n variant={'outlined'}\n >\n {t`View more trends`}\n </Button>\n </Box>\n </Box>\n </Box>\n <ResponseHandler\n inlineSpinner\n loadables={loadables}\n loadingContent={(\n <Box\n sx={{\n display: 'grid',\n gap: 2,\n gridTemplateColumns: 'repeat(1, 1fr)',\n marginBottom: 2,\n [theme.breakpoints.up('md')]: {\n gridTemplateColumns: 'repeat(4, 1fr)',\n },\n [theme.breakpoints.up('sm')]: {\n gridTemplateColumns: 'repeat(2, 1fr)',\n },\n }}\n >\n {[...Array<string>(8)].map((_, index) => (\n <Box\n // eslint-disable-next-line @eslint-react/no-array-index-key\n key={index}\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: 165.75,\n justifyContent: 'center',\n }}\n >\n <Skeleton\n animation={'pulse'}\n height={'100%'}\n variant={'rounded'}\n width={'100%'}\n />\n </Box>\n ))}\n </Box>\n )}\n shouldHideActionButtons\n >\n {statistics.length === 0 && (\n <Box\n sx={{\n marginY: 2,\n }}\n >\n <Typography>\n {t`No trends available.`}\n </Typography>\n </Box>\n )}\n {statistics.length > 0 && (\n <Box\n sx={{\n display: 'grid',\n gap: 2,\n gridTemplateColumns: 'repeat(1, 1fr)',\n marginBottom: 2,\n [theme.breakpoints.up('md')]: {\n gridTemplateColumns: 'repeat(4, 1fr)',\n },\n [theme.breakpoints.up('sm')]: {\n gridTemplateColumns: 'repeat(2, 1fr)',\n },\n }}\n >\n {statistics.map(statistic => (\n <HomePageTrendCard\n callback={statistic.callback}\n callbackLabel={statistic.callbackLabel}\n diffPercentage={statistic.diffPercentage}\n header={statistic.header}\n key={statistic.header}\n sinceLabel={ConfigService.getInstance<CaseDbConfig>().config.trends.homePage.getSinceLabel(t)}\n value={statistic.value}\n />\n ))}\n </Box>\n )}\n </ResponseHandler>\n </Box>\n );\n}, {\n requiredPermissions: [\n { command_name: CaseDbCommandName.RetrieveCaseTypeStatsCommand, permission_type: CaseDbPermissionType.EXECUTE },\n { command_name: CaseDbCommandName.CaseSetCrudCommand, permission_type: CaseDbPermissionType.READ },\n { command_name: CaseDbCommandName.CaseTypeCrudCommand, permission_type: CaseDbPermissionType.READ },\n ],\n});\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { DASHBOARD_COMPONENT_NAME as a } from "../constants/dashboard.js";
5
5
  import { t as o } from "./react.js";
6
6
  import { t as s } from "./dashboardStore.js";
7
7
  import { ContextMenu as c } from "../components/ui/ContextMenu/index.js";
8
- import { ConfigService as l } from "@gen-epix/ui/classes/services/ConfigService";
8
+ import { ConfigService as l } from "@gen-epix/ui-client-common/classes/services/ConfigService";
9
9
  import { Box as u, ListItemIcon as d, ListItemText as f, MenuItem as p, Tooltip as m, useTheme as h } from "@mui/material";
10
10
  import * as g from "react";
11
11
  import _, { createContext as v, use as y, useCallback as b, useMemo as x, useState as S } from "react";
@@ -100,7 +100,7 @@ var O = /* @__PURE__ */ t(((e, t) => {
100
100
  e.useSyncExternalStore = a.useSyncExternalStore === void 0 ? p : a.useSyncExternalStore, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
101
101
  })();
102
102
  })), j = /* @__PURE__ */ t(((e, t) => {
103
- process.env.NODE_ENV === "production" ? t.exports = k() : t.exports = A();
103
+ t.exports = process.env.NODE_ENV === "production" ? k() : A();
104
104
  })), M = /* @__PURE__ */ t(((e) => {
105
105
  var t = O(), n = j();
106
106
  function r(e, t) {
@@ -194,7 +194,7 @@ var O = /* @__PURE__ */ t(((e, t) => {
194
194
  }, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
195
195
  })();
196
196
  })), P = /* @__PURE__ */ t(((e, t) => {
197
- process.env.NODE_ENV === "production" ? t.exports = M() : t.exports = N();
197
+ t.exports = process.env.NODE_ENV === "production" ? M() : N();
198
198
  })), F = /* @__PURE__ */ e(n(), 1), { useSyncExternalStoreWithSelector: I } = (/* @__PURE__ */ e(P(), 1)).default, L = (e) => e;
199
199
  function R(e, t = L, n) {
200
200
  let r = I(e.subscribe, e.getState, e.getInitialState, t, n);