@cccsaurora/howler-ui 2.19.0-dev.1151 → 2.19.0-dev.1260

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 (419) hide show
  1. package/api/analytic/index.d.ts +2 -3
  2. package/api/analytic/index.js +1 -2
  3. package/api/index.d.ts +4 -0
  4. package/api/index.js +10 -2
  5. package/api/search/case.d.ts +4 -0
  6. package/api/search/case.js +8 -0
  7. package/api/search/facet/hit.d.ts +1 -3
  8. package/api/search/facet/index.d.ts +3 -1
  9. package/api/search/index.d.ts +3 -1
  10. package/api/search/index.js +2 -1
  11. package/api/socket/index.d.ts +3 -0
  12. package/api/socket/index.js +6 -0
  13. package/api/socket/viewers.d.ts +2 -0
  14. package/api/socket/viewers.js +8 -0
  15. package/api/socket/viewers.test.js +44 -0
  16. package/api/v2/case/index.d.ts +9 -0
  17. package/api/v2/case/index.js +21 -0
  18. package/api/v2/case/items.d.ts +9 -0
  19. package/api/v2/case/items.js +19 -0
  20. package/api/v2/case/rules.d.ts +6 -0
  21. package/api/v2/case/rules.js +18 -0
  22. package/api/v2/fuzzy.d.ts +17 -0
  23. package/api/v2/fuzzy.js +11 -0
  24. package/api/v2/index.d.ts +5 -0
  25. package/api/v2/index.js +7 -0
  26. package/api/v2/search/facet.d.ts +3 -0
  27. package/api/v2/search/facet.js +12 -0
  28. package/api/v2/search/index.d.ts +6 -0
  29. package/api/v2/search/index.js +24 -0
  30. package/commons/components/leftnav/LeftNavDrawer.js +1 -1
  31. package/components/app/App.js +49 -11
  32. package/components/app/hooks/useMatchers.d.ts +1 -1
  33. package/components/app/hooks/useMatchers.js +23 -11
  34. package/components/app/hooks/useMatchers.test.js +22 -22
  35. package/components/app/hooks/useTitle.js +5 -5
  36. package/components/app/providers/FavouritesProvider.js +2 -2
  37. package/components/app/providers/GridColumnsProvider.js +2 -2
  38. package/components/app/providers/GridColumnsProvider.test.js +3 -3
  39. package/components/app/providers/ModalProvider.d.ts +1 -0
  40. package/components/app/providers/ParameterProvider.d.ts +25 -3
  41. package/components/app/providers/ParameterProvider.js +163 -226
  42. package/components/app/providers/ParameterProvider.test.js +358 -94
  43. package/components/app/providers/RecordProvider.d.ts +23 -0
  44. package/components/app/providers/{HitProvider.js → RecordProvider.js} +46 -42
  45. package/components/app/providers/{HitSearchProvider.d.ts → RecordSearchProvider.d.ts} +6 -6
  46. package/components/app/providers/{HitSearchProvider.js → RecordSearchProvider.js} +22 -35
  47. package/components/app/providers/{HitSearchProvider.test.js → RecordSearchProvider.test.js} +52 -71
  48. package/components/app/providers/SearchResponseProvider.d.ts +4 -4
  49. package/components/app/providers/SearchResponseProvider.js +1 -1
  50. package/components/app/providers/SocketProvider.d.ts +11 -2
  51. package/components/app/providers/SocketProvider.js +18 -5
  52. package/components/app/providers/UserListProvider.js +28 -8
  53. package/components/app/providers/UserListProvider.test.js +150 -0
  54. package/components/elements/ContextMenu.d.ts +56 -0
  55. package/components/elements/ContextMenu.js +109 -0
  56. package/components/elements/ContextMenu.test.d.ts +1 -0
  57. package/components/elements/ContextMenu.test.js +215 -0
  58. package/components/{routes/overviews/OverviewEditor.js → elements/MarkdownEditor.js} +3 -3
  59. package/components/elements/ObjectDetails.d.ts +6 -0
  60. package/components/elements/{hit/HitDetails.js → ObjectDetails.js} +17 -17
  61. package/components/elements/PluginChip.d.ts +1 -1
  62. package/components/elements/PluginChip.js +0 -1
  63. package/components/elements/PluginTypography.d.ts +2 -1
  64. package/components/elements/PluginTypography.js +3 -2
  65. package/components/elements/UserList.d.ts +5 -2
  66. package/components/elements/UserList.js +33 -16
  67. package/components/elements/UserList.test.d.ts +1 -0
  68. package/components/elements/UserList.test.js +122 -0
  69. package/components/elements/addons/lists/TuiListElement.d.ts +1 -1
  70. package/components/elements/addons/lists/TuiListElement.js +0 -1
  71. package/components/elements/addons/search/SearchTotal.js +1 -1
  72. package/components/elements/addons/search/SearchTotal.test.js +2 -2
  73. package/components/elements/addons/search/phrase/Phrase.js +1 -1
  74. package/components/elements/case/CaseCard.d.ts +12 -0
  75. package/components/elements/case/CaseCard.js +43 -0
  76. package/components/elements/case/CasePreview.d.ts +6 -0
  77. package/components/elements/case/CasePreview.js +17 -0
  78. package/components/elements/case/StatusIcon.d.ts +5 -0
  79. package/components/elements/case/StatusIcon.js +13 -0
  80. package/components/elements/display/ChipPopper.d.ts +1 -1
  81. package/components/elements/display/ChipPopper.js +6 -5
  82. package/components/elements/display/Classification.js +1 -1
  83. package/components/elements/display/ClassificationChip.d.ts +14 -0
  84. package/components/elements/display/ClassificationChip.js +36 -0
  85. package/components/elements/display/HowlerCard.js +1 -1
  86. package/components/elements/display/HowlerCard.test.js +5 -9
  87. package/components/elements/display/ItemManager.js +2 -2
  88. package/components/elements/display/Modal.js +2 -0
  89. package/components/elements/display/QueryResultText.d.ts +1 -0
  90. package/components/elements/display/QueryResultText.js +2 -2
  91. package/components/elements/event/EventCard.d.ts +6 -0
  92. package/components/elements/event/EventCard.js +22 -0
  93. package/components/elements/event/EventPreview.d.ts +6 -0
  94. package/components/elements/event/EventPreview.js +12 -0
  95. package/components/elements/hit/HitActions.js +4 -4
  96. package/components/elements/hit/HitBanner.d.ts +1 -0
  97. package/components/elements/hit/HitBanner.js +31 -49
  98. package/components/elements/hit/HitCard.d.ts +4 -0
  99. package/components/elements/hit/HitCard.js +7 -7
  100. package/components/elements/hit/HitLabels.js +2 -2
  101. package/components/elements/hit/HitLabels.test.js +2 -2
  102. package/components/elements/hit/HitOutline.d.ts +1 -0
  103. package/components/elements/hit/HitOutline.js +3 -3
  104. package/components/elements/hit/{HitQuickSearch.d.ts → HitPreview.d.ts} +3 -3
  105. package/components/elements/hit/{HitQuickSearch.js → HitPreview.js} +10 -4
  106. package/components/elements/hit/HitSummary.d.ts +2 -1
  107. package/components/elements/hit/HitSummary.js +6 -5
  108. package/components/elements/hit/aggregate/HitGraph.js +8 -8
  109. package/components/elements/hit/elements/AnalyticLink.d.ts +9 -0
  110. package/components/elements/hit/elements/AnalyticLink.js +22 -0
  111. package/components/elements/hit/elements/{HitUsers.d.ts → Assigned.d.ts} +3 -4
  112. package/components/elements/hit/elements/Assigned.js +36 -0
  113. package/components/elements/hit/elements/Assigned.test.d.ts +1 -0
  114. package/components/elements/hit/elements/Assigned.test.js +65 -0
  115. package/components/elements/hit/grid/AddColumnModal.js +5 -4
  116. package/components/elements/hit/grid/EnhancedCell.d.ts +2 -1
  117. package/components/elements/hit/grid/EnhancedCell.js +2 -2
  118. package/components/elements/hit/grid/{HitRow.d.ts → RecordRow.d.ts} +3 -2
  119. package/components/elements/hit/grid/{HitRow.js → RecordRow.js} +11 -9
  120. package/components/elements/hit/grid/{HitTable.d.ts → RecordTable.d.ts} +5 -4
  121. package/components/elements/hit/grid/{HitTable.js → RecordTable.js} +13 -11
  122. package/components/elements/hit/outlines/DefaultOutline.js +1 -1
  123. package/components/elements/hit/related/RelatedRecords.js +63 -0
  124. package/components/elements/{hit/HitComments.d.ts → record/RecordComments.d.ts} +5 -4
  125. package/components/elements/{hit/HitComments.js → record/RecordComments.js} +29 -28
  126. package/components/elements/{hit/HitContextMenu.d.ts → record/RecordContextMenu.d.ts} +3 -3
  127. package/components/elements/record/RecordContextMenu.js +268 -0
  128. package/components/elements/record/RecordContextMenu.test.d.ts +1 -0
  129. package/components/elements/{hit/HitContextMenu.test.js → record/RecordContextMenu.test.js} +98 -43
  130. package/components/elements/record/RecordRelated.d.ts +7 -0
  131. package/components/elements/record/RecordRelated.js +34 -0
  132. package/components/elements/{hit/HitWorklog.d.ts → record/RecordWorklog.d.ts} +4 -3
  133. package/components/elements/{hit/HitWorklog.js → record/RecordWorklog.js} +15 -13
  134. package/components/elements/search/FuzzySearchBar.d.ts +7 -0
  135. package/components/elements/search/FuzzySearchBar.js +33 -0
  136. package/components/elements/search/FuzzySearchBar.test.d.ts +1 -0
  137. package/components/elements/search/FuzzySearchBar.test.js +87 -0
  138. package/components/elements/view/ViewTitle.d.ts +1 -0
  139. package/components/elements/view/ViewTitle.js +9 -2
  140. package/components/hooks/useHitActions.d.ts +1 -1
  141. package/components/hooks/useHitActions.js +4 -4
  142. package/components/hooks/useMyPreferences.js +10 -1
  143. package/components/hooks/useMySearch.js +2 -2
  144. package/components/hooks/useMySitemap.js +4 -1
  145. package/components/hooks/useMyTheme.js +9 -2
  146. package/components/hooks/{useHitSelection.d.ts → useRecordSelection.d.ts} +2 -2
  147. package/components/hooks/{useHitSelection.js → useRecordSelection.js} +12 -33
  148. package/components/hooks/useRelatedRecords.d.ts +13 -0
  149. package/components/hooks/useRelatedRecords.js +32 -0
  150. package/components/routes/action/edit/ActionEditor.js +2 -2
  151. package/components/routes/action/view/ActionSearch.js +1 -1
  152. package/components/routes/advanced/QueryBuilder.js +4 -27
  153. package/components/routes/advanced/QueryEditor.js +3 -3
  154. package/components/routes/advanced/historyCompletionProvider.js +3 -3
  155. package/components/routes/analytics/AnalyticDetails.js +6 -54
  156. package/components/routes/analytics/AnalyticSearch.js +9 -18
  157. package/components/routes/cases/CaseViewer.d.ts +2 -0
  158. package/components/routes/cases/CaseViewer.js +44 -0
  159. package/components/routes/cases/CaseViewer.test.d.ts +1 -0
  160. package/components/routes/cases/CaseViewer.test.js +133 -0
  161. package/components/routes/cases/Cases.d.ts +2 -0
  162. package/components/routes/cases/Cases.js +140 -0
  163. package/components/routes/cases/constants.d.ts +6 -0
  164. package/components/routes/cases/constants.js +6 -0
  165. package/components/routes/cases/detail/AlertPanel.d.ts +6 -0
  166. package/components/routes/cases/detail/AlertPanel.js +33 -0
  167. package/components/routes/cases/detail/AlertPanel.test.d.ts +1 -0
  168. package/components/routes/cases/detail/AlertPanel.test.js +107 -0
  169. package/components/routes/cases/detail/CaseDashboard.d.ts +7 -0
  170. package/components/routes/cases/detail/CaseDashboard.js +66 -0
  171. package/components/routes/cases/detail/CaseDashboard.test.d.ts +1 -0
  172. package/components/routes/cases/detail/CaseDashboard.test.js +218 -0
  173. package/components/routes/cases/detail/CaseDetails.d.ts +6 -0
  174. package/components/routes/cases/detail/CaseDetails.js +79 -0
  175. package/components/routes/cases/detail/CaseDetails.test.d.ts +1 -0
  176. package/components/routes/cases/detail/CaseDetails.test.js +145 -0
  177. package/components/routes/cases/detail/CaseObservables.d.ts +6 -0
  178. package/components/routes/cases/detail/CaseObservables.js +142 -0
  179. package/components/routes/cases/detail/CaseObservables.test.d.ts +1 -0
  180. package/components/routes/cases/detail/CaseObservables.test.js +169 -0
  181. package/components/routes/cases/detail/CaseOverview.d.ts +7 -0
  182. package/components/routes/cases/detail/CaseOverview.js +43 -0
  183. package/components/routes/cases/detail/CaseRules.d.ts +7 -0
  184. package/components/routes/cases/detail/CaseRules.js +55 -0
  185. package/components/routes/cases/detail/CaseRules.test.d.ts +1 -0
  186. package/components/routes/cases/detail/CaseRules.test.js +238 -0
  187. package/components/routes/cases/detail/CaseSearch.d.ts +3 -0
  188. package/components/routes/cases/detail/CaseSearch.js +78 -0
  189. package/components/routes/cases/detail/CaseSearch.test.d.ts +1 -0
  190. package/components/routes/cases/detail/CaseSearch.test.js +154 -0
  191. package/components/routes/cases/detail/CaseSidebar.d.ts +8 -0
  192. package/components/routes/cases/detail/CaseSidebar.js +147 -0
  193. package/components/routes/cases/detail/CaseSidebar.test.d.ts +1 -0
  194. package/components/routes/cases/detail/CaseSidebar.test.js +155 -0
  195. package/components/routes/cases/detail/CaseTask.d.ts +14 -0
  196. package/components/routes/cases/detail/CaseTask.js +71 -0
  197. package/components/routes/cases/detail/CaseTask.test.d.ts +1 -0
  198. package/components/routes/cases/detail/CaseTask.test.js +143 -0
  199. package/components/routes/cases/detail/CaseTimeline.d.ts +12 -0
  200. package/components/routes/cases/detail/CaseTimeline.js +106 -0
  201. package/components/routes/cases/detail/CaseTimeline.test.d.ts +1 -0
  202. package/components/routes/cases/detail/CaseTimeline.test.js +320 -0
  203. package/components/routes/cases/detail/CreateRuleDialog.d.ts +9 -0
  204. package/components/routes/cases/detail/CreateRuleDialog.js +145 -0
  205. package/components/routes/cases/detail/CreateRuleDialog.test.d.ts +1 -0
  206. package/components/routes/cases/detail/CreateRuleDialog.test.js +284 -0
  207. package/components/routes/cases/detail/ItemPage.d.ts +6 -0
  208. package/components/routes/cases/detail/ItemPage.js +100 -0
  209. package/components/routes/cases/detail/ItemPage.test.d.ts +1 -0
  210. package/components/routes/cases/detail/ItemPage.test.js +238 -0
  211. package/components/routes/cases/detail/MarkdownPage.d.ts +8 -0
  212. package/components/routes/cases/detail/MarkdownPage.js +63 -0
  213. package/components/routes/cases/detail/MarkdownPage.test.d.ts +1 -0
  214. package/components/routes/cases/detail/MarkdownPage.test.js +116 -0
  215. package/components/routes/cases/detail/RelatedCasePanel.d.ts +6 -0
  216. package/components/routes/cases/detail/RelatedCasePanel.js +34 -0
  217. package/components/routes/cases/detail/RelatedCasePanel.test.d.ts +1 -0
  218. package/components/routes/cases/detail/RelatedCasePanel.test.js +115 -0
  219. package/components/routes/cases/detail/TaskPanel.d.ts +7 -0
  220. package/components/routes/cases/detail/TaskPanel.js +95 -0
  221. package/components/routes/cases/detail/TaskPanel.test.d.ts +1 -0
  222. package/components/routes/cases/detail/TaskPanel.test.js +145 -0
  223. package/components/routes/cases/detail/aggregates/CaseAggregate.d.ts +11 -0
  224. package/components/routes/cases/detail/aggregates/CaseAggregate.js +24 -0
  225. package/components/routes/cases/detail/aggregates/SourceAggregate.d.ts +6 -0
  226. package/components/routes/cases/detail/aggregates/SourceAggregate.js +26 -0
  227. package/components/routes/cases/detail/observables/Observable.d.ts +8 -0
  228. package/components/routes/cases/detail/observables/Observable.js +13 -0
  229. package/components/routes/cases/detail/observables/Observable.test.d.ts +1 -0
  230. package/components/routes/cases/detail/observables/Observable.test.js +72 -0
  231. package/components/routes/cases/detail/observables/ObservableTable.d.ts +7 -0
  232. package/components/routes/cases/detail/observables/ObservableTable.js +61 -0
  233. package/components/routes/cases/detail/observables/ObservableTable.test.d.ts +1 -0
  234. package/components/routes/cases/detail/observables/ObservableTable.test.js +85 -0
  235. package/components/routes/cases/detail/sidebar/CaseFolder.d.ts +22 -0
  236. package/components/routes/cases/detail/sidebar/CaseFolder.js +105 -0
  237. package/components/routes/cases/detail/sidebar/CaseFolder.test.d.ts +1 -0
  238. package/components/routes/cases/detail/sidebar/CaseFolder.test.js +98 -0
  239. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.d.ts +32 -0
  240. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.js +99 -0
  241. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.d.ts +1 -0
  242. package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.js +117 -0
  243. package/components/routes/cases/detail/sidebar/FolderEntry.d.ts +25 -0
  244. package/components/routes/cases/detail/sidebar/FolderEntry.js +89 -0
  245. package/components/routes/cases/detail/sidebar/FolderEntry.test.d.ts +1 -0
  246. package/components/routes/cases/detail/sidebar/FolderEntry.test.js +81 -0
  247. package/components/routes/cases/detail/sidebar/RootDropZone.d.ts +5 -0
  248. package/components/routes/cases/detail/sidebar/RootDropZone.js +33 -0
  249. package/components/routes/cases/detail/sidebar/types.d.ts +9 -0
  250. package/components/routes/cases/detail/sidebar/utils.d.ts +10 -0
  251. package/components/routes/cases/detail/sidebar/utils.js +51 -0
  252. package/components/routes/cases/detail/sidebar/utils.test.d.ts +1 -0
  253. package/components/routes/cases/detail/sidebar/utils.test.js +82 -0
  254. package/components/routes/cases/detail/types.d.ts +24 -0
  255. package/components/routes/cases/detail/utils.d.ts +29 -0
  256. package/components/routes/cases/detail/utils.js +114 -0
  257. package/components/routes/cases/detail/utils.test.d.ts +1 -0
  258. package/components/routes/cases/detail/utils.test.js +144 -0
  259. package/components/routes/cases/hooks/useCase.d.ts +13 -0
  260. package/components/routes/cases/hooks/useCase.js +69 -0
  261. package/components/routes/cases/hooks/useCase.test.d.ts +1 -0
  262. package/components/routes/cases/hooks/useCase.test.js +141 -0
  263. package/components/routes/cases/modals/AddRecordToCaseModal.d.ts +7 -0
  264. package/components/routes/cases/modals/AddRecordToCaseModal.js +57 -0
  265. package/components/routes/cases/modals/AddRecordToCaseModal.test.d.ts +1 -0
  266. package/components/routes/cases/modals/AddRecordToCaseModal.test.js +309 -0
  267. package/components/routes/cases/modals/AddToCaseModal.d.ts +9 -0
  268. package/components/routes/cases/modals/AddToCaseModal.js +72 -0
  269. package/components/routes/cases/modals/CaseRecordRow.d.ts +9 -0
  270. package/components/routes/cases/modals/CaseRecordRow.js +14 -0
  271. package/components/routes/cases/modals/CreateCaseModal.d.ts +7 -0
  272. package/components/routes/cases/modals/CreateCaseModal.js +53 -0
  273. package/components/routes/cases/modals/CreateCaseModal.test.d.ts +1 -0
  274. package/components/routes/cases/modals/CreateCaseModal.test.js +319 -0
  275. package/components/routes/cases/modals/RenameItemModal.d.ts +9 -0
  276. package/components/routes/cases/modals/RenameItemModal.js +44 -0
  277. package/components/routes/cases/modals/ResolveModal.d.ts +7 -0
  278. package/components/routes/cases/modals/ResolveModal.js +120 -0
  279. package/components/routes/cases/modals/ResolveModal.test.d.ts +1 -0
  280. package/components/routes/cases/modals/ResolveModal.test.js +520 -0
  281. package/components/routes/cases/modals/hooks.d.ts +7 -0
  282. package/components/routes/cases/modals/hooks.js +40 -0
  283. package/components/routes/cases/modals/types.d.ts +13 -0
  284. package/components/routes/cases/search/CaseAssigneeFilter.d.ts +6 -0
  285. package/components/routes/cases/search/CaseAssigneeFilter.js +33 -0
  286. package/components/routes/cases/search/CaseAssigneeFilter.test.d.ts +1 -0
  287. package/components/routes/cases/search/CaseAssigneeFilter.test.js +127 -0
  288. package/components/routes/cases/search/CaseDateFilter.d.ts +13 -0
  289. package/components/routes/cases/search/CaseDateFilter.js +26 -0
  290. package/components/routes/cases/search/CaseDateFilter.test.d.ts +1 -0
  291. package/components/routes/cases/search/CaseDateFilter.test.js +115 -0
  292. package/components/routes/cases/search/CaseStatusFilter.d.ts +6 -0
  293. package/components/routes/cases/search/CaseStatusFilter.js +13 -0
  294. package/components/routes/cases/search/CaseStatusFilter.test.d.ts +1 -0
  295. package/components/routes/cases/search/CaseStatusFilter.test.js +86 -0
  296. package/components/routes/cases/utils.d.ts +3 -0
  297. package/components/routes/cases/utils.js +21 -0
  298. package/components/routes/dossiers/DossierEditor.js +2 -2
  299. package/components/routes/dossiers/DossierEditor.test.js +1 -1
  300. package/components/routes/events/EventViewer.d.ts +7 -0
  301. package/components/routes/events/EventViewer.js +24 -0
  302. package/components/routes/help/ApiDocumentation.js +1 -1
  303. package/components/routes/help/HitBannerDocumentation.js +1 -0
  304. package/components/routes/help/HitDocumentation.js +1 -3
  305. package/components/routes/help/OverviewDocumentation.d.ts +1 -1
  306. package/components/routes/help/OverviewDocumentation.js +0 -1
  307. package/components/routes/hits/search/InformationPane.d.ts +1 -0
  308. package/components/routes/hits/search/InformationPane.js +51 -64
  309. package/components/routes/hits/search/QuerySettings.js +2 -1
  310. package/components/routes/hits/search/QuerySettings.test.js +14 -9
  311. package/components/routes/hits/search/{HitBrowser.js → RecordBrowser.js} +11 -11
  312. package/components/routes/hits/search/{HitQuery.d.ts → RecordQuery.d.ts} +2 -2
  313. package/components/routes/hits/search/{HitQuery.js → RecordQuery.js} +6 -6
  314. package/components/routes/hits/search/SearchPane.js +24 -46
  315. package/components/routes/hits/search/ViewLink.js +4 -4
  316. package/components/routes/hits/search/ViewLink.test.js +8 -9
  317. package/components/routes/hits/search/grid/RecordGrid.d.ts +3 -0
  318. package/components/routes/hits/search/grid/{HitGrid.js → RecordGrid.js} +15 -15
  319. package/components/routes/hits/search/shared/CustomSpan.test.js +3 -4
  320. package/components/routes/hits/search/shared/IndexPicker.d.ts +8 -0
  321. package/components/routes/hits/search/shared/IndexPicker.js +21 -0
  322. package/components/routes/hits/search/shared/LayoutSettings.js +3 -3
  323. package/components/routes/hits/search/shared/SearchActionMenu.js +3 -9
  324. package/components/routes/hits/view/HitViewer.js +13 -14
  325. package/components/routes/home/ViewCard.js +47 -41
  326. package/components/routes/overviews/OverviewViewer.js +4 -4
  327. package/components/routes/views/ViewComposer.js +49 -23
  328. package/locales/en/translation.json +171 -27
  329. package/locales/fr/translation.json +169 -25
  330. package/models/WithMetadata.d.ts +2 -1
  331. package/models/entities/generated/Analytic.d.ts +0 -3
  332. package/models/entities/generated/ApiType.d.ts +3 -1
  333. package/models/entities/generated/AttachmentsFile.d.ts +12 -0
  334. package/models/entities/generated/Case.d.ts +29 -0
  335. package/models/entities/generated/DestinationOriginal.d.ts +19 -0
  336. package/models/entities/generated/ECSEvent.d.ts +31 -0
  337. package/models/entities/generated/EmailAttachment.d.ts +8 -0
  338. package/models/entities/generated/EmailParent.d.ts +19 -0
  339. package/models/entities/generated/Enrichments.d.ts +7 -0
  340. package/models/entities/generated/EnrichmentsIndicator.d.ts +21 -0
  341. package/models/entities/generated/Event.d.ts +80 -26
  342. package/models/entities/generated/EventCloud.d.ts +20 -0
  343. package/models/entities/generated/EventDestination.d.ts +23 -0
  344. package/models/entities/generated/EventEmail.d.ts +30 -0
  345. package/models/entities/generated/EventFile.d.ts +36 -0
  346. package/models/entities/generated/EventHowler.d.ts +42 -0
  347. package/models/entities/generated/EventHttp.d.ts +11 -0
  348. package/models/entities/generated/EventObserver.d.ts +21 -0
  349. package/models/entities/generated/EventOrganization.d.ts +7 -0
  350. package/models/entities/generated/EventProcess.d.ts +34 -0
  351. package/models/entities/generated/EventSource.d.ts +23 -0
  352. package/models/entities/generated/EventThreat.d.ts +21 -0
  353. package/models/entities/generated/EventTls.d.ts +12 -0
  354. package/models/entities/generated/Hit.d.ts +3 -2
  355. package/models/entities/generated/Howler.d.ts +0 -5
  356. package/models/entities/generated/HttpResponse.d.ts +11 -0
  357. package/models/entities/generated/Item.d.ts +12 -0
  358. package/models/entities/generated/ObserverIngress.d.ts +9 -0
  359. package/models/entities/generated/Rule.d.ts +8 -9
  360. package/models/entities/generated/Task.d.ts +10 -0
  361. package/models/entities/generated/Threat.d.ts +2 -2
  362. package/models/entities/generated/{Enrichment.d.ts → ThreatEnrichment.d.ts} +1 -1
  363. package/models/entities/generated/View.d.ts +1 -0
  364. package/models/socket/CaseUpdate.d.ts +5 -0
  365. package/models/socket/ViewersUpdate.d.ts +4 -0
  366. package/package.json +112 -91
  367. package/plugins/clue/components/ClueTypography.js +2 -2
  368. package/plugins/clue/index.d.ts +1 -1
  369. package/plugins/clue/index.js +0 -1
  370. package/plugins/clue/utils.d.ts +2 -1
  371. package/tests/mocks.d.ts +11 -1
  372. package/tests/mocks.js +12 -7
  373. package/tests/server-handlers.js +11 -1
  374. package/tests/utils.d.ts +4 -0
  375. package/tests/utils.js +21 -0
  376. package/utils/classificationParser.d.ts +195 -0
  377. package/utils/classificationParser.js +680 -0
  378. package/utils/constants.d.ts +4 -3
  379. package/utils/constants.js +6 -0
  380. package/utils/recordFunctions.d.ts +3 -0
  381. package/utils/recordFunctions.js +8 -0
  382. package/utils/recordFunctions.test.d.ts +1 -0
  383. package/utils/{hitFunctions.test.js → recordFunctions.test.js} +1 -1
  384. package/utils/socketUtils.d.ts +14 -0
  385. package/utils/socketUtils.js +17 -1
  386. package/utils/socketUtils.test.js +49 -16
  387. package/utils/typeUtils.d.ts +7 -0
  388. package/utils/typeUtils.js +27 -0
  389. package/utils/viewUtils.js +3 -0
  390. package/api/analytic/rules.d.ts +0 -4
  391. package/api/analytic/rules.js +0 -8
  392. package/components/app/providers/HitProvider.d.ts +0 -22
  393. package/components/elements/display/icons/BundleButton.d.ts +0 -6
  394. package/components/elements/display/icons/BundleButton.js +0 -32
  395. package/components/elements/hit/HitContextMenu.js +0 -239
  396. package/components/elements/hit/HitRelated.d.ts +0 -6
  397. package/components/elements/hit/HitRelated.js +0 -7
  398. package/components/elements/hit/elements/HitUsers.js +0 -33
  399. package/components/routes/advanced/RuleModal.d.ts +0 -7
  400. package/components/routes/advanced/RuleModal.js +0 -83
  401. package/components/routes/analytics/RuleView.d.ts +0 -8
  402. package/components/routes/analytics/RuleView.js +0 -48
  403. package/components/routes/help/BundleDocumentation.d.ts +0 -3
  404. package/components/routes/help/BundleDocumentation.js +0 -12
  405. package/components/routes/help/markdown/en/bundles.md.js +0 -1
  406. package/components/routes/help/markdown/fr/bundles.md.js +0 -1
  407. package/components/routes/hits/search/BundleScroller.d.ts +0 -2
  408. package/components/routes/hits/search/BundleScroller.js +0 -6
  409. package/components/routes/hits/search/grid/HitGrid.d.ts +0 -3
  410. package/components/routes/hits/search/shared/BundleParentMenu.d.ts +0 -6
  411. package/components/routes/hits/search/shared/BundleParentMenu.js +0 -32
  412. package/utils/hitFunctions.d.ts +0 -2
  413. package/utils/hitFunctions.js +0 -8
  414. /package/{components/app/providers/HitSearchProvider.test.d.ts → api/socket/viewers.test.d.ts} +0 -0
  415. /package/components/{elements/hit/HitContextMenu.test.d.ts → app/providers/RecordSearchProvider.test.d.ts} +0 -0
  416. /package/{utils/hitFunctions.test.d.ts → components/app/providers/UserListProvider.test.d.ts} +0 -0
  417. /package/components/{routes/overviews/OverviewEditor.d.ts → elements/MarkdownEditor.d.ts} +0 -0
  418. /package/components/elements/hit/{HitDetails.d.ts → related/RelatedRecords.d.ts} +0 -0
  419. /package/components/routes/hits/search/{HitBrowser.d.ts → RecordBrowser.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { type ChipProps } from '@mui/material';
2
2
  import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
3
- import { type FC } from 'react';
3
+ import type { FC } from 'react';
4
4
  export type PluginChipProps = ChipProps & {
5
5
  value: string;
6
6
  context: string;
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Chip } from '@mui/material';
3
3
  import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
4
- import {} from 'react';
5
4
  import { usePluginStore } from 'react-pluggable';
6
5
  const PluginChip = ({ children, value, context, field, hit, ...props }) => {
7
6
  const pluginStore = usePluginStore();
@@ -1,10 +1,11 @@
1
1
  import { type TypographyProps } from '@mui/material';
2
+ import type { Event } from '@cccsaurora/howler-ui/models/entities/generated/Event';
2
3
  import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
3
4
  export type PluginTypographyProps = TypographyProps & {
4
5
  value: string;
5
6
  context: string;
6
7
  field?: string;
7
- hit?: Hit;
8
+ obj?: Hit | Event;
8
9
  };
9
10
  declare const _default: import("react").NamedExoticComponent<PluginTypographyProps>;
10
11
  export default _default;
@@ -3,7 +3,7 @@ import { Typography } from '@mui/material';
3
3
  import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
4
4
  import { memo } from 'react';
5
5
  import { usePluginStore } from 'react-pluggable';
6
- const PluginTypography = ({ children, value, context, field, hit, ...props }) => {
6
+ const PluginTypography = ({ children, value, context, field, obj, ...props }) => {
7
7
  const pluginStore = usePluginStore();
8
8
  for (const plugin of howlerPluginStore.plugins) {
9
9
  const component = pluginStore.executeFunction(`${plugin}.typography`, {
@@ -11,7 +11,8 @@ const PluginTypography = ({ children, value, context, field, hit, ...props }) =>
11
11
  value,
12
12
  context,
13
13
  field,
14
- hit,
14
+ hit: obj,
15
+ obj,
15
16
  ...props
16
17
  });
17
18
  if (component) {
@@ -2,8 +2,11 @@ import type { SxProps, Theme } from '@mui/material';
2
2
  import type { FC } from 'react';
3
3
  declare const UserList: FC<{
4
4
  buttonSx?: SxProps<Theme>;
5
- userId: string;
6
- onChange: (userId: string) => void;
5
+ userIds: string[];
6
+ onChange: (userIds: string[]) => void;
7
7
  i18nLabel: string;
8
+ avatarHeight?: number;
9
+ disabled?: boolean;
10
+ multiple?: boolean;
8
11
  }>;
9
12
  export default UserList;
@@ -1,26 +1,43 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Autocomplete, Box, IconButton, Popover, TextField, Typography } from '@mui/material';
2
+ import { Add } from '@mui/icons-material';
3
+ import { Autocomplete, AvatarGroup, Box, IconButton, Popover, Stack, TextField, Typography } from '@mui/material';
3
4
  import { UserListContext } from '@cccsaurora/howler-ui/components/app/providers/UserListProvider';
5
+ import { uniq } from 'lodash-es';
4
6
  import { useContext, useEffect, useMemo, useState } from 'react';
5
7
  import { useTranslation } from 'react-i18next';
6
8
  import HowlerAvatar from './display/HowlerAvatar';
7
- const UserList = ({ buttonSx = {}, userId, onChange, i18nLabel }) => {
9
+ const UserList = ({ buttonSx = {}, userIds, onChange, i18nLabel, avatarHeight = 32, multiple = false, disabled = false }) => {
8
10
  const { t } = useTranslation();
9
11
  const [anchorEl, setAnchorEl] = useState(null);
10
- const { users, searchUsers } = useContext(UserListContext);
11
- const userIds = useMemo(() => Object.keys(users), [users]);
12
+ const { users, fetchUsers } = useContext(UserListContext);
13
+ const allUserIds = useMemo(() => Object.keys(users), [users]);
12
14
  useEffect(() => {
13
- searchUsers('uname:*');
14
- }, [searchUsers]);
15
- return (_jsxs(_Fragment, { children: [_jsx(IconButton, { sx: buttonSx, onClick: e => setAnchorEl(e.currentTarget), children: _jsx(HowlerAvatar, { userId: userId }) }), _jsx(Popover, { open: !!anchorEl, onClose: () => setAnchorEl(null), anchorEl: anchorEl, anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, children: _jsx(Box, { sx: { p: 2 }, children: _jsx(Autocomplete, { sx: { minWidth: '300px' }, options: userIds, renderInput: params => _jsx(TextField, { ...params, label: t(i18nLabel), size: "small" }), renderOption: (props, _userId) => {
16
- const user = users[_userId];
17
- return (_jsx("li", { ...props, children: _jsxs(Box, { sx: {
18
- display: 'grid',
19
- gridTemplateColumns: 'auto 1fr',
20
- gridTemplateRows: 'auto auto',
21
- gridTemplateAreas: `"profile name"\n"profile email"`,
22
- columnGap: 1.5
23
- }, children: [_jsx(HowlerAvatar, { sx: { gridArea: 'profile', alignSelf: 'center', height: '32px', width: '32px' }, userId: user.username }), _jsx(Typography, { sx: { gridArea: 'name' }, variant: "body1", children: user.name }), _jsx(Typography, { sx: { gridArea: 'email' }, variant: "caption", children: user.email })] }) }));
24
- }, value: userId, onChange: (__, option) => onChange(option) }) }) })] }));
15
+ fetchUsers(new Set(userIds));
16
+ // eslint-disable-next-line react-hooks/exhaustive-deps
17
+ }, [userIds]);
18
+ const renderInput = params => _jsx(TextField, { ...params, label: t(i18nLabel), size: "small" });
19
+ const renderOption = (props, optionUserId) => {
20
+ const { key, ...optionProps } = props;
21
+ const user = users[optionUserId];
22
+ return (_jsx("li", { ...optionProps, children: _jsxs(Box, { sx: {
23
+ display: 'grid',
24
+ gridTemplateColumns: 'auto 1fr',
25
+ gridTemplateRows: 'auto auto',
26
+ gridTemplateAreas: `"profile name"\n"profile email"`,
27
+ columnGap: 1.5
28
+ }, children: [_jsx(HowlerAvatar, { sx: { gridArea: 'profile', alignSelf: 'center', height: '32px', width: '32px' }, userId: user?.username }), _jsx(Typography, { sx: { gridArea: 'name' }, variant: "body1", children: user?.name ?? optionUserId }), _jsx(Typography, { sx: { gridArea: 'email' }, variant: "caption", children: user?.email ?? '' })] }) }, key));
29
+ };
30
+ const sharedAutocompleteProps = {
31
+ disabled,
32
+ sx: { minWidth: '300px' },
33
+ options: allUserIds,
34
+ renderInput,
35
+ renderOption
36
+ };
37
+ return (_jsxs(_Fragment, { children: [multiple ? (_jsxs(Stack, { direction: "row", spacing: 0.25, alignItems: "center", children: [_jsx(AvatarGroup, { children: uniq(userIds ?? [null]).map(userId => (_jsx(HowlerAvatar, { userId: userId, sx: { height: avatarHeight, width: avatarHeight } }, userId))) }), _jsx(IconButton, { size: "small", sx: buttonSx, disabled: disabled, onClick: e => setAnchorEl(e.currentTarget), children: _jsx(Add, {}) })] })) : (_jsx(IconButton, { sx: buttonSx, disabled: disabled, onClick: e => setAnchorEl(e.currentTarget), children: _jsx(HowlerAvatar, { userId: userIds[0], sx: { height: avatarHeight, width: avatarHeight } }) })), _jsx(Popover, { open: !!anchorEl, onClose: () => setAnchorEl(null), anchorEl: anchorEl, anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, children: _jsx(Box, { sx: { p: 2 }, children: multiple ? (_jsx(Autocomplete, { ...sharedAutocompleteProps, multiple: true, value: userIds, onChange: (__, options) => {
38
+ onChange(options);
39
+ } })) : (_jsx(Autocomplete, { ...sharedAutocompleteProps, value: userIds?.[0] ?? null, onChange: (__, option) => {
40
+ onChange(option ? [option] : []);
41
+ } })) }) })] }));
25
42
  };
26
43
  export default UserList;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,122 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render, screen, waitFor, within } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { UserListContext } from '@cccsaurora/howler-ui/components/app/providers/UserListProvider';
5
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
6
+ vi.mock('react-i18next', () => ({
7
+ useTranslation: () => ({
8
+ t: (key) => key
9
+ })
10
+ }));
11
+ vi.mock('components/elements/display/HowlerAvatar', () => ({
12
+ default: ({ userId }) => _jsx("div", { id: `avatar-${userId ?? 'none'}`, children: userId ?? 'none' })
13
+ }));
14
+ import UserList from './UserList';
15
+ const mockFetchUsers = vi.fn();
16
+ const defaultUsers = {
17
+ analystA: {
18
+ username: 'analystA',
19
+ name: 'Alice Analyst',
20
+ email: 'alice@example.com'
21
+ },
22
+ analystB: {
23
+ username: 'analystB',
24
+ name: 'Bob Analyst',
25
+ email: 'bob@example.com'
26
+ },
27
+ analystC: {
28
+ username: 'analystC',
29
+ name: 'Chris Analyst',
30
+ email: 'chris@example.com'
31
+ }
32
+ };
33
+ const createWrapper = (users) => {
34
+ const Wrapper = ({ children }) => (_jsx(UserListContext.Provider, { value: {
35
+ users,
36
+ fetchUsers: mockFetchUsers,
37
+ searchUsers: vi.fn()
38
+ }, children: children }));
39
+ return Wrapper;
40
+ };
41
+ describe('UserList', () => {
42
+ beforeEach(() => {
43
+ vi.clearAllMocks();
44
+ });
45
+ it('fetches users on mount and whenever userIds change', async () => {
46
+ const onChange = vi.fn();
47
+ const { rerender } = render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA'], onChange: onChange }), {
48
+ wrapper: createWrapper(defaultUsers)
49
+ });
50
+ await waitFor(() => {
51
+ expect(mockFetchUsers).toHaveBeenCalledWith(new Set(['analystA']));
52
+ });
53
+ rerender(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA', 'analystB'], onChange: onChange }));
54
+ await waitFor(() => {
55
+ expect(mockFetchUsers).toHaveBeenCalledWith(new Set(['analystA', 'analystB']));
56
+ });
57
+ });
58
+ it('opens the popover and selects a user in single mode', async () => {
59
+ const user = userEvent.setup();
60
+ const onChange = vi.fn();
61
+ render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA'], onChange: onChange }), {
62
+ wrapper: createWrapper(defaultUsers)
63
+ });
64
+ const avatarButton = screen.getByRole('button');
65
+ await user.click(avatarButton);
66
+ const combo = await screen.findByRole('combobox', { name: 'user.list.label' });
67
+ await user.click(combo);
68
+ const listbox = await screen.findByRole('listbox');
69
+ await user.click(within(listbox).getByText('Bob Analyst'));
70
+ expect(onChange).toHaveBeenCalledWith(['analystB']);
71
+ });
72
+ it('renders deduplicated avatars and appends selection in multiple mode', async () => {
73
+ const user = userEvent.setup();
74
+ const onChange = vi.fn();
75
+ render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA', 'analystA'], onChange: onChange, multiple: true }), {
76
+ wrapper: createWrapper(defaultUsers)
77
+ });
78
+ expect(screen.getAllByText('analystA')).toHaveLength(1);
79
+ const addButton = screen.getByRole('button');
80
+ await user.click(addButton);
81
+ const combo = await screen.findByRole('combobox', { name: 'user.list.label' });
82
+ await user.click(combo);
83
+ const listbox = await screen.findByRole('listbox');
84
+ await user.click(within(listbox).getByText('Bob Analyst'));
85
+ expect(onChange).toHaveBeenCalledWith(expect.arrayContaining(['analystA', 'analystB']));
86
+ });
87
+ it('does not open popover when disabled', async () => {
88
+ const onChange = vi.fn();
89
+ render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA'], onChange: onChange, disabled: true }), {
90
+ wrapper: createWrapper(defaultUsers)
91
+ });
92
+ const button = screen.getByRole('button');
93
+ expect(button).toBeDisabled();
94
+ expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
95
+ });
96
+ it('emits an empty list when single-select value is cleared', async () => {
97
+ const user = userEvent.setup();
98
+ const onChange = vi.fn();
99
+ render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA'], onChange: onChange }), {
100
+ wrapper: createWrapper(defaultUsers)
101
+ });
102
+ const avatarButton = screen.getByRole('button');
103
+ await user.click(avatarButton);
104
+ await screen.findByRole('combobox', { name: 'user.list.label' });
105
+ const clearButton = await screen.findByLabelText(/clear/i);
106
+ await user.click(clearButton);
107
+ expect(onChange).toHaveBeenCalledWith([]);
108
+ });
109
+ it('renders and opens with empty users context without crashing', async () => {
110
+ const user = userEvent.setup();
111
+ const onChange = vi.fn();
112
+ render(_jsx(UserList, { i18nLabel: "user.list.label", userIds: ['analystA'], onChange: onChange }), {
113
+ wrapper: createWrapper({})
114
+ });
115
+ expect(screen.getByText('analystA')).toBeInTheDocument();
116
+ const avatarButton = screen.getByRole('button');
117
+ await user.click(avatarButton);
118
+ const combo = await screen.findByRole('combobox', { name: 'user.list.label' });
119
+ await user.click(combo);
120
+ expect(screen.queryAllByRole('option')).toHaveLength(0);
121
+ });
122
+ });
@@ -1,4 +1,4 @@
1
- import { type TuiListItem, type TuiListItemOnSelect, type TuiListItemRenderer } from '.';
1
+ import type { TuiListItem, TuiListItemOnSelect, TuiListItemRenderer } from '.';
2
2
  type TuiListElementProps<T> = {
3
3
  position: number;
4
4
  item: TuiListItem<T>;
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo, useCallback, useRef } from 'react';
3
- import {} from '.';
4
3
  import VSBoxElement from '../layout/vsbox/VSBoxElement';
