@cccsaurora/howler-ui 2.19.0-dev.913 → 2.19.0-dev.920
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.
|
@@ -19,6 +19,7 @@ const TemplateViewer = () => {
|
|
|
19
19
|
const { dispatchApi } = useMyApi();
|
|
20
20
|
const [templateList, setTemplateList] = useState([]);
|
|
21
21
|
const [selectedTemplate, setSelectedTemplate] = useState(null);
|
|
22
|
+
const [sessionTemplateList, setSessionTemplateList] = useState([]);
|
|
22
23
|
const [displayFields, setDisplayFields] = useState([]);
|
|
23
24
|
const [analytics, setAnalytics] = useState([]);
|
|
24
25
|
const [detections, setDetections] = useState([]);
|
|
@@ -72,19 +73,22 @@ const TemplateViewer = () => {
|
|
|
72
73
|
}, [analytic, detection, dispatchApi, params, setParams, type]);
|
|
73
74
|
useEffect(() => {
|
|
74
75
|
if (analytic && detection) {
|
|
75
|
-
const
|
|
76
|
+
const findTemplate = (_templateList) => (_templateList ?? []).find(_template => _template.analytic === analytic &&
|
|
76
77
|
((detection === 'ANY' && !_template.detection) || _template.detection === detection) &&
|
|
77
78
|
_template.type === type);
|
|
79
|
+
const template = findTemplate(templateList);
|
|
80
|
+
// check if a template has been modified in the session but not saved to the datastore
|
|
81
|
+
const sessionTemplate = findTemplate(sessionTemplateList);
|
|
78
82
|
if (template) {
|
|
79
83
|
setSelectedTemplate(template);
|
|
80
|
-
setDisplayFields(template.keys);
|
|
84
|
+
setDisplayFields(sessionTemplate ? sessionTemplate.keys : template.keys);
|
|
81
85
|
}
|
|
82
86
|
else {
|
|
83
87
|
setSelectedTemplate(null);
|
|
84
|
-
setDisplayFields(DEFAULT_FIELDS);
|
|
88
|
+
setDisplayFields(sessionTemplate ? sessionTemplate.keys : DEFAULT_FIELDS);
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
|
-
}, [analytic, detection, templateList, type]);
|
|
91
|
+
}, [analytic, detection, sessionTemplateList, templateList, type]);
|
|
88
92
|
useEffect(() => {
|
|
89
93
|
if (analytic) {
|
|
90
94
|
params.set('analytic', analytic);
|
|
@@ -117,9 +121,19 @@ const TemplateViewer = () => {
|
|
|
117
121
|
showError: true,
|
|
118
122
|
throwError: false
|
|
119
123
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
setSessionTemplateList(l => l.filter(v => v.analytic != selectedTemplate.analytic ||
|
|
125
|
+
v.detection != selectedTemplate.detection ||
|
|
126
|
+
v.type != selectedTemplate.type));
|
|
127
|
+
setTemplateList(l => l.filter(v => v.analytic != selectedTemplate.analytic ||
|
|
128
|
+
v.detection != selectedTemplate.detection ||
|
|
129
|
+
v.type != selectedTemplate.type));
|
|
130
|
+
}, [
|
|
131
|
+
dispatchApi,
|
|
132
|
+
selectedTemplate?.analytic,
|
|
133
|
+
selectedTemplate?.detection,
|
|
134
|
+
selectedTemplate?.template_id,
|
|
135
|
+
selectedTemplate?.type
|
|
136
|
+
]);
|
|
123
137
|
const onSave = useCallback(async () => {
|
|
124
138
|
if (analytic && detection) {
|
|
125
139
|
try {
|
|
@@ -139,17 +153,39 @@ const TemplateViewer = () => {
|
|
|
139
153
|
setSelectedTemplate(result);
|
|
140
154
|
const newList = [result, ...templateList];
|
|
141
155
|
setTemplateList(newList.filter((v1, i) => newList.findIndex(v2 => v1.template_id === v2.template_id) === i));
|
|
156
|
+
const updatedSessionList = sessionTemplateList.filter(v => v.analytic !== result.analytic || v.detection !== result.detection || v.type !== result.type);
|
|
157
|
+
setSessionTemplateList(updatedSessionList);
|
|
142
158
|
}
|
|
143
159
|
finally {
|
|
144
160
|
setTemplateLoading(false);
|
|
145
161
|
}
|
|
146
162
|
}
|
|
147
|
-
}, [analytic, detection, dispatchApi, displayFields, selectedTemplate, templateList, type]);
|
|
163
|
+
}, [analytic, detection, dispatchApi, displayFields, selectedTemplate, sessionTemplateList, templateList, type]);
|
|
148
164
|
const analyticOrDetectionMissing = useMemo(() => !analytic || !detection, [analytic, detection]);
|
|
149
165
|
const noFieldChange = useMemo(() => displayFields.length < 1 || isEqual(selectedTemplate?.keys ?? DEFAULT_FIELDS, displayFields), [displayFields, selectedTemplate?.keys]);
|
|
150
|
-
|
|
166
|
+
const onTypeToggle = useCallback((_type) => {
|
|
167
|
+
setType(_type);
|
|
168
|
+
if (noFieldChange) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const sessionTemplate = {
|
|
172
|
+
analytic: analytic,
|
|
173
|
+
detection: detection !== 'ANY' ? detection : null,
|
|
174
|
+
type: type,
|
|
175
|
+
keys: displayFields
|
|
176
|
+
};
|
|
177
|
+
const newList = [sessionTemplate, ...sessionTemplateList];
|
|
178
|
+
setSessionTemplateList(newList.filter((v1, i) => newList.findIndex(v2 => v1.analytic === v2.analytic && v1.detection === v2.detection && v1.type === v2.type) === i));
|
|
179
|
+
}, [analytic, detection, displayFields, noFieldChange, sessionTemplateList, type]);
|
|
180
|
+
return (_jsxs(PageCenter, { maxWidth: "1500px", textAlign: "left", height: "100%", children: [_jsx(LinearProgress, { sx: { mb: 1, opacity: +loading } }), _jsxs(Stack, { direction: "column", spacing: 2, divider: _jsx(Divider, { orientation: "horizontal", flexItem: true }), height: "100%", children: [_jsxs(Stack, { direction: "row", spacing: 2, mb: 2, alignItems: "stretch", children: [_jsx(FormControl, { sx: { flex: 1, maxWidth: '450px' }, children: _jsx(Autocomplete, { id: "analytic", options: analytics.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())), getOptionLabel: option => option.name, value: analytics.find(a => a.name === analytic) || null, onChange: (__, newValue) => {
|
|
181
|
+
setAnalytic(newValue ? newValue.name : '');
|
|
182
|
+
setSessionTemplateList([]); // do not keep session memory if analytic or detection is changed
|
|
183
|
+
}, renderInput: autocompleteAnalyticParams => (_jsx(TextField, { ...autocompleteAnalyticParams, label: t('route.templates.analytic'), size: "small" })) }) }), !(detections?.length < 2 && detections[0]?.toLowerCase() === 'rule') ? (_jsx(FormControl, { sx: { flex: 1, maxWidth: '300px' }, disabled: !analytic, children: _jsx(Autocomplete, { id: "detection", options: ['ANY', ...detections.sort()], getOptionLabel: option => option, value: detection ?? '', onChange: (__, newValue) => {
|
|
184
|
+
setDetection(newValue);
|
|
185
|
+
setSessionTemplateList([]); // do not keep session memory if analytic or detection is changed
|
|
186
|
+
}, renderInput: autocompleteDetectionParams => (_jsx(TextField, { ...autocompleteDetectionParams, label: t('route.templates.detection'), size: "small" })) }) })) : (_jsx(Tooltip, { title: t('route.templates.rule.explanation'), children: _jsx(SsidChart, { color: "info", sx: { alignSelf: 'center' } }) })), _jsxs(ToggleButtonGroup, { sx: { display: 'grid', gridTemplateColumns: '1fr 1fr' }, size: "small", exclusive: true, value: type, disabled: analyticOrDetectionMissing, onChange: (__, _type) => {
|
|
151
187
|
if (_type) {
|
|
152
|
-
|
|
188
|
+
onTypeToggle(_type);
|
|
153
189
|
}
|
|
154
190
|
}, children: [_jsx(ToggleButton, { sx: { flex: 1 }, value: "personal", "aria-label": "personal", children: t('route.templates.personal') }), _jsx(ToggleButton, { sx: { flex: 1 }, value: "global", "aria-label": "global", children: t('route.templates.global') })] }), selectedTemplate && (_jsx(Button, { variant: "outlined", startIcon: _jsx(Delete, {}), onClick: onDelete, children: t('button.delete') })), _jsx(Button, { variant: "outlined", disabled: analyticOrDetectionMissing || noFieldChange, startIcon: templateLoading ? _jsx(CircularProgress, { size: 16 }) : _jsx(Check, {}), onClick: onSave, children: t(!analyticOrDetectionMissing && !noFieldChange ? 'button.save' : 'button.saved') })] }), analyticOrDetectionMissing ? (_jsx(AppInfoPanel, { i18nKey: "route.templates.select", sx: { width: '100%', alignSelf: 'start' } })) : (_jsx(TemplateEditor, { hit: exampleHit, fields: displayFields, setFields: setDisplayFields, onAdd: field => setDisplayFields([...displayFields, field]), onRemove: field => setDisplayFields(displayFields.filter(f => f !== field)) }))] })] }));
|
|
155
191
|
};
|
package/package.json
CHANGED
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"@monaco-editor/react": "^4.7.0",
|
|
29
29
|
"ajv": "^8.20.0",
|
|
30
30
|
"ajv-i18n": "^4.2.0",
|
|
31
|
-
"axios": "^1.16.
|
|
31
|
+
"axios": "^1.16.1",
|
|
32
32
|
"axios-retry": "^3.9.1",
|
|
33
33
|
"chart.js": "^4.5.1",
|
|
34
34
|
"chartjs-adapter-dayjs-4": "^1.0.4",
|
|
35
35
|
"chartjs-plugin-zoom": "^2.2.0",
|
|
36
36
|
"dayjs": "^1.11.20",
|
|
37
|
-
"dompurify": "^3.4.
|
|
37
|
+
"dompurify": "^3.4.5",
|
|
38
38
|
"flat": "^6.0.1",
|
|
39
39
|
"fuse.js": "^7.3.0",
|
|
40
40
|
"handlebars": "^4.7.9",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"internal-slot": "1.0.7"
|
|
97
97
|
},
|
|
98
98
|
"type": "module",
|
|
99
|
-
"version": "2.19.0-dev.
|
|
99
|
+
"version": "2.19.0-dev.920",
|
|
100
100
|
"exports": {
|
|
101
101
|
"./i18n": "./i18n.js",
|
|
102
102
|
"./index.css": "./index.css",
|