@odigos/ui-kit 0.0.98 → 0.0.100
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/CHANGELOG.md +20 -0
- package/lib/chunks/ui-components-bd79fd1d.js +1604 -0
- package/lib/chunks/vendor-1dea551d.js +1 -0
- package/lib/components.js +1 -163
- package/lib/constants.js +1 -9
- package/lib/containers.js +163 -5141
- package/lib/functions.js +1 -141
- package/lib/hooks.js +1 -649
- package/lib/icons.js +1 -187
- package/lib/snippets/add-button/index.d.ts +2 -1
- package/lib/snippets.js +1 -28
- package/lib/store/useDarkMode.d.ts +5 -3
- package/lib/store.js +1 -4
- package/lib/theme.js +1 -4
- package/lib/types.js +1 -369
- package/package.json +19 -13
- package/eslint.config.mjs +0 -34
- package/lib/index-0a77c1be.js +0 -11
- package/lib/index-195415d4.js +0 -676
- package/lib/index-1cb4f9e2.js +0 -20
- package/lib/index-5e5f7bda.js +0 -39
- package/lib/index-6a6bea6e.js +0 -37
- package/lib/index-77cf7846.js +0 -124
- package/lib/index-89edd01d.js +0 -1968
- package/lib/index-9475009f.js +0 -225
- package/lib/index-a3c0cecd.js +0 -36
- package/lib/index-c823fbfb.js +0 -342
- package/lib/index-c8b542d8.js +0 -38528
- package/lib/index-d8fb5fed.js +0 -138
- package/lib/index-f18c8530.js +0 -64
- package/lib/useTransition-159c9af8.js +0 -3598
package/lib/hooks.js
CHANGED
|
@@ -1,649 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { ActionKeyTypes, ActionType, StatusType, EntityTypes, FieldTypes } from './types.js';
|
|
3
|
-
import { useState, useEffect, useRef, useMemo } from 'react';
|
|
4
|
-
import 'styled-components';
|
|
5
|
-
import { i as isEmpty, s as safeJsonParse } from './index-5e5f7bda.js';
|
|
6
|
-
import { i as useGenericForm } from './useTransition-159c9af8.js';
|
|
7
|
-
export { b as useClickNode, a as useContainerSize, h as useCopy, e as useInstrumentationRuleFormData, u as useKeyDown, d as useOnClickOutside, c as usePopup, g as useTimeAgo, f as useTransition } from './useTransition-159c9af8.js';
|
|
8
|
-
import { g as getIdFromSseTarget, i as isLegalK8sLabel, m as mapExportedSignals } from './index-6a6bea6e.js';
|
|
9
|
-
|
|
10
|
-
const INITIAL$2 = {
|
|
11
|
-
// @ts-expect-error - we know that the field name is in the parsedFields
|
|
12
|
-
type: '',
|
|
13
|
-
name: '',
|
|
14
|
-
notes: '',
|
|
15
|
-
signals: [],
|
|
16
|
-
disabled: false,
|
|
17
|
-
clusterAttributes: null,
|
|
18
|
-
overwriteExistingValues: false,
|
|
19
|
-
renames: null,
|
|
20
|
-
attributeNamesToDelete: null,
|
|
21
|
-
piiCategories: null,
|
|
22
|
-
fallbackSamplingRatio: null,
|
|
23
|
-
samplingPercentage: null,
|
|
24
|
-
endpointsFilters: null,
|
|
25
|
-
servicesNameFilters: null,
|
|
26
|
-
attributeFilters: null,
|
|
27
|
-
};
|
|
28
|
-
const useActionFormData = () => {
|
|
29
|
-
const { addNotification } = useNotificationStore();
|
|
30
|
-
const { formData, formErrors, handleFormChange, handleErrorChange, resetFormData } = useGenericForm(INITIAL$2);
|
|
31
|
-
const validateForm = (params) => {
|
|
32
|
-
const errors = {};
|
|
33
|
-
let ok = true;
|
|
34
|
-
Object.entries(formData).forEach(([k, v]) => {
|
|
35
|
-
switch (k) {
|
|
36
|
-
case 'type':
|
|
37
|
-
case 'signals':
|
|
38
|
-
if (isEmpty(v))
|
|
39
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
40
|
-
break;
|
|
41
|
-
case ActionKeyTypes.ClusterAttributes:
|
|
42
|
-
if (formData.type === ActionType.AddClusterInfo && isEmpty(v))
|
|
43
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
44
|
-
break;
|
|
45
|
-
case ActionKeyTypes.Renames:
|
|
46
|
-
if (formData.type === ActionType.RenameAttributes && isEmpty(v))
|
|
47
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
48
|
-
break;
|
|
49
|
-
case ActionKeyTypes.AttributeNamesToDelete:
|
|
50
|
-
if (formData.type === ActionType.DeleteAttributes && isEmpty(v))
|
|
51
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
52
|
-
break;
|
|
53
|
-
case ActionKeyTypes.PiiCategories:
|
|
54
|
-
if (formData.type === ActionType.PiiMasking && isEmpty(v))
|
|
55
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
56
|
-
break;
|
|
57
|
-
case ActionKeyTypes.FallbackSamplingRatio:
|
|
58
|
-
if (formData.type === ActionType.ErrorSampler && isEmpty(v))
|
|
59
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
60
|
-
break;
|
|
61
|
-
case ActionKeyTypes.SamplingPercentage:
|
|
62
|
-
if (formData.type === ActionType.ProbabilisticSampler && isEmpty(v))
|
|
63
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
64
|
-
break;
|
|
65
|
-
case ActionKeyTypes.EndpointsFilters:
|
|
66
|
-
if (formData.type === ActionType.LatencySampler) {
|
|
67
|
-
if (isEmpty(v))
|
|
68
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
69
|
-
v?.forEach((endpoint) => {
|
|
70
|
-
if (endpoint.httpRoute.charAt(0) !== '/')
|
|
71
|
-
errors[k] = FORM_ALERTS.LATENCY_HTTP_ROUTE;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
break;
|
|
75
|
-
case ActionKeyTypes.ServicesNameFilters:
|
|
76
|
-
if (formData.type === ActionType.ServiceNameSampler) {
|
|
77
|
-
if (isEmpty(v))
|
|
78
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
79
|
-
v?.forEach((objV) => {
|
|
80
|
-
if (isEmpty(objV))
|
|
81
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
break;
|
|
85
|
-
case ActionKeyTypes.AttributeFilters:
|
|
86
|
-
if (formData.type === ActionType.SpanAttributeSampler && isEmpty(v))
|
|
87
|
-
errors[k] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
ok = !Object.values(errors).length;
|
|
92
|
-
if (!ok && params?.withAlert) {
|
|
93
|
-
addNotification({
|
|
94
|
-
type: StatusType.Warning,
|
|
95
|
-
title: params.alertTitle,
|
|
96
|
-
message: FORM_ALERTS.REQUIRED_FIELDS,
|
|
97
|
-
hideFromHistory: true,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
handleErrorChange(undefined, undefined, errors);
|
|
101
|
-
return ok;
|
|
102
|
-
};
|
|
103
|
-
const loadFormWithDrawerItem = ({ type, spec }) => {
|
|
104
|
-
const updatedData = {
|
|
105
|
-
...INITIAL$2,
|
|
106
|
-
type,
|
|
107
|
-
};
|
|
108
|
-
Object.entries(spec).forEach(([k, v]) => {
|
|
109
|
-
if (!!v) {
|
|
110
|
-
switch (k) {
|
|
111
|
-
case 'actionName': {
|
|
112
|
-
updatedData['name'] = v;
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
case 'type':
|
|
116
|
-
case 'notes':
|
|
117
|
-
case 'signals':
|
|
118
|
-
case 'disabled':
|
|
119
|
-
case ActionKeyTypes.CollectContainerAttributes:
|
|
120
|
-
case ActionKeyTypes.CollectReplicaSetAttributes:
|
|
121
|
-
case ActionKeyTypes.CollectWorkloadId:
|
|
122
|
-
case ActionKeyTypes.CollectClusterId:
|
|
123
|
-
case ActionKeyTypes.LabelsAttributes:
|
|
124
|
-
case ActionKeyTypes.AnnotationsAttributes:
|
|
125
|
-
case ActionKeyTypes.ClusterAttributes:
|
|
126
|
-
case ActionKeyTypes.OverwriteExistingValues:
|
|
127
|
-
case ActionKeyTypes.AttributeNamesToDelete:
|
|
128
|
-
case ActionKeyTypes.Renames:
|
|
129
|
-
case ActionKeyTypes.PiiCategories:
|
|
130
|
-
case ActionKeyTypes.FallbackSamplingRatio:
|
|
131
|
-
case ActionKeyTypes.SamplingPercentage:
|
|
132
|
-
case ActionKeyTypes.EndpointsFilters:
|
|
133
|
-
case ActionKeyTypes.ServicesNameFilters:
|
|
134
|
-
case ActionKeyTypes.AttributeFilters: {
|
|
135
|
-
// @ts-expect-error - we know that the field name is in the parsedFields
|
|
136
|
-
updatedData[k] = v;
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
handleFormChange(undefined, undefined, updatedData);
|
|
143
|
-
};
|
|
144
|
-
return {
|
|
145
|
-
formData,
|
|
146
|
-
formErrors,
|
|
147
|
-
handleFormChange,
|
|
148
|
-
resetFormData,
|
|
149
|
-
validateForm,
|
|
150
|
-
loadFormWithDrawerItem,
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const useClickNotification = () => {
|
|
155
|
-
const { setDrawerType, setDrawerEntityId } = useDrawerStore();
|
|
156
|
-
const { markAsDismissed, markAsSeen } = useNotificationStore();
|
|
157
|
-
const onClickNotification = (notif, options) => {
|
|
158
|
-
const { id, crdType, target } = notif;
|
|
159
|
-
const { dismissToast } = options || {};
|
|
160
|
-
if (crdType && target) {
|
|
161
|
-
switch (crdType) {
|
|
162
|
-
case EntityTypes.InstrumentationRule:
|
|
163
|
-
setDrawerType(EntityTypes.InstrumentationRule);
|
|
164
|
-
setDrawerEntityId(getIdFromSseTarget(target, EntityTypes.InstrumentationRule));
|
|
165
|
-
break;
|
|
166
|
-
case EntityTypes.Source:
|
|
167
|
-
case 'InstrumentationConfig':
|
|
168
|
-
case 'InstrumentationInstance':
|
|
169
|
-
setDrawerType(EntityTypes.Source);
|
|
170
|
-
setDrawerEntityId(getIdFromSseTarget(target, EntityTypes.Source));
|
|
171
|
-
break;
|
|
172
|
-
case EntityTypes.Action:
|
|
173
|
-
setDrawerType(EntityTypes.Action);
|
|
174
|
-
setDrawerEntityId(getIdFromSseTarget(target, EntityTypes.Action));
|
|
175
|
-
break;
|
|
176
|
-
case EntityTypes.Destination:
|
|
177
|
-
case 'Destination':
|
|
178
|
-
setDrawerType(EntityTypes.Destination);
|
|
179
|
-
setDrawerEntityId(getIdFromSseTarget(target, EntityTypes.Destination));
|
|
180
|
-
break;
|
|
181
|
-
default:
|
|
182
|
-
console.warn('notif click not handled for:', { crdType, target });
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
markAsSeen(id);
|
|
187
|
-
if (dismissToast)
|
|
188
|
-
markAsDismissed(id);
|
|
189
|
-
};
|
|
190
|
-
return { onClickNotification };
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const useDataStreamFormData = (initialFormData) => {
|
|
194
|
-
const { addNotification } = useNotificationStore();
|
|
195
|
-
const { formData, handleFormChange, formErrors, handleErrorChange, resetFormData } = useGenericForm(initialFormData);
|
|
196
|
-
const validateForm = (params) => {
|
|
197
|
-
const errors = {};
|
|
198
|
-
let isValid = true;
|
|
199
|
-
if (!formData['name']) {
|
|
200
|
-
isValid = false;
|
|
201
|
-
errors['name'] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
202
|
-
}
|
|
203
|
-
else if (!isLegalK8sLabel(formData['name'])) {
|
|
204
|
-
isValid = false;
|
|
205
|
-
errors['name'] = FORM_ALERTS.ILLEGAL_K8S_LABEL;
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
errors['name'] = undefined;
|
|
209
|
-
}
|
|
210
|
-
if (!isValid && params?.withAlert) {
|
|
211
|
-
addNotification({
|
|
212
|
-
type: StatusType.Warning,
|
|
213
|
-
title: params.alertTitle,
|
|
214
|
-
message: FORM_ALERTS.REQUIRED_FIELDS,
|
|
215
|
-
hideFromHistory: true,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
handleErrorChange(undefined, undefined, errors);
|
|
219
|
-
return isValid;
|
|
220
|
-
};
|
|
221
|
-
const loadFormWithDrawerItem = ({ name }) => {
|
|
222
|
-
const updatedData = {
|
|
223
|
-
...initialFormData,
|
|
224
|
-
name,
|
|
225
|
-
};
|
|
226
|
-
handleFormChange(undefined, undefined, updatedData);
|
|
227
|
-
};
|
|
228
|
-
return {
|
|
229
|
-
formData,
|
|
230
|
-
formErrors,
|
|
231
|
-
handleFormChange,
|
|
232
|
-
resetFormData,
|
|
233
|
-
validateForm,
|
|
234
|
-
loadFormWithDrawerItem,
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const INITIAL$1 = {
|
|
239
|
-
// @ts-expect-error - form should be initialized with empty values
|
|
240
|
-
type: '',
|
|
241
|
-
name: '',
|
|
242
|
-
exportedSignals: {
|
|
243
|
-
logs: false,
|
|
244
|
-
metrics: false,
|
|
245
|
-
traces: false,
|
|
246
|
-
},
|
|
247
|
-
fields: [],
|
|
248
|
-
disabled: false,
|
|
249
|
-
};
|
|
250
|
-
const buildFormDynamicFields = (fields) => {
|
|
251
|
-
return fields
|
|
252
|
-
.filter((f) => !!f)
|
|
253
|
-
.map((f) => {
|
|
254
|
-
const { name, componentType, componentProperties, displayName, initialValue, renderCondition } = f;
|
|
255
|
-
switch (componentType) {
|
|
256
|
-
case FieldTypes.Dropdown: {
|
|
257
|
-
const componentPropertiesJson = safeJsonParse(componentProperties, {});
|
|
258
|
-
const options = Array.isArray(componentPropertiesJson.values)
|
|
259
|
-
? componentPropertiesJson.values.map((value) => ({ id: value, value }))
|
|
260
|
-
: Object.entries(componentPropertiesJson.values).map(([key, value]) => ({ id: key, value }));
|
|
261
|
-
return {
|
|
262
|
-
name,
|
|
263
|
-
componentType: componentType,
|
|
264
|
-
title: displayName,
|
|
265
|
-
value: initialValue,
|
|
266
|
-
placeholder: componentPropertiesJson.placeholder || 'Select an option',
|
|
267
|
-
options,
|
|
268
|
-
renderCondition,
|
|
269
|
-
...componentPropertiesJson,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
default: {
|
|
273
|
-
const componentPropertiesJson = safeJsonParse(componentProperties, {});
|
|
274
|
-
return {
|
|
275
|
-
name,
|
|
276
|
-
componentType,
|
|
277
|
-
title: displayName,
|
|
278
|
-
value: initialValue,
|
|
279
|
-
renderCondition,
|
|
280
|
-
...componentPropertiesJson,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
};
|
|
286
|
-
const useDestinationFormData = (params) => {
|
|
287
|
-
const { supportedSignals, preLoadedFields } = params || {};
|
|
288
|
-
const { addNotification } = useNotificationStore();
|
|
289
|
-
const { formData, formErrors, handleFormChange, handleErrorChange, resetFormData } = useGenericForm(INITIAL$1);
|
|
290
|
-
const [yamlFields, setYamlFields] = useState([]);
|
|
291
|
-
const [dynamicFields, setDynamicFields] = useState([]);
|
|
292
|
-
useEffect(() => {
|
|
293
|
-
if (yamlFields) {
|
|
294
|
-
setDynamicFields(buildFormDynamicFields(yamlFields).map((field) => {
|
|
295
|
-
// if we have preloaded fields, we need to set the value of the field
|
|
296
|
-
// (this can be from an odigos-detected-destination during create, or from an existing destination during edit/update)
|
|
297
|
-
if (!!preLoadedFields) {
|
|
298
|
-
const parsedFields = typeof preLoadedFields === 'string' ? safeJsonParse(preLoadedFields, {}) : preLoadedFields;
|
|
299
|
-
if (field.name in parsedFields) {
|
|
300
|
-
return {
|
|
301
|
-
...field,
|
|
302
|
-
// @ts-expect-error - we know that the field name is in the parsedFields
|
|
303
|
-
value: parsedFields[field.name],
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return field;
|
|
308
|
-
}));
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
setDynamicFields([]);
|
|
312
|
-
}
|
|
313
|
-
}, [yamlFields, preLoadedFields]);
|
|
314
|
-
useEffect(() => {
|
|
315
|
-
if (dynamicFields) {
|
|
316
|
-
const mapped = dynamicFields.map((field) => ({
|
|
317
|
-
key: field.name,
|
|
318
|
-
value: field.value,
|
|
319
|
-
}));
|
|
320
|
-
handleFormChange('fields', mapped);
|
|
321
|
-
}
|
|
322
|
-
}, [dynamicFields]);
|
|
323
|
-
useEffect(() => {
|
|
324
|
-
if (supportedSignals && mapExportedSignals(formData.exportedSignals).length === 0) {
|
|
325
|
-
const { logs, metrics, traces } = supportedSignals;
|
|
326
|
-
handleFormChange('exportedSignals', {
|
|
327
|
-
logs: logs.supported,
|
|
328
|
-
metrics: metrics.supported,
|
|
329
|
-
traces: traces.supported,
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
}, [supportedSignals, formData]);
|
|
333
|
-
const validateForm = (params) => {
|
|
334
|
-
const errors = {};
|
|
335
|
-
let ok = true;
|
|
336
|
-
dynamicFields.forEach(({ name, value, required }) => {
|
|
337
|
-
if (required && !value) {
|
|
338
|
-
ok = false;
|
|
339
|
-
errors[name] = FORM_ALERTS.FIELD_IS_REQUIRED;
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
if (!ok && params?.withAlert) {
|
|
343
|
-
addNotification({
|
|
344
|
-
type: StatusType.Warning,
|
|
345
|
-
title: params.alertTitle,
|
|
346
|
-
message: FORM_ALERTS.REQUIRED_FIELDS,
|
|
347
|
-
hideFromHistory: true,
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
handleErrorChange(undefined, undefined, errors);
|
|
351
|
-
return ok;
|
|
352
|
-
};
|
|
353
|
-
const loadFormWithDrawerItem = ({ destinationType: { type }, name, disabled, exportedSignals, fields }) => {
|
|
354
|
-
const updatedData = {
|
|
355
|
-
...INITIAL$1,
|
|
356
|
-
type,
|
|
357
|
-
name,
|
|
358
|
-
disabled,
|
|
359
|
-
exportedSignals,
|
|
360
|
-
fields: Object.entries(safeJsonParse(fields, {})).map(([key, value]) => ({ key, value })),
|
|
361
|
-
};
|
|
362
|
-
handleFormChange(undefined, undefined, updatedData);
|
|
363
|
-
return updatedData;
|
|
364
|
-
};
|
|
365
|
-
return {
|
|
366
|
-
formData,
|
|
367
|
-
formErrors,
|
|
368
|
-
handleFormChange,
|
|
369
|
-
resetFormData,
|
|
370
|
-
validateForm,
|
|
371
|
-
loadFormWithDrawerItem,
|
|
372
|
-
yamlFields,
|
|
373
|
-
setYamlFields,
|
|
374
|
-
dynamicFields,
|
|
375
|
-
setDynamicFields,
|
|
376
|
-
};
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
const useSessionStorage = () => {
|
|
380
|
-
const getItemSS = (key, defaultValue) => {
|
|
381
|
-
const item = sessionStorage.getItem(key);
|
|
382
|
-
return item ? safeJsonParse(item, defaultValue) : defaultValue;
|
|
383
|
-
};
|
|
384
|
-
const setItemSS = (key, value) => {
|
|
385
|
-
sessionStorage.setItem(key, JSON.stringify(value));
|
|
386
|
-
};
|
|
387
|
-
const removeItemSS = (key) => {
|
|
388
|
-
sessionStorage.removeItem(key);
|
|
389
|
-
};
|
|
390
|
-
return { getItemSS, setItemSS, removeItemSS };
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
const INITIAL = {
|
|
394
|
-
otelServiceName: '',
|
|
395
|
-
currentStreamName: '',
|
|
396
|
-
};
|
|
397
|
-
const useSourceFormData = () => {
|
|
398
|
-
const { formData, formErrors, handleFormChange, handleErrorChange, resetFormData } = useGenericForm(INITIAL);
|
|
399
|
-
const validateForm = () => {
|
|
400
|
-
// We don't have any specific validations for this form yet
|
|
401
|
-
handleErrorChange(undefined, undefined, {});
|
|
402
|
-
return true;
|
|
403
|
-
};
|
|
404
|
-
const loadFormWithDrawerItem = ({ otelServiceName, name }) => {
|
|
405
|
-
const updatedData = {
|
|
406
|
-
...INITIAL,
|
|
407
|
-
otelServiceName: otelServiceName || name || '',
|
|
408
|
-
};
|
|
409
|
-
handleFormChange(undefined, undefined, updatedData);
|
|
410
|
-
};
|
|
411
|
-
return {
|
|
412
|
-
formData,
|
|
413
|
-
formErrors,
|
|
414
|
-
handleFormChange,
|
|
415
|
-
resetFormData,
|
|
416
|
-
validateForm,
|
|
417
|
-
loadFormWithDrawerItem,
|
|
418
|
-
};
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
const mapToAvailableSource = (source, selectedStreamName, selectAll) => {
|
|
422
|
-
const isBooleanOverride = typeof selectAll === 'boolean';
|
|
423
|
-
const isInCurrentStream = source.dataStreamNames?.includes(selectedStreamName) || source.currentStreamName === selectedStreamName;
|
|
424
|
-
const selected = (isBooleanOverride ? selectAll : source.selected) || false;
|
|
425
|
-
return {
|
|
426
|
-
namespace: source.namespace,
|
|
427
|
-
name: source.name,
|
|
428
|
-
kind: source.kind,
|
|
429
|
-
selected: isInCurrentStream || isBooleanOverride ? selected : false,
|
|
430
|
-
numberOfInstances: source.numberOfInstances,
|
|
431
|
-
};
|
|
432
|
-
};
|
|
433
|
-
const mapToSelectedSource = (source, selectedStreamName, selectAll) => {
|
|
434
|
-
return {
|
|
435
|
-
...mapToAvailableSource(source, selectedStreamName, selectAll),
|
|
436
|
-
currentStreamName: selectedStreamName,
|
|
437
|
-
};
|
|
438
|
-
};
|
|
439
|
-
const mapToSelectedNamespace = (ns, selectedStreamName, selectAll) => {
|
|
440
|
-
const isBooleanOverride = typeof selectAll === 'boolean';
|
|
441
|
-
const isInCurrentStream = ns.dataStreamNames?.includes(selectedStreamName);
|
|
442
|
-
const selected = (isBooleanOverride ? selectAll : ns.selected) || false;
|
|
443
|
-
return {
|
|
444
|
-
namespace: ns.name,
|
|
445
|
-
selected: isInCurrentStream || isBooleanOverride ? selected : false,
|
|
446
|
-
currentStreamName: selectedStreamName,
|
|
447
|
-
};
|
|
448
|
-
};
|
|
449
|
-
const mergeAvailableAndSelectedSources = (available, selected, currentStreamName) => {
|
|
450
|
-
const payload = {};
|
|
451
|
-
Object.entries(available).forEach(([namespace, sources]) => {
|
|
452
|
-
payload[namespace] = sources.map((s) => mapToSelectedSource(s, currentStreamName));
|
|
453
|
-
});
|
|
454
|
-
Object.entries(selected).forEach(([namespace, sources]) => {
|
|
455
|
-
sources.forEach((s) => {
|
|
456
|
-
const foundIdx = payload[namespace].findIndex((src) => src.name === s.name && src.kind === s.kind);
|
|
457
|
-
const mapped = mapToSelectedSource(s, currentStreamName);
|
|
458
|
-
if (foundIdx !== -1) {
|
|
459
|
-
payload[namespace][foundIdx] = mapped;
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
payload[namespace].push(mapped);
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
return payload;
|
|
467
|
-
};
|
|
468
|
-
const useSourceSelectionFormData = (params) => {
|
|
469
|
-
const { fetchSingleNamespace } = params || {};
|
|
470
|
-
const { namespaces } = useEntityStore();
|
|
471
|
-
const { selectedStreamName } = useDataStreamStore();
|
|
472
|
-
const mountedRef = useRef(false);
|
|
473
|
-
// only for "onboarding" - get unsaved values and set to state
|
|
474
|
-
// (this is to persist the values when user navigates back to this page)
|
|
475
|
-
const { configuredSources, configuredFutureApps, availableSources: availableSourcesFromStore } = useSetupStore();
|
|
476
|
-
// Keeps intial values fetched from API, so we can later filter the user-specific-selections, therebey minimizing the amount of data sent to the API on "persist sources".
|
|
477
|
-
const [availableSources, setRecordedInitialSources] = useState(availableSourcesFromStore);
|
|
478
|
-
const [isFetchingEachNamespace, setIsFetchingEachNamespace] = useState(false);
|
|
479
|
-
const [selectedAllNamespaces, setSelectedAllNamespaces] = useState(false);
|
|
480
|
-
const [fetchedNamespaces, setFetchedNamespaces] = useState([]);
|
|
481
|
-
const [selectedNamespace, setSelectedNamespace] = useState('');
|
|
482
|
-
const [selectedFutureApps, setSelectedFutureApps] = useState(configuredFutureApps);
|
|
483
|
-
const [selectedSources, setSelectedSources] = useState(mergeAvailableAndSelectedSources(availableSourcesFromStore, configuredSources, selectedStreamName));
|
|
484
|
-
const fetchAndSetThisNamespace = async (ns, selectAll) => {
|
|
485
|
-
if (fetchSingleNamespace) {
|
|
486
|
-
if (fetchedNamespaces.includes(ns.name)) {
|
|
487
|
-
setSelectedSources((prev) => ({
|
|
488
|
-
...prev,
|
|
489
|
-
[ns.name]: prev[ns.name].map((s) => ({
|
|
490
|
-
...s,
|
|
491
|
-
selected: typeof selectAll === 'boolean' ? selectAll : s.selected,
|
|
492
|
-
currentStreamName: selectedStreamName,
|
|
493
|
-
})),
|
|
494
|
-
}));
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
497
|
-
const { data } = await fetchSingleNamespace({ variables: { namespaceName: ns.name } });
|
|
498
|
-
const { name, sources = [] } = data?.computePlatform?.k8sActualNamespace || {};
|
|
499
|
-
if (!name)
|
|
500
|
-
return;
|
|
501
|
-
setFetchedNamespaces((prev) => [...prev, name]);
|
|
502
|
-
setRecordedInitialSources((prev) => ({
|
|
503
|
-
...prev,
|
|
504
|
-
[name]: sources.map((s) => mapToAvailableSource(s, selectedStreamName)),
|
|
505
|
-
}));
|
|
506
|
-
setSelectedSources((prev) => ({
|
|
507
|
-
...prev,
|
|
508
|
-
[name]: typeof selectAll !== 'boolean' && prev[name]?.length ? prev[name] : sources.map((s) => mapToSelectedSource(s, selectedStreamName, selectAll)),
|
|
509
|
-
}));
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
useEffect(() => {
|
|
514
|
-
mountedRef.current = true;
|
|
515
|
-
if (!!namespaces?.length) {
|
|
516
|
-
// initialize empty states to avoid undefined errors
|
|
517
|
-
setRecordedInitialSources((prev) => {
|
|
518
|
-
const payload = { ...prev };
|
|
519
|
-
namespaces.forEach(({ name }) => (payload[name] = payload[name] || []));
|
|
520
|
-
return payload;
|
|
521
|
-
});
|
|
522
|
-
setSelectedSources((prev) => {
|
|
523
|
-
const payload = { ...prev };
|
|
524
|
-
namespaces.forEach(({ name }) => (payload[name] = payload[name] || []));
|
|
525
|
-
return payload;
|
|
526
|
-
});
|
|
527
|
-
setSelectedFutureApps((prev) => {
|
|
528
|
-
const payload = { ...prev };
|
|
529
|
-
namespaces.forEach((ns) => (payload[ns.name] = payload[ns.name] || mapToSelectedNamespace(ns, selectedStreamName)));
|
|
530
|
-
return payload;
|
|
531
|
-
});
|
|
532
|
-
(async () => {
|
|
533
|
-
setIsFetchingEachNamespace(true);
|
|
534
|
-
for await (const ns of namespaces)
|
|
535
|
-
if (mountedRef.current)
|
|
536
|
-
await fetchAndSetThisNamespace(ns);
|
|
537
|
-
setIsFetchingEachNamespace(false);
|
|
538
|
-
})();
|
|
539
|
-
}
|
|
540
|
-
return () => {
|
|
541
|
-
mountedRef.current = false;
|
|
542
|
-
};
|
|
543
|
-
}, [namespaces, selectedStreamName]);
|
|
544
|
-
// form filters
|
|
545
|
-
const [searchText, setSearchText] = useState('');
|
|
546
|
-
const [searchBy, setSearchBy] = useState(EntityTypes.Source);
|
|
547
|
-
const [showSelectedOnly, setShowSelectedOnly] = useState(false);
|
|
548
|
-
const [showRunningOnly, setShowRunningOnly] = useState(false);
|
|
549
|
-
const onSelectAllNamespaces = (selected) => {
|
|
550
|
-
setSelectedAllNamespaces(selected);
|
|
551
|
-
namespaces.forEach((ns) => fetchAndSetThisNamespace(ns, selected));
|
|
552
|
-
};
|
|
553
|
-
const onSelectNamespace = (nsName, selectAll) => {
|
|
554
|
-
const ns = namespaces.find((namespace) => namespace.name === nsName);
|
|
555
|
-
if (ns) {
|
|
556
|
-
setSelectedNamespace((prev) => (prev === nsName && typeof selectAll !== 'boolean' ? '' : nsName));
|
|
557
|
-
fetchAndSetThisNamespace(ns, selectAll);
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
const onSelectSource = (source, nsName) => {
|
|
561
|
-
const id = nsName || selectedNamespace;
|
|
562
|
-
if (!id)
|
|
563
|
-
return;
|
|
564
|
-
const arr = [...(selectedSources[id] || [])];
|
|
565
|
-
const foundIdx = arr.findIndex(({ name, kind }) => name === source.name && kind === source.kind);
|
|
566
|
-
if (foundIdx !== -1) {
|
|
567
|
-
// Replace the item with a new object to avoid mutating a possibly read-only object
|
|
568
|
-
const updatedItem = { ...arr[foundIdx], selected: !arr[foundIdx].selected, currentStreamName: selectedStreamName };
|
|
569
|
-
arr[foundIdx] = updatedItem;
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
arr.push({ ...source, selected: true, currentStreamName: selectedStreamName });
|
|
573
|
-
}
|
|
574
|
-
setSelectedSources((prev) => ({ ...prev, [id]: arr }));
|
|
575
|
-
};
|
|
576
|
-
const onSelectFutureApps = (bool, nsName) => {
|
|
577
|
-
const id = nsName || selectedNamespace;
|
|
578
|
-
if (!id)
|
|
579
|
-
return;
|
|
580
|
-
const ns = namespaces.find((namespace) => namespace.name === nsName);
|
|
581
|
-
if (ns)
|
|
582
|
-
setSelectedFutureApps((prev) => ({ ...prev, [id]: mapToSelectedNamespace(ns, selectedStreamName, bool) }));
|
|
583
|
-
};
|
|
584
|
-
const filteredNamespacesAndSources = useMemo(() => {
|
|
585
|
-
const isSearchOk = (targetText, entityType) => !searchText || searchBy !== entityType || (searchBy === entityType && targetText.toLowerCase().includes(searchText));
|
|
586
|
-
const isOnlySelectedOk = (source) => !showSelectedOnly || source.selected;
|
|
587
|
-
const isRunningOnlyOk = (source) => !showRunningOnly || (source.numberOfInstances || 0) > 0;
|
|
588
|
-
const payload = {};
|
|
589
|
-
const filteredNamespacesMatrix = Object.entries(selectedSources).filter(([ns]) => isSearchOk(ns, EntityTypes.Namespace));
|
|
590
|
-
filteredNamespacesMatrix.forEach(([ns, srcs]) => {
|
|
591
|
-
const filteredSources = srcs.filter((src) => isSearchOk(src.name, EntityTypes.Source) && isOnlySelectedOk(src) && isRunningOnlyOk(src));
|
|
592
|
-
if (filteredSources.length)
|
|
593
|
-
payload[ns] = filteredSources;
|
|
594
|
-
});
|
|
595
|
-
return payload;
|
|
596
|
-
}, [selectedSources, searchText, searchBy, showSelectedOnly, showRunningOnly]);
|
|
597
|
-
// This is to filter the user-specific-selections, therebey minimizing the amount of data sent to the API on "persist sources".
|
|
598
|
-
const getApiSourcesPayload = () => {
|
|
599
|
-
const payload = {};
|
|
600
|
-
Object.entries(selectedSources).forEach(([namespace, sources]) => {
|
|
601
|
-
sources.forEach((source) => {
|
|
602
|
-
const foundInitial = availableSources[namespace]?.find((src) => src.name === source.name && src.kind === source.kind);
|
|
603
|
-
if (foundInitial?.selected !== source.selected) {
|
|
604
|
-
if (!payload[namespace])
|
|
605
|
-
payload[namespace] = [];
|
|
606
|
-
payload[namespace].push(source);
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
});
|
|
610
|
-
return payload;
|
|
611
|
-
};
|
|
612
|
-
// This is to filter the user-specific-selections, therebey minimizing the amount of data sent to the API on "persist namespaces".
|
|
613
|
-
const getApiFutureAppsPayload = () => {
|
|
614
|
-
const payload = {};
|
|
615
|
-
Object.entries(selectedFutureApps).forEach(([namespace, obj]) => {
|
|
616
|
-
const foundInitial = namespaces?.find((ns) => ns.name === namespace);
|
|
617
|
-
if ((obj.selected && !foundInitial?.dataStreamNames?.includes(selectedStreamName)) || (!obj.selected && foundInitial?.dataStreamNames?.includes(selectedStreamName))) {
|
|
618
|
-
payload[namespace] = obj;
|
|
619
|
-
}
|
|
620
|
-
});
|
|
621
|
-
return payload;
|
|
622
|
-
};
|
|
623
|
-
return {
|
|
624
|
-
isFetchingEachNamespace,
|
|
625
|
-
fetchedNamespaces,
|
|
626
|
-
availableSources,
|
|
627
|
-
filteredNamespacesAndSources,
|
|
628
|
-
getApiSourcesPayload,
|
|
629
|
-
getApiFutureAppsPayload,
|
|
630
|
-
selectedNamespace,
|
|
631
|
-
onSelectNamespace,
|
|
632
|
-
selectedAllNamespaces,
|
|
633
|
-
onSelectAllNamespaces,
|
|
634
|
-
selectedSources,
|
|
635
|
-
onSelectSource,
|
|
636
|
-
selectedFutureApps,
|
|
637
|
-
onSelectFutureApps,
|
|
638
|
-
searchText,
|
|
639
|
-
setSearchText,
|
|
640
|
-
searchBy,
|
|
641
|
-
setSearchBy,
|
|
642
|
-
showSelectedOnly,
|
|
643
|
-
setShowSelectedOnly,
|
|
644
|
-
showRunningOnly,
|
|
645
|
-
setShowRunningOnly,
|
|
646
|
-
};
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
export { useActionFormData, useClickNotification, useDataStreamFormData, useDestinationFormData, useGenericForm, useSessionStorage, useSourceFormData, useSourceSelectionFormData };
|
|
1
|
+
export{w as useActionFormData,az as useClickNode,bj as useClickNotification,at as useContainerSize,bA as useCopy,aN as useDataStreamFormData,aY as useDestinationFormData,bB as useGenericForm,bd as useInstrumentationRuleFormData,p as useKeyDown,aF as useOnClickOutside,aA as usePopup,aM as useSessionStorage,bs as useSourceFormData,bw as useSourceSelectionFormData,bi as useTimeAgo,bf as useTransition}from"./chunks/ui-components-bd79fd1d.js";import"./icons.js";import"react";import"zustand";import"javascript-time-ago";import"./chunks/vendor-1dea551d.js";import"styled-components";import"@xyflow/react";import"react-dom";import"prism-react-renderer";import"react-error-boundary";import"lottie-react";
|