5
4
  const TuiListElement = ({ position, item, onSelect: onClick, children }) => {
6
5
  const elementEl = useRef();
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Typography } from '@mui/material';
3
3
  import { Trans } from 'react-i18next';
4
4
  const SearchTotal = ({ total, offset, pageLength, ...typographyProps }) => {
5
- return (_jsx(Typography, { ...typographyProps, children: total <= 1 ? (_jsx(Trans, { i18nKey: "search.result.showing.single", values: {
5
+ return (_jsx(Typography, { ...typographyProps, children: total < 1 ? (_jsx(Trans, { i18nKey: "search.result.showing.single", values: {
6
6
  total: total
7
7
  } })) : (_jsx(Trans, { i18nKey: "search.result.showing", values: {
8
8
  total: total,
@@ -15,9 +15,9 @@ describe('SearchTotal', () => {
15
15
  render(_jsx(SearchTotal, { total: 0, offset: 0, pageLength: 0 }), { wrapper: Wrapper });
16
16
  expect(screen.getByText('No results')).toBeInTheDocument();
17
17
  });
18
- it('renders "No results" text when total is 1', () => {
18
+ it('renders "Showing 1 to 1 of 1 results" text when total is 1', () => {
19
19
  render(_jsx(SearchTotal, { total: 1, offset: 0, pageLength: 1 }), { wrapper: Wrapper });
20
- expect(screen.getByText('No results')).toBeInTheDocument();
20
+ expect(screen.getByText('Showing 1 to 1 of 1 results')).toBeInTheDocument();
21
21
  });
22
22
  it('renders range text when total is greater than 1', () => {
23
23
  render(_jsx(SearchTotal, { total: 50, offset: 0, pageLength: 25 }), { wrapper: Wrapper });
@@ -80,7 +80,7 @@ const Phrase = ({ value = '', variant = 'outlined', suggestions = [], lexer, sug
80
80
  onSelectCapture: _onSelectCapture,
81
81
  startAdornment: startAdornment && _jsx(InputAdornment, { position: "start", children: startAdornment }),
82
82
  endAdornment: endAdornment && _jsx(InputAdornment, { position: "end", children: endAdornment })
83
- } }), _jsx(Popper, { anchorEl: containerRef.current, style: { width: '100%', zIndex: 100 }, open: optionsOpen && (options.length > 0 || (debug && analysisRef.current?.tokens.length > 0)), disablePortal: true, children: _jsx(Paper, { elevation: 2, sx: { maxHeight: 200, overflow: 'auto', borderTopRightRadius: 0, borderTopLeftRadius: 0 }, children: _jsx(MenuList, { ref: menuRef, onKeyDown: _onMenuKeyDown, sx: {
83
+ } }), _jsx(Popper, { anchorEl: containerRef.current, style: { width: '100%', zIndex: 100 }, open: optionsOpen && (options.length > 0 || (debug && analysisRef.current?.tokens.length > 0)), disablePortal: true, children: _jsx(Paper, { elevation: 1, sx: { maxHeight: 200, overflow: 'auto', borderTopRightRadius: 0, borderTopLeftRadius: 0 }, children: _jsx(MenuList, { ref: menuRef, onKeyDown: _onMenuKeyDown, sx: {
84
84
  '&:focus': {
85
85
  outline: 'none'
86
86
  }
@@ -0,0 +1,12 @@
1
+ import { type CardProps } from '@mui/material';
2
+ import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
3
+ import { type FC } from 'react';
4
+ declare const CaseCard: FC<{
5
+ case?: Case;
6
+ caseId?: string;
7
+ className?: string;
8
+ slotProps?: {
9
+ card?: CardProps;
10
+ };
11
+ }>;
12
+ export default CaseCard;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { CheckCircleOutline, HourglassBottom, RadioButtonUnchecked, UpdateOutlined } from '@mui/icons-material';
3
+ import { Chip, Divider, Grid, Skeleton, Stack, Tooltip, Typography, useTheme } from '@mui/material';
4
+ import api from '@cccsaurora/howler-ui/api';
5
+ import StatusIcon from '@cccsaurora/howler-ui/components/elements/case/StatusIcon';
6
+ import HowlerAvatar from '@cccsaurora/howler-ui/components/elements/display/HowlerAvatar';
7
+ import PluginChip from '@cccsaurora/howler-ui/components/elements/PluginChip';
8
+ import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
9
+ import dayjs from 'dayjs';
10
+ import { countBy } from 'lodash-es';
11
+ import { useEffect, useState } from 'react';
12
+ import { useTranslation } from 'react-i18next';
13
+ import { twitterShort } from '@cccsaurora/howler-ui/utils/utils';
14
+ import HowlerCard from '../display/HowlerCard';
15
+ const STATUS_COLORS = {
16
+ resolved: 'success'
17
+ };
18
+ const CaseCard = ({ case: providedCase, caseId, className, slotProps }) => {
19
+ const { t } = useTranslation();
20
+ const { dispatchApi } = useMyApi();
21
+ const theme = useTheme();
22
+ const [_case, setCase] = useState(providedCase);
23
+ useEffect(() => {
24
+ if (providedCase) {
25
+ setCase(providedCase);
26
+ }
27
+ }, [providedCase]);
28
+ useEffect(() => {
29
+ if (caseId) {
30
+ dispatchApi(api.v2.case.get(caseId), { throwError: false }).then(setCase);
31
+ }
32
+ }, [caseId, dispatchApi]);
33
+ if (!_case) {
34
+ return _jsx(Skeleton, { variant: "rounded", height: 250, sx: { mb: 1 }, className: className });
35
+ }
36
+ return (_jsx(HowlerCard, { ...slotProps?.card, sx: [
37
+ { p: 1, mb: 1, borderColor: theme.palette[STATUS_COLORS[_case.status]]?.main },
38
+ ...(Array.isArray(slotProps?.card?.sx) ? slotProps.card.sx : slotProps?.card?.sx ? [slotProps.card.sx] : [])
39
+ ], className: className, children: _jsx(Stack, { direction: "row", alignItems: "start", spacing: 1, children: _jsxs(Stack, { sx: { flex: 1 }, spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsx(Typography, { variant: "h6", display: "flex", alignItems: "start", children: _case.title }), _jsx(StatusIcon, { status: _case.status }), _jsx("div", { style: { flex: 1 } }), _case.start && _case.end && (_jsx(Tooltip, { title: dayjs(_case.updated).toString(), children: _jsx(Chip, { icon: _jsx(HourglassBottom, { fontSize: "small" }), size: "small", label: twitterShort(_case.start) + ' - ' + twitterShort(_case.end) }) })), _jsx(Tooltip, { title: dayjs(_case.updated).toString(), children: _jsx(Chip, { icon: _jsx(UpdateOutlined, { fontSize: "small" }), size: "small", label: twitterShort(_case.updated) }) })] }), _jsx(Typography, { variant: "caption", color: "textSecondary", children: _case.summary.trim().split('\n')[0] }), _case.participants?.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Divider, { flexItem: true }), _jsx(Stack, { direction: "row", spacing: 1, children: _case.participants?.map(participant => (_jsx(HowlerAvatar, { sx: { height: '20px', width: '20px' }, userId: participant }, participant))) })] })), _jsx(Divider, { flexItem: true }), _jsxs(Grid, { container: true, spacing: 0.5, sx: { ml: `${theme.spacing(-0.5)} !important`, mt: `${theme.spacing(0.5)} !important` }, children: [_case.targets?.map(indicator => (_jsx(Grid, { item: true, children: _jsx(PluginChip, { size: "small", color: "primary", context: "casecard", variant: "outlined", value: indicator, label: indicator }) }, indicator))), _case.targets?.length > 0 && (_case.indicators?.length > 0 || _case.threats?.length > 0) && (_jsx(Grid, { item: true, children: _jsx(Divider, { orientation: "vertical" }) })), _case.indicators?.map(indicator => (_jsx(Grid, { item: true, children: _jsx(PluginChip, { variant: "outlined", context: "casecard", value: indicator, label: indicator }) }, indicator))), _case.indicators?.length > 0 && _case.threats?.length > 0 && (_jsx(Grid, { item: true, children: _jsx(Divider, { orientation: "vertical" }) })), _case.threats?.map(indicator => (_jsx(Grid, { item: true, children: _jsx(PluginChip, { size: "small", color: "warning", variant: "outlined", context: "casecard", value: indicator, label: indicator }) }, indicator)))] }), _case.tasks?.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Divider, { flexItem: true }), _jsxs(Stack, { spacing: 0.5, alignItems: "start", children: [_case.tasks.some(task => task.complete) && (_jsx(Chip, { size: "small", color: "success", icon: _jsx(CheckCircleOutline, {}), label: `${countBy(_case.tasks, task => task.complete).true} ${t('complete')}` })), _case.tasks
40
+ .filter(task => !task.complete)
41
+ .map(task => (_jsx(Chip, { icon: _jsx(RadioButtonUnchecked, {}), label: task.summary }, task.id)))] })] }))] }) }) }, _case.case_id));
42
+ };
43
+ export default CaseCard;
@@ -0,0 +1,6 @@
1
+ import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
+ type PreviewProps = {
3
+ case: Case;
4
+ };
5
+ declare const _default: import("react").NamedExoticComponent<PreviewProps>;
6
+ export default _default;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CheckCircleOutline, HourglassBottom, RadioButtonUnchecked, UpdateOutlined } from '@mui/icons-material';
3
+ import { Chip, Stack, Tooltip, Typography, useTheme } from '@mui/material';
4
+ import dayjs from 'dayjs';
5
+ import { countBy } from 'lodash-es';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { twitterShort } from '@cccsaurora/howler-ui/utils/utils';
9
+ import HowlerAvatar from '../display/HowlerAvatar';
10
+ import StatusIcon from './StatusIcon';
11
+ const CasePreview = ({ case: _case }) => {
12
+ const { t } = useTranslation();
13
+ const theme = useTheme();
14
+ const taskCounts = countBy(_case.tasks, task => task.complete);
15
+ return (_jsxs(Stack, { flex: 1, spacing: 1, sx: { overflow: 'hidden', borderBottom: `thin solid ${theme.palette.divider}`, pb: 1, mb: 0 }, children: [_jsxs(Stack, { direction: "row", spacing: 1, children: [_jsxs(Stack, { spacing: 1, children: [_jsx(Typography, { variant: "body1", fontWeight: "bold", children: _case.title }), _jsx(Typography, { variant: "caption", color: "textSecondary", children: _case.summary.trim().split('\n')[0] })] }), _jsx(StatusIcon, { status: _case.status }), _jsx("div", { style: { flex: 1 } }), _jsxs(Stack, { spacing: 1, alignItems: "end", children: [_case.start && _case.end && (_jsx(Tooltip, { title: dayjs(_case.updated).toString(), children: _jsx(Chip, { icon: _jsx(HourglassBottom, { fontSize: "small" }), size: "small", label: twitterShort(_case.start) + ' - ' + twitterShort(_case.end) }) })), _jsx(Tooltip, { title: dayjs(_case.updated).toString(), children: _jsx(Chip, { icon: _jsx(UpdateOutlined, { fontSize: "small" }), size: "small", label: twitterShort(_case.updated) }) })] })] }), _jsxs(Stack, { direction: "row", spacing: 1, children: [_case.participants?.length > 0 && (_jsx(Stack, { direction: "row", spacing: 1, children: _case.participants?.map(participant => (_jsx(HowlerAvatar, { sx: { height: '24px', width: '24px' }, userId: participant }, participant))) })), _jsx(Chip, { color: "success", icon: _jsx(CheckCircleOutline, {}), label: `${taskCounts.true ?? 0} ${t('complete')}` }), _jsx(Chip, { icon: _jsx(RadioButtonUnchecked, {}), label: `${taskCounts.false ?? 0} ${t('incomplete')}` })] })] }));
16
+ };
17
+ export default memo(CasePreview);
@@ -0,0 +1,5 @@
1
+ import type { FC } from 'react';
2
+ declare const StatusIcon: FC<{
3
+ status: string;
4
+ }>;
5
+ export default StatusIcon;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Check, HourglassBottom, Pause, Troubleshoot } from '@mui/icons-material';
3
+ import { Tooltip } from '@mui/material';
4
+ import { useTranslation } from 'react-i18next';
5
+ const StatusIcon = ({ status }) => {
6
+ const { t } = useTranslation();
7
+ return (_jsx(Tooltip, { title: t(`page.cases.status.${status}`), children: {
8
+ 'in-progress': _jsx(HourglassBottom, { color: "warning" }),
9
+ 'on-hold': _jsx(Pause, { color: "disabled" }),
10
+ resolved: _jsx(Check, { color: "success" })
11
+ }[status] ?? _jsx(Troubleshoot, { color: "primary" }) }));
12
+ };
13
+ export default StatusIcon;
@@ -15,8 +15,8 @@ interface ChipPopperProps {
15
15
  onToggle?: (show: boolean) => void;
16
16
  onDelete?: (event?: any) => void;
17
17
  toggleOnDelete?: boolean;
18
- closeOnClick?: boolean;
19
18
  disablePortal?: boolean;
19
+ closeOnClick?: boolean;
20
20
  }
21
21
  declare const _default: import("react").NamedExoticComponent<ChipPopperProps>;
22
22
  export default _default;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Chip, ClickAwayListener, Collapse, Paper, Popper } from '@mui/material';
3
- import { memo, useRef, useState } from 'react';
3
+ import { memo, useState } from 'react';
4
4
  const ChipPopper = ({ icon, deleteIcon, label, children, minWidth, placement = 'bottom-start', onToggle, onDelete, toggleOnDelete = false, closeOnClick = false, disablePortal = true, slotProps = {} }) => {
5
5
  const [show, setShow] = useState(false);
6
- const anchorEl = useRef(null);
6
+ const [anchorEl, setAnchorEl] = useState(null);
7
7
  const handleToggle = (newShow) => {
8
8
  setShow(newShow);
9
9
  onToggle?.(newShow);
@@ -11,7 +11,8 @@ const ChipPopper = ({ icon, deleteIcon, label, children, minWidth, placement = '
11
11
  return (_jsxs(_Fragment, { children: [_jsx(Chip, { icon: icon, deleteIcon: deleteIcon, label: label, onClick: e => {
12
12
  handleToggle(!show);
13
13
  e.stopPropagation();
14
- }, onDelete: onDelete ?? (toggleOnDelete ? () => handleToggle(!show) : null), ref: anchorEl, sx: [
14
+ e.preventDefault();
15
+ }, onDelete: onDelete ?? (toggleOnDelete ? () => handleToggle(!show) : null), ref: setAnchorEl, sx: [
15
16
  theme => ({
16
17
  position: 'relative',
17
18
  zIndex: 1,
@@ -19,8 +20,8 @@ const ChipPopper = ({ icon, deleteIcon, label, children, minWidth, placement = '
19
20
  }),
20
21
  show && { borderBottomLeftRadius: '0', borderBottomRightRadius: '0' },
21
22
  ...(Array.isArray(slotProps.chip?.sx) ? slotProps.chip.sx : [slotProps.chip?.sx])
22
- ], ...(slotProps.chip ?? {}) }), _jsx(Popper, { placement: placement, anchorEl: anchorEl.current, disablePortal: disablePortal, open: true, sx: {
23
- minWidth: Math.max(typeof minWidth === 'number' ? minWidth : parseInt(minWidth?.replace('px', '')) || 0, anchorEl.current?.clientWidth || 0),
23
+ ], ...(slotProps.chip ?? {}) }), _jsx(Popper, { placement: placement, anchorEl: anchorEl, disablePortal: disablePortal, open: !!anchorEl, sx: {
24
+ minWidth: Math.max(typeof minWidth === 'number' ? minWidth : parseInt(minWidth?.replace('px', '')) || 0, anchorEl?.clientWidth || 0),
24
25
  zIndex: 1000
25
26
  }, children: _jsx(Collapse, { in: show, unmountOnExit: true, onClick: () => {
26
27
  if (closeOnClick) {
@@ -16,7 +16,7 @@ const Classification = () => {
16
16
  return config.c12nDef?.RESTRICTED ?? 'Unknown';
17
17
  }
18
18
  }, [config.c12nDef?.RESTRICTED, isSm]);
19
- const color = useMemo(() => config.c12nDef?.levels_styles_map?.[label.replace(/\/\/.+/, '')]?.color ?? 'default', [config.c12nDef?.levels_styles_map, label]);
19
+ const color = useMemo(() => (config.c12nDef?.levels_styles_map?.[label.replace(/\/\/.+/, '')]?.color ?? 'default'), [config.c12nDef?.levels_styles_map, label]);
20
20
  return _jsx(Chip, { label: t(label), color: color, sx: { mr: 1, fontSize: '.9rem', p: 2, textTransform: 'uppercase' } });
21
21
  };
22
22
  export default Classification;
@@ -0,0 +1,14 @@
1
+ import type { ChipOwnProps } from '@mui/material';
2
+ import React from 'react';
3
+ import { type FormatProp } from '@cccsaurora/howler-ui/utils/classificationParser';
4
+ interface EnrichedChipProps {
5
+ classification: string;
6
+ format?: FormatProp;
7
+ isMobile?: boolean;
8
+ }
9
+ declare const _default: React.NamedExoticComponent<EnrichedChipProps & ChipOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
10
+ ref?: React.Ref<HTMLDivElement>;
11
+ }, "icon" | "label" | "size" | "className" | "style" | "classes" | "children" | "color" | "sx" | "tabIndex" | "disabled" | "avatar" | "variant" | "clickable" | "deleteIcon" | "onDelete" | "skipFocusWhenDisabled"> & {
12
+ component?: React.ElementType;
13
+ }>;
14
+ export default _default;
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Chip, Tooltip } from '@mui/material';
3
+ import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
4
+ import React, { memo, useContext, useMemo } from 'react';
5
+ import { getParts, normalizedClassification } from '@cccsaurora/howler-ui/utils/classificationParser';
6
+ const THEME_TYPES = ['default', 'primary', 'secondary', 'error', 'info', 'success', 'warning'];
7
+ const ClassificationChip = React.memo(({ classification, format = 'short', isMobile = true, ...otherProps }) => {
8
+ const { config } = useContext(ApiConfigContext);
9
+ const parts = useMemo(() => {
10
+ if (!config.c12nDef) {
11
+ return null;
12
+ }
13
+ return getParts(classification, config.c12nDef, format, isMobile);
14
+ }, [classification, config.c12nDef, format, isMobile]);
15
+ const normalized = useMemo(() => {
16
+ if (!config.c12nDef || !parts) {
17
+ return classification;
18
+ }
19
+ return normalizedClassification(parts, config.c12nDef, format, isMobile);
20
+ }, [classification, config.c12nDef, format, isMobile, parts]);
21
+ const chipProps = useMemo(() => {
22
+ const definedColor = config.c12nDef?.levels_styles_map[config.c12nDef?.levels_map[parts.lvlIdx]]?.color;
23
+ if (THEME_TYPES.includes(definedColor)) {
24
+ return { color: definedColor };
25
+ }
26
+ if (definedColor) {
27
+ return { sx: { color: definedColor } };
28
+ }
29
+ return { color: 'default' };
30
+ }, [config.c12nDef?.levels_map, config.c12nDef?.levels_styles_map, parts.lvlIdx]);
31
+ return (_jsx(Tooltip, { title: classification, children: _jsx(Chip, { variant: otherProps.variant || 'outlined', label: normalized, ...chipProps, ...otherProps, sx: [
32
+ ...(Array.isArray(chipProps.sx) ? chipProps.sx : [chipProps.sx]),
33
+ ...(Array.isArray(otherProps.sx) ? otherProps.sx : [otherProps.sx])
34
+ ] }) }));
35
+ });
36
+ export default memo(ClassificationChip);
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Card } from '@mui/material';
3
3
  import { memo } from 'react';
4
- const HowlerCard = props => (_jsx(Card, { style: { outline: 'none' }, elevation: props.variant !== 'outlined' ? 4 : 0, ...props }));
4
+ const HowlerCard = props => _jsx(Card, { elevation: props.variant !== 'outlined' ? 1 : 0, ...props });
5
5
  export default memo(HowlerCard);
@@ -12,25 +12,21 @@ describe('HowlerCard', () => {
12
12
  const { container } = render(_jsx(HowlerCard, {}));
13
13
  expect(container.firstChild).toHaveClass('MuiCard-root');
14
14
  });
15
- it('always applies outline: none style', () => {
16
- const { container } = render(_jsx(HowlerCard, {}));
17
- expect(container.firstChild).toHaveStyle({ outline: 'none' });
18
- });
19
15
  });
20
16
  describe('elevation', () => {
21
- it('uses elevation 4 when no variant is specified', () => {
17
+ it('uses elevation when no variant is specified', () => {
22
18
  const { container } = render(_jsx(HowlerCard, {}));
23
- expect(container.firstChild).toHaveClass('MuiPaper-elevation4');
19
+ expect(container.firstChild).toHaveClass('MuiPaper-elevation');
24
20
  });
25
- it('uses elevation 4 when variant is not outlined', () => {
21
+ it('uses elevation when variant is not outlined', () => {
26
22
  const { container } = render(_jsx(HowlerCard, { variant: "elevation" }));
27
- expect(container.firstChild).toHaveClass('MuiPaper-elevation4');
23
+ expect(container.firstChild).toHaveClass('MuiPaper-elevation');
28
24
  });
29
25
  it('uses the outlined variant style (not elevation) when variant is outlined', () => {
30
26
  const { container } = render(_jsx(HowlerCard, { variant: "outlined" }));
31
27
  // MUI renders the outlined variant with MuiPaper-outlined, not an elevation class
32
28
  expect(container.firstChild).toHaveClass('MuiPaper-outlined');
33
- expect(container.firstChild).not.toHaveClass('MuiPaper-elevation4');
29
+ expect(container.firstChild).not.toHaveClass('MuiPaper-elevation');
34
30
  });
35
31
  });
36
32
  describe('prop passthrough', () => {
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Fab, IconButton, LinearProgress, Stack, Tooltip, Typography, useMediaQuery } from '@mui/material';
3
3
  import PageCenter from '@cccsaurora/howler-ui/commons/components/pages/PageCenter';
4
4
  import { useTranslation } from 'react-i18next';
@@ -20,7 +20,7 @@ const ItemManager = ({ aboveSearch, afterSearch, belowSearch, searchFilters, has
20
20
  sx: {
21
21
  pr: 1
22
22
  }
23
- }, startAdornment: _jsx(Tooltip, { title: t(searchPrompt), children: _jsx(IconButton, { onClick: () => onSearch(), children: _jsx(Search, {}) }) }), endAdornment: _jsx(_Fragment, { children: searchAdornment }) }), searching && (_jsx(LinearProgress, { sx: theme => ({
23
+ }, endAdornment: _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Tooltip, { title: t(searchPrompt), children: _jsx(IconButton, { onClick: () => onSearch(), children: _jsx(Search, {}) }) }), searchAdornment] }) }), searching && (_jsx(LinearProgress, { sx: theme => ({
24
24
  mt: -0.5,
25
25
  borderBottomLeftRadius: theme.shape.borderRadius,
26
26
  borderBottomRightRadius: theme.shape.borderRadius
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Box, Modal as MuiModal } from '@mui/material';
3
3
  import { ModalContext } from '@cccsaurora/howler-ui/components/app/providers/ModalProvider';
4
+ import { has } from 'lodash-es';
4
5
  import { useCallback, useContext } from 'react';
5
6
  const Modal = () => {
6
7
  const { content, setContent, options } = useContext(ModalContext);
@@ -15,6 +16,7 @@ const Modal = () => {
15
16
  left: '50%',
16
17
  maxWidth: options.maxWidth || '1200px',
17
18
  maxHeight: options.maxHeight || '400px',
19
+ height: has(options, 'height') ? options.height : '100%',
18
20
  transform: 'translate(-50%, -50%)',
19
21
  backgroundColor: 'background.paper',
20
22
  borderRadius: theme.shape.borderRadius,
@@ -2,5 +2,6 @@ import type { FC } from 'react';
2
2
  declare const QueryResultText: FC<{
3
3
  count: number;
4
4
  query: string;
5
+ mb?: number;
5
6
  }>;
6
7
  export default QueryResultText;