@cccsaurora/howler-ui 2.15.0-dev.318 → 2.15.0-dev.323
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.
- package/api/search/count/hit.js +2 -1
- package/api/search/explain/hit.js +2 -1
- package/api/search/facet/hit.js +2 -1
- package/api/search/grouped/hit.js +2 -1
- package/api/search/histogram/hit.js +2 -1
- package/api/search/hit.d.ts +1 -1
- package/api/search/hit.js +2 -1
- package/components/app/providers/HitSearchProvider.js +4 -4
- package/components/app/providers/ParameterProvider.js +2 -1
- package/components/app/providers/ViewProvider.test.js +4 -4
- package/components/elements/hit/aggregate/HitGraph.js +2 -1
- package/components/routes/advanced/luceneCompletionProvider.js +2 -1
- package/components/routes/dossiers/DossierEditor.test.js +3 -2
- package/components/routes/help/ActionIntroductionDocumentation.js +3 -3
- package/components/routes/hits/search/HitBrowser.js +2 -2
- package/components/routes/hits/search/HitContextMenu.d.ts +15 -0
- package/components/routes/hits/search/HitContextMenu.js +100 -12
- package/components/routes/hits/search/HitContextMenu.test.d.ts +1 -0
- package/components/routes/hits/search/HitContextMenu.test.js +774 -0
- package/components/routes/hits/search/HitQuery.js +4 -3
- package/components/routes/views/ViewComposer.js +2 -2
- package/locales/en/translation.json +1 -0
- package/locales/fr/translation.json +1 -0
- package/package.json +1 -1
- package/setupTests.js +1 -0
- package/tests/server-handlers.js +7 -1
- package/tests/utils.d.ts +12 -0
- package/tests/utils.js +41 -0
- package/utils/constants.d.ts +1 -0
- package/utils/constants.js +1 -0
|
@@ -10,6 +10,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
10
10
|
import { useTranslation } from 'react-i18next';
|
|
11
11
|
import { useLocation } from 'react-router-dom';
|
|
12
12
|
import { useContextSelector } from 'use-context-selector';
|
|
13
|
+
import { DEFAULT_QUERY } from '@cccsaurora/howler-ui/utils/constants';
|
|
13
14
|
import { sanitizeMultilineLucene } from '@cccsaurora/howler-ui/utils/stringUtils';
|
|
14
15
|
const DEFAULT_MULTILINE_HEIGHT = 250;
|
|
15
16
|
const PROMPT_CONTEXT = 'isHitQuery && !suggestWidgetVisible && !renameInputVisible && !inSnippetMode && !quickFixWidgetVisible';
|
|
@@ -18,9 +19,9 @@ const HitQuery = ({ searching = false, disabled = false, compact = false, trigge
|
|
|
18
19
|
const location = useLocation();
|
|
19
20
|
const theme = useTheme();
|
|
20
21
|
const monaco = useMonaco();
|
|
21
|
-
const savedQuery = useContextSelector(ParameterContext, ctx => ctx.query ||
|
|
22
|
+
const savedQuery = useContextSelector(ParameterContext, ctx => ctx.query || DEFAULT_QUERY);
|
|
22
23
|
const prevQuery = useRef(null);
|
|
23
|
-
const [query, setQuery] = useState(new URLSearchParams(window.location.search).get('query') ||
|
|
24
|
+
const [query, setQuery] = useState(new URLSearchParams(window.location.search).get('query') || DEFAULT_QUERY);
|
|
24
25
|
const fzfSearch = useContextSelector(HitSearchContext, ctx => ctx?.fzfSearch ?? false);
|
|
25
26
|
const [loaded, setLoaded] = useState(false);
|
|
26
27
|
const [multiline, setMultiline] = useState(false);
|
|
@@ -128,7 +129,7 @@ const HitQuery = ({ searching = false, disabled = false, compact = false, trigge
|
|
|
128
129
|
p: 0.5,
|
|
129
130
|
height: multiline ? `${DEFAULT_MULTILINE_HEIGHT + y}px` : theme.spacing(5)
|
|
130
131
|
}
|
|
131
|
-
], onKeyDown: e => e.stopPropagation(), children: [_jsx(TuiIconButton, { disabled: query.includes('\n#') || disabled, sx: { mr: 1, alignSelf: 'start' }, onClick: () => setMultiline(!multiline), color: multiline ? 'primary' : theme.palette.text.primary, transparent: !multiline, size: compact ? 'small' : 'medium', children: _jsx(Height, { sx: { fontSize: '20px' } }) }), _jsx(QueryEditor, { id: "hit-query", query: preppedQuery, setQuery: setQuery, language: "lucene", height: multiline ? `${DEFAULT_MULTILINE_HEIGHT - 30}px` : '20px', onMount: onMount, editorOptions: options }), fzfSearch && (_jsx(Tooltip, { title: t('route.history'), children: _jsx(History, {}) })), _jsx(TuiIconButton, { disabled: searching || disabled, onClick: () => setQuery(
|
|
132
|
+
], onKeyDown: e => e.stopPropagation(), children: [_jsx(TuiIconButton, { disabled: query.includes('\n#') || disabled, sx: { mr: 1, alignSelf: 'start' }, onClick: () => setMultiline(!multiline), color: multiline ? 'primary' : theme.palette.text.primary, transparent: !multiline, size: compact ? 'small' : 'medium', children: _jsx(Height, { sx: { fontSize: '20px' } }) }), _jsx(QueryEditor, { id: "hit-query", query: preppedQuery, setQuery: setQuery, language: "lucene", height: multiline ? `${DEFAULT_MULTILINE_HEIGHT - 30}px` : '20px', onMount: onMount, editorOptions: options }), fzfSearch && (_jsx(Tooltip, { title: t('route.history'), children: _jsx(History, {}) })), _jsx(TuiIconButton, { disabled: searching || disabled, onClick: () => setQuery(DEFAULT_QUERY), sx: { ml: 1, alignSelf: 'start', flexShrink: 0 }, size: compact ? 'small' : 'medium', children: _jsx(Tooltip, { title: t('route.clear'), children: _jsx(Clear, { sx: { fontSize: '20px' } }) }) }), _jsx(TuiIconButton, { disabled: searching || disabled, onClick: search, sx: { ml: 1, alignSelf: 'start', flexShrink: 0 }, size: compact ? 'small' : 'medium', children: _jsx(Tooltip, { title: t('route.search'), children: _jsx(Badge, { invisible: !isDirty, color: "warning", variant: "dot", children: _jsx(Search, { sx: { fontSize: '20px' } }) }) }) }), !loaded && (_jsx(Skeleton, { variant: "rectangular", sx: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }, height: "100%" })), multiline && (_jsx(Box, { sx: {
|
|
132
133
|
position: 'absolute',
|
|
133
134
|
left: 0,
|
|
134
135
|
right: 0,
|
|
@@ -22,7 +22,7 @@ import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/us
|
|
|
22
22
|
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
23
23
|
import { useNavigate, useParams } from 'react-router-dom';
|
|
24
24
|
import { useContextSelector } from 'use-context-selector';
|
|
25
|
-
import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
|
|
25
|
+
import { DEFAULT_QUERY, StorageKey } from '@cccsaurora/howler-ui/utils/constants';
|
|
26
26
|
import { convertDateToLucene } from '@cccsaurora/howler-ui/utils/utils';
|
|
27
27
|
import ErrorBoundary from '../ErrorBoundary';
|
|
28
28
|
import HitQuery from '../hits/search/HitQuery';
|
|
@@ -127,7 +127,7 @@ const ViewComposer = () => {
|
|
|
127
127
|
}
|
|
128
128
|
}, [dispatchApi, loadHits, pageCount, setQuery, sort, span]);
|
|
129
129
|
useEffect(() => {
|
|
130
|
-
search(query ||
|
|
130
|
+
search(query || DEFAULT_QUERY);
|
|
131
131
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
132
132
|
}, []);
|
|
133
133
|
// We only run this when ancillary properties (i.e. filters, sorting) change
|
|
@@ -179,6 +179,7 @@
|
|
|
179
179
|
"hit.panel.open": "Open Hit Viewer",
|
|
180
180
|
"hit.panel.close": "Close",
|
|
181
181
|
"hit.panel.hit.noselection": "No hit has been selected",
|
|
182
|
+
"hit.panel.exclude": "Exclude By",
|
|
182
183
|
"hit.panel.details.cluster": "Cluster Size",
|
|
183
184
|
"hit.panel.details.cluster.description": "Size of the cluster",
|
|
184
185
|
"hit.panel.details.no.subjects": "No subjects found",
|
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
"hit.panel.open": "Ouvrir hit",
|
|
181
181
|
"hit.panel.close": "Fermer",
|
|
182
182
|
"hit.panel.hit.noselection": "Aucun résultat n'a été sélectionné",
|
|
183
|
+
"hit.panel.exclude": "Exclure par",
|
|
183
184
|
"hit.panel.details.cluster": "Taille de la grappe",
|
|
184
185
|
"hit.panel.details.cluster.description": "Taille de la grappe",
|
|
185
186
|
"hit.panel.details.no.subjects": "Aucun sujet trouvé",
|
package/package.json
CHANGED
package/setupTests.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as matchers from '@testing-library/jest-dom/matchers';
|
|
|
3
3
|
import '@testing-library/jest-dom/vitest';
|
|
4
4
|
import { configure } from '@testing-library/react';
|
|
5
5
|
import { server } from '@cccsaurora/howler-ui/tests/server';
|
|
6
|
+
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
6
7
|
// Extend vitest with the dom matchers from jest-dom.
|
|
7
8
|
expect.extend(matchers);
|
|
8
9
|
// tell React Testing Library to look for id as the testId.
|
package/tests/server-handlers.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { http, HttpResponse } from 'msw';
|
|
2
|
+
import { createMockAction } from './utils';
|
|
2
3
|
export const MOCK_RESPONSES = {
|
|
3
4
|
'/api/v1/view/example_view_id': {
|
|
4
5
|
owner: 'user',
|
|
@@ -42,7 +43,12 @@ export const MOCK_RESPONSES = {
|
|
|
42
43
|
type: 'personal',
|
|
43
44
|
span: 'date.range.1.month'
|
|
44
45
|
},
|
|
45
|
-
'/api/v1/view/:view_id/favourite': { success: true }
|
|
46
|
+
'/api/v1/view/:view_id/favourite': { success: true },
|
|
47
|
+
'/api/v1/search/action': {
|
|
48
|
+
items: [createMockAction()],
|
|
49
|
+
total: 1,
|
|
50
|
+
rows: 1
|
|
51
|
+
}
|
|
46
52
|
};
|
|
47
53
|
const handlers = [
|
|
48
54
|
...Object.entries(MOCK_RESPONSES).map(([path, data]) => http.all(path, async () => HttpResponse.json({ api_response: data }))),
|
package/tests/utils.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Action } from '@cccsaurora/howler-ui/models/entities/generated/Action';
|
|
2
|
+
import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
|
|
3
|
+
import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
|
|
4
|
+
import type { Template } from '@cccsaurora/howler-ui/models/entities/generated/Template';
|
|
5
|
+
type RecursivePartial<T> = {
|
|
6
|
+
[P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object | undefined ? RecursivePartial<T[P]> : T[P];
|
|
7
|
+
};
|
|
8
|
+
export declare const createMockHit: (overrides?: RecursivePartial<Hit>) => Hit;
|
|
9
|
+
export declare const createMockAnalytic: (overrides?: Partial<Analytic>) => Analytic;
|
|
10
|
+
export declare const createMockTemplate: (overrides?: Partial<Template>) => Template;
|
|
11
|
+
export declare const createMockAction: (overrides?: Partial<Action>) => Action;
|
|
12
|
+
export {};
|
package/tests/utils.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Mock data factories
|
|
2
|
+
export const createMockHit = (overrides) => ({
|
|
3
|
+
howler: {
|
|
4
|
+
id: 'test-hit-1',
|
|
5
|
+
analytic: 'test-analytic',
|
|
6
|
+
detection: 'Test Detection',
|
|
7
|
+
status: 'open',
|
|
8
|
+
assessment: null,
|
|
9
|
+
outline: { indicators: ['a', 'b', 'c'] },
|
|
10
|
+
...overrides?.howler
|
|
11
|
+
},
|
|
12
|
+
event: {
|
|
13
|
+
id: 'event-123',
|
|
14
|
+
...overrides?.event
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
export const createMockAnalytic = (overrides) => ({
|
|
18
|
+
analytic_id: 'test-analytic-id',
|
|
19
|
+
name: 'test-analytic',
|
|
20
|
+
triage_settings: {
|
|
21
|
+
valid_assessments: ['legitimate', 'false_positive'],
|
|
22
|
+
skip_rationale: false,
|
|
23
|
+
...overrides?.triage_settings
|
|
24
|
+
},
|
|
25
|
+
...overrides
|
|
26
|
+
});
|
|
27
|
+
export const createMockTemplate = (overrides) => ({
|
|
28
|
+
keys: ['howler.detection', 'event.id'],
|
|
29
|
+
...overrides
|
|
30
|
+
});
|
|
31
|
+
export const createMockAction = (overrides) => ({
|
|
32
|
+
action_id: 'action-1',
|
|
33
|
+
name: 'Test Action',
|
|
34
|
+
operations: [
|
|
35
|
+
{
|
|
36
|
+
data_json: '{}',
|
|
37
|
+
operation_id: 'transition'
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
...overrides
|
|
41
|
+
});
|
package/utils/constants.d.ts
CHANGED
package/utils/constants.js
CHANGED