@cccsaurora/howler-ui 2.17.0-dev.617 → 2.17.1
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/index.d.ts +0 -2
- package/api/index.js +2 -4
- package/api/search/index.d.ts +1 -2
- package/api/search/index.js +1 -2
- package/commons/components/leftnav/LeftNavDrawer.js +1 -1
- package/components/app/App.js +0 -14
- package/components/app/providers/FavouritesProvider.js +2 -2
- package/components/app/providers/HitSearchProvider.d.ts +1 -0
- package/components/app/providers/HitSearchProvider.js +11 -6
- package/components/app/providers/HitSearchProvider.test.js +32 -11
- package/components/app/providers/LocalStorageProvider.js +1 -1
- package/components/app/providers/ParameterProvider.d.ts +2 -9
- package/components/app/providers/ParameterProvider.js +240 -165
- package/components/app/providers/ParameterProvider.test.js +14 -307
- package/components/elements/EditRow.d.ts +4 -1
- package/components/elements/EditRow.js +4 -4
- package/components/elements/PluginTypography.d.ts +1 -2
- package/components/elements/PluginTypography.js +2 -3
- package/components/elements/UserList.d.ts +2 -5
- package/components/elements/UserList.js +5 -14
- package/components/elements/addons/search/phrase/Phrase.js +1 -1
- package/components/elements/display/ChipPopper.d.ts +1 -1
- package/components/elements/display/ChipPopper.js +1 -1
- package/components/elements/display/HowlerCard.js +1 -1
- package/components/elements/display/Modal.js +0 -1
- package/components/elements/display/icons/BundleButton.d.ts +6 -0
- package/components/elements/display/icons/BundleButton.js +32 -0
- package/components/elements/hit/HitBanner.js +48 -28
- package/components/elements/hit/HitCard.js +1 -1
- package/components/elements/{ObjectDetails.js → hit/HitDetails.js} +17 -17
- package/components/elements/hit/HitOutline.js +7 -3
- package/components/elements/hit/{HitPreview.d.ts → HitQuickSearch.d.ts} +3 -3
- package/components/elements/hit/{HitPreview.js → HitQuickSearch.js} +4 -10
- package/components/elements/hit/HitRelated.d.ts +1 -1
- package/components/elements/hit/HitRelated.js +3 -30
- package/components/elements/hit/outlines/DefaultOutline.js +1 -1
- package/components/elements/hit/related/PivotLink.js +1 -1
- package/components/elements/hit/related/RelatedLink.d.ts +1 -0
- package/components/elements/hit/related/RelatedLink.js +2 -2
- package/components/elements/view/ViewTitle.js +1 -1
- package/components/hooks/useHitActions.d.ts +1 -1
- package/components/hooks/useHitActions.js +2 -2
- package/components/hooks/useHitSelection.js +24 -3
- package/components/hooks/useLocalStorage.d.ts +13 -0
- package/components/hooks/useLocalStorage.js +53 -0
- package/components/hooks/useLocalStorageItem.d.ts +18 -0
- package/components/hooks/useLocalStorageItem.js +78 -0
- package/components/hooks/useLocalStorageItem.test.d.ts +1 -0
- package/components/hooks/useLocalStorageItem.test.js +144 -0
- package/components/hooks/useMyLocalStorage.js +2 -2
- package/components/hooks/useMyPreferences.js +1 -10
- package/components/hooks/useMySearch.js +2 -2
- package/components/hooks/useMySitemap.js +1 -4
- package/components/hooks/useMyTheme.js +2 -9
- package/components/routes/action/view/ActionSearch.js +1 -1
- package/components/routes/advanced/QueryBuilder.js +1 -1
- package/components/routes/analytics/AnalyticDetails.js +2 -2
- package/components/routes/analytics/AnalyticSearch.js +1 -1
- package/components/routes/help/ApiDocumentation.js +1 -1
- package/components/routes/help/BundleDocumentation.d.ts +3 -0
- package/components/routes/help/BundleDocumentation.js +12 -0
- package/components/routes/help/HitDocumentation.js +3 -1
- package/components/routes/help/markdown/en/bundles.md.js +1 -0
- package/components/routes/help/markdown/fr/bundles.md.js +1 -0
- package/components/routes/hits/search/BundleParentMenu.d.ts +6 -0
- package/components/routes/hits/search/BundleParentMenu.js +32 -0
- package/components/routes/hits/search/HitContextMenu.js +2 -3
- package/components/routes/hits/search/InformationPane.d.ts +0 -1
- package/components/routes/hits/search/InformationPane.js +28 -6
- package/components/routes/hits/search/LayoutSettings.d.ts +3 -0
- package/components/routes/hits/search/LayoutSettings.js +18 -0
- package/components/routes/hits/search/QuerySettings.js +1 -2
- package/components/routes/hits/search/QuerySettings.test.js +9 -14
- package/components/routes/hits/search/SearchPane.js +37 -13
- package/components/routes/hits/search/ViewLink.js +1 -1
- package/components/routes/hits/search/grid/EnhancedCell.js +1 -1
- package/components/routes/hits/view/HitViewer.js +4 -3
- package/components/routes/home/AnalyticCard.d.ts +2 -3
- package/components/routes/home/AnalyticCard.js +2 -2
- package/components/routes/home/ViewCard.js +1 -1
- package/components/routes/home/ViewRefresh.d.ts +23 -0
- package/components/routes/home/ViewRefresh.js +67 -0
- package/components/routes/home/index.js +9 -46
- package/components/{elements/MarkdownEditor.js → routes/overviews/OverviewEditor.js} +3 -3
- package/components/routes/overviews/OverviewViewer.js +2 -2
- package/components/routes/settings/LocalSection.js +2 -1
- package/locales/en/translation.json +6 -42
- package/locales/fr/translation.json +4 -35
- package/models/WithMetadata.d.ts +1 -2
- package/models/entities/generated/{ThreatEnrichment.d.ts → Enrichment.d.ts} +1 -1
- package/models/entities/generated/Howler.d.ts +4 -0
- package/models/entities/generated/Rule.d.ts +10 -2
- package/models/entities/generated/Threat.d.ts +2 -2
- package/package.json +1 -16
- package/plugins/clue/components/ClueTypography.js +2 -2
- package/plugins/clue/utils.d.ts +1 -2
- package/utils/constants.d.ts +4 -3
- package/utils/constants.js +1 -0
- package/api/search/case.d.ts +0 -4
- package/api/search/case.js +0 -8
- package/api/v2/case/index.d.ts +0 -6
- package/api/v2/case/index.js +0 -18
- package/api/v2/index.d.ts +0 -4
- package/api/v2/index.js +0 -6
- package/api/v2/search/facet.d.ts +0 -3
- package/api/v2/search/facet.js +0 -12
- package/api/v2/search/index.d.ts +0 -5
- package/api/v2/search/index.js +0 -24
- package/components/elements/ObjectDetails.d.ts +0 -6
- package/components/elements/case/CaseCard.d.ts +0 -8
- package/components/elements/case/CaseCard.js +0 -39
- package/components/elements/case/CasePreview.d.ts +0 -6
- package/components/elements/case/CasePreview.js +0 -17
- package/components/elements/case/StatusIcon.d.ts +0 -5
- package/components/elements/case/StatusIcon.js +0 -13
- package/components/elements/hit/elements/AnalyticLink.d.ts +0 -8
- package/components/elements/hit/elements/AnalyticLink.js +0 -22
- package/components/elements/hit/related/RelatedRecords.js +0 -63
- package/components/elements/observable/ObservableCard.d.ts +0 -5
- package/components/elements/observable/ObservableCard.js +0 -7
- package/components/elements/observable/ObservablePreview.d.ts +0 -6
- package/components/elements/observable/ObservablePreview.js +0 -12
- package/components/hooks/useRelatedRecords.d.ts +0 -13
- package/components/hooks/useRelatedRecords.js +0 -32
- package/components/routes/cases/CaseViewer.d.ts +0 -2
- package/components/routes/cases/CaseViewer.js +0 -24
- package/components/routes/cases/Cases.d.ts +0 -2
- package/components/routes/cases/Cases.js +0 -101
- package/components/routes/cases/constants.d.ts +0 -5
- package/components/routes/cases/constants.js +0 -5
- package/components/routes/cases/detail/AlertPanel.d.ts +0 -6
- package/components/routes/cases/detail/AlertPanel.js +0 -32
- package/components/routes/cases/detail/CaseDashboard.d.ts +0 -7
- package/components/routes/cases/detail/CaseDashboard.js +0 -49
- package/components/routes/cases/detail/CaseDetails.d.ts +0 -6
- package/components/routes/cases/detail/CaseDetails.js +0 -61
- package/components/routes/cases/detail/CaseOverview.d.ts +0 -7
- package/components/routes/cases/detail/CaseOverview.js +0 -43
- package/components/routes/cases/detail/CaseSidebar.d.ts +0 -6
- package/components/routes/cases/detail/CaseSidebar.js +0 -36
- package/components/routes/cases/detail/CaseTask.d.ts +0 -11
- package/components/routes/cases/detail/CaseTask.js +0 -57
- package/components/routes/cases/detail/ItemPage.d.ts +0 -6
- package/components/routes/cases/detail/ItemPage.js +0 -93
- package/components/routes/cases/detail/RelatedCasePanel.d.ts +0 -6
- package/components/routes/cases/detail/RelatedCasePanel.js +0 -31
- package/components/routes/cases/detail/TaskPanel.d.ts +0 -7
- package/components/routes/cases/detail/TaskPanel.js +0 -52
- package/components/routes/cases/detail/aggregates/CaseAggregate.d.ts +0 -12
- package/components/routes/cases/detail/aggregates/CaseAggregate.js +0 -19
- package/components/routes/cases/detail/aggregates/SourceAggregate.d.ts +0 -6
- package/components/routes/cases/detail/aggregates/SourceAggregate.js +0 -27
- package/components/routes/cases/detail/sidebar/CaseFolder.d.ts +0 -13
- package/components/routes/cases/detail/sidebar/CaseFolder.js +0 -134
- package/components/routes/cases/detail/sidebar/types.d.ts +0 -3
- package/components/routes/cases/detail/sidebar/utils.d.ts +0 -3
- package/components/routes/cases/detail/sidebar/utils.js +0 -25
- package/components/routes/cases/hooks/useCase.d.ts +0 -13
- package/components/routes/cases/hooks/useCase.js +0 -38
- package/components/routes/cases/modals/ResolveModal.d.ts +0 -7
- package/components/routes/cases/modals/ResolveModal.js +0 -59
- package/components/routes/hits/search/shared/IndexPicker.d.ts +0 -2
- package/components/routes/hits/search/shared/IndexPicker.js +0 -20
- package/components/routes/observables/ObservableViewer.d.ts +0 -7
- package/components/routes/observables/ObservableViewer.js +0 -27
- package/models/entities/generated/AttachmentsFile.d.ts +0 -12
- package/models/entities/generated/Case.d.ts +0 -28
- package/models/entities/generated/DestinationOriginal.d.ts +0 -19
- package/models/entities/generated/EmailAttachment.d.ts +0 -8
- package/models/entities/generated/EmailParent.d.ts +0 -19
- package/models/entities/generated/Enrichments.d.ts +0 -7
- package/models/entities/generated/EnrichmentsIndicator.d.ts +0 -21
- package/models/entities/generated/HttpResponse.d.ts +0 -11
- package/models/entities/generated/Item.d.ts +0 -9
- package/models/entities/generated/Observable.d.ts +0 -84
- package/models/entities/generated/ObservableCloud.d.ts +0 -20
- package/models/entities/generated/ObservableDestination.d.ts +0 -23
- package/models/entities/generated/ObservableEmail.d.ts +0 -30
- package/models/entities/generated/ObservableFile.d.ts +0 -36
- package/models/entities/generated/ObservableHowler.d.ts +0 -44
- package/models/entities/generated/ObservableHttp.d.ts +0 -11
- package/models/entities/generated/ObservableObserver.d.ts +0 -21
- package/models/entities/generated/ObservableOrganization.d.ts +0 -7
- package/models/entities/generated/ObservableProcess.d.ts +0 -34
- package/models/entities/generated/ObservableSource.d.ts +0 -23
- package/models/entities/generated/ObservableThreat.d.ts +0 -21
- package/models/entities/generated/ObservableTls.d.ts +0 -12
- package/models/entities/generated/ObserverIngress.d.ts +0 -9
- package/models/entities/generated/Task.d.ts +0 -10
- package/utils/typeUtils.d.ts +0 -7
- package/utils/typeUtils.js +0 -18
- /package/components/elements/hit/{related/RelatedRecords.d.ts → HitDetails.d.ts} +0 -0
- /package/components/{elements/MarkdownEditor.d.ts → routes/overviews/OverviewEditor.d.ts} +0 -0
package/api/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ import * as overview from '@cccsaurora/howler-ui/api/overview';
|
|
|
10
10
|
import * as search from '@cccsaurora/howler-ui/api/search';
|
|
11
11
|
import * as template from '@cccsaurora/howler-ui/api/template';
|
|
12
12
|
import * as user from '@cccsaurora/howler-ui/api/user';
|
|
13
|
-
import * as v2 from '@cccsaurora/howler-ui/api/v2';
|
|
14
13
|
import * as view from '@cccsaurora/howler-ui/api/view';
|
|
15
14
|
/**
|
|
16
15
|
* Defining the default export exposing all children routes of '/api/v1/'.
|
|
@@ -29,7 +28,6 @@ declare const api: {
|
|
|
29
28
|
user: typeof user;
|
|
30
29
|
view: typeof view;
|
|
31
30
|
notebook: typeof notebook;
|
|
32
|
-
v2: typeof v2;
|
|
33
31
|
};
|
|
34
32
|
/**
|
|
35
33
|
* The specification interface of an Howler HTTP response.
|
package/api/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import * as overview from '@cccsaurora/howler-ui/api/overview';
|
|
|
10
10
|
import * as search from '@cccsaurora/howler-ui/api/search';
|
|
11
11
|
import * as template from '@cccsaurora/howler-ui/api/template';
|
|
12
12
|
import * as user from '@cccsaurora/howler-ui/api/user';
|
|
13
|
-
import * as v2 from '@cccsaurora/howler-ui/api/v2';
|
|
14
13
|
import * as view from '@cccsaurora/howler-ui/api/view';
|
|
15
14
|
import AxiosClient from '@cccsaurora/howler-ui/rest/AxiosClient';
|
|
16
15
|
import urlJoin from 'url-join';
|
|
@@ -39,8 +38,7 @@ const api = {
|
|
|
39
38
|
template,
|
|
40
39
|
user,
|
|
41
40
|
view,
|
|
42
|
-
notebook
|
|
43
|
-
v2
|
|
41
|
+
notebook
|
|
44
42
|
};
|
|
45
43
|
/**
|
|
46
44
|
* The base section of the Howler API uri.
|
|
@@ -59,7 +57,7 @@ export const uri = () => {
|
|
|
59
57
|
* @returns `string` - properly formatted howler uri.
|
|
60
58
|
*/
|
|
61
59
|
const format = (_uri) => {
|
|
62
|
-
return _uri.startsWith(
|
|
60
|
+
return _uri.startsWith(uri()) ? _uri : `${uri()}/${_uri.replace(/\/$/, '')}`;
|
|
63
61
|
};
|
|
64
62
|
/**
|
|
65
63
|
* Append series of search parameters to the specified uri.
|
package/api/search/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as action from '@cccsaurora/howler-ui/api/search/action';
|
|
2
2
|
import * as analytic from '@cccsaurora/howler-ui/api/search/analytic';
|
|
3
|
-
import * as case_ from '@cccsaurora/howler-ui/api/search/case';
|
|
4
3
|
import * as count from '@cccsaurora/howler-ui/api/search/count';
|
|
5
4
|
import * as dossier from '@cccsaurora/howler-ui/api/search/dossier';
|
|
6
5
|
import * as facet from '@cccsaurora/howler-ui/api/search/facet';
|
|
@@ -61,4 +60,4 @@ export type HowlerExplainSearchResponse = {
|
|
|
61
60
|
explanation: string;
|
|
62
61
|
}[];
|
|
63
62
|
};
|
|
64
|
-
export { action, analytic,
|
|
63
|
+
export { action, analytic, count, dossier, facet, fields, grouped, histogram, hit, overview, template, user, view };
|
package/api/search/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { joinUri, uri as parentUri } from '@cccsaurora/howler-ui/api';
|
|
2
2
|
import * as action from '@cccsaurora/howler-ui/api/search/action';
|
|
3
3
|
import * as analytic from '@cccsaurora/howler-ui/api/search/analytic';
|
|
4
|
-
import * as case_ from '@cccsaurora/howler-ui/api/search/case';
|
|
5
4
|
import * as count from '@cccsaurora/howler-ui/api/search/count';
|
|
6
5
|
import * as dossier from '@cccsaurora/howler-ui/api/search/dossier';
|
|
7
6
|
import * as facet from '@cccsaurora/howler-ui/api/search/facet';
|
|
@@ -16,4 +15,4 @@ import * as view from '@cccsaurora/howler-ui/api/search/view';
|
|
|
16
15
|
export const uri = () => {
|
|
17
16
|
return joinUri(parentUri(), 'search');
|
|
18
17
|
};
|
|
19
|
-
export { action, analytic,
|
|
18
|
+
export { action, analytic, count, dossier, facet, fields, grouped, histogram, hit, overview, template, user, view };
|
|
@@ -75,7 +75,7 @@ const LeftNavDrawer = () => {
|
|
|
75
75
|
}
|
|
76
76
|
}, children: _jsx(AppName, {}) }), !isTopLayout && _jsx(Divider, {})] }));
|
|
77
77
|
const hide = (_jsx(List, { disablePadding: true, children: _jsxs(ListItemButton, { onClick: leftnav.toggle, children: [_jsx(ListItemIcon, { children: leftnav.open ? _jsx(ChevronLeftIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx(ListItemText, { primary: t('drawer.collapse') })] }, "chevron") }));
|
|
78
|
-
return (_jsx(ClickAwayListener, { mouseEvent: "onMouseDown", touchEvent: "onTouchStart", onClickAway: onCloseDrawerIfOpen, children: _jsxs(StyledDrawer, { variant: "permanent", style: { height: '100%' }, width: preferences.leftnav.width, open: leftnav.open, children: [leftnav.open ? (header) : (_jsx(Tooltip, { title: preferences.appName, "aria-label": preferences.appName, placement: "right", children: header })), _jsx(List, { disablePadding: true, children: leftnav.elements.map((e, i) => {
|
|
78
|
+
return (_jsx(ClickAwayListener, { mouseEvent: "onMouseDown", touchEvent: "onTouchStart", onClickAway: onCloseDrawerIfOpen, children: _jsxs(StyledDrawer, { PaperProps: { elevation: 1 }, variant: "permanent", style: { height: '100%' }, width: preferences.leftnav.width, open: leftnav.open, children: [leftnav.open ? (header) : (_jsx(Tooltip, { title: preferences.appName, "aria-label": preferences.appName, placement: "right", children: header })), _jsx(List, { disablePadding: true, children: leftnav.elements.map((e, i) => {
|
|
79
79
|
if (e.type === 'item') {
|
|
80
80
|
const item = e.element;
|
|
81
81
|
return _jsx(LeftNavItem, { item: item, onClick: isSmDown && onCloseDrawerIfOpen }, item.id);
|
package/components/app/App.js
CHANGED
|
@@ -25,8 +25,6 @@ import UserSearchProvider from '@cccsaurora/howler-ui/components/routes/admin/us
|
|
|
25
25
|
import QueryBuilder from '@cccsaurora/howler-ui/components/routes/advanced/QueryBuilder';
|
|
26
26
|
import AnalyticDetails from '@cccsaurora/howler-ui/components/routes/analytics/AnalyticDetails';
|
|
27
27
|
import AnalyticSearch from '@cccsaurora/howler-ui/components/routes/analytics/AnalyticSearch';
|
|
28
|
-
import CaseViewer from '@cccsaurora/howler-ui/components/routes/cases/CaseViewer';
|
|
29
|
-
import Cases from '@cccsaurora/howler-ui/components/routes/cases/Cases';
|
|
30
28
|
import DossierEditor from '@cccsaurora/howler-ui/components/routes/dossiers/DossierEditor';
|
|
31
29
|
import Dossiers from '@cccsaurora/howler-ui/components/routes/dossiers/Dossiers';
|
|
32
30
|
import ActionDocumentation from '@cccsaurora/howler-ui/components/routes/help/ActionDocumentation';
|
|
@@ -187,18 +185,6 @@ const router = createBrowserRouter([
|
|
|
187
185
|
path: 'bundles/:id',
|
|
188
186
|
element: _jsx(HitBrowser, {})
|
|
189
187
|
},
|
|
190
|
-
{
|
|
191
|
-
path: 'cases',
|
|
192
|
-
element: _jsx(Cases, {})
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
path: 'cases/:id',
|
|
196
|
-
element: _jsx(CaseViewer, {})
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
path: 'cases/:id/*',
|
|
200
|
-
element: _jsx(CaseViewer, {})
|
|
201
|
-
},
|
|
202
188
|
{
|
|
203
189
|
path: 'templates',
|
|
204
190
|
element: _jsx(Templates, {})
|
|
@@ -120,11 +120,11 @@ const FavouriteProvider = ({ children }) => {
|
|
|
120
120
|
(async () => {
|
|
121
121
|
const analyticElement = processAnalyticElement();
|
|
122
122
|
if (analyticElement) {
|
|
123
|
-
newElements.splice(
|
|
123
|
+
newElements.splice(1, 0, analyticElement);
|
|
124
124
|
}
|
|
125
125
|
const viewElement = await processViewElement();
|
|
126
126
|
if (viewElement) {
|
|
127
|
-
newElements.splice(
|
|
127
|
+
newElements.splice(1, 0, viewElement);
|
|
128
128
|
}
|
|
129
129
|
leftNav.setElements(newElements);
|
|
130
130
|
})();
|
|
@@ -11,6 +11,7 @@ export interface HitSearchContextType {
|
|
|
11
11
|
searching: boolean;
|
|
12
12
|
error: string | null;
|
|
13
13
|
response: HowlerSearchResponse<WithMetadata<Hit>> | null;
|
|
14
|
+
bundleId: string | null;
|
|
14
15
|
fzfSearch: boolean;
|
|
15
16
|
setDisplayType: (type: 'list' | 'grid') => void;
|
|
16
17
|
setFzfSearch: Dispatch<SetStateAction<boolean>>;
|
|
@@ -33,7 +33,6 @@ const HitSearchProvider = ({ children }) => {
|
|
|
33
33
|
const trackTotalHits = useContextSelector(ParameterContext, ctx => ctx.trackTotalHits);
|
|
34
34
|
const sort = useContextSelector(ParameterContext, ctx => ctx.sort);
|
|
35
35
|
const span = useContextSelector(ParameterContext, ctx => ctx.span);
|
|
36
|
-
const indexes = useContextSelector(ParameterContext, ctx => ctx.indexes);
|
|
37
36
|
const allFilters = useContextSelector(ParameterContext, ctx => ctx.filters);
|
|
38
37
|
const startDate = useContextSelector(ParameterContext, ctx => ctx.startDate);
|
|
39
38
|
const endDate = useContextSelector(ParameterContext, ctx => ctx.endDate);
|
|
@@ -48,6 +47,7 @@ const HitSearchProvider = ({ children }) => {
|
|
|
48
47
|
'howler.id: *': new Date().toISOString()
|
|
49
48
|
});
|
|
50
49
|
const [fzfSearch, setFzfSearch] = useState(false);
|
|
50
|
+
const bundleId = useMemo(() => (location.pathname.startsWith('/bundles') ? routeParams.id : null), [location.pathname, routeParams.id]);
|
|
51
51
|
const filters = useMemo(() => allFilters.filter(filter => !filter.endsWith('*')), [allFilters]);
|
|
52
52
|
// On load check to filter out any queries older than one month
|
|
53
53
|
useEffect(() => {
|
|
@@ -70,6 +70,11 @@ const HitSearchProvider = ({ children }) => {
|
|
|
70
70
|
else if (startDate && endDate) {
|
|
71
71
|
_filters.push(`event.created:${convertCustomDateRangeToLucene(startDate, endDate)}`);
|
|
72
72
|
}
|
|
73
|
+
// Add bundle filter
|
|
74
|
+
const bundle = location.pathname.startsWith('/bundles') && routeParams.id;
|
|
75
|
+
if (bundle) {
|
|
76
|
+
_filters.push(`howler.bundles:${bundle}`);
|
|
77
|
+
}
|
|
73
78
|
// Fetch all view queries
|
|
74
79
|
if (views.length > 0) {
|
|
75
80
|
const viewObjects = await getCurrentViews({ views });
|
|
@@ -80,7 +85,7 @@ const HitSearchProvider = ({ children }) => {
|
|
|
80
85
|
.forEach(viewQuery => _filters.push(viewQuery));
|
|
81
86
|
}
|
|
82
87
|
return _filters;
|
|
83
|
-
}, [endDate, filters, getCurrentViews, span, startDate, views]);
|
|
88
|
+
}, [endDate, filters, getCurrentViews, location.pathname, routeParams.id, span, startDate, views]);
|
|
84
89
|
const search = useCallback(async (_query, appendResults) => {
|
|
85
90
|
THROTTLER.debounce(async () => {
|
|
86
91
|
if (_query === 'woof!') {
|
|
@@ -100,7 +105,7 @@ const HitSearchProvider = ({ children }) => {
|
|
|
100
105
|
setSearching(true);
|
|
101
106
|
setError(null);
|
|
102
107
|
try {
|
|
103
|
-
const _response = await dispatchApi(api.
|
|
108
|
+
const _response = await dispatchApi(api.search.hit.post({
|
|
104
109
|
offset: appendResults && response ? response.rows : offset,
|
|
105
110
|
rows: pageCount,
|
|
106
111
|
query: _query || DEFAULT_QUERY,
|
|
@@ -142,7 +147,6 @@ const HitSearchProvider = ({ children }) => {
|
|
|
142
147
|
startDate,
|
|
143
148
|
endDate,
|
|
144
149
|
filters,
|
|
145
|
-
indexes,
|
|
146
150
|
setQuery,
|
|
147
151
|
location.pathname,
|
|
148
152
|
routeParams.id,
|
|
@@ -161,14 +165,14 @@ const HitSearchProvider = ({ children }) => {
|
|
|
161
165
|
if (span?.endsWith('custom') && (!startDate || !endDate)) {
|
|
162
166
|
return;
|
|
163
167
|
}
|
|
164
|
-
if (views.length > 0 || (query && query !== DEFAULT_QUERY) || offset > 0 || filters.length > 0) {
|
|
168
|
+
if (views.length > 0 || bundleId || (query && query !== DEFAULT_QUERY) || offset > 0 || filters.length > 0) {
|
|
165
169
|
search(query);
|
|
166
170
|
}
|
|
167
171
|
else {
|
|
168
172
|
setResponse(null);
|
|
169
173
|
}
|
|
170
174
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
171
|
-
}, [offset, pageCount, sort, span,
|
|
175
|
+
}, [offset, pageCount, sort, span, bundleId, location.pathname, startDate, endDate, filters, query, views]);
|
|
172
176
|
return (_jsx(HitSearchContext.Provider, { value: {
|
|
173
177
|
displayType,
|
|
174
178
|
setDisplayType,
|
|
@@ -177,6 +181,7 @@ const HitSearchProvider = ({ children }) => {
|
|
|
177
181
|
getFilters,
|
|
178
182
|
error,
|
|
179
183
|
response,
|
|
184
|
+
bundleId,
|
|
180
185
|
setQueryHistory,
|
|
181
186
|
queryHistory,
|
|
182
187
|
fzfSearch,
|
|
@@ -30,7 +30,6 @@ let mockParameterContext = {
|
|
|
30
30
|
mockParameterContext.offset = parseInt(offset);
|
|
31
31
|
},
|
|
32
32
|
views: [],
|
|
33
|
-
indexes: ['hit'],
|
|
34
33
|
addView: vi.fn()
|
|
35
34
|
};
|
|
36
35
|
const originalMockParameterContext = cloneDeep(mockParameterContext);
|
|
@@ -65,14 +64,22 @@ describe('HitSearchContext', () => {
|
|
|
65
64
|
searching: ctx.searching,
|
|
66
65
|
error: ctx.error,
|
|
67
66
|
response: ctx.response,
|
|
67
|
+
bundleId: ctx.bundleId,
|
|
68
68
|
fzfSearch: ctx.fzfSearch
|
|
69
69
|
})), { wrapper: Wrapper });
|
|
70
70
|
expect(hook.result.current.displayType).toBe('list');
|
|
71
71
|
expect(hook.result.current.searching).toBe(false);
|
|
72
72
|
expect(hook.result.current.error).toBeNull();
|
|
73
73
|
expect(hook.result.current.response).toBeNull();
|
|
74
|
+
expect(hook.result.current.bundleId).toBeNull();
|
|
74
75
|
expect(hook.result.current.fzfSearch).toBe(false);
|
|
75
76
|
});
|
|
77
|
+
it('should set bundleId when on bundles route', () => {
|
|
78
|
+
mockLocation.pathname = '/bundles/test_bundle_id';
|
|
79
|
+
mockParams.mockReturnValue({ id: 'test_bundle_id' });
|
|
80
|
+
const hook = renderHook(() => useContextSelector(HitSearchContext, ctx => ctx.bundleId), { wrapper: Wrapper });
|
|
81
|
+
expect(hook.result.current).toBe('test_bundle_id');
|
|
82
|
+
});
|
|
76
83
|
it('should initialize queryHistory from localStorage', () => {
|
|
77
84
|
const mockHistory = { 'test:query': new Date().toISOString() };
|
|
78
85
|
mockLocalStorage.setItem(`${MY_LOCAL_STORAGE_PREFIX}.${StorageKey.QUERY_HISTORY}`, JSON.stringify(mockHistory));
|
|
@@ -130,7 +137,7 @@ describe('HitSearchContext', () => {
|
|
|
130
137
|
hook.result.current.search('test query');
|
|
131
138
|
});
|
|
132
139
|
await waitFor(() => {
|
|
133
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
140
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
134
141
|
query: expect.stringContaining('test query')
|
|
135
142
|
}));
|
|
136
143
|
});
|
|
@@ -214,13 +221,27 @@ describe('HitSearchContext', () => {
|
|
|
214
221
|
expect(hook.result.current.response?.items.length).toBe(2);
|
|
215
222
|
});
|
|
216
223
|
});
|
|
224
|
+
it('should include bundle filter when on bundles route', async () => {
|
|
225
|
+
mockLocation.pathname = '/bundles/test_bundle_id';
|
|
226
|
+
mockParams.mockReturnValue({ id: 'test_bundle_id' });
|
|
227
|
+
const hook = renderHook(() => useContextSelector(HitSearchContext, ctx => ctx.search), { wrapper: Wrapper });
|
|
228
|
+
act(() => {
|
|
229
|
+
hook.result.current('test query');
|
|
230
|
+
});
|
|
231
|
+
await waitFor(() => {
|
|
232
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
233
|
+
query: 'test query',
|
|
234
|
+
filters: ['event.created:[now-1w TO now]', 'howler.bundles:test_bundle_id']
|
|
235
|
+
}));
|
|
236
|
+
});
|
|
237
|
+
});
|
|
217
238
|
it('should apply date range filter from span', async () => {
|
|
218
239
|
const hook = renderHook(() => useContextSelector(HitSearchContext, ctx => ctx.search), { wrapper: Wrapper });
|
|
219
240
|
act(() => {
|
|
220
241
|
hook.result.current('test query');
|
|
221
242
|
});
|
|
222
243
|
await waitFor(() => {
|
|
223
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
244
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
224
245
|
filters: expect.arrayContaining([expect.stringContaining('event.created:')])
|
|
225
246
|
}));
|
|
226
247
|
});
|
|
@@ -234,7 +255,7 @@ describe('HitSearchContext', () => {
|
|
|
234
255
|
hook.result.current('test query');
|
|
235
256
|
});
|
|
236
257
|
await waitFor(() => {
|
|
237
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
258
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
238
259
|
filters: expect.arrayContaining([expect.stringContaining('event.created:')])
|
|
239
260
|
}));
|
|
240
261
|
});
|
|
@@ -246,7 +267,7 @@ describe('HitSearchContext', () => {
|
|
|
246
267
|
hook.result.current('test query');
|
|
247
268
|
});
|
|
248
269
|
await waitFor(() => {
|
|
249
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
270
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
250
271
|
filters: expect.not.arrayContaining([expect.stringContaining('howler.escalation:*')])
|
|
251
272
|
}));
|
|
252
273
|
});
|
|
@@ -299,7 +320,7 @@ describe('HitSearchContext', () => {
|
|
|
299
320
|
expect(hpost).toHaveBeenCalled();
|
|
300
321
|
}, { timeout: 2000 });
|
|
301
322
|
});
|
|
302
|
-
it('should not trigger search when query is DEFAULT_QUERY', async () => {
|
|
323
|
+
it('should not trigger search when query is DEFAULT_QUERY and no bundleId', async () => {
|
|
303
324
|
mockParameterContext.query = DEFAULT_QUERY;
|
|
304
325
|
renderHook(() => useContextSelector(HitSearchContext, ctx => ctx.response), { wrapper: Wrapper });
|
|
305
326
|
await waitFor(() => {
|
|
@@ -337,7 +358,7 @@ describe('HitSearchContext', () => {
|
|
|
337
358
|
expect(hpost).toHaveBeenCalledTimes(1);
|
|
338
359
|
}, { timeout: 2000 });
|
|
339
360
|
});
|
|
340
|
-
it('should clear response when query becomes DEFAULT_QUERY without viewId', async () => {
|
|
361
|
+
it('should clear response when query becomes DEFAULT_QUERY without viewId or bundleId', async () => {
|
|
341
362
|
const hook = renderHook(() => useContextSelector(HitSearchContext, ctx => ctx.response), { wrapper: Wrapper });
|
|
342
363
|
await waitFor(() => {
|
|
343
364
|
expect(hook.result.current).toBeDefined();
|
|
@@ -363,7 +384,7 @@ describe('HitSearchContext', () => {
|
|
|
363
384
|
hook.result.current('test query');
|
|
364
385
|
});
|
|
365
386
|
await waitFor(() => {
|
|
366
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
387
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
367
388
|
query: 'test query',
|
|
368
389
|
filters: expect.arrayContaining(['howler.status:open', 'howler.priority:high'])
|
|
369
390
|
}));
|
|
@@ -381,7 +402,7 @@ describe('HitSearchContext', () => {
|
|
|
381
402
|
hook.result.current('test query');
|
|
382
403
|
});
|
|
383
404
|
await waitFor(() => {
|
|
384
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
405
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
385
406
|
query: 'test query',
|
|
386
407
|
filters: [
|
|
387
408
|
'event.created:[now-1w TO now]',
|
|
@@ -438,7 +459,7 @@ describe('HitSearchContext', () => {
|
|
|
438
459
|
hook.result.current('test query');
|
|
439
460
|
});
|
|
440
461
|
await waitFor(() => {
|
|
441
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
462
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
442
463
|
query: expect.stringContaining('test query'),
|
|
443
464
|
filters: ['event.created:[now-1w TO now]']
|
|
444
465
|
}));
|
|
@@ -455,7 +476,7 @@ describe('HitSearchContext', () => {
|
|
|
455
476
|
hook.result.current('test query');
|
|
456
477
|
});
|
|
457
478
|
await waitFor(() => {
|
|
458
|
-
expect(hpost).toHaveBeenCalledWith('/api/
|
|
479
|
+
expect(hpost).toHaveBeenCalledWith('/api/v1/search/hit', expect.objectContaining({
|
|
459
480
|
query: 'test query',
|
|
460
481
|
filters: ['event.created:[now-1w TO now]', 'howler.status:open', 'howler.priority:high']
|
|
461
482
|
}));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import useLocalStorage from '@cccsaurora/howler-ui/
|
|
2
|
+
import useLocalStorage from '@cccsaurora/howler-ui/components/hooks/useLocalStorage';
|
|
3
3
|
import { createContext, useCallback, useEffect, useState } from 'react';
|
|
4
4
|
import { MY_LOCAL_STORAGE_PREFIX, StorageKey } from '@cccsaurora/howler-ui/utils/constants';
|
|
5
5
|
export const LocalStorageContext = createContext(null);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { FC, PropsWithChildren } from 'react';
|
|
2
|
-
export type SearchIndex = 'hit' | 'observable' | 'case';
|
|
3
2
|
export interface ParameterContextType {
|
|
4
3
|
selected?: string;
|
|
5
4
|
query?: string;
|
|
@@ -7,7 +6,6 @@ export interface ParameterContextType {
|
|
|
7
6
|
trackTotalHits: boolean;
|
|
8
7
|
sort?: string;
|
|
9
8
|
span?: string;
|
|
10
|
-
indexes?: SearchIndex[];
|
|
11
9
|
filters?: string[];
|
|
12
10
|
startDate?: string;
|
|
13
11
|
endDate?: string;
|
|
@@ -21,16 +19,11 @@ export interface ParameterContextType {
|
|
|
21
19
|
addFilter: (filter: string) => void;
|
|
22
20
|
removeFilter: (filter: string) => void;
|
|
23
21
|
setFilter: (index: number, filter: string) => void;
|
|
24
|
-
|
|
25
|
-
addIndex: (index: SearchIndex) => void;
|
|
26
|
-
removeIndex: (index: SearchIndex) => void;
|
|
27
|
-
setIndex: (position: number, index: SearchIndex) => void;
|
|
28
|
-
setIndexes: (indexes: SearchIndex[]) => void;
|
|
29
|
-
resetIndexes: () => void;
|
|
22
|
+
clearFilters: () => void;
|
|
30
23
|
addView: (view: string) => void;
|
|
31
24
|
removeView: (view: string) => void;
|
|
32
25
|
setView: (index: number, view: string) => void;
|
|
33
|
-
|
|
26
|
+
clearViews: () => void;
|
|
34
27
|
}
|
|
35
28
|
export declare const ParameterContext: import("use-context-selector").Context<ParameterContextType>;
|
|
36
29
|
/**
|