@cccsaurora/howler-ui 2.12.0 → 2.13.0-dev.75
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/facet/hit.d.ts +4 -2
- package/api/search/facet/hit.js +5 -5
- package/api/search/facet/index.d.ts +1 -0
- package/components/elements/hit/HitSummary.js +5 -5
- package/components/elements/hit/aggregate/HitGraph.js +6 -9
- package/components/routes/advanced/luceneCompletionProvider.js +4 -2
- package/components/routes/analytics/widgets/Assessment.js +3 -2
- package/components/routes/analytics/widgets/Escalation.js +4 -3
- package/components/routes/analytics/widgets/Stacked.js +4 -3
- package/components/routes/dossiers/DossierEditor.js +1 -1
- package/components/routes/hits/search/shared/HitFilter.js +2 -2
- package/components/routes/hits/view/LeadRenderer.js +1 -1
- package/package.json +109 -105
- package/plugins/HowlerPlugin.d.ts +1 -1
- package/plugins/borealis/Provider.d.ts +3 -0
- package/plugins/borealis/Provider.js +14 -0
- package/plugins/borealis/components/BorealisChip.d.ts +3 -0
- package/plugins/borealis/components/BorealisChip.js +27 -0
- package/plugins/borealis/components/BorealisLeadForm.d.ts +4 -0
- package/plugins/borealis/components/BorealisLeadForm.js +23 -0
- package/plugins/borealis/components/BorealisPivot.d.ts +3 -0
- package/plugins/borealis/components/BorealisPivot.js +83 -0
- package/plugins/borealis/components/BorealisPivotForm.d.ts +4 -0
- package/plugins/borealis/components/BorealisPivotForm.js +44 -0
- package/plugins/borealis/components/BorealisTypography.d.ts +3 -0
- package/plugins/borealis/components/BorealisTypography.js +53 -0
- package/plugins/borealis/helpers.d.ts +6 -0
- package/plugins/borealis/helpers.js +137 -0
- package/plugins/borealis/index.d.ts +21 -0
- package/plugins/borealis/index.js +46 -0
- package/plugins/borealis/locales/borealis.en.json +7 -0
- package/plugins/borealis/locales/borealis.fr.json +7 -0
- package/plugins/borealis/setup.d.ts +2 -0
- package/plugins/borealis/setup.js +44 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { HowlerFacetSearchRequest, HowlerFacetSearchResponse } from '@cccsaurora/howler-ui/api/search/facet';
|
|
2
|
-
export declare const uri: (
|
|
3
|
-
export declare const post: (
|
|
2
|
+
export declare const uri: () => string;
|
|
3
|
+
export declare const post: (request?: HowlerFacetSearchRequest) => Promise<{
|
|
4
|
+
[index: string]: HowlerFacetSearchResponse;
|
|
5
|
+
}>;
|
package/api/search/facet/hit.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { hpost,
|
|
1
|
+
import { hpost, joinUri } from '@cccsaurora/howler-ui/api';
|
|
2
2
|
import { uri as parentUri } from '@cccsaurora/howler-ui/api/search/facet';
|
|
3
|
-
export const uri = (
|
|
4
|
-
return
|
|
3
|
+
export const uri = () => {
|
|
4
|
+
return joinUri(parentUri(), 'hit');
|
|
5
5
|
};
|
|
6
|
-
export const post = (
|
|
7
|
-
return hpost(uri(
|
|
6
|
+
export const post = (request) => {
|
|
7
|
+
return hpost(uri(), { ...(request || {}), query: request?.query || 'howler.id:*' });
|
|
8
8
|
};
|
|
@@ -84,10 +84,10 @@ const HitSummary = ({ query, response, onStart, onComplete }) => {
|
|
|
84
84
|
setAggregateResults({});
|
|
85
85
|
// Sort the fields based on the number of occurrences
|
|
86
86
|
const sortedKeys = Object.keys(_keyCounts).sort((a, b) => (_keyCounts[b]?.count ?? 0) - (_keyCounts[a]?.count ?? 0));
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
if (sortedKeys.length > 0) {
|
|
88
|
+
setLoading(true);
|
|
89
|
+
const result = await dispatchApi(api.search.facet.hit.post({
|
|
90
|
+
fields: sortedKeys,
|
|
91
91
|
query,
|
|
92
92
|
rows: pageCount,
|
|
93
93
|
filters
|
|
@@ -99,7 +99,7 @@ const HitSummary = ({ query, response, onStart, onComplete }) => {
|
|
|
99
99
|
if (result) {
|
|
100
100
|
setAggregateResults(_results => ({
|
|
101
101
|
..._results,
|
|
102
|
-
|
|
102
|
+
...result
|
|
103
103
|
}));
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -41,7 +41,6 @@ const HitGraph = ({ query }) => {
|
|
|
41
41
|
const addHitToSelection = useContextSelector(HitContext, ctx => ctx.addHitToSelection);
|
|
42
42
|
const removeHitFromSelection = useContextSelector(HitContext, ctx => ctx.removeHitFromSelection);
|
|
43
43
|
const viewId = useContextSelector(HitSearchContext, ctx => ctx.viewId);
|
|
44
|
-
const searching = useContextSelector(HitSearchContext, ctx => ctx.searching);
|
|
45
44
|
const error = useContextSelector(HitSearchContext, ctx => ctx.error);
|
|
46
45
|
const chartRef = useRef();
|
|
47
46
|
const [loading, setLoading] = useState(false);
|
|
@@ -63,6 +62,9 @@ const HitGraph = ({ query }) => {
|
|
|
63
62
|
else if (startDate && endDate) {
|
|
64
63
|
filters.push(`event.created:${convertCustomDateRangeToLucene(startDate, endDate)}`);
|
|
65
64
|
}
|
|
65
|
+
if (escalationFilter) {
|
|
66
|
+
filters.push(`howler.escalation:${escalationFilter}`);
|
|
67
|
+
}
|
|
66
68
|
const total = (await dispatchApi(api.search.count.hit.post({
|
|
67
69
|
query,
|
|
68
70
|
filters
|
|
@@ -75,13 +77,8 @@ const HitGraph = ({ query }) => {
|
|
|
75
77
|
else {
|
|
76
78
|
setDisabled(false);
|
|
77
79
|
}
|
|
78
|
-
const subQueries = [query || 'howler.id:*'];
|
|
79
|
-
if (escalationFilter) {
|
|
80
|
-
subQueries.push(`howler.escalation:${escalationFilter}`);
|
|
81
|
-
}
|
|
82
|
-
const graphQuery = subQueries.map(_query => `(${_query})`).join(' AND ');
|
|
83
80
|
const _data = await dispatchApi(api.search.grouped.hit.post(filterField, {
|
|
84
|
-
query:
|
|
81
|
+
query: query || 'howler.id:*',
|
|
85
82
|
fl: 'event.created,howler.assessment,howler.analytic,howler.detection,howler.outline.threat,howler.outline.target,howler.outline.summary,howler.id',
|
|
86
83
|
// We want a generally random sample across all date ranges, so we use hash.
|
|
87
84
|
// If we used event.created instead, when 1 million hits/hour are created, you'd only see hits from this past minute
|
|
@@ -116,12 +113,12 @@ const HitGraph = ({ query }) => {
|
|
|
116
113
|
}
|
|
117
114
|
}, [dispatchApi, endDate, escalationFilter, filterField, override, query, span, startDate]);
|
|
118
115
|
useEffect(() => {
|
|
119
|
-
if ((!query && !viewId) ||
|
|
116
|
+
if ((!query && !viewId) || error) {
|
|
120
117
|
return;
|
|
121
118
|
}
|
|
122
119
|
performQuery();
|
|
123
120
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
124
|
-
}, [query, viewId,
|
|
121
|
+
}, [query, viewId, error, span]);
|
|
125
122
|
const options = useMemo(() => {
|
|
126
123
|
const parentOptions = scatter('hit.summary.title', 'hit.summary.subtitle');
|
|
127
124
|
return {
|
|
@@ -41,10 +41,12 @@ const useLuceneCompletionProvider = () => {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
const options = await api.search.facet.hit
|
|
44
|
+
const options = await api.search.facet.hit
|
|
45
|
+
.post({ query: 'howler.id:*', rows: 250, fields: [key] })
|
|
46
|
+
.catch(() => ({}));
|
|
45
47
|
const _position = model.getWordUntilPosition(position);
|
|
46
48
|
return {
|
|
47
|
-
suggestions: Object.keys(options).map(_value => ({
|
|
49
|
+
suggestions: Object.keys(options[key] || {}).map(_value => ({
|
|
48
50
|
label: _value,
|
|
49
51
|
kind: monaco.languages.CompletionItemKind.Constant,
|
|
50
52
|
insertText: `"${_value}"`,
|
|
@@ -18,10 +18,11 @@ const Assessment = forwardRef(({ analytic }, ref) => {
|
|
|
18
18
|
}
|
|
19
19
|
setLoading(true);
|
|
20
20
|
api.search.facet.hit
|
|
21
|
-
.post(
|
|
21
|
+
.post({
|
|
22
|
+
fields: ['howler.assessment'],
|
|
22
23
|
query: `howler.analytic:("${analytic.name}")`
|
|
23
24
|
})
|
|
24
|
-
.then(data => setAssessmentData(data))
|
|
25
|
+
.then(data => setAssessmentData(data['howler.assessment']))
|
|
25
26
|
.finally(() => setLoading(false));
|
|
26
27
|
}, [analytic]);
|
|
27
28
|
if (!loading && assessmentData.length < 1) {
|
|
@@ -18,10 +18,11 @@ const Escalation = forwardRef(({ analytic, maxWidth = '45%' }, ref) => {
|
|
|
18
18
|
}
|
|
19
19
|
setLoading(true);
|
|
20
20
|
api.search.facet.hit
|
|
21
|
-
.post(
|
|
22
|
-
query: `howler.analytic:("${analytic.name}")
|
|
21
|
+
.post({
|
|
22
|
+
query: `howler.analytic:("${analytic.name}")`,
|
|
23
|
+
fields: ['howler.escalation']
|
|
23
24
|
})
|
|
24
|
-
.then(data => setEscalationData(data))
|
|
25
|
+
.then(data => setEscalationData(data['howler.escalation']))
|
|
25
26
|
.finally(() => setLoading(false));
|
|
26
27
|
}, [analytic]);
|
|
27
28
|
return analytic && !loading ? (_jsx("div", { style: { maxWidth }, children: _jsx(Doughnut, { ref: ref, options: doughnut('route.analytics.escalation.title', ''), data: {
|
|
@@ -13,10 +13,11 @@ const Stacked = forwardRef(({ analytic, field, color }, ref) => {
|
|
|
13
13
|
const fetchData = useCallback(async () => {
|
|
14
14
|
try {
|
|
15
15
|
setLoading(true);
|
|
16
|
-
const result = await api.search.facet.hit.post(
|
|
17
|
-
query: `howler.analytic:("${analytic.name}")
|
|
16
|
+
const result = await api.search.facet.hit.post({
|
|
17
|
+
query: `howler.analytic:("${analytic.name}")`,
|
|
18
|
+
fields: [field]
|
|
18
19
|
});
|
|
19
|
-
const values = Object.entries(result)
|
|
20
|
+
const values = Object.entries(result[field])
|
|
20
21
|
.sort(([__, valA], [___, valB]) => valB - valA)
|
|
21
22
|
.map(([key]) => key);
|
|
22
23
|
setDatasets(await Promise.all(values.map(async (_value) => {
|
|
@@ -56,7 +56,7 @@ const DossierEditor = () => {
|
|
|
56
56
|
lead.content)) {
|
|
57
57
|
return t('route.dossiers.manager.validation.error.leads');
|
|
58
58
|
}
|
|
59
|
-
if (!dossier.pivots
|
|
59
|
+
if (!(dossier.pivots ?? []).every(pivot => pivot.icon && iconExists(pivot.icon) && pivot.label && pivot.label.en && pivot.label.fr && pivot.format)) {
|
|
60
60
|
return t('route.dossiers.manager.validation.error.pivots');
|
|
61
61
|
}
|
|
62
62
|
if (!dossier.pivots?.every(pivot => (pivot.mappings ?? []).length === uniqBy(pivot.mappings ?? [], 'key').length)) {
|
|
@@ -42,8 +42,8 @@ const HitFilter = ({ size }) => {
|
|
|
42
42
|
setFilter('');
|
|
43
43
|
setSavedFilter(null);
|
|
44
44
|
if (!config.lookups[_category]) {
|
|
45
|
-
const facets = await api.search.facet.hit.post(
|
|
46
|
-
setCustomLookups(Object.keys(facets));
|
|
45
|
+
const facets = await api.search.facet.hit.post({ query: 'howler.id:*', fields: [_category] });
|
|
46
|
+
setCustomLookups(Object.keys(facets[_category]));
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
49
|
setCustomLookups([]);
|
|
@@ -12,7 +12,7 @@ const LeadRenderer = ({ lead, hit }) => {
|
|
|
12
12
|
mt: -2
|
|
13
13
|
}, children: _jsx(HandlebarsMarkdown, { disableLinks: true, md: lead.content, object: hit ?? lead }) }));
|
|
14
14
|
}
|
|
15
|
-
const pluginLead = pluginStore.executeFunction(`lead.${lead.format}`, lead.content, lead.metadata);
|
|
15
|
+
const pluginLead = pluginStore.executeFunction(`lead.${lead.format}`, lead.content, lead.metadata, hit);
|
|
16
16
|
if (pluginLead) {
|
|
17
17
|
return pluginLead;
|
|
18
18
|
}
|
package/package.json
CHANGED
|
@@ -96,158 +96,162 @@
|
|
|
96
96
|
"internal-slot": "1.0.7"
|
|
97
97
|
},
|
|
98
98
|
"type": "module",
|
|
99
|
-
"version": "2.
|
|
99
|
+
"version": "2.13.0-dev.75",
|
|
100
100
|
"exports": {
|
|
101
101
|
"./i18n": "./i18n.js",
|
|
102
102
|
"./index.css": "./index.css",
|
|
103
|
-
"./plugins/*": "./plugins/*.js",
|
|
104
|
-
"./components/*": "./components/*.js",
|
|
105
|
-
"./locales/*.json": "./locales/*.json",
|
|
106
|
-
"./api/*": "./api/*.js",
|
|
107
|
-
"./api": "./api/index.js",
|
|
108
|
-
"./rest/*": "./rest/*.js",
|
|
109
|
-
"./rest": "./rest/index.js",
|
|
110
103
|
"./models/*": "./models/*.js",
|
|
111
|
-
"./commons/*": "./commons/*.js",
|
|
112
104
|
"./branding/*": "./branding/*.js",
|
|
105
|
+
"./commons/*": "./commons/*.js",
|
|
113
106
|
"./utils/*": "./utils/*.js",
|
|
114
107
|
"./utils/*.json": "./utils/*.json",
|
|
115
|
-
"./
|
|
116
|
-
"./
|
|
117
|
-
"./components
|
|
108
|
+
"./rest/*": "./rest/*.js",
|
|
109
|
+
"./rest": "./rest/index.js",
|
|
110
|
+
"./components/*": "./components/*.js",
|
|
111
|
+
"./plugins/*": "./plugins/*.js",
|
|
112
|
+
"./api/*": "./api/*.js",
|
|
113
|
+
"./api": "./api/index.js",
|
|
114
|
+
"./locales/*.json": "./locales/*.json",
|
|
115
|
+
"./models/socket/*": "./models/socket/*.js",
|
|
116
|
+
"./models/entities/*": "./models/entities/*.js",
|
|
117
|
+
"./models/entities/generated/*": "./models/entities/generated/*.js",
|
|
118
|
+
"./commons/components/*": "./commons/components/*.js",
|
|
119
|
+
"./commons/components/notification/*": "./commons/components/notification/*.js",
|
|
120
|
+
"./commons/components/notification": "./commons/components/notification/index.js",
|
|
121
|
+
"./commons/components/search/*": "./commons/components/search/*.js",
|
|
122
|
+
"./commons/components/display/*": "./commons/components/display/*.js",
|
|
123
|
+
"./commons/components/breadcrumbs/*": "./commons/components/breadcrumbs/*.js",
|
|
124
|
+
"./commons/components/app/*": "./commons/components/app/*.js",
|
|
125
|
+
"./commons/components/utils/*": "./commons/components/utils/*.js",
|
|
126
|
+
"./commons/components/topnav/*": "./commons/components/topnav/*.js",
|
|
127
|
+
"./commons/components/pages/*": "./commons/components/pages/*.js",
|
|
128
|
+
"./commons/components/leftnav/*": "./commons/components/leftnav/*.js",
|
|
129
|
+
"./commons/components/notification/elements/*": "./commons/components/notification/elements/*.js",
|
|
130
|
+
"./commons/components/notification/elements/item/*": "./commons/components/notification/elements/item/*.js",
|
|
131
|
+
"./commons/components/display/hooks/*": "./commons/components/display/hooks/*.js",
|
|
132
|
+
"./commons/components/app/hooks/*": "./commons/components/app/hooks/*.js",
|
|
133
|
+
"./commons/components/app/hooks": "./commons/components/app/hooks/index.js",
|
|
134
|
+
"./commons/components/app/providers/*": "./commons/components/app/providers/*.js",
|
|
135
|
+
"./commons/components/utils/hooks/*": "./commons/components/utils/hooks/*.js",
|
|
136
|
+
"./commons/components/pages/hooks/*": "./commons/components/pages/hooks/*.js",
|
|
118
137
|
"./components/hooks/*": "./components/hooks/*.js",
|
|
119
138
|
"./components/elements/*": "./components/elements/*.js",
|
|
120
|
-
"./components/
|
|
121
|
-
"./components/
|
|
122
|
-
"./components/
|
|
123
|
-
"./components/app/providers/*": "./components/app/providers/*.js",
|
|
124
|
-
"./components/app/drawers/*": "./components/app/drawers/*.js",
|
|
125
|
-
"./components/routes/help/*": "./components/routes/help/*.js",
|
|
126
|
-
"./components/routes/views/*": "./components/routes/views/*.js",
|
|
127
|
-
"./components/routes/overviews/*": "./components/routes/overviews/*.js",
|
|
128
|
-
"./components/routes/action/*": "./components/routes/action/*.js",
|
|
129
|
-
"./components/routes/analytics/*": "./components/routes/analytics/*.js",
|
|
130
|
-
"./components/routes/hits/*": "./components/routes/hits/*.js",
|
|
131
|
-
"./components/routes/home/*": "./components/routes/home/*.js",
|
|
132
|
-
"./components/routes/home": "./components/routes/home/index.js",
|
|
133
|
-
"./components/routes/advanced/*": "./components/routes/advanced/*.js",
|
|
134
|
-
"./components/routes/templates/*": "./components/routes/templates/*.js",
|
|
135
|
-
"./components/routes/settings/*": "./components/routes/settings/*.js",
|
|
136
|
-
"./components/routes/admin/*": "./components/routes/admin/*.js",
|
|
137
|
-
"./components/routes/dossiers/*": "./components/routes/dossiers/*.js",
|
|
138
|
-
"./components/routes/help/components/*": "./components/routes/help/components/*.js",
|
|
139
|
-
"./components/routes/help/markdown/*.md": "./components/routes/help/markdown/*.md.js",
|
|
140
|
-
"./components/routes/help/markdown/en/*.md": "./components/routes/help/markdown/en/*.md.js",
|
|
141
|
-
"./components/routes/help/markdown/fr/*.md": "./components/routes/help/markdown/fr/*.md.js",
|
|
142
|
-
"./components/routes/action/view/*": "./components/routes/action/view/*.js",
|
|
143
|
-
"./components/routes/action/shared/*": "./components/routes/action/shared/*.js",
|
|
144
|
-
"./components/routes/action/edit/*": "./components/routes/action/edit/*.js",
|
|
145
|
-
"./components/routes/analytics/widgets/*": "./components/routes/analytics/widgets/*.js",
|
|
146
|
-
"./components/routes/hits/view/*": "./components/routes/hits/view/*.js",
|
|
147
|
-
"./components/routes/hits/search/*": "./components/routes/hits/search/*.js",
|
|
148
|
-
"./components/routes/hits/search/grid/*": "./components/routes/hits/search/grid/*.js",
|
|
149
|
-
"./components/routes/hits/search/shared/*": "./components/routes/hits/search/shared/*.js",
|
|
150
|
-
"./components/routes/admin/users/*": "./components/routes/admin/users/*.js",
|
|
139
|
+
"./components/app/*": "./components/app/*.js",
|
|
140
|
+
"./components/routes/*": "./components/routes/*.js",
|
|
141
|
+
"./components/logins/*": "./components/logins/*.js",
|
|
151
142
|
"./components/elements/display/*": "./components/elements/display/*.js",
|
|
152
143
|
"./components/elements/view/*": "./components/elements/view/*.js",
|
|
153
144
|
"./components/elements/addons/*": "./components/elements/addons/*.js",
|
|
154
145
|
"./components/elements/hit/*": "./components/elements/hit/*.js",
|
|
155
|
-
"./components/elements/display/modals/*": "./components/elements/display/modals/*.js",
|
|
156
|
-
"./components/elements/display/features/*": "./components/elements/display/features/*.js",
|
|
157
146
|
"./components/elements/display/handlebars/*": "./components/elements/display/handlebars/*.js",
|
|
158
|
-
"./components/elements/display/
|
|
159
|
-
"./components/elements/display/icons/*": "./components/elements/display/icons/*.js",
|
|
147
|
+
"./components/elements/display/features/*": "./components/elements/display/features/*.js",
|
|
160
148
|
"./components/elements/display/json/*": "./components/elements/display/json/*.js",
|
|
149
|
+
"./components/elements/display/modals/*": "./components/elements/display/modals/*.js",
|
|
150
|
+
"./components/elements/display/icons/*": "./components/elements/display/icons/*.js",
|
|
151
|
+
"./components/elements/display/markdownPlugins/*.md": "./components/elements/display/markdownPlugins/*.md.js",
|
|
161
152
|
"./components/elements/display/icons/svg/*": "./components/elements/display/icons/svg/*.js",
|
|
162
|
-
"./components/elements/addons/
|
|
163
|
-
"./components/elements/addons/lists": "./components/elements/addons/lists/index.js",
|
|
153
|
+
"./components/elements/addons/search/*": "./components/elements/addons/search/*.js",
|
|
164
154
|
"./components/elements/addons/buttons/*": "./components/elements/addons/buttons/*.js",
|
|
165
155
|
"./components/elements/addons/buttons": "./components/elements/addons/buttons/index.js",
|
|
166
156
|
"./components/elements/addons/layout/*": "./components/elements/addons/layout/*.js",
|
|
167
|
-
"./components/elements/addons/
|
|
168
|
-
"./components/elements/addons/lists
|
|
169
|
-
"./components/elements/addons/lists/table/*": "./components/elements/addons/lists/table/*.js",
|
|
170
|
-
"./components/elements/addons/lists/table": "./components/elements/addons/lists/table/index.js",
|
|
171
|
-
"./components/elements/addons/layout/vsbox/*": "./components/elements/addons/layout/vsbox/*.js",
|
|
157
|
+
"./components/elements/addons/lists/*": "./components/elements/addons/lists/*.js",
|
|
158
|
+
"./components/elements/addons/lists": "./components/elements/addons/lists/index.js",
|
|
172
159
|
"./components/elements/addons/search/phrase/*": "./components/elements/addons/search/phrase/*.js",
|
|
173
160
|
"./components/elements/addons/search/phrase": "./components/elements/addons/search/phrase/index.js",
|
|
174
161
|
"./components/elements/addons/search/phrase/word/*": "./components/elements/addons/search/phrase/word/*.js",
|
|
175
162
|
"./components/elements/addons/search/phrase/word/consumers/*": "./components/elements/addons/search/phrase/word/consumers/*.js",
|
|
176
|
-
"./components/elements/
|
|
163
|
+
"./components/elements/addons/layout/vsbox/*": "./components/elements/addons/layout/vsbox/*.js",
|
|
164
|
+
"./components/elements/addons/lists/hooks/*": "./components/elements/addons/lists/hooks/*.js",
|
|
165
|
+
"./components/elements/addons/lists/table/*": "./components/elements/addons/lists/table/*.js",
|
|
166
|
+
"./components/elements/addons/lists/table": "./components/elements/addons/lists/table/index.js",
|
|
177
167
|
"./components/elements/hit/aggregate/*": "./components/elements/hit/aggregate/*.js",
|
|
168
|
+
"./components/elements/hit/actions/*": "./components/elements/hit/actions/*.js",
|
|
169
|
+
"./components/elements/hit/related/*": "./components/elements/hit/related/*.js",
|
|
178
170
|
"./components/elements/hit/elements/*": "./components/elements/hit/elements/*.js",
|
|
179
171
|
"./components/elements/hit/outlines/*": "./components/elements/hit/outlines/*.js",
|
|
180
|
-
"./components/elements/hit/actions/*": "./components/elements/hit/actions/*.js",
|
|
181
172
|
"./components/elements/hit/outlines/al/*": "./components/elements/hit/outlines/al/*.js",
|
|
182
|
-
"./
|
|
183
|
-
"./
|
|
184
|
-
"./
|
|
185
|
-
"./
|
|
173
|
+
"./components/app/hooks/*": "./components/app/hooks/*.js",
|
|
174
|
+
"./components/app/drawers/*": "./components/app/drawers/*.js",
|
|
175
|
+
"./components/app/providers/*": "./components/app/providers/*.js",
|
|
176
|
+
"./components/routes/home/*": "./components/routes/home/*.js",
|
|
177
|
+
"./components/routes/home": "./components/routes/home/index.js",
|
|
178
|
+
"./components/routes/dossiers/*": "./components/routes/dossiers/*.js",
|
|
179
|
+
"./components/routes/views/*": "./components/routes/views/*.js",
|
|
180
|
+
"./components/routes/action/*": "./components/routes/action/*.js",
|
|
181
|
+
"./components/routes/overviews/*": "./components/routes/overviews/*.js",
|
|
182
|
+
"./components/routes/admin/*": "./components/routes/admin/*.js",
|
|
183
|
+
"./components/routes/settings/*": "./components/routes/settings/*.js",
|
|
184
|
+
"./components/routes/help/*": "./components/routes/help/*.js",
|
|
185
|
+
"./components/routes/hits/*": "./components/routes/hits/*.js",
|
|
186
|
+
"./components/routes/analytics/*": "./components/routes/analytics/*.js",
|
|
187
|
+
"./components/routes/advanced/*": "./components/routes/advanced/*.js",
|
|
188
|
+
"./components/routes/templates/*": "./components/routes/templates/*.js",
|
|
189
|
+
"./components/routes/action/view/*": "./components/routes/action/view/*.js",
|
|
190
|
+
"./components/routes/action/shared/*": "./components/routes/action/shared/*.js",
|
|
191
|
+
"./components/routes/action/edit/*": "./components/routes/action/edit/*.js",
|
|
192
|
+
"./components/routes/admin/users/*": "./components/routes/admin/users/*.js",
|
|
193
|
+
"./components/routes/help/components/*": "./components/routes/help/components/*.js",
|
|
194
|
+
"./components/routes/help/markdown/*.md": "./components/routes/help/markdown/*.md.js",
|
|
195
|
+
"./components/routes/help/markdown/en/*.md": "./components/routes/help/markdown/en/*.md.js",
|
|
196
|
+
"./components/routes/help/markdown/fr/*.md": "./components/routes/help/markdown/fr/*.md.js",
|
|
197
|
+
"./components/routes/hits/search/*": "./components/routes/hits/search/*.js",
|
|
198
|
+
"./components/routes/hits/view/*": "./components/routes/hits/view/*.js",
|
|
199
|
+
"./components/routes/hits/search/grid/*": "./components/routes/hits/search/grid/*.js",
|
|
200
|
+
"./components/routes/hits/search/shared/*": "./components/routes/hits/search/shared/*.js",
|
|
201
|
+
"./components/routes/analytics/widgets/*": "./components/routes/analytics/widgets/*.js",
|
|
202
|
+
"./components/logins/hooks/*": "./components/logins/hooks/*.js",
|
|
203
|
+
"./components/logins/auth/*": "./components/logins/auth/*.js",
|
|
204
|
+
"./plugins/borealis/*": "./plugins/borealis/*.js",
|
|
205
|
+
"./plugins/borealis": "./plugins/borealis/index.js",
|
|
206
|
+
"./plugins/borealis/components/*": "./plugins/borealis/components/*.js",
|
|
207
|
+
"./plugins/borealis/locales/*": "./plugins/borealis/locales/*.js",
|
|
208
|
+
"./api/search/*": "./api/search/*.js",
|
|
209
|
+
"./api/search": "./api/search/index.js",
|
|
186
210
|
"./api/analytic/*": "./api/analytic/*.js",
|
|
187
211
|
"./api/analytic": "./api/analytic/index.js",
|
|
188
212
|
"./api/auth/*": "./api/auth/*.js",
|
|
189
213
|
"./api/auth": "./api/auth/index.js",
|
|
190
|
-
"./api/
|
|
191
|
-
"./api/
|
|
214
|
+
"./api/template/*": "./api/template/*.js",
|
|
215
|
+
"./api/template": "./api/template/index.js",
|
|
192
216
|
"./api/view/*": "./api/view/*.js",
|
|
193
217
|
"./api/view": "./api/view/index.js",
|
|
218
|
+
"./api/action/*": "./api/action/*.js",
|
|
219
|
+
"./api/action": "./api/action/index.js",
|
|
194
220
|
"./api/user/*": "./api/user/*.js",
|
|
195
221
|
"./api/user": "./api/user/index.js",
|
|
196
|
-
"./api/dossier/*": "./api/dossier/*.js",
|
|
197
|
-
"./api/dossier": "./api/dossier/index.js",
|
|
198
|
-
"./api/template/*": "./api/template/*.js",
|
|
199
|
-
"./api/template": "./api/template/index.js",
|
|
200
|
-
"./api/configs/*": "./api/configs/*.js",
|
|
201
|
-
"./api/configs": "./api/configs/index.js",
|
|
202
222
|
"./api/overview/*": "./api/overview/*.js",
|
|
203
223
|
"./api/overview": "./api/overview/index.js",
|
|
204
|
-
"./api/
|
|
205
|
-
"./api/
|
|
206
|
-
"./api/
|
|
207
|
-
"./api/
|
|
224
|
+
"./api/configs/*": "./api/configs/*.js",
|
|
225
|
+
"./api/configs": "./api/configs/index.js",
|
|
226
|
+
"./api/dossier/*": "./api/dossier/*.js",
|
|
227
|
+
"./api/dossier": "./api/dossier/index.js",
|
|
208
228
|
"./api/hit/*": "./api/hit/*.js",
|
|
209
229
|
"./api/hit": "./api/hit/index.js",
|
|
210
|
-
"./api/
|
|
211
|
-
"./api/
|
|
212
|
-
"./api/
|
|
213
|
-
"./api/
|
|
214
|
-
"./api/
|
|
215
|
-
"./api/user/avatar": "./api/user/avatar/index.js",
|
|
230
|
+
"./api/notebook/*": "./api/notebook/*.js",
|
|
231
|
+
"./api/notebook": "./api/notebook/index.js",
|
|
232
|
+
"./api/search/grouped/*": "./api/search/grouped/*.js",
|
|
233
|
+
"./api/search/grouped": "./api/search/grouped/index.js",
|
|
234
|
+
"./api/search/sigma/*": "./api/search/sigma/*.js",
|
|
216
235
|
"./api/search/histogram/*": "./api/search/histogram/*.js",
|
|
217
236
|
"./api/search/histogram": "./api/search/histogram/index.js",
|
|
218
237
|
"./api/search/eql/*": "./api/search/eql/*.js",
|
|
238
|
+
"./api/search/facet/*": "./api/search/facet/*.js",
|
|
239
|
+
"./api/search/facet": "./api/search/facet/index.js",
|
|
219
240
|
"./api/search/fields/*": "./api/search/fields/*.js",
|
|
220
241
|
"./api/search/fields": "./api/search/fields/index.js",
|
|
221
242
|
"./api/search/count/*": "./api/search/count/*.js",
|
|
222
243
|
"./api/search/count": "./api/search/count/index.js",
|
|
223
|
-
"./api/
|
|
224
|
-
"./api/
|
|
225
|
-
"./api/
|
|
226
|
-
"./api/
|
|
227
|
-
"./api/
|
|
244
|
+
"./api/analytic/notebooks/*": "./api/analytic/notebooks/*.js",
|
|
245
|
+
"./api/analytic/notebooks": "./api/analytic/notebooks/index.js",
|
|
246
|
+
"./api/analytic/comments/*": "./api/analytic/comments/*.js",
|
|
247
|
+
"./api/analytic/comments": "./api/analytic/comments/index.js",
|
|
248
|
+
"./api/user/avatar/*": "./api/user/avatar/*.js",
|
|
249
|
+
"./api/user/avatar": "./api/user/avatar/index.js",
|
|
228
250
|
"./api/hit/comments/*": "./api/hit/comments/*.js",
|
|
229
251
|
"./api/hit/comments": "./api/hit/comments/index.js",
|
|
230
|
-
"./
|
|
231
|
-
"./
|
|
232
|
-
"./
|
|
233
|
-
"./
|
|
234
|
-
"./commons/components/app/*": "./commons/components/app/*.js",
|
|
235
|
-
"./commons/components/breadcrumbs/*": "./commons/components/breadcrumbs/*.js",
|
|
236
|
-
"./commons/components/notification/*": "./commons/components/notification/*.js",
|
|
237
|
-
"./commons/components/notification": "./commons/components/notification/index.js",
|
|
238
|
-
"./commons/components/display/*": "./commons/components/display/*.js",
|
|
239
|
-
"./commons/components/topnav/*": "./commons/components/topnav/*.js",
|
|
240
|
-
"./commons/components/search/*": "./commons/components/search/*.js",
|
|
241
|
-
"./commons/components/utils/*": "./commons/components/utils/*.js",
|
|
242
|
-
"./commons/components/leftnav/*": "./commons/components/leftnav/*.js",
|
|
243
|
-
"./commons/components/pages/*": "./commons/components/pages/*.js",
|
|
244
|
-
"./commons/components/app/hooks/*": "./commons/components/app/hooks/*.js",
|
|
245
|
-
"./commons/components/app/hooks": "./commons/components/app/hooks/index.js",
|
|
246
|
-
"./commons/components/app/providers/*": "./commons/components/app/providers/*.js",
|
|
247
|
-
"./commons/components/notification/elements/*": "./commons/components/notification/elements/*.js",
|
|
248
|
-
"./commons/components/notification/elements/item/*": "./commons/components/notification/elements/item/*.js",
|
|
249
|
-
"./commons/components/display/hooks/*": "./commons/components/display/hooks/*.js",
|
|
250
|
-
"./commons/components/utils/hooks/*": "./commons/components/utils/hooks/*.js",
|
|
251
|
-
"./commons/components/pages/hooks/*": "./commons/components/pages/hooks/*.js"
|
|
252
|
+
"./locales/en/*.json": "./locales/en/*.json",
|
|
253
|
+
"./locales/fr/*.json": "./locales/fr/*.json",
|
|
254
|
+
"./locales/en/help/*.json": "./locales/en/help/*.json",
|
|
255
|
+
"./locales/fr/help/*.json": "./locales/fr/help/*.json"
|
|
252
256
|
}
|
|
253
257
|
}
|
|
@@ -25,7 +25,7 @@ declare abstract class HowlerPlugin implements IPlugin {
|
|
|
25
25
|
init(pluginStore: PluginStore): void;
|
|
26
26
|
activate(): void;
|
|
27
27
|
deactivate(): void;
|
|
28
|
-
addLead(format: string, form: (props: LeadFormProps) => React.ReactNode, renderer: (content: string, metadata: any) => React.ReactNode): void;
|
|
28
|
+
addLead(format: string, form: (props: LeadFormProps) => React.ReactNode, renderer: (content: string, metadata: any, hit?: Hit) => React.ReactNode): void;
|
|
29
29
|
addPivot(format: string, form: (props: PivotFormProps) => React.ReactNode, renderer: (props: PivotLinkProps) => React.ReactNode): void;
|
|
30
30
|
addOperation(format: string, form: (props: CustomActionProps) => React.ReactNode, documentation: PluginDocumentation): void;
|
|
31
31
|
on(_event: string, _hit: Hit): any;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { BorealisProvider } from 'borealis-ui/dist/hooks/BorealisProvider';
|
|
3
|
+
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
4
|
+
import { useContext } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
|
|
7
|
+
import { getStored } from '@cccsaurora/howler-ui/utils/localStorage';
|
|
8
|
+
const Provider = ({ children }) => {
|
|
9
|
+
const apiConfig = useContext(ApiConfigContext);
|
|
10
|
+
return (_jsx(BorealisProvider, { baseURL: location.origin + '/api/v1/borealis', getToken: () => getStored(StorageKey.APP_TOKEN), enabled: apiConfig.config?.configuration?.features?.borealis, publicIconify: false, customIconify: location.origin.includes('localhost')
|
|
11
|
+
? 'https://icons.dev.analysis.cyber.gc.ca'
|
|
12
|
+
: location.origin.replace(/howler(-stg)?/, 'icons'), defaultTimeout: 5, i18next: useTranslation('borealis'), chunkSize: 50, children: children }));
|
|
13
|
+
};
|
|
14
|
+
export default Provider;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Chip } from '@mui/material';
|
|
3
|
+
import { EnrichedChip, useBorealisEnrichSelector } from 'borealis-ui';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
const BorealisChip = ({ children, value, context, ...props }) => {
|
|
6
|
+
const guessType = useBorealisEnrichSelector(ctx => ctx.guessType);
|
|
7
|
+
const type = guessType(value);
|
|
8
|
+
if (!type) {
|
|
9
|
+
return _jsx(Chip, { ...props, children: children });
|
|
10
|
+
}
|
|
11
|
+
let enrichedProps = {
|
|
12
|
+
...props,
|
|
13
|
+
value
|
|
14
|
+
};
|
|
15
|
+
delete enrichedProps.label;
|
|
16
|
+
if (context === 'summary') {
|
|
17
|
+
enrichedProps = {
|
|
18
|
+
...enrichedProps,
|
|
19
|
+
sx: [
|
|
20
|
+
...(Array.isArray(enrichedProps.sx) ? enrichedProps.sx : [enrichedProps.sx]),
|
|
21
|
+
[{ height: '24px', '& .iconify': { fontSize: '1em' } }]
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return _jsx(EnrichedChip, { ...enrichedProps, type: type });
|
|
26
|
+
};
|
|
27
|
+
export default memo(BorealisChip);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Autocomplete, Divider, ListItemText, TextField, Typography } from '@mui/material';
|
|
3
|
+
import { useBorealisEnrichSelector, useBorealisFetcherSelector } from 'borealis-ui';
|
|
4
|
+
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
5
|
+
import { useContext, useState } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
const BorealisLeadForm = ({ lead, metadata, update, updateMetadata }) => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const { config } = useContext(ApiConfigContext);
|
|
10
|
+
const fetchers = useBorealisFetcherSelector(ctx => ctx.fetchers);
|
|
11
|
+
const types = useBorealisEnrichSelector(ctx => ctx.typesDetection);
|
|
12
|
+
const [showCustom, setShowCustom] = useState(false);
|
|
13
|
+
return (_jsxs(_Fragment, { children: [_jsx(Divider, { orientation: "horizontal" }), _jsx(Autocomplete, { disabled: !lead, options: Object.keys(fetchers), renderInput: params => _jsx(TextField, { ...params, size: "small", label: t('route.dossiers.manager.borealis') }), value: Object.keys(fetchers).includes(lead?.content) ? lead.content : '', onChange: (_ev, content) => update({ content, metadata: '{}' }), renderOption: (props, option) => (_jsx(ListItemText, { ...props, sx: { flexDirection: 'column', alignItems: 'start !important' }, primary: _jsx("code", { children: option }), secondary: fetchers[option].description })) }), _jsx(Autocomplete, { options: Object.keys(types), renderInput: params => _jsx(TextField, { ...params, size: "small", label: t('route.dossiers.manager.borealis.type') }), value: metadata?.type ?? '', onChange: (_ev, type) => updateMetadata({ type }) }), _jsx(Autocomplete, { options: ['custom', ...Object.keys(config.indexes.hit)], disabled: !metadata?.type || !types[metadata.type], renderInput: params => (_jsx(TextField, { ...params, size: "small", label: t('route.dossiers.manager.borealis.value') })), getOptionLabel: opt => t(opt), value: metadata?.value ?? '', onChange: (_ev, value) => {
|
|
14
|
+
if (value === 'custom') {
|
|
15
|
+
setShowCustom(true);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
setShowCustom(false);
|
|
19
|
+
updateMetadata({ value });
|
|
20
|
+
}
|
|
21
|
+
} }), showCustom && (_jsxs(_Fragment, { children: [_jsx(TextField, { size: "small", label: t('route.dossiers.manager.borealis.value.custom'), value: metadata?.value ?? '', disabled: !metadata?.type || !types[metadata.type], fullWidth: true, onChange: ev => updateMetadata({ value: ev.target.value }) }), _jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mt: '0 !important' }, children: t('route.dossiers.manager.borealis.value.description') })] }))] }));
|
|
22
|
+
};
|
|
23
|
+
export default BorealisLeadForm;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@iconify/react/dist/iconify.js';
|
|
3
|
+
import { Settings } from '@mui/icons-material';
|
|
4
|
+
import { Divider, IconButton, Stack, Typography } from '@mui/material';
|
|
5
|
+
import { useBorealisActionsSelector, useBorealisEnrichSelector } from 'borealis-ui';
|
|
6
|
+
import HowlerCard from '@cccsaurora/howler-ui/components/elements/display/HowlerCard';
|
|
7
|
+
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
8
|
+
import { get } from 'lodash-es';
|
|
9
|
+
import { memo, useCallback, useState } from 'react';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
const BorealisPivot = ({ pivot, hit, compact }) => {
|
|
12
|
+
const guessType = useBorealisEnrichSelector(ctx => ctx?.guessType);
|
|
13
|
+
const { showErrorMessage } = useMySnackbar();
|
|
14
|
+
const { i18n, t } = useTranslation();
|
|
15
|
+
const actions = useBorealisActionsSelector(ctx => ctx?.availableActions ?? {});
|
|
16
|
+
const executeAction = useBorealisActionsSelector(ctx => ctx?.executeAction);
|
|
17
|
+
const [loading, setLoading] = useState(false);
|
|
18
|
+
const onBorealisClick = useCallback(async (event, forceMenu = false) => {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
event.stopPropagation();
|
|
21
|
+
if (loading) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!actions[pivot.value]) {
|
|
25
|
+
showErrorMessage(t('pivot.borealis.missing'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setLoading(true);
|
|
29
|
+
const data = Object.fromEntries(pivot.mappings.map(_mapping => {
|
|
30
|
+
const value = _mapping.field !== 'custom' ? get(hit, _mapping.field) : _mapping.custom_value;
|
|
31
|
+
if (['selector', 'selectors'].includes(_mapping.key)) {
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
return [
|
|
34
|
+
_mapping.key,
|
|
35
|
+
value.map(val => ({
|
|
36
|
+
// TODO: Use the mapped borealis values here eventually
|
|
37
|
+
type: guessType(val),
|
|
38
|
+
value: val
|
|
39
|
+
}))
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
_mapping.key,
|
|
44
|
+
{
|
|
45
|
+
// TODO: Use the mapped borealis values here eventually
|
|
46
|
+
type: guessType(value),
|
|
47
|
+
value
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return [_mapping.key, value];
|
|
52
|
+
}));
|
|
53
|
+
const selectors = (actions[pivot.value].accept_multiple ? [data.selectors] : [data.selector]).flat();
|
|
54
|
+
delete data.selector;
|
|
55
|
+
delete data.selectors;
|
|
56
|
+
try {
|
|
57
|
+
await executeAction(pivot.value, selectors, data, { forceMenu });
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
setLoading(false);
|
|
61
|
+
}
|
|
62
|
+
}, [actions, executeAction, guessType, hit, loading, pivot.mappings, pivot.value, showErrorMessage, t]);
|
|
63
|
+
if (!actions[pivot.value]) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
return (_jsx(HowlerCard, { variant: compact ? 'outlined' : 'elevation', onClick: e => onBorealisClick(e), sx: [
|
|
67
|
+
theme => ({
|
|
68
|
+
backgroundColor: 'transparent',
|
|
69
|
+
transition: theme.transitions.create(['border-color']),
|
|
70
|
+
'&:hover': { borderColor: 'primary.main' },
|
|
71
|
+
'& > div': {
|
|
72
|
+
height: '100%'
|
|
73
|
+
}
|
|
74
|
+
}),
|
|
75
|
+
loading
|
|
76
|
+
? { opacity: 0.5, pointerEvents: 'none' }
|
|
77
|
+
: {
|
|
78
|
+
cursor: 'pointer'
|
|
79
|
+
},
|
|
80
|
+
!compact && { border: 'thin solid', borderColor: 'transparent' }
|
|
81
|
+
], children: _jsxs(Stack, { direction: "row", p: compact ? 0.5 : 1, spacing: 1, alignItems: "center", children: [_jsx(Icon, { fontSize: "1.5rem", icon: pivot.icon }), _jsx(Typography, { children: pivot.label[i18n.language] }), _jsx(Divider, { orientation: "vertical", flexItem: true }), _jsx(IconButton, { size: "small", onClick: e => onBorealisClick(e, true), children: _jsx(Settings, { fontSize: "small" }) })] }) }));
|
|
82
|
+
};
|
|
83
|
+
export default memo(BorealisPivot);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Autocomplete, Divider, Stack, TextField, Typography, useTheme } from '@mui/material';
|
|
3
|
+
import { useBorealisActionsSelector } from 'borealis-ui';
|
|
4
|
+
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
5
|
+
import { Fragment, useContext } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
const BorealisPivotForm = ({ pivot, update }) => {
|
|
8
|
+
const theme = useTheme();
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const { config } = useContext(ApiConfigContext);
|
|
11
|
+
const actions = useBorealisActionsSelector(ctx => ctx?.availableActions);
|
|
12
|
+
return (_jsxs(_Fragment, { children: [_jsx(Autocomplete, { fullWidth: true, disabled: !pivot, options: Object.entries(actions)
|
|
13
|
+
.filter(([_key, definition]) => !!definition && definition.format == 'pivot')
|
|
14
|
+
.map(([key]) => key), renderOption: ({ key, ...optionProps }, actionId) => {
|
|
15
|
+
const definition = actions[actionId];
|
|
16
|
+
return (_jsxs(Stack, { component: "li", ...optionProps, spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 1, alignSelf: "start", alignItems: "center", children: [_jsx(Typography, { children: definition.name }), _jsx("pre", { style: {
|
|
17
|
+
fontSize: '0.85rem',
|
|
18
|
+
border: `thin solid ${theme.palette.divider}`,
|
|
19
|
+
padding: theme.spacing(0.5),
|
|
20
|
+
borderRadius: theme.shape.borderRadius
|
|
21
|
+
}, children: actionId })] }), _jsx(Typography, { variant: "body2", color: "text.secondary", alignSelf: "start", children: definition.summary })] }, key));
|
|
22
|
+
}, getOptionLabel: opt => actions[opt]?.name ?? '', renderInput: params => (_jsx(TextField, { ...params, size: "small", fullWidth: true, label: t('route.dossiers.manager.pivot.value') })), value: pivot?.value ?? '', onChange: (_ev, value) => update({
|
|
23
|
+
value,
|
|
24
|
+
mappings: [
|
|
25
|
+
{ key: actions[value].accept_multiple ? 'selectors' : 'selector', field: 'howler.id' },
|
|
26
|
+
...Object.entries(actions[value].params?.properties ?? [])
|
|
27
|
+
.filter(([property]) => !['selector', 'selectors'].includes(property))
|
|
28
|
+
.map(([prop, schema]) => ({
|
|
29
|
+
key: prop,
|
|
30
|
+
field: typeof schema === 'boolean' || !schema.default ? null : 'custom',
|
|
31
|
+
custom_value: typeof schema !== 'boolean' && !!schema.default ? schema.default.toString() : null
|
|
32
|
+
}))
|
|
33
|
+
]
|
|
34
|
+
}) }), _jsx(Divider, { flexItem: true }), _jsx(Typography, { children: t('route.dossiers.manager.pivot.mappings') }), pivot?.mappings?.map((_mapping, index) => (
|
|
35
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
36
|
+
_jsxs(Fragment, { children: [_jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(TextField, { size: "small", label: t('route.dossiers.manager.pivot.mapping.key'), disabled: !pivot, value: _mapping?.key ?? '', onChange: ev => update({
|
|
37
|
+
mappings: pivot.mappings.map((_m, _index) => index === _index ? { ..._m, key: ev.target.value } : _m)
|
|
38
|
+
}) }), _jsx(Autocomplete, { fullWidth: true, disabled: !pivot, options: ['custom', 'unset', ...Object.keys(config.indexes.hit)], renderInput: params => (_jsx(TextField, { ...params, size: "small", fullWidth: true, label: t('route.dossiers.manager.pivot.mapping.field'), sx: { minWidth: '150px' } })), getOptionLabel: opt => t(opt), value: _mapping.field ?? '', onChange: (_ev, field) => update({
|
|
39
|
+
mappings: pivot.mappings.map((_m, _index) => (index === _index ? { ..._m, field } : _m))
|
|
40
|
+
}) })] }), _mapping.field === 'custom' && (_jsx(TextField, { size: "small", label: t('route.dossiers.manager.pivot.mapping.custom'), disabled: !pivot, value: _mapping?.custom_value ?? '', onChange: ev => update({
|
|
41
|
+
mappings: pivot.mappings.map((_m, _index) => index === _index ? { ..._m, custom_value: ev.target.value } : _m)
|
|
42
|
+
}) }))] }, index)))] }));
|
|
43
|
+
};
|
|
44
|
+
export default BorealisPivotForm;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from '@mui/material';
|
|
3
|
+
import { EnrichedTypography, useBorealisEnrichSelector } from 'borealis-ui';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
const BorealisTypography = ({ children, value, context, ...props }) => {
|
|
6
|
+
const guessType = useBorealisEnrichSelector(ctx => ctx.guessType);
|
|
7
|
+
const type = guessType(value);
|
|
8
|
+
if (!type) {
|
|
9
|
+
return _jsx(Typography, { ...props, children: children });
|
|
10
|
+
}
|
|
11
|
+
let enrichedProps = {
|
|
12
|
+
...props,
|
|
13
|
+
value
|
|
14
|
+
};
|
|
15
|
+
if (context === 'banner') {
|
|
16
|
+
enrichedProps = {
|
|
17
|
+
...enrichedProps,
|
|
18
|
+
slotProps: { stack: { component: 'span' } }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
else if (context === 'outline') {
|
|
22
|
+
enrichedProps = {
|
|
23
|
+
...enrichedProps,
|
|
24
|
+
hideLoading: true,
|
|
25
|
+
slotProps: {
|
|
26
|
+
stack: {
|
|
27
|
+
sx: { mr: 'auto' },
|
|
28
|
+
onClick: e => {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
e.stopPropagation();
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
popover: {
|
|
34
|
+
onClick: e => {
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else if (context === 'table') {
|
|
43
|
+
enrichedProps = {
|
|
44
|
+
...enrichedProps,
|
|
45
|
+
hideLoading: true,
|
|
46
|
+
slotProps: {
|
|
47
|
+
stack: { sx: { width: '100%', '& > p': { textOverflow: 'ellipsis', overflow: 'hidden' } } }
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return _jsx(EnrichedTypography, { ...enrichedProps, type: type });
|
|
52
|
+
};
|
|
53
|
+
export default memo(BorealisTypography);
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
import { Checkbox, Paper, Stack, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material';
|
|
4
|
+
import { EnrichedTypography, Entry, Fetcher, Group, useBorealisEnrichSelector } from 'borealis-ui';
|
|
5
|
+
import FlexOne from '@cccsaurora/howler-ui/components/elements/addons/layout/FlexOne';
|
|
6
|
+
import i18nInstance from '@cccsaurora/howler-ui/i18n';
|
|
7
|
+
import { capitalize, groupBy, uniq } from 'lodash-es';
|
|
8
|
+
import { useState } from 'react';
|
|
9
|
+
import { useTranslation } from 'react-i18next';
|
|
10
|
+
const BorealisTypography = props => {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
try {
|
|
13
|
+
const guessType = useBorealisEnrichSelector(ctx => ctx.guessType);
|
|
14
|
+
let type = props.type;
|
|
15
|
+
if (!type || type?.toLowerCase() === 'guess') {
|
|
16
|
+
type = guessType(props.value);
|
|
17
|
+
}
|
|
18
|
+
if (!type) {
|
|
19
|
+
return _jsx("span", { children: props.value });
|
|
20
|
+
}
|
|
21
|
+
return _jsx(EnrichedTypography, { ...props, type: type });
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
return (_jsxs(Stack, { children: [_jsx("strong", { style: { color: 'red' }, children: t('markdown.error') }), _jsx("strong", { children: err.toString() }), _jsx("code", { style: { fontSize: '0.8rem' }, children: _jsx("pre", { children: err.stack }) })] }));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const BorealisGroup = props => {
|
|
28
|
+
if (!props.enabled) {
|
|
29
|
+
return _jsx(_Fragment, { children: props.children });
|
|
30
|
+
}
|
|
31
|
+
if (!props.type) {
|
|
32
|
+
console.error('Missing required props for group helper');
|
|
33
|
+
return (_jsxs(Stack, { spacing: 1, children: [_jsx("strong", { style: { color: 'red' }, children: i18nInstance.t('markdown.error') }), _jsxs("code", { style: { fontSize: '0.8rem' }, children: [i18nInstance.t('markdown.props.missing'), ": type"] })] }));
|
|
34
|
+
}
|
|
35
|
+
return _jsx(Group, { type: props.type, children: props.children });
|
|
36
|
+
};
|
|
37
|
+
const BorealisEntry = ({ value }) => {
|
|
38
|
+
const [checked, setChecked] = useState(false);
|
|
39
|
+
return (_jsx(Entry, { entry: value, selected: checked, children: _jsx(Paper, { sx: { p: 1 }, children: _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Checkbox, { checked: checked, onChange: (_event, _checked) => setChecked(_checked) }), _jsx(BorealisTypography, { value: value }), _jsx(FlexOne, {})] }) }) }));
|
|
40
|
+
};
|
|
41
|
+
const BorealisCheckbox = ({ value }) => {
|
|
42
|
+
const [checked, setChecked] = useState(false);
|
|
43
|
+
return (_jsx(Entry, { entry: value, selected: checked, children: _jsx(Checkbox, { checked: checked, onChange: (_event, _checked) => setChecked(_checked) }) }));
|
|
44
|
+
};
|
|
45
|
+
const HELPERS = [
|
|
46
|
+
{
|
|
47
|
+
keyword: 'borealis',
|
|
48
|
+
documentation: 'Given a selector, this helper enriches the selector through borealis.',
|
|
49
|
+
componentCallback: (type, value) => {
|
|
50
|
+
if (typeof type !== 'string' || typeof value !== 'string') {
|
|
51
|
+
return (_jsxs(Stack, { spacing: 1, children: [_jsx("strong", { style: { color: 'red' }, children: i18nInstance.t('markdown.error') }), _jsx("code", { style: { fontSize: '0.8rem' }, children: "You must provide at least two arguments: type and value." })] }));
|
|
52
|
+
}
|
|
53
|
+
return (_jsx(BorealisTypography, { slotProps: { stack: { component: 'span', sx: { width: 'fit-content' } } }, component: "span", type: type, value: typeof value === 'string' ? value : null }));
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
keyword: 'fetcher',
|
|
58
|
+
documentation: 'Given a selector, this helper fetches data for the selector through borealis.',
|
|
59
|
+
componentCallback: (...args) => {
|
|
60
|
+
const options = args.pop();
|
|
61
|
+
const props = options?.hash ?? {};
|
|
62
|
+
if (!props.type || !props.value || !props.fetcherId) {
|
|
63
|
+
console.error('Missing required props for fetcher helper');
|
|
64
|
+
return (_jsxs(Stack, { spacing: 1, children: [_jsx("strong", { style: { color: 'red' }, children: i18nInstance.t('markdown.error') }), _jsxs("code", { style: { fontSize: '0.8rem' }, children: [i18nInstance.t('markdown.props.missing'), ":", ' ', ['type', 'value', 'fetcherId'].filter(key => !props[key]).join(', ')] })] }));
|
|
65
|
+
}
|
|
66
|
+
console.debug(`Rendering fetcher (${props.fetcherId}) for selector ${props.type}:${props.value}`);
|
|
67
|
+
return (_jsx(Fetcher, { slotProps: { stack: { component: 'span', sx: { width: 'fit-content' } } }, component: "span", ...props }));
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
keyword: 'borealis_group',
|
|
72
|
+
documentation: 'Initializes a borealis group',
|
|
73
|
+
componentCallback: (values, ...args) => {
|
|
74
|
+
const options = args.pop();
|
|
75
|
+
const props = options?.hash ?? {};
|
|
76
|
+
const missing = [];
|
|
77
|
+
if (!Array.isArray(values)) {
|
|
78
|
+
missing.push('values');
|
|
79
|
+
}
|
|
80
|
+
if (!props.type) {
|
|
81
|
+
missing.push('type');
|
|
82
|
+
}
|
|
83
|
+
if (missing.length > 0) {
|
|
84
|
+
return (_jsxs(Stack, { spacing: 1, children: [_jsx("strong", { style: { color: 'red' }, children: i18nInstance.t('markdown.error') }), _jsxs("code", { style: { fontSize: '0.8rem' }, children: [i18nInstance.t('markdown.props.missing'), ": ", missing.join(', ')] })] }));
|
|
85
|
+
}
|
|
86
|
+
return (_jsx(BorealisGroup, { type: props.type, enabled: true, children: _jsx(Stack, { spacing: 1, mt: 1, children: uniq(values).map(value => (_jsx(BorealisEntry, { value: value }, value))) }) }));
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
keyword: 'borealis_table',
|
|
91
|
+
documentation: `Render a table with optional Borealis enrichments and actions.
|
|
92
|
+
|
|
93
|
+
Borealis enrichments are performed for cells with a borealis_type.
|
|
94
|
+
|
|
95
|
+
Borealis actions are enabled by specifying a borealis action type using the optional borealis_action_type parameter. If enabled, cells with borealis_entity==true will be selectable for use with Borealis enrichments and actions, with a value of action_value if present, and otherwise value.
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
\`\`\`markdown
|
|
99
|
+
{{curly 'borealis_table borealis_table_cells borealis_action_type="ip"'}}
|
|
100
|
+
\`\`\`
|
|
101
|
+
where borealis_table_cells is an array with properties:
|
|
102
|
+
|
|
103
|
+
\`\`\`
|
|
104
|
+
column: string;
|
|
105
|
+
row: string;
|
|
106
|
+
value: string;
|
|
107
|
+
borealis_type (optional): string;
|
|
108
|
+
borealis_entity (optional): boolean;
|
|
109
|
+
action_value (optional): string;
|
|
110
|
+
\`\`\`
|
|
111
|
+
`,
|
|
112
|
+
componentCallback: (cells, ...args) => {
|
|
113
|
+
const options = args.pop();
|
|
114
|
+
const props = options?.hash ?? {};
|
|
115
|
+
const columns = Object.keys(groupBy(cells, 'column'));
|
|
116
|
+
const rows = groupBy(cells, 'row');
|
|
117
|
+
const enableBorealisActions = !props.borealis_action_type ? false : true;
|
|
118
|
+
const borealisActionType = !props.borealis_action_type ? 'false' : props.borealis_action_type;
|
|
119
|
+
return (_jsx(Paper, { sx: { width: '95%', overflowX: 'auto', m: 1 }, children: _jsx(BorealisGroup, { type: borealisActionType, enabled: enableBorealisActions, children: _jsxs(Table, { children: [_jsx(TableHead, { children: _jsx(TableRow, { children: columns.map(col => (_jsx(TableCell, { sx: { maxWidth: '150px' }, children: col
|
|
120
|
+
.split(/[_-]/)
|
|
121
|
+
.map(word => capitalize(word))
|
|
122
|
+
.join(' ') }, col))) }) }), _jsx(TableBody, { sx: { '& td': { wordBreak: 'break-word' } }, children: Object.entries(rows).map(([rowId, _cells]) => {
|
|
123
|
+
return (_jsx(TableRow, { children: columns.map(col => {
|
|
124
|
+
const cell = _cells.find(row => row.column === col);
|
|
125
|
+
return (_jsxs(TableCell, { children: [enableBorealisActions && cell.borealis_entity === true ? (_jsx(BorealisCheckbox, { value: cell.action_value ?? cell.value })) : null, typeof cell.borealis_type === 'string' ? (_jsx(BorealisTypography, { slotProps: {
|
|
126
|
+
stack: {
|
|
127
|
+
component: 'span',
|
|
128
|
+
sx: { width: 'fit-content' },
|
|
129
|
+
display: 'inline-flex'
|
|
130
|
+
}
|
|
131
|
+
}, component: "span", type: cell?.borealis_type, value: cell?.value })) : ((cell?.value ?? 'N/A'))] }, col + cell?.value));
|
|
132
|
+
}) }, rowId));
|
|
133
|
+
}) })] }) }) }));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
];
|
|
137
|
+
export default HELPERS;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HowlerHelper } from '@cccsaurora/howler-ui/components/elements/display/handlebars/helpers';
|
|
2
|
+
import type { PluginChipProps } from '@cccsaurora/howler-ui/components/elements/PluginChip';
|
|
3
|
+
import type { PluginTypographyProps } from '@cccsaurora/howler-ui/components/elements/PluginTypography';
|
|
4
|
+
import { type i18n as I18N } from 'i18next';
|
|
5
|
+
import HowlerPlugin from '@cccsaurora/howler-ui/plugins/HowlerPlugin';
|
|
6
|
+
declare class BorealisPlugin extends HowlerPlugin {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
author: string;
|
|
10
|
+
description: string;
|
|
11
|
+
activate(): void;
|
|
12
|
+
provider(): import("react").FC<{
|
|
13
|
+
children?: import("react").ReactNode | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
setup(): () => void;
|
|
16
|
+
localization(i18nInstance: I18N): void;
|
|
17
|
+
helpers(): HowlerHelper[];
|
|
18
|
+
typography(_props: PluginTypographyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
chip(_props: PluginChipProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
}
|
|
21
|
+
export default BorealisPlugin;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from '@mui/material';
|
|
3
|
+
import { Fetcher } from 'borealis-ui';
|
|
4
|
+
import borealisEN from 'borealis-ui/dist/en/translation.json';
|
|
5
|
+
import borealisFR from 'borealis-ui/dist/fr/translation.json';
|
|
6
|
+
import {} from 'i18next';
|
|
7
|
+
import HowlerPlugin from '@cccsaurora/howler-ui/plugins/HowlerPlugin';
|
|
8
|
+
import BorealisChip from './components/BorealisChip';
|
|
9
|
+
import BorealisLeadForm from './components/BorealisLeadForm';
|
|
10
|
+
import BorealisPivot from './components/BorealisPivot';
|
|
11
|
+
import BorealisPivotForm from './components/BorealisPivotForm';
|
|
12
|
+
import BorealisTypography from './components/BorealisTypography';
|
|
13
|
+
import HELPERS from './helpers';
|
|
14
|
+
import Provider from './Provider';
|
|
15
|
+
import useSetup from './setup';
|
|
16
|
+
class BorealisPlugin extends HowlerPlugin {
|
|
17
|
+
name = 'BorealisPlugin';
|
|
18
|
+
version = '0.0.1';
|
|
19
|
+
author = 'Matthew Rafuse <matthew.rafuse@cyber.gc.ca>';
|
|
20
|
+
description = 'This plugin enables borealis enrichment in Howler.';
|
|
21
|
+
activate() {
|
|
22
|
+
super.activate();
|
|
23
|
+
super.addLead('borealis', props => _jsx(BorealisLeadForm, { ...props }), (content, metadata) => (_jsx(Box, { p: 1, flex: 1, display: "flex", alignItems: "stretch", children: _jsx(Fetcher, { fetcherId: content, ...JSON.parse(metadata) }) })));
|
|
24
|
+
super.addPivot('borealis', props => _jsx(BorealisPivotForm, { ...props }), props => _jsx(BorealisPivot, { ...props }));
|
|
25
|
+
}
|
|
26
|
+
provider() {
|
|
27
|
+
return Provider;
|
|
28
|
+
}
|
|
29
|
+
setup() {
|
|
30
|
+
return useSetup;
|
|
31
|
+
}
|
|
32
|
+
localization(i18nInstance) {
|
|
33
|
+
i18nInstance.addResourceBundle('en', 'borealis', borealisEN, true, true);
|
|
34
|
+
i18nInstance.addResourceBundle('fr', 'borealis', borealisFR, true, true);
|
|
35
|
+
}
|
|
36
|
+
helpers() {
|
|
37
|
+
return HELPERS;
|
|
38
|
+
}
|
|
39
|
+
typography(_props) {
|
|
40
|
+
return _jsx(BorealisTypography, { ..._props });
|
|
41
|
+
}
|
|
42
|
+
chip(_props) {
|
|
43
|
+
return _jsx(BorealisChip, { ..._props });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export default BorealisPlugin;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"route.dossiers.manager.borealis": "Borealis Fetcher ID",
|
|
3
|
+
"route.dossiers.manager.borealis.type": "Selector Type",
|
|
4
|
+
"route.dossiers.manager.borealis.value": "Selector Value",
|
|
5
|
+
"route.dossiers.manager.borealis.value.custom": "Custom Selector Value",
|
|
6
|
+
"route.dossiers.manager.borealis.value.description": "You can use handlebars notation to insert fields from the corresponding alert (i.e. {{howler.id}})."
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"route.dossiers.manager.borealis": "ID du sélecteur Borealis",
|
|
3
|
+
"route.dossiers.manager.borealis.type": "Type de sélecteur",
|
|
4
|
+
"route.dossiers.manager.borealis.value": "Valeur du sélecteur",
|
|
5
|
+
"route.dossiers.manager.borealis.value.custom": "Valeur du sélecteur personnalisé",
|
|
6
|
+
"route.dossiers.manager.borealis.value.description": "Vous pouvez utiliser la notation « handlebars » pour insérer des champs à partir de l'alerte correspondante (c'est-à-dire {{howler.id}})."
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SNACKBAR_EVENT_ID, useBorealis } from 'borealis-ui';
|
|
2
|
+
import { useAppUser } from '@cccsaurora/howler-ui/commons/components/app/hooks';
|
|
3
|
+
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
4
|
+
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
5
|
+
import { useContext, useEffect } from 'react';
|
|
6
|
+
const useSetup = () => {
|
|
7
|
+
const borealis = useBorealis();
|
|
8
|
+
const appUser = useAppUser();
|
|
9
|
+
const apiConfig = useContext(ApiConfigContext);
|
|
10
|
+
const { showSuccessMessage, showErrorMessage, showInfoMessage, showWarningMessage } = useMySnackbar();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
// eslint-disable-next-line no-console
|
|
13
|
+
console.debug('Initializing borealis snackbar event handler');
|
|
14
|
+
const handleMessage = (event) => {
|
|
15
|
+
const { detail } = event;
|
|
16
|
+
if (detail.level === 'success') {
|
|
17
|
+
showSuccessMessage(detail.message, detail.timeout, detail.options);
|
|
18
|
+
}
|
|
19
|
+
else if (detail.level === 'error') {
|
|
20
|
+
showErrorMessage(detail.message, detail.timeout, detail.options);
|
|
21
|
+
}
|
|
22
|
+
else if (detail.level === 'info') {
|
|
23
|
+
showInfoMessage(detail.message, detail.timeout, detail.options);
|
|
24
|
+
}
|
|
25
|
+
else if (detail.level === 'warning') {
|
|
26
|
+
showWarningMessage(detail.message, detail.timeout, detail.options);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
window.addEventListener(SNACKBAR_EVENT_ID, handleMessage);
|
|
30
|
+
return () => {
|
|
31
|
+
window.removeEventListener(SNACKBAR_EVENT_ID, handleMessage);
|
|
32
|
+
};
|
|
33
|
+
}, [showErrorMessage, showInfoMessage, showSuccessMessage, showWarningMessage]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!appUser.isReady()) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (apiConfig.config.configuration?.features?.borealis) {
|
|
39
|
+
borealis.setReady(true);
|
|
40
|
+
}
|
|
41
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
|
+
}, [apiConfig.config.configuration?.features?.borealis, appUser.isReady()]);
|
|
43
|
+
};
|
|
44
|
+
export default useSetup;
|