@cccsaurora/howler-ui 2.17.0-dev.526 → 2.17.0-dev.539

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 (143) hide show
  1. package/api/index.d.ts +0 -2
  2. package/api/index.js +2 -4
  3. package/api/search/index.d.ts +1 -2
  4. package/api/search/index.js +1 -2
  5. package/commons/components/leftnav/LeftNavDrawer.js +1 -1
  6. package/components/app/App.js +0 -14
  7. package/components/app/providers/FavouritesProvider.js +2 -2
  8. package/components/elements/PluginTypography.d.ts +1 -2
  9. package/components/elements/PluginTypography.js +2 -3
  10. package/components/elements/UserList.d.ts +2 -5
  11. package/components/elements/UserList.js +5 -14
  12. package/components/elements/addons/search/phrase/Phrase.js +1 -1
  13. package/components/elements/display/HowlerCard.js +1 -1
  14. package/components/elements/display/Modal.js +0 -1
  15. package/components/elements/display/icons/BundleButton.d.ts +6 -0
  16. package/components/elements/display/icons/BundleButton.js +32 -0
  17. package/components/elements/hit/HitBanner.js +48 -27
  18. package/components/elements/{ObjectDetails.d.ts → hit/HitDetails.d.ts} +1 -2
  19. package/components/elements/{ObjectDetails.js → hit/HitDetails.js} +17 -17
  20. package/components/elements/hit/outlines/DefaultOutline.js +1 -1
  21. package/components/elements/view/ViewTitle.js +1 -1
  22. package/components/hooks/useHitActions.d.ts +1 -1
  23. package/components/hooks/useHitActions.js +2 -2
  24. package/components/hooks/useHitSelection.js +35 -1
  25. package/components/hooks/useMyPreferences.js +1 -10
  26. package/components/hooks/useMySitemap.js +1 -4
  27. package/components/hooks/useMyTheme.js +2 -9
  28. package/components/routes/action/view/ActionSearch.js +1 -1
  29. package/components/routes/action/view/Integrations.js +9 -1
  30. package/components/routes/action/view/markdown/integrations.en.md.js +1 -0
  31. package/components/routes/action/view/markdown/integrations.fr.md.js +1 -0
  32. package/components/routes/advanced/QueryBuilder.js +1 -1
  33. package/components/routes/analytics/AnalyticDetails.js +2 -2
  34. package/components/routes/analytics/AnalyticSearch.js +1 -1
  35. package/components/routes/help/ApiDocumentation.js +1 -1
  36. package/components/routes/help/BundleDocumentation.d.ts +3 -0
  37. package/components/routes/help/BundleDocumentation.js +12 -0
  38. package/components/routes/help/HitDocumentation.js +3 -1
  39. package/components/routes/help/markdown/en/bundles.md.js +1 -0
  40. package/components/routes/help/markdown/fr/bundles.md.js +1 -0
  41. package/components/routes/hits/search/BundleParentMenu.d.ts +6 -0
  42. package/components/routes/hits/search/BundleParentMenu.js +32 -0
  43. package/components/routes/hits/search/HitContextMenu.js +27 -4
  44. package/components/routes/hits/search/HitContextMenu.test.js +140 -0
  45. package/components/routes/hits/search/InformationPane.d.ts +0 -1
  46. package/components/routes/hits/search/InformationPane.js +28 -6
  47. package/components/routes/hits/search/SearchPane.js +5 -3
  48. package/components/routes/hits/search/ViewLink.js +1 -1
  49. package/components/routes/hits/search/grid/EnhancedCell.js +1 -1
  50. package/components/routes/hits/search/shared/CustomSpan.js +6 -4
  51. package/components/routes/hits/search/shared/SearchSpan.js +4 -2
  52. package/components/routes/hits/view/HitViewer.js +4 -3
  53. package/components/routes/home/ViewCard.js +1 -1
  54. package/components/{elements/MarkdownEditor.js → routes/overviews/OverviewEditor.js} +3 -3
  55. package/components/routes/overviews/OverviewViewer.js +2 -2
  56. package/locales/en/translation.json +396 -423
  57. package/locales/fr/translation.json +421 -445
  58. package/models/entities/generated/{ThreatEnrichment.d.ts → Enrichment.d.ts} +1 -1
  59. package/models/entities/generated/Howler.d.ts +4 -0
  60. package/models/entities/generated/Rule.d.ts +10 -2
  61. package/models/entities/generated/Threat.d.ts +2 -2
  62. package/package.json +4 -17
  63. package/plugins/clue/components/ClueTypography.js +2 -2
  64. package/plugins/clue/utils.d.ts +1 -2
  65. package/utils/constants.d.ts +3 -3
  66. package/api/search/case.d.ts +0 -4
  67. package/api/search/case.js +0 -8
  68. package/api/v2/case/index.d.ts +0 -6
  69. package/api/v2/case/index.js +0 -18
  70. package/api/v2/index.d.ts +0 -4
  71. package/api/v2/index.js +0 -6
  72. package/api/v2/search/facet.d.ts +0 -3
  73. package/api/v2/search/facet.js +0 -12
  74. package/api/v2/search/index.d.ts +0 -6
  75. package/api/v2/search/index.js +0 -18
  76. package/components/elements/hit/elements/AnalyticLink.d.ts +0 -8
  77. package/components/elements/hit/elements/AnalyticLink.js +0 -22
  78. package/components/routes/cases/CaseCard.d.ts +0 -8
  79. package/components/routes/cases/CaseCard.js +0 -39
  80. package/components/routes/cases/CaseViewer.d.ts +0 -2
  81. package/components/routes/cases/CaseViewer.js +0 -24
  82. package/components/routes/cases/Cases.d.ts +0 -2
  83. package/components/routes/cases/Cases.js +0 -101
  84. package/components/routes/cases/components/StatusIcon.d.ts +0 -5
  85. package/components/routes/cases/components/StatusIcon.js +0 -13
  86. package/components/routes/cases/constants.d.ts +0 -5
  87. package/components/routes/cases/constants.js +0 -5
  88. package/components/routes/cases/detail/AlertPanel.d.ts +0 -6
  89. package/components/routes/cases/detail/AlertPanel.js +0 -32
  90. package/components/routes/cases/detail/CaseDashboard.d.ts +0 -7
  91. package/components/routes/cases/detail/CaseDashboard.js +0 -49
  92. package/components/routes/cases/detail/CaseDetails.d.ts +0 -6
  93. package/components/routes/cases/detail/CaseDetails.js +0 -61
  94. package/components/routes/cases/detail/CaseOverview.d.ts +0 -7
  95. package/components/routes/cases/detail/CaseOverview.js +0 -43
  96. package/components/routes/cases/detail/CaseSidebar.d.ts +0 -6
  97. package/components/routes/cases/detail/CaseSidebar.js +0 -36
  98. package/components/routes/cases/detail/CaseTask.d.ts +0 -11
  99. package/components/routes/cases/detail/CaseTask.js +0 -57
  100. package/components/routes/cases/detail/ItemPage.d.ts +0 -6
  101. package/components/routes/cases/detail/ItemPage.js +0 -93
  102. package/components/routes/cases/detail/RelatedCasePanel.d.ts +0 -6
  103. package/components/routes/cases/detail/RelatedCasePanel.js +0 -31
  104. package/components/routes/cases/detail/TaskPanel.d.ts +0 -7
  105. package/components/routes/cases/detail/TaskPanel.js +0 -52
  106. package/components/routes/cases/detail/aggregates/CaseAggregate.d.ts +0 -12
  107. package/components/routes/cases/detail/aggregates/CaseAggregate.js +0 -19
  108. package/components/routes/cases/detail/aggregates/SourceAggregate.d.ts +0 -6
  109. package/components/routes/cases/detail/aggregates/SourceAggregate.js +0 -27
  110. package/components/routes/cases/detail/sidebar/CaseFolder.d.ts +0 -12
  111. package/components/routes/cases/detail/sidebar/CaseFolder.js +0 -179
  112. package/components/routes/cases/detail/sidebar/types.d.ts +0 -3
  113. package/components/routes/cases/hooks/useCase.d.ts +0 -13
  114. package/components/routes/cases/hooks/useCase.js +0 -38
  115. package/components/routes/cases/modals/ResolveModal.d.ts +0 -7
  116. package/components/routes/cases/modals/ResolveModal.js +0 -59
  117. package/components/routes/observables/ObservableViewer.d.ts +0 -7
  118. package/components/routes/observables/ObservableViewer.js +0 -27
  119. package/models/entities/generated/AttachmentsFile.d.ts +0 -12
  120. package/models/entities/generated/Case.d.ts +0 -28
  121. package/models/entities/generated/DestinationOriginal.d.ts +0 -19
  122. package/models/entities/generated/EmailAttachment.d.ts +0 -8
  123. package/models/entities/generated/EmailParent.d.ts +0 -19
  124. package/models/entities/generated/Enrichments.d.ts +0 -7
  125. package/models/entities/generated/EnrichmentsIndicator.d.ts +0 -21
  126. package/models/entities/generated/HttpResponse.d.ts +0 -11
  127. package/models/entities/generated/Item.d.ts +0 -9
  128. package/models/entities/generated/Observable.d.ts +0 -84
  129. package/models/entities/generated/ObservableCloud.d.ts +0 -20
  130. package/models/entities/generated/ObservableDestination.d.ts +0 -23
  131. package/models/entities/generated/ObservableEmail.d.ts +0 -30
  132. package/models/entities/generated/ObservableFile.d.ts +0 -36
  133. package/models/entities/generated/ObservableHowler.d.ts +0 -44
  134. package/models/entities/generated/ObservableHttp.d.ts +0 -11
  135. package/models/entities/generated/ObservableObserver.d.ts +0 -21
  136. package/models/entities/generated/ObservableOrganization.d.ts +0 -7
  137. package/models/entities/generated/ObservableProcess.d.ts +0 -34
  138. package/models/entities/generated/ObservableSource.d.ts +0 -23
  139. package/models/entities/generated/ObservableThreat.d.ts +0 -21
  140. package/models/entities/generated/ObservableTls.d.ts +0 -12
  141. package/models/entities/generated/ObserverIngress.d.ts +0 -9
  142. package/models/entities/generated/Task.d.ts +0 -10
  143. /package/components/{elements/MarkdownEditor.d.ts → routes/overviews/OverviewEditor.d.ts} +0 -0
