@cccsaurora/howler-ui 2.18.0 → 2.19.0-cases.1040

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 (468) hide show
  1. package/api/action/index.d.ts +5 -4
  2. package/api/action/index.js +8 -8
  3. package/api/analytic/index.d.ts +3 -2
  4. package/api/analytic/index.js +4 -4
  5. package/api/analytic/owner.d.ts +2 -1
  6. package/api/analytic/owner.js +2 -2
  7. package/api/analytic/rules.d.ts +2 -1
  8. package/api/analytic/rules.js +2 -2
  9. package/api/dossier/index.d.ts +4 -3
  10. package/api/dossier/index.js +6 -6
  11. package/api/hit/index.d.ts +3 -2
  12. package/api/hit/index.js +4 -4
  13. package/api/hit/labels.d.ts +3 -2
  14. package/api/hit/labels.js +4 -4
  15. package/api/hit/overwrite.d.ts +2 -1
  16. package/api/hit/overwrite.js +2 -2
  17. package/api/hit/transition.d.ts +2 -1
  18. package/api/hit/transition.js +2 -2
  19. package/api/index.d.ts +9 -4
  20. package/api/index.js +18 -10
  21. package/api/overview/index.d.ts +4 -3
  22. package/api/overview/index.js +6 -6
  23. package/api/search/case.d.ts +4 -0
  24. package/api/search/case.js +8 -0
  25. package/api/search/facet/hit.d.ts +1 -3
  26. package/api/search/facet/index.d.ts +3 -1
  27. package/api/search/index.d.ts +2 -1
  28. package/api/search/index.js +2 -1
  29. package/api/search/overview.d.ts +2 -2
  30. package/api/socket/index.d.ts +3 -0
  31. package/api/socket/index.js +6 -0
  32. package/api/socket/viewers.d.ts +2 -0
  33. package/api/socket/viewers.js +8 -0
  34. package/api/socket/viewers.test.js +44 -0
  35. package/api/template/index.d.ts +4 -3
  36. package/api/template/index.js +6 -6
  37. package/api/user/index.d.ts +2 -1
  38. package/api/user/index.js +2 -2
  39. package/api/v2/case/index.d.ts +9 -0
  40. package/api/v2/case/index.js +21 -0
  41. package/api/v2/case/items.d.ts +6 -0
  42. package/api/v2/case/items.js +18 -0
  43. package/api/v2/case/rules.d.ts +6 -0
  44. package/api/v2/case/rules.js +18 -0
  45. package/api/v2/index.d.ts +4 -0
  46. package/api/v2/index.js +6 -0
  47. package/api/v2/search/facet.d.ts +3 -0
  48. package/api/v2/search/facet.js +12 -0
  49. package/api/v2/search/index.d.ts +5 -0
  50. package/api/v2/search/index.js +24 -0
  51. package/api/view/index.d.ts +4 -3
  52. package/api/view/index.js +6 -6
  53. package/commons/components/leftnav/LeftNavDrawer.js +1 -1
  54. package/components/app/App.d.ts +1 -0
  55. package/components/app/App.js +64 -13
  56. package/components/app/hooks/useMatchers.d.ts +1 -1
  57. package/components/app/hooks/useMatchers.js +23 -11
  58. package/components/app/hooks/useMatchers.test.js +22 -22
  59. package/components/app/hooks/useTitle.js +5 -5
  60. package/components/app/providers/FavouritesProvider.js +2 -6
  61. package/components/app/providers/ModalProvider.d.ts +2 -0
  62. package/components/app/providers/ModalProvider.js +5 -1
  63. package/components/app/providers/ParameterProvider.d.ts +9 -2
  64. package/components/app/providers/ParameterProvider.js +165 -240
  65. package/components/app/providers/ParameterProvider.test.js +346 -94
  66. package/components/app/providers/RecordProvider.d.ts +23 -0
  67. package/components/app/providers/{HitProvider.js → RecordProvider.js} +42 -42
  68. package/components/app/providers/{HitSearchProvider.d.ts → RecordSearchProvider.d.ts} +6 -6
  69. package/components/app/providers/{HitSearchProvider.js → RecordSearchProvider.js} +12 -17
  70. package/components/app/providers/{HitSearchProvider.test.js → RecordSearchProvider.test.js} +52 -71
  71. package/components/app/providers/SearchResponseProvider.d.ts +21 -0
  72. package/components/app/providers/SearchResponseProvider.js +81 -0
  73. package/components/app/providers/SearchResponseProvider.test.d.ts +1 -0
  74. package/components/app/providers/SearchResponseProvider.test.js +406 -0
  75. package/components/app/providers/SocketProvider.d.ts +11 -2
  76. package/components/app/providers/SocketProvider.js +18 -5
  77. package/components/app/providers/UserListProvider.js +28 -8
  78. package/components/app/providers/ViewProvider.test.js +4 -1
  79. package/components/elements/ContextMenu.d.ts +56 -0
  80. package/components/elements/ContextMenu.js +109 -0
  81. package/components/elements/ContextMenu.test.d.ts +1 -0
  82. package/components/elements/ContextMenu.test.js +215 -0
  83. package/components/{routes/overviews/OverviewEditor.js → elements/MarkdownEditor.js} +3 -3
  84. package/components/elements/ObjectDetails.d.ts +6 -0
  85. package/components/elements/{hit/HitDetails.js → ObjectDetails.js} +17 -17
  86. package/components/elements/PluginTypography.d.ts +2 -1
  87. package/components/elements/PluginTypography.js +3 -2
  88. package/components/elements/UserList.d.ts +5 -2
  89. package/components/elements/UserList.js +18 -8
  90. package/components/elements/addons/buttons/CustomButton.test.d.ts +1 -0
  91. package/components/elements/addons/buttons/CustomButton.test.js +106 -0
  92. package/components/elements/addons/layout/FlexOne.test.d.ts +1 -0
  93. package/components/elements/addons/layout/FlexOne.test.js +30 -0
  94. package/components/elements/addons/lists/TuiListBase.js +4 -0
  95. package/components/elements/addons/lists/TuiListElement.js +6 -3
  96. package/components/elements/addons/lists/index.d.ts +1 -0
  97. package/components/elements/addons/search/SearchPagination.d.ts +2 -1
  98. package/components/elements/addons/search/SearchPagination.js +4 -4
  99. package/components/elements/addons/search/SearchPagination.test.d.ts +1 -0
  100. package/components/elements/addons/search/SearchPagination.test.js +80 -0
  101. package/components/elements/addons/search/SearchTotal.test.d.ts +1 -0
  102. package/components/elements/addons/search/SearchTotal.test.js +47 -0
  103. package/components/elements/addons/search/phrase/Phrase.js +1 -1
  104. package/components/elements/case/CaseCard.d.ts +12 -0
  105. package/components/elements/case/CaseCard.js +42 -0
  106. package/components/elements/case/CasePreview.d.ts +6 -0
  107. package/components/elements/case/CasePreview.js +17 -0
  108. package/components/elements/case/StatusIcon.d.ts +5 -0
  109. package/components/elements/case/StatusIcon.js +13 -0
  110. package/components/elements/display/ChipPopper.d.ts +1 -1
  111. package/components/elements/display/ChipPopper.js +5 -5
  112. package/components/elements/display/DocumentationButton.test.d.ts +1 -0
  113. package/components/elements/display/DocumentationButton.test.js +84 -0
  114. package/components/elements/display/DynamicTabs.test.d.ts +1 -0
  115. package/components/elements/display/DynamicTabs.test.js +93 -0
  116. package/components/elements/display/HowlerAvatar.js +2 -1
  117. package/components/elements/display/HowlerCard.js +1 -1
  118. package/components/elements/display/HowlerCard.test.d.ts +1 -0
  119. package/components/elements/display/HowlerCard.test.js +51 -0
  120. package/components/elements/display/Image.test.d.ts +1 -0
  121. package/components/elements/display/Image.test.js +79 -0
  122. package/components/elements/display/ItemManager.d.ts +2 -2
  123. package/components/elements/display/ItemManager.js +1 -1
  124. package/components/elements/display/Markdown.js +9 -2
  125. package/components/elements/display/Modal.js +2 -0
  126. package/components/elements/display/QueryResultText.test.d.ts +1 -0
  127. package/components/elements/display/QueryResultText.test.js +48 -0
  128. package/components/elements/display/TextDivider.test.d.ts +1 -0
  129. package/components/elements/display/TextDivider.test.js +43 -0
  130. package/components/elements/display/TypingIndicator.test.d.ts +1 -0
  131. package/components/elements/display/TypingIndicator.test.js +33 -0
  132. package/components/elements/display/modals/ConfirmDeleteModal.d.ts +4 -0
  133. package/components/elements/display/modals/ConfirmDeleteModal.js +4 -2
  134. package/components/elements/hit/HitActions.js +4 -4
  135. package/components/elements/hit/HitBanner.d.ts +1 -0
  136. package/components/elements/hit/HitBanner.js +34 -51
  137. package/components/elements/hit/HitCard.d.ts +2 -0
  138. package/components/elements/hit/HitCard.js +7 -7
  139. package/components/elements/hit/HitLabels.js +2 -2
  140. package/components/elements/hit/HitOutline.d.ts +1 -0
  141. package/components/elements/hit/HitOutline.js +3 -3
  142. package/components/elements/hit/{HitQuickSearch.d.ts → HitPreview.d.ts} +3 -3
  143. package/components/elements/hit/{HitQuickSearch.js → HitPreview.js} +10 -4
  144. package/components/elements/hit/HitSummary.d.ts +2 -1
  145. package/components/elements/hit/HitSummary.js +9 -7
  146. package/components/elements/hit/aggregate/HitGraph.js +8 -8
  147. package/components/elements/hit/elements/AnalyticLink.d.ts +9 -0
  148. package/components/elements/hit/elements/AnalyticLink.js +22 -0
  149. package/components/elements/hit/elements/Assigned.d.ts +2 -0
  150. package/components/elements/hit/elements/Assigned.js +21 -16
  151. package/components/elements/hit/elements/Assigned.test.d.ts +1 -0
  152. package/components/elements/hit/elements/Assigned.test.js +65 -0
  153. package/components/elements/hit/outlines/DefaultOutline.js +1 -1
  154. package/components/elements/hit/related/RelatedRecords.js +63 -0
  155. package/components/elements/observable/ObservableCard.d.ts +6 -0
  156. package/components/elements/observable/ObservableCard.js +22 -0
  157. package/components/elements/observable/ObservablePreview.d.ts +6 -0
  158. package/components/elements/observable/ObservablePreview.js +12 -0
  159. package/components/elements/{hit/HitComments.d.ts → record/RecordComments.d.ts} +5 -4
  160. package/components/elements/{hit/HitComments.js → record/RecordComments.js} +29 -28
  161. package/components/{routes/hits/search/HitContextMenu.d.ts → elements/record/RecordContextMenu.d.ts} +3 -3
  162. package/components/elements/record/RecordContextMenu.js +268 -0
  163. package/components/elements/record/RecordContextMenu.test.d.ts +1 -0
  164. package/components/{routes/hits/search/HitContextMenu.test.js → elements/record/RecordContextMenu.test.js} +190 -39
  165. package/components/elements/record/RecordRelated.d.ts +7 -0
  166. package/components/elements/record/RecordRelated.js +34 -0
  167. package/components/elements/{hit/HitWorklog.d.ts → record/RecordWorklog.d.ts} +4 -3
  168. package/components/elements/{hit/HitWorklog.js → record/RecordWorklog.js} +15 -13
  169. package/components/elements/view/ViewTitle.d.ts +1 -0
  170. package/components/elements/view/ViewTitle.js +9 -2
  171. package/components/hooks/useHitActions.d.ts +1 -1
  172. package/components/hooks/useHitActions.js +4 -4
  173. package/components/hooks/useMyApi.d.ts +1 -1
  174. package/components/hooks/useMyPreferences.js +12 -2
  175. package/components/hooks/useMySearch.js +2 -2
  176. package/components/hooks/useMySitemap.js +4 -1
  177. package/components/hooks/useMyTheme.js +9 -2
  178. package/components/hooks/{useHitSelection.d.ts → useRecordSelection.d.ts} +2 -2
  179. package/components/hooks/{useHitSelection.js → useRecordSelection.js} +12 -33
  180. package/components/hooks/useRelatedRecords.d.ts +13 -0
  181. package/components/hooks/useRelatedRecords.js +32 -0
  182. package/components/routes/403.d.ts +3 -0
  183. package/components/routes/403.js +10 -0
  184. package/components/routes/403.test.d.ts +1 -0
  185. package/components/routes/403.test.js +27 -0
  186. package/components/routes/404.test.d.ts +1 -0
  187. package/components/routes/404.test.js +26 -0
  188. package/components/routes/ErrorBoundary.test.d.ts +1 -0
  189. package/components/routes/ErrorBoundary.test.js +43 -0
  190. package/components/routes/ErrorOccured.test.d.ts +1 -0
  191. package/components/routes/ErrorOccured.test.js +35 -0
  192. package/components/routes/Logout.test.d.ts +1 -0
  193. package/components/routes/Logout.test.js +59 -0
  194. package/components/routes/action/edit/ActionEditor.js +3 -3
  195. package/components/routes/action/useMyActionFunctions.js +9 -3
  196. package/components/routes/action/view/ActionDetails.js +15 -2
  197. package/components/routes/action/view/ActionSearch.js +32 -20
  198. package/components/routes/action/view/markdown/integrations.en.md.js +1 -1
  199. package/components/routes/action/view/markdown/integrations.fr.md.js +1 -1
  200. package/components/routes/advanced/QueryBuilder.js +1 -1
  201. package/components/routes/advanced/QueryEditor.js +3 -3
  202. package/components/routes/advanced/historyCompletionProvider.js +3 -3
  203. package/components/routes/analytics/AnalyticDetails.js +12 -8
  204. package/components/routes/analytics/AnalyticSearch.js +7 -7
  205. package/components/routes/cases/CaseViewer.d.ts +2 -0
  206. package/components/routes/cases/CaseViewer.js +44 -0
  207. package/components/routes/cases/CaseViewer.test.d.ts +1 -0
  208. package/components/routes/cases/CaseViewer.test.js +133 -0
  209. package/components/routes/cases/Cases.d.ts +2 -0
  210. package/components/routes/cases/Cases.js +147 -0
  211. package/components/routes/cases/constants.d.ts +6 -0
  212. package/components/routes/cases/constants.js +6 -0
  213. package/components/routes/cases/detail/AlertPanel.d.ts +6 -0
  214. package/components/routes/cases/detail/AlertPanel.js +33 -0
  215. package/components/routes/cases/detail/CaseAssets.d.ts +11 -0
  216. package/components/routes/cases/detail/CaseAssets.js +104 -0
  217. package/components/routes/cases/detail/CaseAssets.test.d.ts +1 -0
  218. package/components/routes/cases/detail/CaseAssets.test.js +167 -0
  219. package/components/routes/cases/detail/CaseDashboard.d.ts +7 -0
  220. package/components/routes/cases/detail/CaseDashboard.js +66 -0
  221. package/components/routes/cases/detail/CaseDetails.d.ts +6 -0
  222. package/components/routes/cases/detail/CaseDetails.js +70 -0
  223. package/components/routes/cases/detail/CaseOverview.d.ts +7 -0
  224. package/components/routes/cases/detail/CaseOverview.js +43 -0
  225. package/components/routes/cases/detail/CaseRules.d.ts +7 -0
  226. package/components/routes/cases/detail/CaseRules.js +57 -0
  227. package/components/routes/cases/detail/CaseRules.test.d.ts +1 -0
  228. package/components/routes/cases/detail/CaseRules.test.js +221 -0
  229. package/components/routes/cases/detail/CaseSidebar.d.ts +8 -0
  230. package/components/routes/cases/detail/CaseSidebar.js +107 -0
  231. package/components/routes/cases/detail/CaseSidebar.test.d.ts +1 -0
  232. package/components/routes/cases/detail/CaseSidebar.test.js +266 -0
  233. package/components/routes/cases/detail/CaseTask.d.ts +11 -0
  234. package/components/routes/cases/detail/CaseTask.js +66 -0
  235. package/components/routes/cases/detail/CaseTimeline.d.ts +12 -0
  236. package/components/routes/cases/detail/CaseTimeline.js +106 -0
  237. package/components/routes/cases/detail/CaseTimeline.test.d.ts +1 -0
  238. package/components/routes/cases/detail/CaseTimeline.test.js +320 -0
  239. package/components/routes/cases/detail/CreateRuleDialog.d.ts +9 -0
  240. package/components/routes/cases/detail/CreateRuleDialog.js +163 -0
  241. package/components/routes/cases/detail/CreateRuleDialog.test.d.ts +1 -0
  242. package/components/routes/cases/detail/CreateRuleDialog.test.js +259 -0
  243. package/components/routes/cases/detail/ItemPage.d.ts +6 -0
  244. package/components/routes/cases/detail/ItemPage.js +95 -0
  245. package/components/routes/cases/detail/RelatedCasePanel.d.ts +6 -0
  246. package/components/routes/cases/detail/RelatedCasePanel.js +34 -0
  247. package/components/routes/cases/detail/TaskPanel.d.ts +7 -0
  248. package/components/routes/cases/detail/TaskPanel.js +52 -0
  249. package/components/routes/cases/detail/aggregates/CaseAggregate.d.ts +11 -0
  250. package/components/routes/cases/detail/aggregates/CaseAggregate.js +24 -0
  251. package/components/routes/cases/detail/aggregates/SourceAggregate.d.ts +6 -0
  252. package/components/routes/cases/detail/aggregates/SourceAggregate.js +26 -0
  253. package/components/routes/cases/detail/assets/Asset.d.ts +14 -0
  254. package/components/routes/cases/detail/assets/Asset.js +12 -0
  255. package/components/routes/cases/detail/assets/Asset.test.d.ts +1 -0
  256. package/components/routes/cases/detail/assets/Asset.test.js +72 -0
  257. package/components/routes/cases/detail/sidebar/CaseFolder.d.ts +20 -0
  258. package/components/routes/cases/detail/sidebar/CaseFolder.js +83 -0
  259. package/components/routes/cases/detail/sidebar/CaseFolder.test.d.ts +1 -0
  260. package/components/routes/cases/detail/sidebar/CaseFolder.test.js +295 -0
  261. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.d.ts +34 -0
  262. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.js +103 -0
  263. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.d.ts +1 -0
  264. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.js +363 -0
  265. package/components/routes/cases/detail/sidebar/FolderEntry.d.ts +25 -0
  266. package/components/routes/cases/detail/sidebar/FolderEntry.js +88 -0
  267. package/components/routes/cases/detail/sidebar/FolderEntry.test.d.ts +1 -0
  268. package/components/routes/cases/detail/sidebar/FolderEntry.test.js +206 -0
  269. package/components/routes/cases/detail/sidebar/RootDropZone.d.ts +5 -0
  270. package/components/routes/cases/detail/sidebar/RootDropZone.js +33 -0
  271. package/components/routes/cases/detail/sidebar/types.d.ts +9 -0
  272. package/components/routes/cases/detail/sidebar/utils.d.ts +3 -0
  273. package/components/routes/cases/detail/sidebar/utils.js +29 -0
  274. package/components/routes/cases/detail/sidebar/utils.test.d.ts +1 -0
  275. package/components/routes/cases/detail/sidebar/utils.test.js +82 -0
  276. package/components/routes/cases/hooks/useCase.d.ts +13 -0
  277. package/components/routes/cases/hooks/useCase.js +69 -0
  278. package/components/routes/cases/hooks/useCase.test.d.ts +1 -0
  279. package/components/routes/cases/hooks/useCase.test.js +141 -0
  280. package/components/routes/cases/modals/AddToCaseModal.d.ts +7 -0
  281. package/components/routes/cases/modals/AddToCaseModal.js +59 -0
  282. package/components/routes/cases/modals/AddToCaseModal.test.d.ts +1 -0
  283. package/components/routes/cases/modals/AddToCaseModal.test.js +313 -0
  284. package/components/routes/cases/modals/CaseRecordRow.d.ts +9 -0
  285. package/components/routes/cases/modals/CaseRecordRow.js +15 -0
  286. package/components/routes/cases/modals/CreateCaseModal.d.ts +7 -0
  287. package/components/routes/cases/modals/CreateCaseModal.js +55 -0
  288. package/components/routes/cases/modals/CreateCaseModal.test.d.ts +1 -0
  289. package/components/routes/cases/modals/CreateCaseModal.test.js +358 -0
  290. package/components/routes/cases/modals/RenameItemModal.d.ts +9 -0
  291. package/components/routes/cases/modals/RenameItemModal.js +48 -0
  292. package/components/routes/cases/modals/ResolveModal.d.ts +7 -0
  293. package/components/routes/cases/modals/ResolveModal.js +116 -0
  294. package/components/routes/cases/modals/ResolveModal.test.d.ts +1 -0
  295. package/components/routes/cases/modals/ResolveModal.test.js +454 -0
  296. package/components/routes/cases/modals/hooks.d.ts +7 -0
  297. package/components/routes/cases/modals/hooks.js +44 -0
  298. package/components/routes/cases/modals/types.d.ts +5 -0
  299. package/components/routes/cases/search/CaseAssigneeFilter.d.ts +6 -0
  300. package/components/routes/cases/search/CaseAssigneeFilter.js +33 -0
  301. package/components/routes/cases/search/CaseAssigneeFilter.test.d.ts +1 -0
  302. package/components/routes/cases/search/CaseAssigneeFilter.test.js +127 -0
  303. package/components/routes/cases/search/CaseDateFilter.d.ts +13 -0
  304. package/components/routes/cases/search/CaseDateFilter.js +26 -0
  305. package/components/routes/cases/search/CaseDateFilter.test.d.ts +1 -0
  306. package/components/routes/cases/search/CaseDateFilter.test.js +115 -0
  307. package/components/routes/cases/search/CaseStatusFilter.d.ts +6 -0
  308. package/components/routes/cases/search/CaseStatusFilter.js +13 -0
  309. package/components/routes/cases/search/CaseStatusFilter.test.d.ts +1 -0
  310. package/components/routes/cases/search/CaseStatusFilter.test.js +86 -0
  311. package/components/routes/dossiers/DossierEditor.js +2 -2
  312. package/components/routes/dossiers/DossierEditor.test.js +1 -1
  313. package/components/routes/dossiers/Dossiers.js +25 -19
  314. package/components/routes/help/ActionIntroductionDocumentation.js +1 -1
  315. package/components/routes/help/ApiDocumentation.js +1 -1
  316. package/components/routes/help/HitBannerDocumentation.js +1 -0
  317. package/components/routes/help/HitDocumentation.js +1 -3
  318. package/components/routes/help/markdown/en/client.md.js +1 -1
  319. package/components/routes/help/markdown/en/retention.md.js +1 -1
  320. package/components/routes/help/markdown/fr/client.md.js +1 -1
  321. package/components/routes/help/markdown/fr/retention.md.js +1 -1
  322. package/components/routes/hits/search/InformationPane.d.ts +1 -0
  323. package/components/routes/hits/search/InformationPane.js +50 -63
  324. package/components/routes/hits/search/LayoutSettings.js +3 -3
  325. package/components/routes/hits/search/QuerySettings.js +2 -1
  326. package/components/routes/hits/search/QuerySettings.test.js +14 -9
  327. package/components/routes/hits/search/{HitBrowser.js → RecordBrowser.js} +9 -9
  328. package/components/routes/hits/search/{HitQuery.d.ts → RecordQuery.d.ts} +2 -2
  329. package/components/routes/hits/search/{HitQuery.js → RecordQuery.js} +6 -6
  330. package/components/routes/hits/search/SearchPane.js +26 -49
  331. package/components/routes/hits/search/ViewLink.js +3 -3
  332. package/components/routes/hits/search/ViewLink.test.js +8 -8
  333. package/components/routes/hits/search/grid/AddColumnModal.js +5 -4
  334. package/components/routes/hits/search/grid/EnhancedCell.d.ts +2 -1
  335. package/components/routes/hits/search/grid/EnhancedCell.js +2 -2
  336. package/components/routes/hits/search/grid/HitGrid.js +20 -18
  337. package/components/routes/hits/search/grid/{HitRow.d.ts → RecordRow.d.ts} +3 -2
  338. package/components/routes/hits/search/grid/{HitRow.js → RecordRow.js} +10 -8
  339. package/components/routes/hits/search/shared/CustomSpan.js +7 -7
  340. package/components/routes/hits/search/shared/CustomSpan.test.d.ts +1 -0
  341. package/components/routes/hits/search/shared/CustomSpan.test.js +170 -0
  342. package/components/routes/hits/search/shared/IndexPicker.d.ts +2 -0
  343. package/components/routes/hits/search/shared/IndexPicker.js +20 -0
  344. package/components/routes/hits/view/HitViewer.js +12 -13
  345. package/components/routes/home/AddNewCard.js +1 -1
  346. package/components/routes/home/AddNewCard.test.d.ts +1 -0
  347. package/components/routes/home/AddNewCard.test.js +86 -0
  348. package/components/routes/home/ViewCard.js +47 -41
  349. package/components/routes/home/ViewRefresh.test.d.ts +1 -0
  350. package/components/routes/home/ViewRefresh.test.js +79 -0
  351. package/components/routes/observables/ObservableViewer.d.ts +7 -0
  352. package/components/routes/observables/ObservableViewer.js +27 -0
  353. package/components/routes/overviews/OverviewCard.test.d.ts +1 -0
  354. package/components/routes/overviews/OverviewCard.test.js +108 -0
  355. package/components/routes/overviews/OverviewViewer.js +18 -10
  356. package/components/routes/overviews/Overviews.js +25 -19
  357. package/components/routes/overviews/template/en.md.js +1 -1
  358. package/components/routes/overviews/template/fr.md.js +1 -1
  359. package/components/routes/settings/LocalSection.js +2 -1
  360. package/components/routes/settings/SettingsSection.test.d.ts +1 -0
  361. package/components/routes/settings/SettingsSection.test.js +19 -0
  362. package/components/routes/templates/TemplateCard.d.ts +3 -1
  363. package/components/routes/templates/TemplateCard.js +8 -4
  364. package/components/routes/templates/TemplateCard.test.d.ts +1 -0
  365. package/components/routes/templates/TemplateCard.test.js +115 -0
  366. package/components/routes/templates/TemplateViewer.js +62 -16
  367. package/components/routes/templates/Templates.js +35 -13
  368. package/components/routes/views/ViewComposer.js +46 -19
  369. package/components/routes/views/Views.js +21 -14
  370. package/locales/en/translation.json +146 -8
  371. package/locales/fr/translation.json +144 -8
  372. package/models/WithMetadata.d.ts +2 -1
  373. package/models/entities/generated/ApiType.d.ts +1 -1
  374. package/models/entities/generated/AttachmentsFile.d.ts +12 -0
  375. package/models/entities/generated/Case.d.ts +28 -0
  376. package/models/entities/generated/DestinationOriginal.d.ts +19 -0
  377. package/models/entities/generated/EmailAttachment.d.ts +8 -0
  378. package/models/entities/generated/EmailParent.d.ts +19 -0
  379. package/models/entities/generated/Enrichments.d.ts +7 -0
  380. package/models/entities/generated/EnrichmentsIndicator.d.ts +21 -0
  381. package/models/entities/generated/Hit.d.ts +2 -0
  382. package/models/entities/generated/Howler.d.ts +1 -5
  383. package/models/entities/generated/HttpResponse.d.ts +11 -0
  384. package/models/entities/generated/Item.d.ts +9 -0
  385. package/models/entities/generated/Observable.d.ts +85 -0
  386. package/models/entities/generated/ObservableCloud.d.ts +20 -0
  387. package/models/entities/generated/ObservableDestination.d.ts +23 -0
  388. package/models/entities/generated/ObservableEmail.d.ts +30 -0
  389. package/models/entities/generated/ObservableFile.d.ts +36 -0
  390. package/models/entities/generated/ObservableHowler.d.ts +42 -0
  391. package/models/entities/generated/ObservableHttp.d.ts +11 -0
  392. package/models/entities/generated/ObservableObserver.d.ts +21 -0
  393. package/models/entities/generated/ObservableOrganization.d.ts +7 -0
  394. package/models/entities/generated/ObservableProcess.d.ts +34 -0
  395. package/models/entities/generated/ObservableSource.d.ts +23 -0
  396. package/models/entities/generated/ObservableThreat.d.ts +21 -0
  397. package/models/entities/generated/ObservableTls.d.ts +12 -0
  398. package/models/entities/generated/ObserverIngress.d.ts +9 -0
  399. package/models/entities/generated/Rule.d.ts +6 -9
  400. package/models/entities/generated/Task.d.ts +10 -0
  401. package/models/entities/generated/Threat.d.ts +2 -2
  402. package/models/entities/generated/{Enrichment.d.ts → ThreatEnrichment.d.ts} +1 -1
  403. package/models/entities/generated/UserUser.d.ts +2 -0
  404. package/models/entities/generated/View.d.ts +1 -0
  405. package/models/socket/CaseUpdate.d.ts +5 -0
  406. package/models/socket/ViewersUpdate.d.ts +4 -0
  407. package/package.json +147 -132
  408. package/plugins/clue/components/ClueTypography.js +2 -2
  409. package/plugins/clue/utils.d.ts +2 -1
  410. package/rest/FetchClient.test.d.ts +1 -0
  411. package/rest/FetchClient.test.js +81 -0
  412. package/setupTests.js +5 -0
  413. package/tests/mocks.d.ts +11 -1
  414. package/tests/mocks.js +12 -7
  415. package/tests/server-handlers.js +6 -1
  416. package/tests/utils.d.ts +4 -0
  417. package/tests/utils.js +20 -0
  418. package/utils/Throttler.test.d.ts +1 -0
  419. package/utils/Throttler.test.js +135 -0
  420. package/utils/actionUtils.test.d.ts +1 -0
  421. package/utils/actionUtils.test.js +140 -0
  422. package/utils/constants.d.ts +5 -3
  423. package/utils/constants.js +7 -0
  424. package/utils/hitFunctions.d.ts +2 -1
  425. package/utils/hitFunctions.js +4 -4
  426. package/utils/hitFunctions.test.d.ts +1 -0
  427. package/utils/hitFunctions.test.js +52 -0
  428. package/utils/localStorage.test.d.ts +1 -0
  429. package/utils/localStorage.test.js +96 -0
  430. package/utils/menuUtils.js +1 -1
  431. package/utils/menuUtils.test.d.ts +1 -0
  432. package/utils/menuUtils.test.js +198 -0
  433. package/utils/sessionStorage.test.d.ts +1 -0
  434. package/utils/sessionStorage.test.js +81 -0
  435. package/utils/socketUtils.d.ts +14 -0
  436. package/utils/socketUtils.js +17 -1
  437. package/utils/socketUtils.test.d.ts +1 -0
  438. package/utils/socketUtils.test.js +59 -0
  439. package/utils/stringUtils.test.d.ts +1 -0
  440. package/utils/stringUtils.test.js +159 -0
  441. package/utils/typeUtils.d.ts +7 -0
  442. package/utils/typeUtils.js +27 -0
  443. package/utils/utils.test.d.ts +1 -0
  444. package/utils/utils.test.js +292 -0
  445. package/utils/viewUtils.js +3 -0
  446. package/utils/viewUtils.test.d.ts +1 -0
  447. package/utils/viewUtils.test.js +45 -0
  448. package/utils/xsrf.test.d.ts +1 -0
  449. package/utils/xsrf.test.js +41 -0
  450. package/components/app/providers/HitProvider.d.ts +0 -22
  451. package/components/elements/display/icons/BundleButton.d.ts +0 -6
  452. package/components/elements/display/icons/BundleButton.js +0 -32
  453. package/components/elements/hit/HitRelated.d.ts +0 -6
  454. package/components/elements/hit/HitRelated.js +0 -7
  455. package/components/routes/help/BundleDocumentation.d.ts +0 -3
  456. package/components/routes/help/BundleDocumentation.js +0 -12
  457. package/components/routes/help/markdown/en/bundles.md.js +0 -1
  458. package/components/routes/help/markdown/fr/bundles.md.js +0 -1
  459. package/components/routes/hits/search/BundleParentMenu.d.ts +0 -6
  460. package/components/routes/hits/search/BundleParentMenu.js +0 -32
  461. package/components/routes/hits/search/BundleScroller.d.ts +0 -2
  462. package/components/routes/hits/search/BundleScroller.js +0 -6
  463. package/components/routes/hits/search/HitContextMenu.js +0 -229
  464. /package/{components/app/providers/HitSearchProvider.test.d.ts → api/socket/viewers.test.d.ts} +0 -0
  465. /package/components/{routes/hits/search/HitContextMenu.test.d.ts → app/providers/RecordSearchProvider.test.d.ts} +0 -0
  466. /package/components/{routes/overviews/OverviewEditor.d.ts → elements/MarkdownEditor.d.ts} +0 -0
  467. /package/components/elements/hit/{HitDetails.d.ts → related/RelatedRecords.d.ts} +0 -0
  468. /package/components/routes/hits/search/{HitBrowser.d.ts → RecordBrowser.d.ts} +0 -0
