@cccsaurora/howler-ui 2.19.0-dev.1276 → 2.19.0-dev.1282

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.
@@ -5,7 +5,6 @@ declare const Assigned: FC<{
5
5
  hit: Hit;
6
6
  layout: HitLayout;
7
7
  hideLabel?: boolean;
8
- showAssessor?: boolean;
9
8
  showAssigned?: boolean;
10
9
  }>;
11
10
  export default Assigned;
@@ -16,14 +16,13 @@ const AvatarChip = ({ userId, noUser, placeholder, layout, hideLabel }) => {
16
16
  }
17
17
  }, icon: userAvatar, label: userId && userId !== noUser ? userId : placeholder, size: layout !== HitLayout.COMFY ? 'small' : 'medium' }));
18
18
  };
19
- const Assigned = ({ hit, layout, hideLabel = false, showAssessor = false, showAssigned = false }) => {
19
+ const Assigned = ({ hit, layout, hideLabel = false, showAssigned = false }) => {
20
20
  const { t } = useTranslation();
21
21
  const { user } = useAppUser();
22
22
  const { viewers } = useContext(SocketContext);
23
23
  const hitViewers = uniq(viewers[hit?.howler?.id] ?? []).filter(viewer => viewer !== user.username);
24
- const assessorVisible = showAssessor || hit.howler.assessment != null;
25
- const assigneeVisible = !hit.howler.assessor && (showAssigned || hit.howler.assignment !== 'unassigned');
26
- return (_jsxs(Stack, { direction: "row", spacing: 0.5, 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 })] }))] }), hitViewers.length > 0 && hideLabel && _jsx(Divider, { orientation: "vertical", flexItem: true, variant: "middle" }), _jsx(AvatarGroup, { max: 3, sx: { [`.${avatarClasses.root}`]: { border: 0, marginLeft: 0.5 } }, componentsProps: {
24
+ const assigneeVisible = showAssigned || hit.howler.assignment !== 'unassigned';
25
+ return (_jsxs(Stack, { direction: "row", spacing: 0.5, 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 })] })), hitViewers.length > 0 && hideLabel && _jsx(Divider, { orientation: "vertical", flexItem: true, variant: "middle" }), _jsx(AvatarGroup, { max: 3, sx: { [`.${avatarClasses.root}`]: { border: 0, marginLeft: 0.5 } }, componentsProps: {
27
26
  additionalAvatar: {
28
27
  sx: {
29
28
  height: layout !== HitLayout.COMFY ? 24 : 32,
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { act, render, screen, waitFor } from '@testing-library/react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
3
  import userEvent from '@testing-library/user-event';
4
4
  import { describe, expect, it, vi } from 'vitest';
5
5
  globalThis.IS_REACT_ACT_ENVIRONMENT = true;
@@ -70,9 +70,7 @@ describe('CreateRuleDialog', () => {
70
70
  it('disables submit when destination is empty', async () => {
71
71
  const user = userEvent.setup();
72
72
  render(_jsx(CreateRuleDialog, { ...defaultProps }));
73
- await act(async () => {
74
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
75
- });
73
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
76
74
  expect(screen.getByTestId('rule-submit-button')).toBeDisabled();
77
75
  });
78
76
  it('enables submit when query, destination are filled and search has been run', async () => {
@@ -80,15 +78,9 @@ describe('CreateRuleDialog', () => {
80
78
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 5, offset: 0, rows: 0 });
81
79
  api.search.hit.post.mockReturnValue('search-request');
82
80
  render(_jsx(CreateRuleDialog, { ...defaultProps }));
83
- await act(async () => {
84
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
85
- });
86
- await act(async () => {
87
- await user.click(screen.getByTestId('rule-search-button'));
88
- });
89
- await act(async () => {
90
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
91
- });
81
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
82
+ await user.click(screen.getByTestId('rule-search-button'));
83
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
92
84
  await waitFor(() => {
93
85
  expect(screen.getByTestId('rule-submit-button')).not.toBeDisabled();
94
86
  });
@@ -99,18 +91,10 @@ describe('CreateRuleDialog', () => {
99
91
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 1, offset: 0, rows: 0 });
100
92
  api.search.hit.post.mockReturnValue('search-request');
101
93
  render(_jsx(CreateRuleDialog, { ...defaultProps, onSubmit: onSubmit }));
102
- await act(async () => {
103
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
104
- });
105
- await act(async () => {
106
- await user.click(screen.getByTestId('rule-search-button'));
107
- });
108
- await act(async () => {
109
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
110
- });
111
- await act(async () => {
112
- await user.click(screen.getByTestId('rule-submit-button'));
113
- });
94
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
95
+ await user.click(screen.getByTestId('rule-search-button'));
96
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
97
+ await user.click(screen.getByTestId('rule-submit-button'));
114
98
  await waitFor(() => {
115
99
  expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
116
100
  query: 'event.kind:alert',
@@ -123,9 +107,7 @@ describe('CreateRuleDialog', () => {
123
107
  const user = userEvent.setup();
124
108
  const onClose = vi.fn();
125
109
  render(_jsx(CreateRuleDialog, { ...defaultProps, onClose: onClose }));
126
- await act(async () => {
127
- await user.click(screen.getByText('cancel'));
128
- });
110
+ await user.click(screen.getByText('cancel'));
129
111
  expect(onClose).toHaveBeenCalled();
130
112
  });
131
113
  it('shows search results after triggering search', async () => {
@@ -133,12 +115,8 @@ describe('CreateRuleDialog', () => {
133
115
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 42, offset: 0, rows: 0 });
134
116
  api.search.hit.post.mockReturnValue('search-request');
135
117
  render(_jsx(CreateRuleDialog, { ...defaultProps }));
136
- await act(async () => {
137
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
138
- });
139
- await act(async () => {
140
- await user.click(screen.getByTestId('rule-search-button'));
141
- });
118
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
119
+ await user.click(screen.getByTestId('rule-search-button'));
142
120
  await waitFor(() => {
143
121
  expect(screen.getByTestId('query-result-text')).toBeInTheDocument();
144
122
  expect(screen.getByText(/42 results/)).toBeInTheDocument();
@@ -155,18 +133,10 @@ describe('CreateRuleDialog', () => {
155
133
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 1, offset: 0, rows: 0 });
156
134
  api.search.hit.post.mockReturnValue('search-request');
157
135
  render(_jsx(CreateRuleDialog, { ...defaultProps, onSubmit: onSubmit }));
158
- await act(async () => {
159
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
160
- });
161
- await act(async () => {
162
- await user.click(screen.getByTestId('rule-search-button'));
163
- });
164
- await act(async () => {
165
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
166
- });
167
- await act(async () => {
168
- await user.click(screen.getByTestId('rule-submit-button'));
169
- });
136
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
137
+ await user.click(screen.getByTestId('rule-search-button'));
138
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
139
+ await user.click(screen.getByTestId('rule-submit-button'));
170
140
  await waitFor(() => {
171
141
  expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
172
142
  timeframe: 14
@@ -179,21 +149,11 @@ describe('CreateRuleDialog', () => {
179
149
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 1, offset: 0, rows: 0 });
180
150
  api.search.hit.post.mockReturnValue('search-request');
181
151
  render(_jsx(CreateRuleDialog, { ...defaultProps, onSubmit: onSubmit }));
182
- await act(async () => {
183
- await user.click(screen.getByTestId('rule-no-expiry-checkbox'));
184
- });
185
- await act(async () => {
186
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
187
- });
188
- await act(async () => {
189
- await user.click(screen.getByTestId('rule-search-button'));
190
- });
191
- await act(async () => {
192
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
193
- });
194
- await act(async () => {
195
- await user.click(screen.getByTestId('rule-submit-button'));
196
- });
152
+ await user.click(screen.getByTestId('rule-no-expiry-checkbox'));
153
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
154
+ await user.click(screen.getByTestId('rule-search-button'));
155
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
156
+ await user.click(screen.getByTestId('rule-submit-button'));
197
157
  await waitFor(() => {
198
158
  expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
199
159
  query: 'event.kind:alert',
@@ -208,21 +168,11 @@ describe('CreateRuleDialog', () => {
208
168
  mockDispatchApi.mockResolvedValueOnce({ items: [], total: 1, offset: 0, rows: 0 });
209
169
  api.search.hit.post.mockReturnValue('search-request');
210
170
  render(_jsx(CreateRuleDialog, { ...defaultProps, onSubmit: onSubmit }));
211
- await act(async () => {
212
- await user.click(screen.getByTestId('rule-expire-after-resolved'));
213
- });
214
- await act(async () => {
215
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
216
- });
217
- await act(async () => {
218
- await user.click(screen.getByTestId('rule-search-button'));
219
- });
220
- await act(async () => {
221
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
222
- });
223
- await act(async () => {
224
- await user.click(screen.getByTestId('rule-submit-button'));
225
- });
171
+ await user.click(screen.getByTestId('rule-expire-after-resolved'));
172
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
173
+ await user.click(screen.getByTestId('rule-search-button'));
174
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
175
+ await user.click(screen.getByTestId('rule-submit-button'));
226
176
  await waitFor(() => {
227
177
  expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
228
178
  timeframe: 14,
@@ -244,24 +194,12 @@ describe('CreateRuleDialog', () => {
244
194
  api.search.hit.post.mockReturnValue('search-request');
245
195
  render(_jsx(CreateRuleDialog, { ...defaultProps, onSubmit: onSubmit }));
246
196
  // Open the index Autocomplete and select 'event'
247
- await act(async () => {
248
- await user.click(screen.getByRole('combobox'));
249
- });
250
- await act(async () => {
251
- await user.click(screen.getByRole('option', { name: 'hit.search.index.event' }));
252
- });
253
- await act(async () => {
254
- await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
255
- });
256
- await act(async () => {
257
- await user.click(screen.getByTestId('rule-search-button'));
258
- });
259
- await act(async () => {
260
- await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
261
- });
262
- await act(async () => {
263
- await user.click(screen.getByTestId('rule-submit-button'));
264
- });
197
+ await user.click(screen.getByRole('combobox'));
198
+ await user.click(screen.getByRole('option', { name: 'hit.search.index.event' }));
199
+ await user.type(screen.getByTestId('rule-query-editor'), 'event.kind:alert');
200
+ await user.click(screen.getByTestId('rule-search-button'));
201
+ await user.type(screen.getByTestId('rule-destination-input'), 'alerts/incoming');
202
+ await user.click(screen.getByTestId('rule-submit-button'));
265
203
  await waitFor(() => {
266
204
  expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
267
205
  indexes: expect.arrayContaining(['hit', 'event'])
@@ -272,12 +210,8 @@ describe('CreateRuleDialog', () => {
272
210
  const user = userEvent.setup();
273
211
  render(_jsx(CreateRuleDialog, { ...defaultProps }));
274
212
  // 'hit' is selected by default; open the dropdown and try to deselect it
275
- await act(async () => {
276
- await user.click(screen.getByRole('combobox'));
277
- });
278
- await act(async () => {
279
- await user.click(screen.getByRole('option', { name: 'hit.search.index.hit' }));
280
- });
213
+ await user.click(screen.getByRole('combobox'));
214
+ await user.click(screen.getByRole('option', { name: 'hit.search.index.hit' }));
281
215
  // 'hit' should still be selected because deselecting the last index is prevented
282
216
  expect(screen.getAllByText('hit.search.index.hit').length).toBeGreaterThan(0);
283
217
  });
@@ -254,11 +254,9 @@ describe('QuerySettings', () => {
254
254
  const chipButton = screen.getByRole('button');
255
255
  await user.click(chipButton);
256
256
  const addFilterButton = screen.getByLabelText(i18n.t('hit.search.filter.add'));
257
- await act(async () => {
258
- await user.click(addFilterButton);
259
- await user.click(addFilterButton);
260
- await user.click(addFilterButton);
261
- });
257
+ await user.click(addFilterButton);
258
+ await user.click(addFilterButton);
259
+ await user.click(addFilterButton);
262
260
  expect(mockAddFilter).toHaveBeenCalledTimes(3);
263
261
  expect(mockAddFilter).toHaveBeenCalledWith('howler.assessment:*');
264
262
  });
@@ -19,6 +19,7 @@ const ACCEPTED_SORTS = [
19
19
  'event.provider',
20
20
  'organization.name',
21
21
  'howler.score',
22
+ 'howler.triaged',
22
23
  CUSTOM
23
24
  ];
24
25
  const HitSort = ({ size = 'small' }) => {
@@ -27,9 +27,6 @@
27
27
  "apikey.impersonate": "Impersonate",
28
28
  "apikey.read": "Read",
29
29
  "apikey.write": "Write",
30
- "app.drawer.hit.assessment.assessor": "Assessor",
31
- "app.drawer.hit.assessment.unknown.name": "Unknown",
32
- "app.drawer.hit.assignment.assignee": "Assignee",
33
30
  "app.drawer.hit.assignment.autocomplete.label": "Choose Assignee",
34
31
  "app.drawer.hit.assignment.description": "Choose a user to assign this hit to.",
35
32
  "app.drawer.hit.assignment.success": "User assigned to hit sucessfully.",
@@ -27,9 +27,6 @@
27
27
  "apikey.impersonate": "Imiter",
28
28
  "apikey.read": "Lire",
29
29
  "apikey.write": "Écrire",
30
- "app.drawer.hit.assessment.assessor": "Évaluateur",
31
- "app.drawer.hit.assessment.unknown.name": "Inconnu",
32
- "app.drawer.hit.assignment.assignee": "Cessionnaire",
33
30
  "app.drawer.hit.assignment.autocomplete.label": "Choisissez le destinataire",
34
31
  "app.drawer.hit.assignment.description": "Choisissez un utilisateur à qui assigner ce hit.",
35
32
  "app.drawer.hit.assignment.success": "L'utilisateur a été assigné au hit avec succès.",
@@ -13,7 +13,6 @@ import type { Votes } from './Votes';
13
13
  export interface Howler {
14
14
  analytic: string;
15
15
  assessment?: string;
16
- assessor?: string;
17
16
  assignment: string;
18
17
  comment?: HowlerComment[];
19
18
  confidence?: number;
@@ -39,6 +38,7 @@ export interface Howler {
39
38
  scrutiny?: string;
40
39
  severity?: number;
41
40
  status?: string;
41
+ triaged?: string;
42
42
  volume?: number;
43
43
  votes?: Votes;
44
44
  }
package/package.json CHANGED
@@ -93,7 +93,7 @@
93
93
  "url": "https://github.com/CybercentreCanada/howler"
94
94
  },
95
95
  "type": "module",
96
- "version": "2.19.0-dev.1276",
96
+ "version": "2.19.0-dev.1282",
97
97
  "exports": {
98
98
  "./i18n": "./i18n.js",
99
99
  "./index.css": "./index.css",