@@ -4,7 +4,7 @@ import type { Matched } from './Matched';
4
4
  /**
5
5
  * NOTE: This is an auto-generated file. Don't edit this manually.
6
6
  */
7
- export interface ThreatEnrichment {
7
+ export interface Enrichment {
8
8
  indicator?: Indicator;
9
9
  matched?: Matched;
10
10
  }
@@ -14,6 +14,8 @@ export interface Howler {
14
14
  analytic: string;
15
15
  assessment?: string;
16
16
  assignment: string;
17
+ bundle_size?: number;
18
+ bundles?: string[];
17
19
  comment?: HowlerComment[];
18
20
  confidence?: number;
19
21
  data?: string[];
@@ -22,8 +24,10 @@ export interface Howler {
22
24
  escalation?: string;
23
25
  expiry?: string;
24
26
  hash: string;
27
+ hits?: string[];
25
28
  id: string;
26
29
  incidents?: Incident[];
30
+ is_bundle?: boolean;
27
31
  labels?: Labels;
28
32
  links?: Link[];
29
33
  log?: Log[];
@@ -2,6 +2,14 @@
2
2
  * NOTE: This is an auto-generated file. Don't edit this manually.
3
3
  */
4
4
  export interface Rule {
5
- destination?: string;
6
- query?: string;
5
+ author?: string;
6
+ category?: string;
7
+ description?: string;
8
+ id?: string;
9
+ license?: string;
10
+ name?: string;
11
+ reference?: string;
12
+ ruleset?: string;
13
+ uuid?: string;
14
+ version?: string;
7
15
  }
@@ -1,6 +1,6 @@
1
+ import type { Enrichment } from './Enrichment';
1
2
  import type { Feed } from './Feed';
2
3
  import type { Software } from './Software';
3
- import type { ThreatEnrichment } from './ThreatEnrichment';
4
4
  import type { ThreatGroup } from './ThreatGroup';
5
5
  import type { ThreatIndicator } from './ThreatIndicator';
6
6
  import type { ThreatTactic } from './ThreatTactic';
@@ -10,7 +10,7 @@ import type { ThreatTechnique } from './ThreatTechnique';
10
10
  * NOTE: This is an auto-generated file. Don't edit this manually.
11
11
  */
12
12
  export interface Threat {
13
- enrichments?: ThreatEnrichment[];
13
+ enrichments?: Enrichment[];
14
14
  feed?: Feed;
15
15
  framework?: string;
16
16
  group?: ThreatGroup;
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "@dnd-kit/modifiers": "^7.0.0",
18
18
  "@dnd-kit/sortable": "^8.0.0",
19
19
  "@dnd-kit/utilities": "^3.2.2",
20
- "@fontsource/roboto": "^5.2.9",
20
+ "@fontsource/roboto": "^5.2.10",
21
21
  "@iconify/icons-logos": "^1.2.36",
22
22
  "@iconify/icons-simple-icons": "^1.2.74",
23
23
  "@iconify/react": "^4.1.1",
@@ -28,7 +28,7 @@
28
28
  "@monaco-editor/react": "^4.7.0",
29
29
  "ajv": "^8.18.0",
30
30
  "ajv-i18n": "^4.2.0",
31
- "axios": "^1.13.5",
31
+ "axios": "^1.13.6",
32
32
  "axios-retry": "^3.9.1",
33
33
  "chart.js": "^4.5.1",
34
34
  "chartjs-adapter-dayjs-4": "^1.0.4",
@@ -101,7 +101,7 @@
101
101
  "internal-slot": "1.0.7"
102
102
  },
103
103
  "type": "module",
104
- "version": "2.17.0-dev.526",
104
+ "version": "2.17.0-dev.539",
105
105
  "exports": {
106
106
  "./i18n": "./i18n.js",
107
107
  "./index.css": "./index.css",
@@ -172,11 +172,10 @@
172
172
  "./components/routes/help/*": "./components/routes/help/*.js",
173
173
  "./components/routes/admin/*": "./components/routes/admin/*.js",
174
174
  "./components/routes/settings/*": "./components/routes/settings/*.js",
175
- "./components/routes/observables/*": "./components/routes/observables/*.js",
176
- "./components/routes/cases/*": "./components/routes/cases/*.js",
177
175
  "./components/routes/action/edit/*": "./components/routes/action/edit/*.js",
178
176
  "./components/routes/action/view/*": "./components/routes/action/view/*.js",
179
177
  "./components/routes/action/shared/*": "./components/routes/action/shared/*.js",
178
+ "./components/routes/action/view/markdown/*.md": "./components/routes/action/view/markdown/*.md.js",
180
179
  "./components/routes/overviews/template/*": "./components/routes/overviews/template/*.js",
181
180
  "./components/routes/hits/search/*": "./components/routes/hits/search/*.js",
182
181
  "./components/routes/hits/view/*": "./components/routes/hits/view/*.js",
@@ -188,12 +187,6 @@
188
187
  "./components/routes/help/markdown/fr/*.md": "./components/routes/help/markdown/fr/*.md.js",
189
188
  "./components/routes/help/markdown/en/*.md": "./components/routes/help/markdown/en/*.md.js",
190
189
  "./components/routes/admin/users/*": "./components/routes/admin/users/*.js",
191
- "./components/routes/cases/components/*": "./components/routes/cases/components/*.js",
192
- "./components/routes/cases/modals/*": "./components/routes/cases/modals/*.js",
193
- "./components/routes/cases/hooks/*": "./components/routes/cases/hooks/*.js",
194
- "./components/routes/cases/detail/*": "./components/routes/cases/detail/*.js",
195
- "./components/routes/cases/detail/sidebar/*": "./components/routes/cases/detail/sidebar/*.js",
196
- "./components/routes/cases/detail/aggregates/*": "./components/routes/cases/detail/aggregates/*.js",
197
190
  "./commons/components/*": "./commons/components/*.js",
198
191
  "./commons/components/breadcrumbs/*": "./commons/components/breadcrumbs/*.js",
199
192
  "./commons/components/app/*": "./commons/components/app/*.js",
@@ -219,8 +212,6 @@
219
212
  "./locales/en/help/*.json": "./locales/en/help/*.json",
220
213
  "./api/overview/*": "./api/overview/*.js",
221
214
  "./api/overview": "./api/overview/index.js",
222
- "./api/v2/*": "./api/v2/*.js",
223
- "./api/v2": "./api/v2/index.js",
224
215
  "./api/action/*": "./api/action/*.js",
225
216
  "./api/action": "./api/action/index.js",
226
217
  "./api/auth/*": "./api/auth/*.js",
@@ -243,10 +234,6 @@
243
234
  "./api/hit": "./api/hit/index.js",
244
235
  "./api/view/*": "./api/view/*.js",
245
236
  "./api/view": "./api/view/index.js",
246
- "./api/v2/search/*": "./api/v2/search/*.js",
247
- "./api/v2/search": "./api/v2/search/index.js",
248
- "./api/v2/case/*": "./api/v2/case/*.js",
249
- "./api/v2/case": "./api/v2/case/index.js",
250
237
  "./api/analytic/comments/*": "./api/analytic/comments/*.js",
251
238
  "./api/analytic/comments": "./api/analytic/comments/index.js",
252
239
  "./api/analytic/notebooks/*": "./api/analytic/notebooks/*.js",
@@ -3,8 +3,8 @@ import EnrichedTypography from '@cccsaurora/clue-ui/components/EnrichedTypograph
3
3
  import { Typography } from '@mui/material';
4
4
  import { memo } from 'react';
5
5
  import { useType } from '../utils';
6
- const ClueTypography = ({ children, value, context, field, obj, ...props }) => {
7
- const type = useType(obj, field, value);
6
+ const ClueTypography = ({ children, value, context, field, hit, ...props }) => {
7
+ const type = useType(hit, field, value);
8
8
  if (!type) {
9
9
  return _jsx(Typography, { ...props, children: children ?? value });
10
10
  }
@@ -1,3 +1,2 @@
1
1
  import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
- import type { Observable } from '@cccsaurora/howler-ui/models/entities/generated/Observable';
3
- export declare const useType: (hit?: Hit | Observable, field?: string, value?: string) => any;
2
+ export declare const useType: (hit?: Hit, field?: string, value?: string) => any;
@@ -5,9 +5,9 @@ export declare const VERSION: any;
5
5
  export declare const MY_LOCAL_STORAGE_PREFIX = "howler.ui";
6
6
  export declare const MY_SESSION_STORAGE_PREFIX = "howler.ui.cache";
7
7
  export declare const ESCALATION_COLORS: {
8
- alert: "warning";
9
- evidence: "error";
10
- hit: "primary";
8
+ alert: string;
9
+ evidence: string;
10
+ hit: string;
11
11
  };
12
12
  export declare const STATUS_COLORS: {
13
13
  open: string;
@@ -1,4 +0,0 @@
1
- import type { HowlerSearchRequest, HowlerSearchResponse } from '@cccsaurora/howler-ui/api/search';
2
- import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
3
- export declare const uri: () => string;
4
- export declare const post: (request?: HowlerSearchRequest) => Promise<HowlerSearchResponse<Case>>;
@@ -1,8 +0,0 @@
1
- import { hpost, joinUri } from '@cccsaurora/howler-ui/api';
2
- import { uri as parentUri } from '@cccsaurora/howler-ui/api/search';
3
- export const uri = () => {
4
- return joinUri(parentUri(), 'case');
5
- };
6
- export const post = (request) => {
7
- return hpost(uri(), { ...(request || {}), query: request?.query || 'case_id:*' });
8
- };
@@ -1,6 +0,0 @@
1
- import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
- export declare const uri: (id?: string) => string;
3
- export declare const get: (id: string) => Promise<Case>;
4
- export declare const post: (newData: Partial<Case>) => Promise<Case>;
5
- export declare const put: (id: string, _case: Partial<Case>) => Promise<Case>;
6
- export declare const del: (id: string) => Promise<void>;
@@ -1,18 +0,0 @@
1
- // eslint-disable-next-line import/no-cycle
2
- import { hdelete, hget, hpost, hput, joinAllUri, joinUri } from '@cccsaurora/howler-ui/api';
3
- import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
4
- export const uri = (id) => {
5
- return id ? joinAllUri(parentUri(), 'case', id) : joinUri(parentUri(), 'case');
6
- };
7
- export const get = (id) => {
8
- return hget(uri(id));
9
- };
10
- export const post = (newData) => {
11
- return hpost(uri(), newData);
12
- };
13
- export const put = (id, _case) => {
14
- return hput(uri(id), _case);
15
- };
16
- export const del = (id) => {
17
- return hdelete(uri(id));
18
- };
package/api/v2/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import * as case_ from '@cccsaurora/howler-ui/api/v2/case';
2
- import * as search from '@cccsaurora/howler-ui/api/v2/search';
3
- export declare const uri: () => string;
4
- export { case_ as case, search };
package/api/v2/index.js DELETED
@@ -1,6 +0,0 @@
1
- import * as case_ from '@cccsaurora/howler-ui/api/v2/case';
2
- import * as search from '@cccsaurora/howler-ui/api/v2/search';
3
- export const uri = () => {
4
- return '/api/v2';
5
- };
6
- export { case_ as case, search };
@@ -1,3 +0,0 @@
1
- import type { HowlerFacetSearchRequest, HowlerFacetSearchResponse } from '@cccsaurora/howler-ui/api/search/facet';
2
- export declare const uri: (indexes: string[]) => string;
3
- export declare const post: (indexes: string | string[], request?: HowlerFacetSearchRequest) => Promise<HowlerFacetSearchResponse>;
@@ -1,12 +0,0 @@
1
- // eslint-disable-next-line import/no-cycle
2
- import { hpost, joinAllUri } from '@cccsaurora/howler-ui/api';
3
- import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
4
- export const uri = (indexes) => {
5
- return joinAllUri(parentUri(), 'search', 'facet', indexes.join(','));
6
- };
7
- export const post = (indexes, request) => {
8
- if (typeof indexes === 'string') {
9
- indexes = indexes.split(',');
10
- }
11
- return hpost(uri(indexes), { ...(request || {}), query: request?.query || 'howler.id:*' });
12
- };
@@ -1,6 +0,0 @@
1
- import type { HowlerSearchRequest, HowlerSearchResponse } from '@cccsaurora/howler-ui/api/search';
2
- import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
3
- import * as facet from './facet';
4
- export declare const uri: (indexes: string[]) => string;
5
- export declare const post: <T = Hit>(indexes: string | string[], request?: HowlerSearchRequest) => Promise<HowlerSearchResponse<T>>;
6
- export { facet };
@@ -1,18 +0,0 @@
1
- // eslint-disable-next-line import/no-cycle
2
- import { hpost, joinAllUri } from '@cccsaurora/howler-ui/api';
3
- import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
4
- import * as facet from './facet';
5
- export const uri = (indexes) => {
6
- return joinAllUri(parentUri(), 'search', indexes.join(','));
7
- };
8
- export const post = (indexes, request) => {
9
- if (typeof indexes === 'string') {
10
- indexes = indexes.split(',');
11
- }
12
- if (indexes.some(index => !['hit', 'observable'].includes(index))) {
13
- // eslint-disable-next-line no-console
14
- console.error('Only hit and observable indexes should be used currently.');
15
- }
16
- return hpost(uri(indexes), { ...(request || {}), query: request?.query || 'howler.id:*' });
17
- };
18
- export { facet };
@@ -1,8 +0,0 @@
1
- import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
- import { type FC } from 'react';
3
- declare const AnalyticLink: FC<{
4
- hit: Hit;
5
- compressed?: boolean;
6
- alignSelf?: string;
7
- }>;
8
- export default AnalyticLink;
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Typography } from '@mui/material';
3
- import useMatchers from '@cccsaurora/howler-ui/components/app/hooks/useMatchers';
4
- import { useEffect, useState } from 'react';
5
- import { Link } from 'react-router-dom';
6
- const AnalyticLink = ({ hit, compressed, alignSelf = 'start' }) => {
7
- const { getMatchingAnalytic } = useMatchers();
8
- const [analyticId, setAnalyticId] = useState();
9
- useEffect(() => {
10
- if (!hit?.howler.analytic) {
11
- return;
12
- }
13
- getMatchingAnalytic(hit).then(analytic => setAnalyticId(analytic?.analytic_id));
14
- // eslint-disable-next-line react-hooks/exhaustive-deps
15
- }, [hit?.howler.analytic]);
16
- return (_jsxs(Typography, { variant: compressed ? 'body1' : 'h6', fontWeight: compressed && 'bold', sx: { alignSelf, '& a': { color: 'text.primary' } }, children: [analyticId ? (_jsx(Link, { to: `/analytics/${analyticId}`, onAuxClick: e => {
17
- e.stopPropagation();
18
- }, onClick: e => {
19
- e.stopPropagation();
20
- }, children: hit.howler.analytic })) : (hit.howler.analytic), hit.howler.detection && ': ', hit.howler.detection] }));
21
- };
22
- export default AnalyticLink;
@@ -1,8 +0,0 @@
1
- import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
- import { type FC } from 'react';
3
- declare const CaseCard: FC<{
4
- case?: Case;
5
- caseId?: string;
6
- className?: string;
7
- }>;
8
- export default CaseCard;
@@ -1,39 +0,0 @@
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 { Card, Chip, Divider, Grid, Skeleton, Stack, Tooltip, Typography, useTheme } from '@mui/material';
4
- import api from '@cccsaurora/howler-ui/api';
5
- import HowlerAvatar from '@cccsaurora/howler-ui/components/elements/display/HowlerAvatar';
6
- import PluginChip from '@cccsaurora/howler-ui/components/elements/PluginChip';
7
- import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
8
- import dayjs from 'dayjs';
9
- import { countBy } from 'lodash-es';
10
- import { useEffect, useState } from 'react';
11
- import { useTranslation } from 'react-i18next';
12
- import { twitterShort } from '@cccsaurora/howler-ui/utils/utils';
13
- import StatusIcon from './components/StatusIcon';
14
- const STATUS_COLORS = {
15
- resolved: 'success'
16
- };
17
- const CaseCard = ({ case: providedCase, caseId, className }) => {
18
- const { t } = useTranslation();
19
- const { dispatchApi } = useMyApi();
20
- const theme = useTheme();
21
- const [_case, setCase] = useState(providedCase);
22
- useEffect(() => {
23
- if (providedCase) {
24
- setCase(providedCase);
25
- }
26
- }, [providedCase]);
27
- useEffect(() => {
28
- if (caseId) {
29
- dispatchApi(api.v2.case.get(caseId), { throwError: false }).then(setCase);
30
- }
31
- }, [caseId, dispatchApi]);
32
- if (!_case) {
33
- return _jsx(Skeleton, { variant: "rounded", height: 250, sx: { mb: 1 }, className: className });
34
- }
35
- return (_jsx(Card, { variant: "outlined", sx: { p: 1, mb: 1, borderColor: theme.palette[STATUS_COLORS[_case.status]]?.main }, 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: 1, 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
36
- .filter(task => !task.complete)
37
- .map(task => (_jsx(Chip, { icon: _jsx(RadioButtonUnchecked, {}), label: task.summary }, task.id)))] })] }))] }) }) }, _case.case_id));
38
- };
39
- export default CaseCard;
@@ -1,2 +0,0 @@
1
- declare const _default: import("react").NamedExoticComponent<{}>;
2
- export default _default;
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Stack } from '@mui/material';
3
- import { memo } from 'react';
4
- import { useParams } from 'react-router-dom';
5
- import NotFoundPage from '../404';
6
- import ErrorBoundary from '../ErrorBoundary';
7
- import CaseDashboard from './detail/CaseDashboard';
8
- import CaseDetails from './detail/CaseDetails';
9
- import CaseSidebar from './detail/CaseSidebar';
10
- import ItemPage from './detail/ItemPage';
11
- import useCase from './hooks/useCase';
12
- const CaseViewer = () => {
13
- const params = useParams();
14
- const { case: _case, missing } = useCase({ caseId: params.id });
15
- if (missing) {
16
- return _jsx(NotFoundPage, {});
17
- }
18
- return (_jsxs(Stack, { direction: "row", height: "100%", children: [_jsx(CaseSidebar, { case: _case }), _jsx(Box, { sx: {
19
- maxHeight: 'calc(100vh - 64px)',
20
- flex: 1,
21
- overflow: 'auto'
22
- }, children: _jsx(ErrorBoundary, { children: !_case || location.pathname.endsWith(_case.case_id) ? (_jsx(CaseDashboard, { case: _case })) : (_jsx(ItemPage, { case: _case })) }) }), _jsx(CaseDetails, { case: _case })] }));
23
- };
24
- export default memo(CaseViewer);
@@ -1,2 +0,0 @@
1
- declare const Cases: () => import("react/jsx-runtime").JSX.Element;
2
- export default Cases;
@@ -1,101 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Topic } from '@mui/icons-material';
3
- import { Typography } from '@mui/material';
4
- import api from '@cccsaurora/howler-ui/api';
5
- import { TuiListProvider } from '@cccsaurora/howler-ui/components/elements/addons/lists';
6
- import { TuiListMethodContext } from '@cccsaurora/howler-ui/components/elements/addons/lists/TuiListProvider';
7
- import ItemManager from '@cccsaurora/howler-ui/components/elements/display/ItemManager';
8
- import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
9
- import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
10
- import { useCallback, useContext, useEffect, useState } from 'react';
11
- import { useTranslation } from 'react-i18next';
12
- import { useNavigate, useSearchParams } from 'react-router-dom';
13
- import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
14
- import CaseCard from './CaseCard';
15
- const CasesBase = () => {
16
- const { t } = useTranslation();
17
- const navigate = useNavigate();
18
- const { dispatchApi } = useMyApi();
19
- const [searchParams, setSearchParams] = useSearchParams();
20
- const { load } = useContext(TuiListMethodContext);
21
- const pageCount = useMyLocalStorageItem(StorageKey.PAGE_COUNT, 25)[0];
22
- const [phrase, setPhrase] = useState('');
23
- const [offset, setOffset] = useState(parseInt(searchParams.get('offset')) || 0);
24
- const [response, setResponse] = useState(null);
25
- const [hasError, setHasError] = useState(false);
26
- const [loading, setLoading] = useState(false);
27
- const onSearch = useCallback(async () => {
28
- try {
29
- setLoading(true);
30
- setHasError(false);
31
- if (phrase) {
32
- searchParams.set('phrase', phrase);
33
- }
34
- else {
35
- searchParams.delete('phrase');
36
- }
37
- setSearchParams(searchParams, { replace: true });
38
- // Check for the actual search query
39
- const query = phrase ? `*:*${phrase}*` : '*:*';
40
- // Ensure the overview should be visible and/or matches the type we are filtering for
41
- setResponse(await dispatchApi(api.search.case.post({
42
- query,
43
- rows: pageCount,
44
- offset
45
- })));
46
- }
47
- catch (e) {
48
- setHasError(true);
49
- }
50
- finally {
51
- setLoading(false);
52
- }
53
- }, [phrase, setSearchParams, searchParams, dispatchApi, pageCount, offset]);
54
- // Load the items into list when response changes.
55
- // This hook should only trigger when the 'response' changes.
56
- useEffect(() => {
57
- if (response) {
58
- load(response.items.map((item) => ({
59
- id: item.case_id,
60
- item,
61
- selected: false,
62
- cursor: false
63
- })));
64
- }
65
- // eslint-disable-next-line react-hooks/exhaustive-deps
66
- }, [response, load]);
67
- const onPageChange = useCallback((_offset) => {
68
- if (_offset !== offset) {
69
- searchParams.set('offset', _offset.toString());
70
- setSearchParams(searchParams, { replace: true });
71
- setOffset(_offset);
72
- }
73
- }, [offset, searchParams, setSearchParams]);
74
- useEffect(() => {
75
- onSearch();
76
- if (!searchParams.has('offset')) {
77
- searchParams.set('offset', '0');
78
- setSearchParams(searchParams, { replace: true });
79
- }
80
- // eslint-disable-next-line react-hooks/exhaustive-deps
81
- }, []);
82
- useEffect(() => {
83
- if (response?.total <= offset) {
84
- setOffset(0);
85
- searchParams.set('offset', '0');
86
- setSearchParams(searchParams, { replace: true });
87
- }
88
- }, [offset, response?.total, searchParams, setSearchParams]);
89
- useEffect(() => {
90
- if (!loading) {
91
- onSearch();
92
- }
93
- // eslint-disable-next-line react-hooks/exhaustive-deps
94
- }, [offset]);
95
- const renderer = useCallback((item, className) => _jsx(CaseCard, { case: item, className: className }), []);
96
- return (_jsx(ItemManager, { onSearch: onSearch, onPageChange: onPageChange, phrase: phrase, setPhrase: setPhrase, hasError: hasError, searching: loading, aboveSearch: _jsx(Typography, { sx: theme => ({ fontStyle: 'italic', color: theme.palette.text.disabled, mb: 0.5 }), variant: "body2", children: t('route.cases.search.prompt') }), renderer: ({ item }, classRenderer) => renderer(item.item, classRenderer()), response: response, onSelect: (item) => navigate(`/cases/${item.id}`), onCreate: () => navigate('/cases/create'), createPrompt: "route.cases.create", searchPrompt: "route.cases.manager.search", createIcon: _jsx(Topic, { sx: { mr: 1 } }) }));
97
- };
98
- const Cases = () => {
99
- return (_jsx(TuiListProvider, { children: _jsx(CasesBase, {}) }));
100
- };
101
- export default Cases;
@@ -1,5 +0,0 @@
1
- import type { FC } from 'react';
2
- declare const StatusIcon: FC<{
3
- status: string;
4
- }>;
5
- export default StatusIcon;
@@ -1,13 +0,0 @@
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;
@@ -1,5 +0,0 @@
1
- export declare const ESCALATION_COLOR_MAP: {
2
- normal: string;
3
- focus: string;
4
- crisis: string;
5
- };
@@ -1,5 +0,0 @@
1
- export const ESCALATION_COLOR_MAP = {
2
- normal: 'default',
3
- focus: 'warning',
4
- crisis: 'error'
5
- };
@@ -1,6 +0,0 @@
1
- import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
- import { type FC } from 'react';
3
- declare const AlertPanel: FC<{
4
- case: Case;
5
- }>;
6
- export default AlertPanel;
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Divider, Pagination, Skeleton, Stack, Typography, useTheme } from '@mui/material';
3
- import HitCard from '@cccsaurora/howler-ui/components/elements/hit/HitCard';
4
- import { HitLayout } from '@cccsaurora/howler-ui/components/elements/hit/HitLayout';
5
- import { chunk, uniq } from 'lodash-es';
6
- import { useMemo, useState } from 'react';
7
- import { useTranslation } from 'react-i18next';
8
- import { Link } from 'react-router-dom';
9
- const AlertPanel = ({ case: _case }) => {
10
- const theme = useTheme();
11
- const { t } = useTranslation();
12
- const [alertPage, setAlertPage] = useState(1);
13
- const alertPages = useMemo(() => chunk(uniq((_case?.items ?? []).filter(item => item.type === 'hit')), 5), [_case?.items]);
14
- if (!_case) {
15
- return _jsx(Skeleton, { height: 240 });
16
- }
17
- return (_jsxs(Stack, { spacing: 1, children: [_jsxs(Stack, { direction: "row", children: [_jsx(Typography, { flex: 1, variant: "h4", children: t('page.cases.dashboard.alerts') }), _jsx(Pagination, { count: alertPages.length, page: alertPage, onChange: (_, page) => setAlertPage(page) })] }), _jsx(Divider, {}), alertPages[alertPage - 1].map(item => (_jsxs(Box, { position: "relative", children: [_jsx(HitCard, { layout: HitLayout.DENSE, id: item.id }), _jsx(Box, { component: Link, to: item.path, sx: {
18
- position: 'absolute',
19
- top: 0,
20
- left: 0,
21
- width: '100%',
22
- height: '100%',
23
- cursor: 'pointer',
24
- zIndex: 100,
25
- borderRadius: '4px',
26
- '&:hover': {
27
- background: theme.palette.divider,
28
- border: `thin solid ${theme.palette.primary.light}`
29
- }
30
- } })] }, item.id)))] }));
31
- };
32
- export default AlertPanel;
@@ -1,7 +0,0 @@
1
- import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
2
- import { type FC } from 'react';
3
- declare const CaseDashboard: FC<{
4
- case?: Case;
5
- caseId?: string;
6
- }>;
7
- export default CaseDashboard;