package/tests/utils.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // Mock data factories
2
2
  export const createMockHit = (overrides) => ({
3
+ ...overrides,
4
+ __index: 'hit',
3
5
  howler: {
4
6
  id: 'test-hit-1',
5
7
  analytic: 'test-analytic',
@@ -14,6 +16,17 @@ export const createMockHit = (overrides) => ({
14
16
  ...overrides?.event
15
17
  }
16
18
  });
19
+ export const createMockObservable = (overrides) => ({
20
+ ...overrides,
21
+ __index: 'observable',
22
+ howler: {
23
+ id: 'test-observable-1',
24
+ analytic: 'test-analytic',
25
+ detection: 'Test Detection',
26
+ hash: '',
27
+ ...overrides?.howler
28
+ }
29
+ });
17
30
  export const createMockAnalytic = (overrides) => ({
18
31
  analytic_id: 'test-analytic-id',
19
32
  name: 'test-analytic',
@@ -52,6 +65,13 @@ export const createMockView = (overrides) => ({
52
65
  },
53
66
  ...overrides
54
67
  });
68
+ export const createMockCase = (overrides) => ({
69
+ case_id: 'test-case-id',
70
+ title: 'Test Case',
71
+ summary: 'Test case summary',
72
+ items: [],
73
+ ...overrides
74
+ });
55
75
  // Helper function to create mock dossiers
56
76
  export const createMockDossier = (overrides) => ({
57
77
  dossier_id: 'test-dossier-id',
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,135 @@
1
+ /// <reference types="vitest" />
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import Throttler from './Throttler';
4
+ describe('Throttler', () => {
5
+ beforeEach(() => {
6
+ vi.useFakeTimers();
7
+ });
8
+ afterEach(() => {
9
+ vi.useRealTimers();
10
+ });
11
+ // -------------------------------------------------------------------------
12
+ // throttle
13
+ // -------------------------------------------------------------------------
14
+ describe('throttle', () => {
15
+ it('calls fn immediately on the first invocation', () => {
16
+ const fn = vi.fn();
17
+ const t = new Throttler(100);
18
+ t.throttle(fn);
19
+ expect(fn).toHaveBeenCalledTimes(1);
20
+ });
21
+ it('suppresses subsequent calls within the throttle window', () => {
22
+ const fn = vi.fn();
23
+ const t = new Throttler(100);
24
+ t.throttle(fn);
25
+ t.throttle(fn);
26
+ t.throttle(fn);
27
+ expect(fn).toHaveBeenCalledTimes(1);
28
+ });
29
+ it('allows another call after the throttle interval expires', () => {
30
+ const fn = vi.fn();
31
+ const t = new Throttler(100);
32
+ t.throttle(fn);
33
+ vi.advanceTimersByTime(150);
34
+ t.throttle(fn);
35
+ expect(fn).toHaveBeenCalledTimes(2);
36
+ });
37
+ it('does not fire a second call if the interval has not yet elapsed', () => {
38
+ const fn = vi.fn();
39
+ const t = new Throttler(200);
40
+ t.throttle(fn);
41
+ vi.advanceTimersByTime(100);
42
+ t.throttle(fn);
43
+ expect(fn).toHaveBeenCalledTimes(1);
44
+ });
45
+ });
46
+ // -------------------------------------------------------------------------
47
+ // debounce
48
+ // -------------------------------------------------------------------------
49
+ describe('debounce', () => {
50
+ it('does not call fn immediately', () => {
51
+ const fn = vi.fn();
52
+ const t = new Throttler(100);
53
+ t.debounce(fn);
54
+ expect(fn).not.toHaveBeenCalled();
55
+ });
56
+ it('calls fn after the delay elapses', () => {
57
+ const fn = vi.fn();
58
+ const t = new Throttler(100);
59
+ t.debounce(fn);
60
+ vi.advanceTimersByTime(100);
61
+ expect(fn).toHaveBeenCalledTimes(1);
62
+ });
63
+ it('resets the delay when called again before it fires', () => {
64
+ const fn = vi.fn();
65
+ const t = new Throttler(100);
66
+ t.debounce(fn);
67
+ vi.advanceTimersByTime(80);
68
+ t.debounce(fn);
69
+ vi.advanceTimersByTime(80);
70
+ expect(fn).not.toHaveBeenCalled();
71
+ vi.advanceTimersByTime(30);
72
+ expect(fn).toHaveBeenCalledTimes(1);
73
+ });
74
+ it('calls fn only once after many rapid invocations', () => {
75
+ const fn = vi.fn();
76
+ const t = new Throttler(100);
77
+ for (let i = 0; i < 10; i++) {
78
+ t.debounce(fn);
79
+ }
80
+ vi.advanceTimersByTime(200);
81
+ expect(fn).toHaveBeenCalledTimes(1);
82
+ });
83
+ it('fires a second call correctly after the first has resolved', () => {
84
+ const fn = vi.fn();
85
+ const t = new Throttler(100);
86
+ t.debounce(fn);
87
+ vi.advanceTimersByTime(150);
88
+ t.debounce(fn);
89
+ vi.advanceTimersByTime(150);
90
+ expect(fn).toHaveBeenCalledTimes(2);
91
+ });
92
+ });
93
+ // -------------------------------------------------------------------------
94
+ // delayAsync
95
+ // -------------------------------------------------------------------------
96
+ describe('delayAsync', () => {
97
+ it('does not invoke fn before the delay', async () => {
98
+ const fn = vi.fn().mockResolvedValue('x');
99
+ const t = new Throttler(100);
100
+ t.delayAsync(fn);
101
+ expect(fn).not.toHaveBeenCalled();
102
+ });
103
+ it('resolves with the return value of fn', async () => {
104
+ const fn = vi.fn().mockResolvedValue('result');
105
+ const t = new Throttler(100);
106
+ const promise = t.delayAsync(fn);
107
+ vi.advanceTimersByTime(100);
108
+ await expect(promise).resolves.toBe('result');
109
+ });
110
+ it('passes variadic arguments through to fn', async () => {
111
+ const fn = vi.fn().mockImplementation(async (a, b) => a + b);
112
+ const t = new Throttler(100);
113
+ const promise = t.delayAsync(fn, 3, 4);
114
+ vi.advanceTimersByTime(100);
115
+ await expect(promise).resolves.toBe(7);
116
+ });
117
+ it('rejects when fn throws', async () => {
118
+ const fn = vi.fn().mockRejectedValue(new Error('boom'));
119
+ const t = new Throttler(100);
120
+ const promise = t.delayAsync(fn);
121
+ vi.advanceTimersByTime(100);
122
+ await expect(promise).rejects.toThrow('boom');
123
+ });
124
+ it('cancels the previous pending call when invoked again', async () => {
125
+ const fn = vi.fn().mockResolvedValue(42);
126
+ const t = new Throttler(100);
127
+ t.delayAsync(fn);
128
+ vi.advanceTimersByTime(50);
129
+ const second = t.delayAsync(fn);
130
+ vi.advanceTimersByTime(100);
131
+ await expect(second).resolves.toBe(42);
132
+ expect(fn).toHaveBeenCalledTimes(1);
133
+ });
134
+ });
135
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,140 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { checkArgsAreFilled, getArgsByContext, getOptionsByContext, operationReady } from './actionUtils';
3
+ // ---------------------------------------------------------------------------
4
+ // Helpers
5
+ // ---------------------------------------------------------------------------
6
+ const makeStep = (args, options = {}) => ({
7
+ args,
8
+ options,
9
+ validation: {}
10
+ });
11
+ const makeAction = (steps) => ({
12
+ id: 'test-action',
13
+ title: 'Test Action',
14
+ i18nKey: 'test.action',
15
+ description: { short: '', long: '' },
16
+ roles: [],
17
+ steps,
18
+ triggers: []
19
+ });
20
+ // ---------------------------------------------------------------------------
21
+ // checkArgsAreFilled
22
+ // ---------------------------------------------------------------------------
23
+ describe('checkArgsAreFilled', () => {
24
+ it('returns false when values is empty/falsy', () => {
25
+ const step = makeStep({ status: [] });
26
+ expect(checkArgsAreFilled(step, '')).toBe(false);
27
+ });
28
+ it('returns true when all required args are present and truthy', () => {
29
+ const step = makeStep({ status: [] });
30
+ expect(checkArgsAreFilled(step, JSON.stringify({ status: 'open' }))).toBe(true);
31
+ });
32
+ it('returns false when a required arg is missing from values', () => {
33
+ const step = makeStep({ status: [], assignment: [] });
34
+ expect(checkArgsAreFilled(step, JSON.stringify({ status: 'open' }))).toBe(false);
35
+ });
36
+ it('returns false when a required arg is present but falsy (empty string)', () => {
37
+ const step = makeStep({ status: [] });
38
+ expect(checkArgsAreFilled(step, JSON.stringify({ status: '' }))).toBe(false);
39
+ });
40
+ it('returns true when there are no required args', () => {
41
+ const step = makeStep({});
42
+ expect(checkArgsAreFilled(step, JSON.stringify({}))).toBe(true);
43
+ });
44
+ });
45
+ // ---------------------------------------------------------------------------
46
+ // getOptionsByContext
47
+ // ---------------------------------------------------------------------------
48
+ describe('getOptionsByContext', () => {
49
+ it('returns an empty array when the arg is not in options', () => {
50
+ const options = {};
51
+ expect(getOptionsByContext(options, 'status', '{}')).toEqual([]);
52
+ });
53
+ it('returns the full list when the arg maps to a plain array', () => {
54
+ const options = { status: ['open', 'in-progress', 'resolved'] };
55
+ expect(getOptionsByContext(options, 'status', '{}')).toEqual(['open', 'in-progress', 'resolved']);
56
+ });
57
+ it('returns options matching the current context when arg has conditional options', () => {
58
+ const options = {
59
+ assessment: {
60
+ 'status:open': ['false_positive', 'legitimate'],
61
+ 'status:resolved': ['correct']
62
+ }
63
+ };
64
+ const context = JSON.stringify({ status: 'open' });
65
+ expect(getOptionsByContext(options, 'assessment', context)).toEqual(['false_positive', 'legitimate']);
66
+ });
67
+ it('returns an empty array when context does not match any conditional key', () => {
68
+ const options = {
69
+ assessment: {
70
+ 'status:open': ['false_positive']
71
+ }
72
+ };
73
+ const context = JSON.stringify({ status: 'resolved' });
74
+ expect(getOptionsByContext(options, 'assessment', context)).toEqual([]);
75
+ });
76
+ });
77
+ // ---------------------------------------------------------------------------
78
+ // getArgsByContext
79
+ // ---------------------------------------------------------------------------
80
+ describe('getArgsByContext', () => {
81
+ it('always returns an arg with an empty conditions array', () => {
82
+ const args = { status: [] };
83
+ expect(getArgsByContext(args, '{}')).toContain('status');
84
+ });
85
+ it('includes an arg whose condition matches the current context', () => {
86
+ const args = { assessment: ['status:open'] };
87
+ const values = JSON.stringify({ status: 'open' });
88
+ expect(getArgsByContext(args, values)).toContain('assessment');
89
+ });
90
+ it('excludes an arg whose condition does not match the current context', () => {
91
+ const args = { assessment: ['status:open'] };
92
+ const values = JSON.stringify({ status: 'resolved' });
93
+ expect(getArgsByContext(args, values)).not.toContain('assessment');
94
+ });
95
+ it('includes an arg when any one of multiple conditions matches (OR logic)', () => {
96
+ const args = { rationale: ['status:open', 'status:in-progress'] };
97
+ const values = JSON.stringify({ status: 'in-progress' });
98
+ expect(getArgsByContext(args, values)).toContain('rationale');
99
+ });
100
+ it('returns an empty array when no args match', () => {
101
+ const args = { assessment: ['status:open'] };
102
+ const values = JSON.stringify({ status: 'resolved' });
103
+ expect(getArgsByContext(args, values)).toEqual([]);
104
+ });
105
+ });
106
+ // ---------------------------------------------------------------------------
107
+ // operationReady
108
+ // ---------------------------------------------------------------------------
109
+ describe('operationReady', () => {
110
+ it('returns false when data is null/falsy', () => {
111
+ const action = makeAction([makeStep({ status: [] })]);
112
+ expect(operationReady(null, action)).toBe(false);
113
+ });
114
+ it('returns falsy when action is falsy', () => {
115
+ expect(operationReady(JSON.stringify({ status: 'open' }), null)).toBeFalsy();
116
+ });
117
+ it('returns true when all unconditional args are present', () => {
118
+ const action = makeAction([makeStep({ status: [] })]);
119
+ const data = JSON.stringify({ status: 'open' });
120
+ expect(operationReady(data, action)).toBe(true);
121
+ });
122
+ it('returns false when a required unconditional arg is missing', () => {
123
+ const action = makeAction([makeStep({ status: [], assessment: [] })]);
124
+ const data = JSON.stringify({ status: 'open' });
125
+ expect(operationReady(data, action)).toBe(false);
126
+ });
127
+ it('ignores conditional args that do not apply in the current context', () => {
128
+ // assessment only required when status=open; here status=resolved so assessment is not required
129
+ const action = makeAction([makeStep({ status: [], assessment: ['status:open'] })]);
130
+ const data = JSON.stringify({ status: 'resolved' });
131
+ expect(operationReady(data, action)).toBe(true);
132
+ });
133
+ it('merges args across multiple steps', () => {
134
+ const step1 = makeStep({ status: [] });
135
+ const step2 = makeStep({ assignment: [] });
136
+ const action = makeAction([step1, step2]);
137
+ const data = JSON.stringify({ status: 'open', assignment: 'alice' });
138
+ expect(operationReady(data, action)).toBe(true);
139
+ });
140
+ });
@@ -5,9 +5,9 @@ export declare const VERSION: any;
5
5
  export declare const MY_LOCAL_STORAGE_PREFIX = "howler.ui";
6
6
  export declare const MY_SESSION_STORAGE_PREFIX = "howler.ui.cache";
7
7
  export declare const ESCALATION_COLORS: {
8
- alert: string;
9
- evidence: string;
10
- hit: string;
8
+ alert: "warning";
9
+ evidence: "error";
10
+ hit: "primary";
11
11
  };
12
12
  export declare const STATUS_COLORS: {
13
13
  open: string;
@@ -49,6 +49,7 @@ export declare enum StorageKey {
49
49
  COMPACT_JSON = "compact_json_view",
50
50
  FLATTEN_JSON = "flatten_json_view",
51
51
  FORCE_DRAWER = "force_drawer",
52
+ SHOW_HIT_SUMMARY_GRAPH = "show_hit_summary_graph",
52
53
  LAST_VIEW = "last_view",
53
54
  ONLY_RULES = "only_rules",
54
55
  PAGE_COUNT = "page_count",
@@ -74,6 +75,7 @@ export declare const RULE_INTERVALS: {
74
75
  crontab: string;
75
76
  }[];
76
77
  export declare const DATE_RANGES: string[];
78
+ export declare const DATE_RANGE_LUCENE: Partial<Record<(typeof DATE_RANGES)[number], string>>;
77
79
  interface LabelData {
78
80
  icon?: ReactElement;
79
81
  color?: string;
@@ -54,6 +54,7 @@ export var StorageKey;
54
54
  StorageKey["COMPACT_JSON"] = "compact_json_view";
55
55
  StorageKey["FLATTEN_JSON"] = "flatten_json_view";
56
56
  StorageKey["FORCE_DRAWER"] = "force_drawer";
57
+ StorageKey["SHOW_HIT_SUMMARY_GRAPH"] = "show_hit_summary_graph";
57
58
  StorageKey["LAST_VIEW"] = "last_view";
58
59
  StorageKey["ONLY_RULES"] = "only_rules";
59
60
  StorageKey["PAGE_COUNT"] = "page_count";
@@ -104,6 +105,12 @@ export const DATE_RANGES = [
104
105
  'date.range.all',
105
106
  'date.range.custom'
106
107
  ];
108
+ export const DATE_RANGE_LUCENE = {
109
+ 'date.range.1.day': 'now-1d/d',
110
+ 'date.range.3.day': 'now-3d/d',
111
+ 'date.range.1.week': 'now-7d/d',
112
+ 'date.range.1.month': 'now-1M/M'
113
+ };
107
114
  export const LABEL_TYPES = {
108
115
  insight: { icon: _jsx(PsychologyAlt, { fontSize: "small" }), color: '#FFFFFF' }, //brain icon
109
116
  mitigation: { icon: _jsx(LocalPolice, { fontSize: "small" }), color: blue[600] }, //police badge
@@ -1,2 +1,3 @@
1
1
  import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
- export declare const getUserList: (hit: Hit) => Set<string>;
2
+ import type { Observable } from '@cccsaurora/howler-ui/models/entities/generated/Observable';
3
+ export declare const getUserList: (record: Hit | Observable) => Set<string>;
@@ -1,8 +1,8 @@
1
- export const getUserList = (hit) => {
1
+ export const getUserList = (record) => {
2
2
  const ids = new Set();
3
- if (hit) {
4
- hit.howler?.log?.forEach(l => ids.add(l.user));
5
- hit.howler?.comment?.forEach(c => ids.add(c.user), ids);
3
+ if (record) {
4
+ record.howler?.log?.forEach(l => ids.add(l.user));
5
+ record.howler?.comment?.forEach(c => ids.add(c.user), ids);
6
6
  }
7
7
  return ids;
8
8
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getUserList } from './hitFunctions';
3
+ const makeHit = (howlerOverrides = {}) => ({
4
+ howler: {
5
+ log: [],
6
+ comment: [],
7
+ ...howlerOverrides
8
+ }
9
+ });
10
+ describe('getUserList', () => {
11
+ it('returns an empty Set when the hit is null', () => {
12
+ expect(getUserList(null)).toEqual(new Set());
13
+ });
14
+ it('returns an empty Set when the hit is undefined', () => {
15
+ expect(getUserList(undefined)).toEqual(new Set());
16
+ });
17
+ it('returns an empty Set when both log and comment are empty', () => {
18
+ expect(getUserList(makeHit())).toEqual(new Set());
19
+ });
20
+ it('collects users from the log array', () => {
21
+ const hit = makeHit({ log: [{ user: 'alice' }, { user: 'bob' }] });
22
+ expect(getUserList(hit)).toEqual(new Set(['alice', 'bob']));
23
+ });
24
+ it('collects users from the comment array', () => {
25
+ const hit = makeHit({ comment: [{ user: 'carol' }] });
26
+ expect(getUserList(hit)).toEqual(new Set(['carol']));
27
+ });
28
+ it('collects users from both log and comment', () => {
29
+ const hit = makeHit({
30
+ log: [{ user: 'alice' }],
31
+ comment: [{ user: 'bob' }]
32
+ });
33
+ expect(getUserList(hit)).toEqual(new Set(['alice', 'bob']));
34
+ });
35
+ it('deduplicates users that appear in both arrays', () => {
36
+ const hit = makeHit({
37
+ log: [{ user: 'alice' }],
38
+ comment: [{ user: 'alice' }]
39
+ });
40
+ const result = getUserList(hit);
41
+ expect(result).toEqual(new Set(['alice']));
42
+ expect(result.size).toBe(1);
43
+ });
44
+ it('deduplicates users that appear multiple times in the same array', () => {
45
+ const hit = makeHit({ log: [{ user: 'alice' }, { user: 'alice' }] });
46
+ expect(getUserList(hit).size).toBe(1);
47
+ });
48
+ it('handles a hit with no howler field gracefully', () => {
49
+ const hit = {};
50
+ expect(getUserList(hit)).toEqual(new Set());
51
+ });
52
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,96 @@
1
+ /// <reference types="vitest" />
2
+ import { afterEach, describe, expect, it } from 'vitest';
3
+ import { StorageKey } from './constants';
4
+ import { getStored, removeStored, saveLoginCredential, setStored } from './localStorage';
5
+ const PREFIX = 'howler.ui';
6
+ describe('localStorage utilities', () => {
7
+ afterEach(() => {
8
+ localStorage.clear();
9
+ });
10
+ // -------------------------------------------------------------------------
11
+ // setStored / getStored
12
+ // -------------------------------------------------------------------------
13
+ describe('setStored / getStored', () => {
14
+ it('stores and retrieves a string value', () => {
15
+ setStored(StorageKey.USERNAME, 'alice');
16
+ expect(getStored(StorageKey.USERNAME)).toBe('alice');
17
+ });
18
+ it('stores and retrieves an object value', () => {
19
+ const value = { token: 'abc', expires: 123 };
20
+ setStored(StorageKey.APP_TOKEN, value);
21
+ expect(getStored(StorageKey.APP_TOKEN)).toEqual(value);
22
+ });
23
+ it('uses the prefixed key in the underlying localStorage', () => {
24
+ setStored(StorageKey.USERNAME, 'bob');
25
+ expect(localStorage.getItem(`${PREFIX}.${StorageKey.USERNAME}`)).toBe(JSON.stringify('bob'));
26
+ });
27
+ it('returns null for a key that has not been set', () => {
28
+ expect(getStored(StorageKey.USERNAME)).toBeNull();
29
+ });
30
+ it('overwrites an existing value', () => {
31
+ setStored(StorageKey.USERNAME, 'alice');
32
+ setStored(StorageKey.USERNAME, 'bob');
33
+ expect(getStored(StorageKey.USERNAME)).toBe('bob');
34
+ });
35
+ it('stores a number value', () => {
36
+ setStored(StorageKey.PAGE_COUNT, 25);
37
+ expect(getStored(StorageKey.PAGE_COUNT)).toBe(25);
38
+ });
39
+ });
40
+ // -------------------------------------------------------------------------
41
+ // removeStored
42
+ // -------------------------------------------------------------------------
43
+ describe('removeStored', () => {
44
+ it('removes an existing key so it returns null on subsequent reads', () => {
45
+ setStored(StorageKey.USERNAME, 'alice');
46
+ removeStored(StorageKey.USERNAME);
47
+ expect(getStored(StorageKey.USERNAME)).toBeNull();
48
+ });
49
+ it('does not throw when removing a key that was never stored', () => {
50
+ expect(() => removeStored(StorageKey.USERNAME)).not.toThrow();
51
+ });
52
+ it('removes only the targeted key and leaves others intact', () => {
53
+ setStored(StorageKey.USERNAME, 'alice');
54
+ setStored(StorageKey.PROVIDER, 'howler');
55
+ removeStored(StorageKey.USERNAME);
56
+ expect(getStored(StorageKey.USERNAME)).toBeNull();
57
+ expect(getStored(StorageKey.PROVIDER)).toBe('howler');
58
+ });
59
+ });
60
+ // -------------------------------------------------------------------------
61
+ // saveLoginCredential
62
+ // -------------------------------------------------------------------------
63
+ describe('saveLoginCredential', () => {
64
+ it('returns true and stores app_token when app_token is present', () => {
65
+ const result = saveLoginCredential({ app_token: 'tok123' });
66
+ expect(result).toBe(true);
67
+ expect(getStored(StorageKey.APP_TOKEN)).toBe('tok123');
68
+ });
69
+ it('also stores refresh_token and provider when they are present', () => {
70
+ saveLoginCredential({ app_token: 'tok', refresh_token: 'ref', provider: 'howler' });
71
+ expect(getStored(StorageKey.REFRESH_TOKEN)).toBe('ref');
72
+ expect(getStored(StorageKey.PROVIDER)).toBe('howler');
73
+ });
74
+ it('does not store refresh_token when it is absent', () => {
75
+ saveLoginCredential({ app_token: 'tok' });
76
+ expect(getStored(StorageKey.REFRESH_TOKEN)).toBeNull();
77
+ });
78
+ it('returns false and clears stored tokens when app_token is absent', () => {
79
+ setStored(StorageKey.APP_TOKEN, 'old-token');
80
+ setStored(StorageKey.REFRESH_TOKEN, 'old-refresh');
81
+ const result = saveLoginCredential({});
82
+ expect(result).toBe(false);
83
+ expect(getStored(StorageKey.APP_TOKEN)).toBeNull();
84
+ expect(getStored(StorageKey.REFRESH_TOKEN)).toBeNull();
85
+ });
86
+ it('clears APP_TOKEN, REFRESH_TOKEN, and PROVIDER on empty credential', () => {
87
+ setStored(StorageKey.APP_TOKEN, 't');
88
+ setStored(StorageKey.REFRESH_TOKEN, 'r');
89
+ setStored(StorageKey.PROVIDER, 'p');
90
+ saveLoginCredential({});
91
+ expect(getStored(StorageKey.APP_TOKEN)).toBeNull();
92
+ expect(getStored(StorageKey.REFRESH_TOKEN)).toBeNull();
93
+ expect(getStored(StorageKey.PROVIDER)).toBeNull();
94
+ });
95
+ });
96
+ });
@@ -1,5 +1,5 @@
1
- import { MainMenuInsertOperation } from '../plugins/store';
2
1
  import { isNil } from 'lodash-es';
2
+ import { MainMenuInsertOperation } from '../plugins/store';
3
3
  class AppMenuBuilder {
4
4
  items;
5
5
  indexMap;
@@ -0,0 +1 @@
1
+ export {};