@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
@@ -105,6 +105,12 @@ export const DATE_RANGES = [
105
105
  'date.range.all',
106
106
  'date.range.custom'
107
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
+ };
108
114
  export const LABEL_TYPES = {
109
115
  insight: { icon: _jsx(PsychologyAlt, { fontSize: "small" }), color: '#FFFFFF' }, //brain icon
110
116
  mitigation: { icon: _jsx(LocalPolice, { fontSize: "small" }), color: blue[600] }, //police badge
@@ -0,0 +1,3 @@
1
+ import type { Event } from '@cccsaurora/howler-ui/models/entities/generated/Event';
2
+ import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
3
+ export declare const getUserList: (record: Hit | Event) => Set<string>;
@@ -0,0 +1,8 @@
1
+ export const getUserList = (record) => {
2
+ const ids = new Set();
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
+ }
7
+ return ids;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { getUserList } from './hitFunctions';
2
+ import { getUserList } from './recordFunctions';
3
3
  const makeHit = (howlerOverrides = {}) => ({
4
4
  howler: {
5
5
  log: [],
@@ -1,8 +1,22 @@
1
1
  import type { RecievedDataType } from '@cccsaurora/howler-ui/components/app/providers/SocketProvider';
2
+ import type { CaseUpdate } from '@cccsaurora/howler-ui/models/socket/CaseUpdate';
2
3
  import type { HitUpdate } from '@cccsaurora/howler-ui/models/socket/HitUpdate';
4
+ import type { ViewersUpdate } from '@cccsaurora/howler-ui/models/socket/ViewersUpdate';
3
5
  /**
4
6
  * Checks to see if the data recieved from the socket is a hit update
5
7
  * @param data The data recieved from the socket
6
8
  * @returns whether the data is a hit update
7
9
  */
8
10
  export declare const isHitUpdate: (data: any) => data is RecievedDataType<HitUpdate>;
11
+ /**
12
+ * Checks to see if the data received from the socket is a case update
13
+ * @param data The data received from the socket
14
+ * @returns whether the data is a case update
15
+ */
16
+ export declare const isCaseUpdate: (data: any) => data is RecievedDataType<CaseUpdate>;
17
+ /**
18
+ * Checks to see if the data received from the socket is a viewers update
19
+ * @param data The data received from the socket
20
+ * @returns whether the data is a viewers update
21
+ */
22
+ export declare const isViewersUpdate: (data: any) => data is RecievedDataType<ViewersUpdate>;
@@ -4,5 +4,21 @@
4
4
  * @returns whether the data is a hit update
5
5
  */
6
6
  export const isHitUpdate = (data) => {
7
- return data.version && data.hit;
7
+ return !!(data.version && data.hit);
8
+ };
9
+ /**
10
+ * Checks to see if the data received from the socket is a case update
11
+ * @param data The data received from the socket
12
+ * @returns whether the data is a case update
13
+ */
14
+ export const isCaseUpdate = (data) => {
15
+ return !!(data.type === 'cases' && data.case);
16
+ };
17
+ /**
18
+ * Checks to see if the data received from the socket is a viewers update
19
+ * @param data The data received from the socket
20
+ * @returns whether the data is a viewers update
21
+ */
22
+ export const isViewersUpdate = (data) => {
23
+ return !!(data.type === 'viewers_update' && data.viewers && data.id);
8
24
  };
@@ -1,26 +1,59 @@
1
- /// <reference types="vitest" />
2
1
  import { describe, expect, it } from 'vitest';
3
- import { isHitUpdate } from './socketUtils';
2
+ import { isCaseUpdate, isHitUpdate, isViewersUpdate } from './socketUtils';
4
3
  describe('isHitUpdate', () => {
5
- it('returns truthy when data has both a truthy version and a hit', () => {
6
- expect(isHitUpdate({ version: 1, hit: {} })).toBeTruthy();
4
+ it('returns true when data has version and hit', () => {
5
+ const data = { version: '1', hit: { howler: { id: 'h1' } }, type: 'hits', error: false, message: '', status: 200 };
6
+ expect(isHitUpdate(data)).toBeTruthy();
7
7
  });
8
- it('returns truthy when version is a non-empty string', () => {
9
- expect(isHitUpdate({ version: 'v1', hit: { howler: {} } })).toBeTruthy();
8
+ it('returns false when hit is missing', () => {
9
+ const data = { version: '1', type: 'hits', error: false, message: '', status: 200 };
10
+ expect(isHitUpdate(data)).toBeFalsy();
10
11
  });
11
- it('returns falsy when version is missing', () => {
12
- expect(isHitUpdate({ hit: {} })).toBeFalsy();
12
+ it('returns false when version is missing', () => {
13
+ const data = { hit: { howler: { id: 'h1' } }, type: 'hits', error: false, message: '', status: 200 };
14
+ expect(isHitUpdate(data)).toBeFalsy();
13
15
  });
14
- it('returns falsy when hit is missing', () => {
15
- expect(isHitUpdate({ version: 1 })).toBeFalsy();
16
+ });
17
+ describe('isCaseUpdate', () => {
18
+ it('returns true when type is cases and case is present', () => {
19
+ const data = { type: 'cases', case: { case_id: 'c1' }, error: false, message: '', status: 200 };
20
+ expect(isCaseUpdate(data)).toBeTruthy();
21
+ });
22
+ it('returns false when type is not cases', () => {
23
+ const data = { type: 'hits', case: { case_id: 'c1' }, error: false, message: '', status: 200 };
24
+ expect(isCaseUpdate(data)).toBeFalsy();
25
+ });
26
+ it('returns false when case is missing', () => {
27
+ const data = { type: 'cases', error: false, message: '', status: 200 };
28
+ expect(isCaseUpdate(data)).toBeFalsy();
29
+ });
30
+ it('returns false when case is null', () => {
31
+ const data = { type: 'cases', case: null, error: false, message: '', status: 200 };
32
+ expect(isCaseUpdate(data)).toBeFalsy();
33
+ });
34
+ });
35
+ describe('isViewersUpdate', () => {
36
+ it('returns true when type is viewers_update with id and viewers', () => {
37
+ const data = {
38
+ type: 'viewers_update',
39
+ id: 'entity-1',
40
+ viewers: ['alice', 'bob'],
41
+ error: false,
42
+ message: '',
43
+ status: 200
44
+ };
45
+ expect(isViewersUpdate(data)).toBeTruthy();
16
46
  });
17
- it('returns falsy when both fields are missing', () => {
18
- expect(isHitUpdate({})).toBeFalsy();
47
+ it('returns false when type is wrong', () => {
48
+ const data = { type: 'cases', id: 'entity-1', viewers: ['alice'], error: false, message: '', status: 200 };
49
+ expect(isViewersUpdate(data)).toBeFalsy();
19
50
  });
20
- it('returns falsy when version is 0 (falsy)', () => {
21
- expect(isHitUpdate({ version: 0, hit: {} })).toBeFalsy();
51
+ it('returns false when viewers is missing', () => {
52
+ const data = { type: 'viewers_update', id: 'entity-1', error: false, message: '', status: 200 };
53
+ expect(isViewersUpdate(data)).toBeFalsy();
22
54
  });
23
- it('returns falsy when hit is null (falsy)', () => {
24
- expect(isHitUpdate({ version: 1, hit: null })).toBeFalsy();
55
+ it('returns false when id is missing', () => {
56
+ const data = { type: 'viewers_update', viewers: ['alice'], error: false, message: '', status: 200 };
57
+ expect(isViewersUpdate(data)).toBeFalsy();
25
58
  });
26
59
  });
@@ -0,0 +1,7 @@
1
+ import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
+ import type { Event } from '@cccsaurora/howler-ui/models/entities/generated/Event';
3
+ import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
4
+ import type { WithMetadata } from '@cccsaurora/howler-ui/models/WithMetadata';
5
+ export declare const isHit: (obj: WithMetadata<any>) => obj is Hit;
6
+ export declare const isCase: (obj: WithMetadata<any>) => obj is Case;
7
+ export declare const isEvent: (obj: WithMetadata<any>) => obj is Event;
@@ -0,0 +1,27 @@
1
+ export const isHit = (obj) => {
2
+ if (!obj) {
3
+ return false;
4
+ }
5
+ if (obj.__index === 'hit') {
6
+ return true;
7
+ }
8
+ return false;
9
+ };
10
+ export const isCase = (obj) => {
11
+ if (!obj) {
12
+ return false;
13
+ }
14
+ if (obj.__index === 'case') {
15
+ return true;
16
+ }
17
+ return false;
18
+ };
19
+ export const isEvent = (obj) => {
20
+ if (!obj) {
21
+ return false;
22
+ }
23
+ if (obj.__index === 'event') {
24
+ return true;
25
+ }
26
+ return false;
27
+ };
@@ -7,5 +7,8 @@ export const buildViewUrl = (view) => {
7
7
  if (view.sort) {
8
8
  params.set('sort', view.sort);
9
9
  }
10
+ if (view.indexes && view.indexes.length > 0) {
11
+ view.indexes.forEach(index => params.append('index', index));
12
+ }
10
13
  return `/search?${params.toString()}`;
11
14
  };
@@ -1,4 +0,0 @@
1
- import { type HowlerRefreshParam } from '@cccsaurora/howler-ui/api';
2
- import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
- export declare const uri: () => string;
4
- export declare const post: (body: Pick<Analytic, "description" | "name" | "rule" | "rule_type" | "rule_crontab">, refresh?: HowlerRefreshParam) => Promise<Analytic>;
@@ -1,8 +0,0 @@
1
- import { hpost, joinUri } from '@cccsaurora/howler-ui/api';
2
- import { uri as parentUri } from '@cccsaurora/howler-ui/api/analytic';
3
- export const uri = () => {
4
- return joinUri(parentUri(), 'rules');
5
- };
6
- export const post = (body, refresh) => {
7
- return hpost(uri(), body, undefined, refresh ? new URLSearchParams({ refresh }) : undefined);
8
- };
@@ -1,22 +0,0 @@
1
- import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
- import type { WithMetadata } from '@cccsaurora/howler-ui/models/WithMetadata';
3
- import type { FC, PropsWithChildren } from 'react';
4
- export interface HitContextType {
5
- hits: {
6
- [index: string]: Hit;
7
- };
8
- selectedHits: Hit[];
9
- addHitToSelection: (id: string) => void;
10
- removeHitFromSelection: (id: string) => void;
11
- clearSelectedHits: (except?: string) => void;
12
- loadHits: (hits: Hit[]) => void;
13
- updateHit: (newHit: Hit) => void;
14
- getHit: (id: string, force?: boolean) => Promise<WithMetadata<Hit>>;
15
- }
16
- export declare const HitContext: import("use-context-selector").Context<HitContextType>;
17
- /**
18
- * Central repository for storing individual hit data across the application. Allows efficient retrieval of hits across componenents.
19
- */
20
- declare const HitProvider: FC<PropsWithChildren>;
21
- export declare const useHitContextSelector: <Selected>(selector: (value: HitContextType) => Selected) => Selected;
22
- export default HitProvider;
@@ -1,6 +0,0 @@
1
- import type { FC } from 'react';
2
- declare const BundleButton: FC<{
3
- ids: string[];
4
- disabled?: boolean;
5
- }>;
6
- export default BundleButton;
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AccountTree } from '@mui/icons-material';
3
- import { ListItemText, Menu, MenuItem, Typography } from '@mui/material';
4
- import TuiIconButton from '@cccsaurora/howler-ui/components/elements/addons/buttons/CustomIconButton';
5
- import { useCallback, useState } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
- import { useNavigate } from 'react-router-dom';
8
- const BundleButton = ({ ids, disabled = false }) => {
9
- const { t } = useTranslation();
10
- const navigate = useNavigate();
11
- const [anchorEl, setAnchorEl] = useState(null);
12
- const onClick = useCallback((event) => {
13
- if (ids.length === 1) {
14
- navigate(`/bundles/${ids[0]}`);
15
- }
16
- else {
17
- setAnchorEl(event.currentTarget);
18
- }
19
- }, [ids, navigate]);
20
- const handleClose = useCallback(() => setAnchorEl(null), []);
21
- return (_jsxs(_Fragment, { children: [_jsx(TuiIconButton, { size: "small", tooltip: t(`hit.panel.bundles.open${ids.length > 1 ? '' : '.prompt'}`), onClick: onClick, disabled: disabled, "aria-disabled": disabled, "aria-haspopup": "true", "aria-controls": anchorEl ? 'bundle-action-menu' : undefined, "aria-expanded": anchorEl ? 'true' : undefined, children: _jsx(AccountTree, {}) }), _jsx(Menu, { id: "bundle-action-menu", anchorEl: anchorEl, open: !!anchorEl, onClose: handleClose, MenuListProps: {
22
- dense: true,
23
- 'aria-labelledby': `bundle-button`
24
- }, anchorOrigin: {
25
- vertical: 'bottom',
26
- horizontal: 'right'
27
- }, transformOrigin: {
28
- vertical: 'top',
29
- horizontal: 'right'
30
- }, children: ids.map(id => (_jsx(MenuItem, { onClick: () => navigate(`/bundles/${id}`), children: _jsx(ListItemText, { primary: t('hit.panel.bundles.open.prompt'), secondary: _jsx(Typography, { variant: "caption", color: "text.secondary", children: id }) }) }, id))) })] }));
31
- };
32
- export default BundleButton;
@@ -1,239 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { AddCircleOutline, Assignment, Edit, HowToVote, KeyboardArrowRight, OpenInNew, QueryStats, RemoveCircleOutline, SettingsSuggest, Terminal } from '@mui/icons-material';
3
- import { Box, Divider, Fade, ListItemIcon, ListItemText, Menu, MenuItem, MenuList, Paper } from '@mui/material';
4
- import api from '@cccsaurora/howler-ui/api';
5
- import { useAppUser } from '@cccsaurora/howler-ui/commons/components/app/hooks';
6
- import useMatchers from '@cccsaurora/howler-ui/components/app/hooks/useMatchers';
7
- import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
8
- import { HitContext } from '@cccsaurora/howler-ui/components/app/providers/HitProvider';
9
- import { ParameterContext } from '@cccsaurora/howler-ui/components/app/providers/ParameterProvider';
10
- import { TOP_ROW, VOTE_OPTIONS } from '@cccsaurora/howler-ui/components/elements/hit/actions/SharedComponents';
11
- import useHitActions from '@cccsaurora/howler-ui/components/hooks/useHitActions';
12
- import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
13
- import useMyActionFunctions from '@cccsaurora/howler-ui/components/routes/action/useMyActionFunctions';
14
- import { capitalize, get, groupBy, isEmpty, toString } from 'lodash-es';
15
- import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
16
- import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
17
- import { useTranslation } from 'react-i18next';
18
- import { usePluginStore } from 'react-pluggable';
19
- import { Link } from 'react-router-dom';
20
- import { useContextSelector } from 'use-context-selector';
21
- import { DEFAULT_QUERY } from '@cccsaurora/howler-ui/utils/constants';
22
- import { sanitizeLuceneQuery } from '@cccsaurora/howler-ui/utils/stringUtils';
23
- /**
24
- * Order in which action types should be displayed in the context menu
25
- */
26
- const ORDER = ['assessment', 'vote', 'action'];
27
- /**
28
- * The margin at the bottom of the screen by which the context menu should be inverted.
29
- * That is, if right clicking within this many pixels of the bottom, render the context menu to the top right
30
- * of the pointer instead of the bottom right.
31
- */
32
- const CONTEXTMENU_MARGIN = 350;
33
- /**
34
- * Icon mapping for different action types
35
- */
36
- const ICON_MAP = {
37
- assessment: _jsx(Assignment, {}),
38
- vote: _jsx(HowToVote, {}),
39
- action: _jsx(Edit, {})
40
- };
41
- /**
42
- * Context menu component for hit operations.
43
- * Provides quick access to common hit actions including assessment, voting,
44
- * transitions, and exclusion filters based on template fields.
45
- */
46
- const HitContextMenu = ({ children, getSelectedId, Component = Box }) => {
47
- const { t } = useTranslation();
48
- const { dispatchApi } = useMyApi();
49
- const { executeAction } = useMyActionFunctions();
50
- const appUser = useAppUser();
51
- const { config } = useContext(ApiConfigContext);
52
- const pluginStore = usePluginStore();
53
- const { getMatchingAnalytic, getMatchingTemplate } = useMatchers();
54
- const query = useContextSelector(ParameterContext, ctx => ctx?.query);
55
- const setQuery = useContextSelector(ParameterContext, ctx => ctx?.setQuery);
56
- const [id, setId] = useState(null);
57
- const hit = useContextSelector(HitContext, ctx => ctx.hits[id]);
58
- const selectedHits = useContextSelector(HitContext, ctx => ctx.selectedHits);
59
- const [analytic, setAnalytic] = useState(null);
60
- const [template, setTemplate] = useState(null);
61
- const [anchorEl, setAnchorEl] = useState();
62
- const [transformProps, setTransformProps] = useState({});
63
- const [actions, setActions] = useState([]);
64
- const [show, setShow] = useState({});
65
- const hits = useMemo(() => (selectedHits.some(_hit => _hit.howler.id === hit?.howler.id) ? selectedHits : [hit]), [hit, selectedHits]);
66
- const { availableTransitions, canVote, canAssess, assess, vote } = useHitActions(hits);
67
- /**
68
- * Checks if the current user has permission to run actions.
69
- * Users must have one of the automation or actionrunner roles, or be an admin.
70
- */
71
- const canRunActions = useCallback(() => {
72
- const roles = ['admin', 'automation_advanced', 'automation_basic', 'actionrunner_advanced', 'actionrunner_basic'];
73
- return roles.some((role) => appUser.user?.roles?.includes(role));
74
- }, [appUser.user?.roles]);
75
- /**
76
- * Handles right-click context menu events.
77
- * Opens the context menu at the click location and loads available actions.
78
- */
79
- const onContextMenu = useCallback(async (event) => {
80
- if (anchorEl) {
81
- event.preventDefault();
82
- setAnchorEl(null);
83
- return;
84
- }
85
- event.preventDefault();
86
- const _id = getSelectedId(event);
87
- setId(_id);
88
- if (window.innerHeight - event.clientY < 300) {
89
- setTransformProps({
90
- position: 'fixed',
91
- bottom: `${window.innerHeight - event.clientY}px !important`,
92
- top: 'unset !important',
93
- left: `${event.clientX}px !important`
94
- });
95
- }
96
- else {
97
- setTransformProps({
98
- position: 'fixed',
99
- top: `${event.clientY}px !important`,
100
- left: `${event.clientX}px !important`
101
- });
102
- }
103
- setAnchorEl(event.target);
104
- // TODO: Bumping the number of rows is a temporary fix - we'll need to improve this.
105
- const _actions = (await dispatchApi(api.search.action.post({ query: 'action_id:*', rows: 100, sort: 'name asc' }), {
106
- throwError: false
107
- }))?.items;
108
- if (_actions) {
109
- setActions(_actions);
110
- }
111
- }, [anchorEl, dispatchApi, getSelectedId]);
112
- const rowStatus = useMemo(() => ({
113
- assessment: canAssess,
114
- vote: canVote
115
- }), [canAssess, canVote]);
116
- const pluginActions = howlerPluginStore.plugins.flatMap(plugin => pluginStore.executeFunction(`${plugin}.actions`, hits));
117
- /**
118
- * Generates grouped action entries for the context menu.
119
- * Combines transitions, plugin actions, votes, and assessments based on permissions.
120
- */
121
- const entries = useMemo(() => {
122
- let _actions = [...availableTransitions, ...pluginActions];
123
- if (canVote) {
124
- _actions = [
125
- ..._actions,
126
- ...VOTE_OPTIONS.map(option => ({ ...option, actionFunction: () => vote(option.name.toLowerCase()) }))
127
- ];
128
- }
129
- if (config.lookups?.['howler.assessment'] && canAssess) {
130
- _actions = [
131
- ..._actions,
132
- ...config.lookups['howler.assessment']
133
- .filter(_assessment => analytic?.triage_settings?.valid_assessments
134
- ? analytic.triage_settings?.valid_assessments.includes(_assessment)
135
- : true)
136
- .sort((a, b) => +TOP_ROW.includes(b) - +TOP_ROW.includes(a))
137
- .map(assessment => ({
138
- type: 'assessment',
139
- name: assessment,
140
- actionFunction: async () => {
141
- await assess(assessment, analytic?.triage_settings?.skip_rationale);
142
- }
143
- }))
144
- ];
145
- }
146
- return Object.entries(groupBy(_actions, 'type')).sort(([a], [b]) => ORDER.indexOf(a) - ORDER.indexOf(b));
147
- }, [analytic, assess, availableTransitions, canAssess, canVote, config.lookups, vote, pluginActions]);
148
- /**
149
- * Calculates appropriate styles for submenu positioning.
150
- * Adjusts position based on available screen space to prevent overflow.
151
- */
152
- const calculateSubMenuStyles = useCallback((parent) => {
153
- const baseStyles = { position: 'absolute', maxHeight: '300px', overflow: 'auto' };
154
- const defaultStyles = { ...baseStyles, top: 0, left: '100%' };
155
- if (!parent) {
156
- return defaultStyles;
157
- }
158
- const parentBounds = parent.getBoundingClientRect();
159
- if (window.innerHeight - parentBounds.y < CONTEXTMENU_MARGIN) {
160
- return { ...baseStyles, bottom: 0, left: '100%' };
161
- }
162
- return defaultStyles;
163
- }, []);
164
- // Load analytic and template data when a hit is selected
165
- useEffect(() => {
166
- if (!hit?.howler.analytic) {
167
- return;
168
- }
169
- getMatchingAnalytic(hit).then(setAnalytic);
170
- getMatchingTemplate(hit).then(setTemplate);
171
- // eslint-disable-next-line react-hooks/exhaustive-deps
172
- }, [hit]);
173
- // Reset menu state when context menu is closed
174
- useEffect(() => {
175
- if (!anchorEl) {
176
- setShow({});
177
- setAnalytic(null);
178
- }
179
- }, [anchorEl]);
180
- return (_jsxs(Component, { id: "contextMenu", onContextMenu: onContextMenu, children: [children, _jsxs(Menu, { id: "hit-menu", open: !!anchorEl, anchorEl: anchorEl, onClose: () => setAnchorEl(null), slotProps: {
181
- paper: {
182
- sx: {
183
- ...transformProps,
184
- overflow: 'visible !important'
185
- }
186
- }
187
- }, MenuListProps: { dense: true, sx: { minWidth: '250px' } }, anchorOrigin: { vertical: 'top', horizontal: 'left' }, onClick: () => setAnchorEl(null), children: [_jsxs(MenuItem, { component: Link, to: `/hits/${hit?.howler.id}`, disabled: !hit, children: [_jsx(ListItemIcon, { children: _jsx(OpenInNew, {}) }), _jsx(ListItemText, { children: t('hit.panel.open') })] }), _jsxs(MenuItem, { component: Link, to: `/analytics/${analytic?.analytic_id}`, disabled: !analytic, children: [_jsx(ListItemIcon, { children: _jsx(QueryStats, {}) }), _jsx(ListItemText, { children: t('hit.panel.analytic.open') })] }), _jsx(Divider, {}), entries.map(([type, items]) => (_jsxs(MenuItem, { id: `${type}-menu-item`, sx: { position: 'relative' }, onMouseEnter: ev => setShow(_show => ({ ..._show, [type]: ev.target })), onMouseLeave: () => setShow(_show => ({ ..._show, [type]: null })), disabled: rowStatus[type] === false, children: [_jsx(ListItemIcon, { children: ICON_MAP[type] ?? _jsx(Terminal, {}) }), _jsx(ListItemText, { sx: { flex: 1 }, children: t(`hit.details.actions.${type}`) }), rowStatus[type] !== false && (_jsx(KeyboardArrowRight, { fontSize: "small", sx: { color: 'text.secondary', mr: -1 } })), _jsx(Fade, { in: !!show[type], unmountOnExit: true, children: _jsx(Paper, { id: `${type}-submenu`, sx: calculateSubMenuStyles(show[type]), elevation: 8, children: _jsx(MenuList, { sx: { p: 0, borderTopLeftRadius: 0 }, dense: true, role: "group", children: items.map(a => (_jsx(MenuItem, { value: a.name, onClick: a.actionFunction, children: a.i18nKey ? t(a.i18nKey) : capitalize(a.name) }, a.name))) }) }) })] }, type))), _jsxs(MenuItem, { id: "actions-menu-item", sx: { position: 'relative' }, onMouseEnter: ev => setShow(_show => ({ ..._show, actions: ev.target })), onMouseLeave: () => setShow(_show => ({ ..._show, actions: null })), disabled: actions.length < 1 || !canRunActions(), children: [_jsx(ListItemIcon, { children: _jsx(SettingsSuggest, {}) }), _jsx(ListItemText, { sx: { flex: 1 }, children: t('route.actions.change') }), actions.length > 0 && _jsx(KeyboardArrowRight, { fontSize: "small", sx: { color: 'text.secondary', mr: -1 } }), _jsx(Fade, { in: !!show.actions, unmountOnExit: true, children: _jsx(Paper, { id: "actions-submenu", sx: calculateSubMenuStyles(show.actions), elevation: 8, children: _jsx(MenuList, { sx: { p: 0 }, dense: true, role: "group", children: actions.map(action => (_jsx(MenuItem, { onClick: () => executeAction(action.action_id, `howler.id:${hit?.howler.id}`), children: _jsx(ListItemText, { children: action.name }) }, action.action_id))) }) }) })] }), !isEmpty(template?.keys ?? []) && setQuery && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsxs(MenuItem, { id: "excludes-menu-item", sx: { position: 'relative' }, onMouseEnter: ev => setShow(_show => ({ ..._show, excludes: ev.target })), onMouseLeave: () => setShow(_show => ({ ..._show, excludes: null })), children: [_jsx(ListItemIcon, { children: _jsx(RemoveCircleOutline, {}) }), _jsx(ListItemText, { sx: { flex: 1 }, children: t('hit.panel.exclude') }), _jsx(KeyboardArrowRight, { fontSize: "small", sx: { color: 'text.secondary', mr: -1 } }), _jsx(Fade, { in: !!show.excludes, unmountOnExit: true, children: _jsx(Paper, { id: "excludes-submenu", sx: calculateSubMenuStyles(show.excludes), elevation: 8, children: _jsx(MenuList, { sx: { p: 0 }, dense: true, role: "group", children: template?.keys.map(key => {
188
- // Build exclusion query based on current query and field value
189
- let newQuery = '';
190
- if (query !== DEFAULT_QUERY) {
191
- newQuery = `(${query}) AND `;
192
- }
193
- const value = get(hit, key);
194
- if (!value) {
195
- return null;
196
- }
197
- else if (Array.isArray(value)) {
198
- // Handle array values by excluding all items
199
- const sanitizedValues = value
200
- .map(toString)
201
- .filter(val => !!val)
202
- .map(val => `"${sanitizeLuceneQuery(val)}"`);
203
- if (sanitizedValues.length < 1) {
204
- return null;
205
- }
206
- newQuery += `-${key}:(${sanitizedValues.join(' OR ')})`;
207
- }
208
- else {
209
- // Handle single value
210
- newQuery += `-${key}:"${sanitizeLuceneQuery(value.toString())}"`;
211
- }
212
- return (_jsx(MenuItem, { onClick: () => setQuery(newQuery), children: _jsx(ListItemText, { children: key }) }, key));
213
- }) }) }) })] }), _jsxs(MenuItem, { id: "includes-menu-item", sx: { position: 'relative' }, onMouseEnter: ev => setShow(_show => ({ ..._show, includes: ev.target })), onMouseLeave: () => setShow(_show => ({ ..._show, includes: null })), children: [_jsx(ListItemIcon, { children: _jsx(AddCircleOutline, {}) }), _jsx(ListItemText, { sx: { flex: 1 }, children: t('hit.panel.include') }), _jsx(KeyboardArrowRight, { fontSize: "small", sx: { color: 'text.secondary', mr: -1 } }), _jsx(Fade, { in: !!show.includes, unmountOnExit: true, children: _jsx(Paper, { id: "includes-submenu", sx: calculateSubMenuStyles(show.includes), elevation: 8, children: _jsx(MenuList, { sx: { p: 0 }, dense: true, role: "group", children: template?.keys.map(key => {
214
- // Build inclusion query based on current query and field
215
- // If default, we include default query
216
- let newQuery = `(${query}) AND `;
217
- const value = get(hit, key);
218
- if (!value) {
219
- return null;
220
- }
221
- else if (Array.isArray(value)) {
222
- // Handle array values by including all items
223
- const sanitizedValues = value
224
- .map(toString)
225
- .filter(val => !!val)
226
- .map(val => `"${sanitizeLuceneQuery(val)}"`);
227
- if (sanitizedValues.length < 1) {
228
- return null;
229
- }
230
- newQuery += `${key}:(${sanitizedValues.join(' OR ')})`;
231
- }
232
- else {
233
- // Handle single value
234
- newQuery += `${key}:"${sanitizeLuceneQuery(value.toString())}"`;
235
- }
236
- return (_jsx(MenuItem, { onClick: () => setQuery(newQuery), children: _jsx(ListItemText, { children: key }) }, key));
237
- }) }) }) })] })] }))] })] }));
238
- };
239
- export default HitContextMenu;
@@ -1,6 +0,0 @@
1
- import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
- import type { FC } from 'react';
3
- declare const HitRelated: FC<{
4
- hit: Hit;
5
- }>;
6
- export default HitRelated;
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Grid } from '@mui/material';
3
- import RelatedLink from './related/RelatedLink';
4
- const HitRelated = ({ hit }) => {
5
- return (_jsx(Grid, { container: true, spacing: 1, pr: 2, children: hit?.howler.links?.map(l => (_jsx(Grid, { item: true, xs: 6, sm: 4, md: 3, children: _jsx(RelatedLink, { ...l }) }, l.title + l.href))) }));
6
- };
7
- export default HitRelated;
@@ -1,33 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { avatarClasses, AvatarGroup, Chip, Divider, Stack, Typography } from '@mui/material';
3
- import { useAppUser } from '@cccsaurora/howler-ui/commons/components/app/hooks';
4
- import HowlerAvatar from '@cccsaurora/howler-ui/components/elements/display/HowlerAvatar';
5
- import { useTranslation } from 'react-i18next';
6
- import { HitLayout } from '../HitLayout';
7
- const AvatarChip = ({ userId, noUser, placeholder, layout, hideLabel }) => {
8
- const userAvatar = (_jsx(HowlerAvatar, { userId: userId, sx: { height: layout !== HitLayout.COMFY ? 24 : 32, width: layout !== HitLayout.COMFY ? 24 : 32 } }));
9
- return hideLabel ? (userAvatar) : (_jsx(Chip, { variant: "outlined", sx: {
10
- width: 'fit-content',
11
- '& .MuiChip-icon': {
12
- marginLeft: 0
13
- }
14
- }, icon: userAvatar, label: userId && userId !== noUser ? userId : placeholder, size: layout !== HitLayout.COMFY ? 'small' : 'medium' }));
15
- };
16
- const HitUsers = ({ hit, layout, hideLabel = false, showAssigned = false, showAssessor = false }) => {
17
- const { t } = useTranslation();
18
- const { user } = useAppUser();
19
- const assessorVisible = showAssessor || hit.howler.assessment != null;
20
- const assigneeVisible = !hit.howler.assessor && (showAssigned || hit.howler.assignment !== 'unassigned');
21
- return (_jsxs(Stack, { direction: hideLabel ? 'row' : 'column', spacing: 0.5, alignItems: "flex-start", children: [_jsxs(Stack, { display: "grid", gridTemplateColumns: "repeat(2, 1fr)", alignItems: "center", columnGap: 0.5, rowGap: 0.25, children: [assigneeVisible && (_jsxs(_Fragment, { children: [!hideLabel && _jsxs(Typography, { variant: "caption", children: [t('app.drawer.hit.assignment.assignee'), ":"] }), _jsx(AvatarChip, { userId: hit?.howler.assignment, noUser: "unassigned", placeholder: t('app.drawer.hit.assignment.unassigned.name'), layout: layout, hideLabel: hideLabel })] })), assessorVisible && (_jsxs(_Fragment, { children: [!hideLabel && _jsxs(Typography, { variant: "caption", children: [t('app.drawer.hit.assessment.assessor'), ":"] }), _jsx(AvatarChip, { userId: hit.howler.assessor, noUser: "unknown", placeholder: t('app.drawer.hit.assessment.unknown.name'), layout: layout, hideLabel: hideLabel })] }))] }), hit.howler.viewers?.length > 0 && hideLabel && _jsx(Divider, { orientation: "vertical", flexItem: true, variant: "middle" }), _jsx(AvatarGroup, { max: 3, sx: { [`.${avatarClasses.root}`]: { border: 0, marginLeft: 0.5 } }, componentsProps: {
22
- additionalAvatar: {
23
- sx: {
24
- height: layout !== HitLayout.COMFY ? 24 : 32,
25
- width: layout !== HitLayout.COMFY ? 24 : 32,
26
- fontSize: '12px'
27
- }
28
- }
29
- }, children: [...new Set(hit?.howler.viewers)]
30
- .filter(viewer => viewer !== user.username)
31
- .map(viewer => (_jsx(HowlerAvatar, { userId: viewer, sx: { height: layout !== HitLayout.COMFY ? 24 : 32, width: layout !== HitLayout.COMFY ? 24 : 32 } }, viewer))) })] }));
32
- };
33
- export default HitUsers;
@@ -1,7 +0,0 @@
1
- import type { FC } from 'react';
2
- declare const RuleModal: FC<{
3
- onSubmit: () => void;
4
- fileData: string;
5
- type: 'eql' | 'lucene' | 'yaml';
6
- }>;
7
- export default RuleModal;