@odigos/ui-kit 0.0.27 → 0.0.28

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.28](https://github.com/odigos-io/ui-kit/compare/ui-kit-v0.0.27...ui-kit-v0.0.28) (2025-05-19)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * state of source selection ([#118](https://github.com/odigos-io/ui-kit/issues/118)) ([7b73ae3](https://github.com/odigos-io/ui-kit/commit/7b73ae34778d6576a9a3c6645a434ae2ec4a2674))
9
+ * stream name input to include initial value, and validated as required ([#119](https://github.com/odigos-io/ui-kit/issues/119)) ([31a7f97](https://github.com/odigos-io/ui-kit/commit/31a7f9791def013cf1b99dcb36e043d6fa77021a))
10
+
3
11
  ## [0.0.27](https://github.com/odigos-io/ui-kit/compare/ui-kit-v0.0.26...ui-kit-v0.0.27) (2025-05-19)
4
12
 
5
13
 
@@ -16,6 +16,7 @@ interface AutocompleteInputProps extends InputHTMLAttributes<HTMLInputElement> {
16
16
  onTextChange?: (text: string) => void;
17
17
  style?: CSSProperties;
18
18
  disabled?: boolean;
19
+ errorMessage?: string;
19
20
  }
20
21
  declare const AutocompleteInput: FC<AutocompleteInputProps>;
21
22
  export { AutocompleteInput, type AutocompleteInputProps };
package/lib/components.js CHANGED
@@ -1,6 +1,6 @@
1
- import { B as Button } from './index-QaNawEGJ.js';
2
- export { a as AutocompleteInput, b as Badge, a1 as CenterThis, C as Checkbox, c as Code, d as ConditionDetails, D as DataCard, f as DataCardFieldTypes, e as DataCardFields, g as DataTab, h as Divider, i as DocsButton, j as Drawer, l as DrawerFooter, k as DrawerHeader, m as Dropdown, E as ExtendArrow, F as FadeLoader, n as FieldError, o as FieldLabel, a0 as FlexColumn, $ as FlexRow, H as Header, I as IconButton, p as IconGroup, q as IconTitleBadge, r as IconWrapped, s as IconsNav, t as ImageControlled, u as Input, v as InputList, w as InputTable, x as InteractiveTable, K as KeyValueInputsList, M as Modal, a4 as ModalBody, y as MonitorsCheckboxes, z as MonitorsIcons, N as NavigationButtons, G as NoDataFound, J as NotificationNote, a3 as Overlay, S as ScrollX, L as SectionTitle, O as Segment, P as SelectionButton, Q as SkeletonLoader, R as Status, U as Stepper, a5 as TableContainer, a6 as TableTitleWrap, a7 as TableWrap, V as Text, W as TextArea, X as Toggle, T as ToggleCodeComponent, Y as Tooltip, Z as TraceLoader, a2 as VerticalScroll, _ as WarningModal } from './index-QaNawEGJ.js';
3
- export { C as CancelWarning, D as DeleteWarning } from './index-DlCB8lqz.js';
1
+ import { B as Button } from './index-CX75oR-h.js';
2
+ export { a as AutocompleteInput, b as Badge, a1 as CenterThis, C as Checkbox, c as Code, d as ConditionDetails, D as DataCard, f as DataCardFieldTypes, e as DataCardFields, g as DataTab, h as Divider, i as DocsButton, j as Drawer, l as DrawerFooter, k as DrawerHeader, m as Dropdown, E as ExtendArrow, F as FadeLoader, n as FieldError, o as FieldLabel, a0 as FlexColumn, $ as FlexRow, H as Header, I as IconButton, p as IconGroup, q as IconTitleBadge, r as IconWrapped, s as IconsNav, t as ImageControlled, u as Input, v as InputList, w as InputTable, x as InteractiveTable, K as KeyValueInputsList, M as Modal, a4 as ModalBody, y as MonitorsCheckboxes, z as MonitorsIcons, N as NavigationButtons, G as NoDataFound, J as NotificationNote, a3 as Overlay, S as ScrollX, L as SectionTitle, O as Segment, P as SelectionButton, Q as SkeletonLoader, R as Status, U as Stepper, a5 as TableContainer, a6 as TableTitleWrap, a7 as TableWrap, V as Text, W as TextArea, X as Toggle, T as ToggleCodeComponent, Y as Tooltip, Z as TraceLoader, a2 as VerticalScroll, _ as WarningModal } from './index-CX75oR-h.js';
3
+ export { C as CancelWarning, D as DeleteWarning } from './index-8BSRffGz.js';
4
4
  import React, { Component, createElement, createContext } from 'react';
5
5
  import Theme from './theme.js';
6
6
  import 'styled-components';
@@ -4,6 +4,7 @@ interface DataStreamSelectionFormProps {
4
4
  onClickSummary?: () => void;
5
5
  }
6
6
  interface DataStreamSelectionFormRef {
7
+ validateForm: () => boolean;
7
8
  getFormValues: () => {
8
9
  name: string;
9
10
  };
package/lib/containers.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle, useMemo, memo, useContext, createContext, useCallback, useLayoutEffect, Fragment } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
- import { D as DISPLAY_TITLES, A as ACTION_OPTIONS, M as MONITORS_OPTIONS, B as BUTTON_TEXTS, I as INSTRUMENTATION_RULE_OPTIONS, F as FORM_ALERTS } from './index-CTgLYGo-.js';
3
+ import { D as DISPLAY_TITLES, A as ACTION_OPTIONS, M as MONITORS_OPTIONS, B as BUTTON_TEXTS, F as FORM_ALERTS, I as INSTRUMENTATION_RULE_OPTIONS } from './index-CTgLYGo-.js';
4
4
  import { ActionType, EntityTypes, StatusType, Crud, OtherStatus, NodeTypes, AddNodeTypes, EdgeTypes, FieldTypes, SignalType, CodeAttributesKeyTypes, PayloadCollectionKeyTypes, InstrumentationRuleType } from './types.js';
5
- import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, M as Modal, N as NavigationButtons, a4 as ModalBody, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, a0 as FlexColumn, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, J as NotificationNote, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-QaNawEGJ.js';
5
+ import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, M as Modal, N as NavigationButtons, a4 as ModalBody, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, a0 as FlexColumn, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, J as NotificationNote, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-CX75oR-h.js';
6
6
  import { h as usePendingStore, g as useNotificationStore, b as useDrawerStore, c as useEntityStore, f as useModalStore, d as useFilterStore, s as styleInject, i as useSelectedStore, e as useInstrumentStore, a as useDataStreamStore, k as getEntityId, j as useSetupStore, u as useDarkMode } from './index-DMXaEyAB.js';
7
7
  import Theme from './theme.js';
8
8
  import { i as isEmpty, s as safeJsonParse } from './index-BZS1ijMm.js';
9
9
  import { i as CheckCircledIcon, O as OdigosLogo } from './index-IKusBlIE.js';
10
10
  import { C as CrossCircledIcon, O as OdigosLogoText, a as OverviewIcon, F as FilterIcon, D as DataStreamsIcon, N as NotificationIcon, S as SlackLogo, K as KeyIcon, T as TerminalIcon } from './index-CamnKrev.js';
11
11
  import { g as getActionIcon, a as getInstrumentationRuleIcon } from './index-CFnxjzaW.js';
12
- import { u as useActionFormData, a as useClickNode, c as useDestinationFormData, b as useClickNotification, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-DAxuVELF.js';
13
- import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-BSKilkmZ.js';
12
+ import { u as useActionFormData, a as useClickNode, c as useDestinationFormData, b as useClickNotification, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-CoaXePS_.js';
13
+ import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, b as useGenericForm, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-BSKilkmZ.js';
14
14
  import { E as EditIcon } from './index-CWbxXTof.js';
15
15
  import { T as TrashIcon, S as SearchIcon, P as PlusIcon$1, f as CheckIcon, A as ArrowIcon, a as CopyIcon, g as CrossIcon } from './index-BJxaoI0G.js';
16
- import { D as DeleteWarning, C as CancelWarning } from './index-DlCB8lqz.js';
16
+ import { D as DeleteWarning, C as CancelWarning } from './index-8BSRffGz.js';
17
17
  import { m as mapConditions, b as getStatusIcon, c as capitalizeFirstLetter } from './index-CJs4RDHU.js';
18
18
  import { f as filterActions, i as getConditionsBooleans, n as getEntityLabel, m as getEntityIcon, v as sleep$1, p as getPlatformIcon, q as getPlatformLabel, h as formatBytes, k as getContainersIcons, r as getValueForRange, l as getDestinationIcon, u as mapExportedSignals, g as filterSourcesByStream, e as filterSources, b as filterDestinationsByStream, a as filterDestinations, c as compareCondition, d as deepClone, o as getMetricForEntity, s as getWorkloadId, j as getContainersInstrumentedCount, t as isOverTime } from './index-BfatCMWq.js';
19
19
  import { createPortal } from 'react-dom';
20
- import { N as NoteBackToSummary, E as EditButton } from './index-KyiD2AtF.js';
20
+ import { N as NoteBackToSummary, E as EditButton } from './index-R9xRto5r.js';
21
21
  import { D as DESTINATION_CATEGORIES } from './index-Dqief9td.js';
22
22
  import { a6 as RulesIcon, a7 as SourcesIcon, a3 as ActionsIcon, a4 as DestinationsIcon } from './index-BRW_Nl-n.js';
23
23
  import './index-DGel4E-Z.js';
@@ -13999,19 +13999,30 @@ const DataFlowActionsMenu = ({ addEntity, onClickNewDataStream }) => {
13999
13999
  };
14000
14000
 
14001
14001
  const DataStreamSelectionForm = forwardRef(({ isModal, onClickSummary }, ref) => {
14002
- const { dataStreams } = useDataStreamStore();
14003
- const [nameInput, setNameInput] = useState('');
14002
+ const { selectedStreamName, dataStreams } = useDataStreamStore();
14003
+ const { formData, handleFormChange, formErrors, handleErrorChange } = useGenericForm({
14004
+ name: selectedStreamName,
14005
+ });
14004
14006
  useImperativeHandle(ref, () => ({
14005
- getFormValues: () => ({
14006
- name: nameInput,
14007
- }),
14007
+ validateForm: () => {
14008
+ let isValid = true;
14009
+ if (!formData['name']) {
14010
+ isValid = false;
14011
+ handleErrorChange('name', FORM_ALERTS.FIELD_IS_REQUIRED);
14012
+ }
14013
+ else {
14014
+ handleErrorChange('name', undefined);
14015
+ }
14016
+ return isValid;
14017
+ },
14018
+ getFormValues: () => formData,
14008
14019
  }));
14009
14020
  const dataStreamOptions = useMemo(() => dataStreams.map(({ name }) => ({ label: name })), [dataStreams]);
14010
14021
  return (React.createElement(ModalBody, { "$isNotModal": !isModal, "$minHeight": '70vh' },
14011
14022
  React.createElement(FlexColumn, { "$gap": 24 },
14012
14023
  onClickSummary && React.createElement(NoteBackToSummary, { onClick: onClickSummary }),
14013
14024
  React.createElement(SectionTitle, { title: DISPLAY_TITLES.NAME_YOUR_STREAM, description: DISPLAY_TITLES.STREAM_DESCRIPTION }),
14014
- React.createElement(AutocompleteInput, { placeholder: DISPLAY_TITLES.NAME_YOUR_STREAM_PLACEHOLDER, autoFocus: true, options: dataStreamOptions, defaultText: nameInput, onTextChange: setNameInput }))));
14025
+ React.createElement(AutocompleteInput, { placeholder: DISPLAY_TITLES.NAME_YOUR_STREAM_PLACEHOLDER, required: true, autoFocus: true, options: dataStreamOptions, defaultText: formData['name'], onTextChange: (v) => handleFormChange('name', v), errorMessage: formErrors['name'] }))));
14015
14026
  });
14016
14027
 
14017
14028
  const buildMonitorsList = (exportedSignals) => Object.keys(exportedSignals)
@@ -15763,10 +15774,10 @@ const SearchWrapper = styled.div `
15763
15774
  `;
15764
15775
  const SourceSelectionForm = forwardRef(({ isModal, fetchSingleNamespace, onClickSummary }, ref) => {
15765
15776
  const formState = useSourceSelectionFormData({ fetchSingleNamespace });
15766
- const { recordedInitialSources, selectedSources, getApiSourcesPayload, getApiFutureAppsPayload, searchText, setSearchText, showSelectedOnly, setShowSelectedOnly } = formState;
15777
+ const { availableSources, selectedSources, getApiSourcesPayload, getApiFutureAppsPayload, searchText, setSearchText, showSelectedOnly, setShowSelectedOnly } = formState;
15767
15778
  useImperativeHandle(ref, () => ({
15768
15779
  getFormValues: () => ({
15769
- initial: recordedInitialSources,
15780
+ initial: availableSources,
15770
15781
  apps: getApiSourcesPayload(),
15771
15782
  futureApps: getApiFutureAppsPayload(),
15772
15783
  }),
@@ -6,7 +6,7 @@ interface UseSourceFormDataParams {
6
6
  fetchSingleNamespace: FetchSingleNamespace;
7
7
  }
8
8
  export interface UseSourceSelectionFormData {
9
- recordedInitialSources: AvailableSourcesByNamespace;
9
+ availableSources: AvailableSourcesByNamespace;
10
10
  filteredNamespacesAndSources: AvailableSourcesByNamespace;
11
11
  getApiSourcesPayload: () => SourceSelectionFormData;
12
12
  getApiFutureAppsPayload: () => NamespaceSelectionFormData;
package/lib/hooks.js CHANGED
@@ -1,4 +1,4 @@
1
- export { u as useActionFormData, a as useClickNode, b as useClickNotification, c as useDestinationFormData, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-DAxuVELF.js';
1
+ export { u as useActionFormData, a as useClickNode, b as useClickNotification, c as useDestinationFormData, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-CoaXePS_.js';
2
2
  export { u as useContainerSize, a as useCopy, b as useGenericForm, c as useInstrumentationRuleFormData, d as useKeyDown, e as useOnClickOutside, f as useTimeAgo, g as useTransition } from './useTransition-BSKilkmZ.js';
3
3
  import './types.js';
4
4
  import 'react';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { _ as WarningModal } from './index-QaNawEGJ.js';
2
+ import { _ as WarningModal } from './index-CX75oR-h.js';
3
3
  import { StatusType, EntityTypes } from './types.js';
4
4
  import './index-DMXaEyAB.js';
5
5
  import 'styled-components';
@@ -26,6 +26,18 @@ const Text = ({ children, color, size, weight, align, family, opacity, decoratio
26
26
  return (React.createElement(TextWrapper$2, { "$color": color, "$size": size, "$weight": weight, "$align": align, "$family": family, "$opacity": opacity, "$decoration": decoration, ...props }, children));
27
27
  };
28
28
 
29
+ const ErrorWrapper = styled.div `
30
+ padding: 4px 0 0 0;
31
+ `;
32
+ const ErrorMessage = styled(Text) `
33
+ font-size: 12px;
34
+ color: ${({ theme }) => theme.text.error};
35
+ `;
36
+ const FieldError = ({ children }) => {
37
+ return (React.createElement(ErrorWrapper, null,
38
+ React.createElement(ErrorMessage, null, children)));
39
+ };
40
+
29
41
  const AutocompleteContainer = styled.div `
30
42
  position: relative;
31
43
  width: 100%;
@@ -39,13 +51,13 @@ const InputWrapper$2 = styled.div `
39
51
  padding-left: 12px;
40
52
  transition: border-color 0.3s;
41
53
  border-radius: 32px;
42
- border: 1px solid ${({ theme }) => theme.colors.border};
54
+ border: 1px solid ${({ theme, $hasError }) => ($hasError ? theme.text.error : theme.colors.border)};
43
55
 
44
56
  &:hover {
45
- border-color: ${({ theme }) => theme.colors.secondary};
57
+ border-color: ${({ theme, $hasError }) => ($hasError ? theme.text.error_secondary : theme.colors.secondary)};
46
58
  }
47
59
  &:focus-within {
48
- border-color: ${({ theme }) => theme.colors.secondary};
60
+ border-color: ${({ theme, $hasError }) => ($hasError ? theme.text.error_secondary : theme.colors.secondary)};
49
61
  }
50
62
  `;
51
63
  const StyledInput$1 = styled.input `
@@ -146,7 +158,7 @@ const filterOptions = (optionsList, input) => {
146
158
  return acc;
147
159
  }, []);
148
160
  };
149
- const AutocompleteInput = ({ placeholder = 'Type to search...', options, selectedOption, onOptionSelect, defaultText, onTextChange, style, disabled, ...props }) => {
161
+ const AutocompleteInput = ({ placeholder = 'Type to search...', options, selectedOption, onOptionSelect, defaultText, onTextChange, style, disabled, errorMessage, ...props }) => {
150
162
  const [query, setQuery] = useState(selectedOption?.label || defaultText || '');
151
163
  const [filteredOptions, setFilteredOptions] = useState(filterOptions(options, query));
152
164
  const [showOptions, setShowOptions] = useState(false);
@@ -178,10 +190,11 @@ const AutocompleteInput = ({ placeholder = 'Type to search...', options, selecte
178
190
  return;
179
191
  };
180
192
  return (React.createElement(AutocompleteContainer, { style: style },
181
- React.createElement(InputWrapper$2, null,
193
+ React.createElement(InputWrapper$2, { "$hasError": !!errorMessage },
182
194
  Icon && React.createElement(Icon, null),
183
195
  React.createElement(StyledInput$1, { type: 'text', value: query, placeholder: placeholder, onChange: handleChange, onKeyDown: handleKeyDown, disabled: disabled, onBlur: () => !disabled && setShowOptions(false), onFocus: () => !disabled && setShowOptions(true), ...props })),
184
- showOptions && filteredOptions.length ? (React.createElement(OptionsList, null, filteredOptions.map((option) => (React.createElement(OptionItem, { key: option.type || option.label, option: option, onClick: handleOptionClick }))))) : null));
196
+ showOptions && filteredOptions.length ? (React.createElement(OptionsList, null, filteredOptions.map((option) => (React.createElement(OptionItem, { key: option.type || option.label, option: option, onClick: handleOptionClick }))))) : null,
197
+ errorMessage && React.createElement(FieldError, null, errorMessage)));
185
198
  };
186
199
  const OptionItem = ({ option, renderIcon = true, onClick }) => {
187
200
  const hasSubItems = !!option.items && option.items.length > 0;
@@ -455,18 +468,6 @@ const Popup = forwardRef(({ top, left, children }, ref) => {
455
468
  return ReactDOM.createPortal(React.createElement(PopupContainer, { ref: ref, "$top": top, "$left": left }, children), document.body);
456
469
  });
457
470
 
458
- const ErrorWrapper = styled.div `
459
- padding: 4px 0 0 0;
460
- `;
461
- const ErrorMessage = styled(Text) `
462
- font-size: 12px;
463
- color: ${({ theme }) => theme.text.error};
464
- `;
465
- const FieldError = ({ children }) => {
466
- return (React.createElement(ErrorWrapper, null,
467
- React.createElement(ErrorMessage, null, children)));
468
- };
469
-
470
471
  const Container$t = styled.div `
471
472
  display: flex;
472
473
  align-items: center;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import Theme from './theme.js';
3
3
  import { E as EditIcon } from './index-CWbxXTof.js';
4
4
  import { B as BUTTON_TEXTS, D as DISPLAY_TITLES } from './index-CTgLYGo-.js';
5
- import { B as Button, V as Text, J as NotificationNote } from './index-QaNawEGJ.js';
5
+ import { B as Button, V as Text, J as NotificationNote } from './index-CX75oR-h.js';
6
6
  import { StatusType } from './types.js';
7
7
  import './index-DMXaEyAB.js';
8
8
  import 'styled-components';
package/lib/snippets.js CHANGED
@@ -1,5 +1,5 @@
1
- export { A as AddButton } from './index-QaNawEGJ.js';
2
- export { E as EditButton, N as NoteBackToSummary } from './index-KyiD2AtF.js';
1
+ export { A as AddButton } from './index-CX75oR-h.js';
2
+ export { E as EditButton, N as NoteBackToSummary } from './index-R9xRto5r.js';
3
3
  import 'react';
4
4
  import './theme.js';
5
5
  import './index-DMXaEyAB.js';
@@ -373,10 +373,12 @@ const useSourceFormData = () => {
373
373
  };
374
374
 
375
375
  const mapSourceToAvailableSource = (source, selectedStreamName, selectAll) => {
376
+ const sourceIsInCurrentStream = source.dataStreamNames?.includes(selectedStreamName) || source.currentStreamName === selectedStreamName;
377
+ const selected = typeof selectAll === 'boolean' ? selectAll : sourceIsInCurrentStream ? source.selected : false;
376
378
  return {
377
379
  name: source.name,
378
380
  kind: source.kind,
379
- selected: typeof selectAll === 'boolean' ? selectAll : source.selected && source.dataStreamNames?.includes(selectedStreamName) ? source.selected : false,
381
+ selected,
380
382
  numberOfInstances: source.numberOfInstances,
381
383
  };
382
384
  };
@@ -386,18 +388,37 @@ const mapSourceToSelectedSource = (source, selectedStreamName, selectAll) => {
386
388
  currentStreamName: selectedStreamName,
387
389
  };
388
390
  };
391
+ const mergeAvailableAndSelectedSources = (available, selected, currentStreamName) => {
392
+ const payload = {};
393
+ Object.entries(available).forEach(([namespace, sources]) => {
394
+ payload[namespace] = sources.map((s) => mapSourceToSelectedSource(s, currentStreamName));
395
+ });
396
+ Object.entries(selected).forEach(([namespace, sources]) => {
397
+ sources.forEach((s) => {
398
+ const foundIdx = payload[namespace].findIndex((src) => src.name === s.name && src.kind === s.kind);
399
+ const mapped = mapSourceToSelectedSource(s, currentStreamName);
400
+ if (foundIdx !== -1) {
401
+ payload[namespace][foundIdx] = mapped;
402
+ }
403
+ else {
404
+ payload[namespace].push(mapped);
405
+ }
406
+ });
407
+ });
408
+ return payload;
409
+ };
389
410
  const useSourceSelectionFormData = (params) => {
390
411
  const { fetchSingleNamespace } = params || {};
391
412
  const { namespaces } = useEntityStore();
392
413
  const { selectedStreamName } = useDataStreamStore();
393
414
  // only for "onboarding" - get unsaved values and set to state
394
415
  // (this is to persist the values when user navigates back to this page)
395
- const { configuredSources, configuredFutureApps, availableSources } = useSetupStore();
416
+ const { configuredSources, configuredFutureApps, availableSources: availableSourcesFromStore } = useSetupStore();
396
417
  // 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".
397
- const [recordedInitialSources, setRecordedInitialSources] = useState(availableSources);
418
+ const [availableSources, setRecordedInitialSources] = useState(availableSourcesFromStore);
398
419
  const [selectedNamespace, setSelectedNamespace] = useState('');
399
- const [selectedSources, setSelectedSources] = useState(configuredSources);
400
420
  const [selectedFutureApps, setSelectedFutureApps] = useState(configuredFutureApps);
421
+ const [selectedSources, setSelectedSources] = useState(mergeAvailableAndSelectedSources(availableSourcesFromStore, configuredSources, selectedStreamName));
401
422
  const fetchAndSetThisNamespace = (ns, selectAll) => {
402
423
  fetchSingleNamespace?.({ variables: { namespaceName: ns } }).then(({ data }) => {
403
424
  const { name, sources = [] } = data?.computePlatform?.k8sActualNamespace || {};
@@ -480,7 +501,7 @@ const useSourceSelectionFormData = (params) => {
480
501
  const payload = {};
481
502
  Object.entries(selectedSources).forEach(([namespace, sources]) => {
482
503
  sources.forEach((source) => {
483
- const foundInitial = recordedInitialSources[namespace]?.find((initialSource) => initialSource.name === source.name && initialSource.kind === source.kind);
504
+ const foundInitial = availableSources[namespace]?.find((initialSource) => initialSource.name === source.name && initialSource.kind === source.kind);
484
505
  if (foundInitial?.selected !== source.selected) {
485
506
  if (!payload[namespace])
486
507
  payload[namespace] = [];
@@ -502,7 +523,7 @@ const useSourceSelectionFormData = (params) => {
502
523
  return payload;
503
524
  };
504
525
  return {
505
- recordedInitialSources,
526
+ availableSources,
506
527
  filteredNamespacesAndSources,
507
528
  getApiSourcesPayload,
508
529
  getApiFutureAppsPayload,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odigos/ui-kit",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "author": "Odigos",
5
5
  "repository": {
6
6
  "type": "git",