Skip to content

Commit 62ac31e

Browse files
committed
fixes
1 parent 86913d6 commit 62ac31e

File tree

2 files changed

+206
-57
lines changed

2 files changed

+206
-57
lines changed

src/components/ComponentsSelection/ComponentsSelectionContainer.tsx

Lines changed: 88 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useRef } from 'react';
1+
import React, { useEffect, useMemo, useRef, useState } from 'react';
22
import { ComponentsSelection } from './ComponentsSelection.tsx';
33

44
import IllustratedError from '../Shared/IllustratedError.tsx';
@@ -9,10 +9,12 @@ import { useApiResource } from '../../lib/api/useApiResource.ts';
99
import Loading from '../Shared/Loading.tsx';
1010
import { ComponentsListItem, removeComponents } from '../../lib/api/types/crate/createManagedControlPlane.ts';
1111
import { useTranslation } from 'react-i18next';
12+
import { ManagedControlPlaneTemplate } from '../../lib/api/types/templates/mcpTemplate.ts';
1213

1314
export interface ComponentsSelectionProps {
1415
componentsList: ComponentsListItem[];
1516
setComponentsList: (components: ComponentsListItem[]) => void;
17+
managedControlPlaneTemplate?: ManagedControlPlaneTemplate;
1618
initialSelection?: Record<string, { isSelected: boolean; version: string }>;
1719
}
1820

@@ -31,14 +33,27 @@ export const getSelectedComponents = (components: ComponentsListItem[]) => {
3133
});
3234
};
3335

36+
type TemplateDefaultComponent = {
37+
name: string;
38+
version: string;
39+
removable?: boolean;
40+
versionChangeable?: boolean;
41+
};
42+
3443
export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> = ({
3544
setComponentsList,
3645
componentsList,
46+
managedControlPlaneTemplate,
3747
initialSelection,
3848
}) => {
3949
const { data: availableManagedComponentsListData, error, isLoading } = useApiResource(ListManagedComponents());
4050
const { t } = useTranslation();
4151
const initialized = useRef(false);
52+
const [templateDefaultsError, setTemplateDefaultsError] = useState<string | null>(null);
53+
const defaultComponents = useMemo<TemplateDefaultComponent[]>(
54+
() => managedControlPlaneTemplate?.spec?.spec?.components?.defaultComponents ?? [],
55+
[managedControlPlaneTemplate],
56+
);
4257

4358
useEffect(() => {
4459
if (
@@ -49,37 +64,83 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
4964
return;
5065
}
5166

52-
let newComponentsList = availableManagedComponentsListData.items
67+
const newComponentsList = availableManagedComponentsListData.items
5368
.map((item) => {
5469
const versions = sortVersions(item.status.versions);
70+
const template = defaultComponents.find((dc) => dc.name === item.metadata.name);
71+
const templateVersion = template?.version;
72+
let selectedVersion = template
73+
? templateVersion && versions.includes(templateVersion)
74+
? templateVersion
75+
: ''
76+
: (versions[0] ?? '');
77+
let isSelected = !!template;
78+
79+
const initSel = initialSelection?.[item.metadata.name];
80+
if (initSel) {
81+
// Override selection and version from initial selection if provided
82+
isSelected = Boolean(initSel.isSelected);
83+
selectedVersion = initSel.version && versions.includes(initSel.version) ? initSel.version : '';
84+
}
5585
return {
5686
name: item.metadata.name,
5787
versions,
58-
selectedVersion: versions[0] ?? '',
59-
isSelected: false,
88+
selectedVersion,
89+
isSelected,
6090
documentationUrl: '',
6191
};
6292
})
6393
.filter((component) => !removeComponents.find((item) => item === component.name));
6494

65-
// Apply initial selection when provided (edit mode)
66-
if (initialSelection) {
67-
newComponentsList = newComponentsList.map((component) => {
68-
const init = initialSelection[component.name];
69-
if (!init) return component;
70-
// Ensure selectedVersion exists in versions list; if not, keep as-is
71-
const selectedVersion = component.versions.includes(init.version) ? init.version : component.selectedVersion;
72-
return {
73-
...component,
74-
isSelected: init.isSelected,
75-
selectedVersion,
76-
};
77-
});
78-
}
79-
8095
setComponentsList(newComponentsList);
8196
initialized.current = true;
82-
}, [availableManagedComponentsListData, setComponentsList, initialSelection]);
97+
}, [availableManagedComponentsListData, setComponentsList, defaultComponents, initialSelection]);
98+
99+
useEffect(() => {
100+
const items = availableManagedComponentsListData?.items ?? [];
101+
if (items.length === 0 || !defaultComponents.length) {
102+
setTemplateDefaultsError(null);
103+
return;
104+
}
105+
106+
const errs: string[] = [];
107+
defaultComponents.forEach((dc: TemplateDefaultComponent) => {
108+
if (!dc?.name) return;
109+
const item = items.find((it) => it.metadata.name === dc.name);
110+
if (!item) {
111+
errs.push(`Component "${dc.name}" from template is not available.`);
112+
return;
113+
}
114+
const versions: string[] = Array.isArray(item.status?.versions) ? item.status.versions : [];
115+
if (dc.version && !versions.includes(dc.version)) {
116+
errs.push(`Component "${dc.name}" version "${dc.version}" from template is not available.`);
117+
}
118+
});
119+
120+
setTemplateDefaultsError(errs.length ? errs.join('\n') : null);
121+
}, [availableManagedComponentsListData, defaultComponents]);
122+
123+
useEffect(() => {
124+
if (!initialized.current) return;
125+
if (!defaultComponents?.length) return;
126+
if (!componentsList?.length) return;
127+
// If initialSelection is provided, do not auto-apply template defaults
128+
if (initialSelection && Object.keys(initialSelection).length > 0) return;
129+
130+
const anySelected = componentsList.some((c) => c.isSelected);
131+
if (anySelected) return;
132+
133+
const updated = componentsList.map((c) => {
134+
const template = defaultComponents.find((dc) => dc.name === c.name);
135+
if (!template) return c;
136+
const templateVersion = template.version;
137+
const selectedVersion =
138+
templateVersion && Array.isArray(c.versions) && c.versions.includes(templateVersion) ? templateVersion : '';
139+
return { ...c, isSelected: true, selectedVersion };
140+
});
141+
142+
setComponentsList(updated);
143+
}, [defaultComponents, componentsList, setComponentsList]);
83144

84145
if (isLoading) {
85146
return <Loading />;
@@ -94,5 +155,11 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
94155
return <IllustratedError title={t('componentsSelection.cannotLoad')} compact={true} />;
95156
}
96157

97-
return <ComponentsSelection componentsList={componentsList} setComponentsList={setComponentsList} />;
158+
return (
159+
<ComponentsSelection
160+
componentsList={componentsList}
161+
setComponentsList={setComponentsList}
162+
templateDefaultsError={templateDefaultsError || undefined}
163+
/>
164+
);
98165
};

0 commit comments

Comments
 (0)