@cccsaurora/howler-ui 2.19.0-dev.913 → 2.19.0-dev.916

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 template = (templateList ?? []).find(_template => _template.analytic === analytic &&
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
- setSelectedTemplate(null);
121
- setDisplayFields(DEFAULT_FIELDS);
122
- }, [dispatchApi, selectedTemplate?.template_id]);
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
- 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) => setAnalytic(newValue ? newValue.name : ''), 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) => setDetection(newValue), 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) => {
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
- setType(_type);
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
@@ -96,7 +96,7 @@
96
96
  "internal-slot": "1.0.7"
97
97
  },
98
98
  "type": "module",
99
- "version": "2.19.0-dev.913",
99
+ "version": "2.19.0-dev.916",
100
100
  "exports": {
101
101
  "./i18n": "./i18n.js",
102
102
  "./index.css": "./index.css",