1- import React , { useEffect , useMemo , useRef , useState } from 'react' ;
1+ import React , { useEffect , useMemo , useState } from 'react' ;
22import { ComponentsSelection } from './ComponentsSelection.tsx' ;
33
44import IllustratedError from '../Shared/IllustratedError.tsx' ;
@@ -14,7 +14,11 @@ import { ManagedControlPlaneTemplate } from '../../lib/api/types/templates/mcpTe
1414export interface ComponentsSelectionProps {
1515 componentsList : ComponentsListItem [ ] ;
1616 setComponentsList : ( components : ComponentsListItem [ ] ) => void ;
17+ setInitialComponentsList : ( components : ComponentsListItem [ ] ) => void ;
1718 managedControlPlaneTemplate ?: ManagedControlPlaneTemplate ;
19+ initialSelection ?: Record < string , { isSelected : boolean ; version : string } > ;
20+ isOnMcpPage ?: boolean ;
21+ initializedComponents : React . RefObject < boolean > ;
1822}
1923
2024/**
@@ -25,9 +29,7 @@ export const getSelectedComponents = (components: ComponentsListItem[]) => {
2529 const isCrossplaneSelected = components . some ( ( { name, isSelected } ) => name === 'crossplane' && isSelected ) ;
2630 return components . filter ( ( component ) => {
2731 if ( ! component . isSelected ) return false ;
28- if ( component . name ?. includes ( 'provider' ) && ! isCrossplaneSelected ) {
29- return false ;
30- }
32+ if ( component . name ?. includes ( 'provider' ) && ! isCrossplaneSelected ) return false ;
3133 return true ;
3234 } ) ;
3335} ;
@@ -43,71 +45,112 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
4345 setComponentsList,
4446 componentsList,
4547 managedControlPlaneTemplate,
48+ initialSelection,
49+ isOnMcpPage,
50+ setInitialComponentsList,
51+ initializedComponents,
4652} ) => {
47- const { data : availableManagedComponentsListData , error, isLoading } = useApiResource ( ListManagedComponents ( ) ) ;
53+ const {
54+ data : availableManagedComponentsListData ,
55+ error,
56+ isLoading,
57+ } = useApiResource ( ListManagedComponents ( ) , undefined , ! ! isOnMcpPage ) ;
4858 const { t } = useTranslation ( ) ;
49- const initialized = useRef ( false ) ;
59+
5060 const [ templateDefaultsError , setTemplateDefaultsError ] = useState < string | null > ( null ) ;
5161 const defaultComponents = useMemo < TemplateDefaultComponent [ ] > (
5262 ( ) => managedControlPlaneTemplate ?. spec ?. spec ?. components ?. defaultComponents ?? [ ] ,
5363 [ managedControlPlaneTemplate ] ,
5464 ) ;
5565
5666 useEffect ( ( ) => {
57- const items = availableManagedComponentsListData ?. items ?? [ ] ;
58-
59- if ( ! items . length ) {
60- if ( ! initialized . current ) return ;
61- setTemplateDefaultsError ( null ) ;
67+ if (
68+ initializedComponents . current ||
69+ ! availableManagedComponentsListData ?. items ||
70+ availableManagedComponentsListData . items . length === 0
71+ ) {
6272 return ;
6373 }
6474
65- if ( ! initialized . current ) {
66- const newComponentsList = items
67- . map ( ( item ) => {
68- const versions = sortVersions ( item . status . versions ) ;
69- const template = defaultComponents . find ( ( dc ) => dc . name === item . metadata . name ) ;
70- const templateVersion = template ?. version ;
71- const selectedVersion = template
72- ? templateVersion && versions . includes ( templateVersion )
73- ? templateVersion
74- : ''
75- : ( versions [ 0 ] ?? '' ) ;
76- return {
77- name : item . metadata . name ,
78- versions,
79- selectedVersion,
80- isSelected : ! ! template ,
81- documentationUrl : '' ,
82- } ;
83- } )
84- . filter ( ( component ) => ! removeComponents . find ( ( item ) => item === component . name ) ) ;
85-
86- setComponentsList ( newComponentsList ) ;
87- initialized . current = true ;
88- }
75+ const newComponentsList = availableManagedComponentsListData . items
76+ . map ( ( item ) => {
77+ const versions = sortVersions ( item . status ?. versions ?? [ ] ) ;
78+ const template = defaultComponents . find ( ( dc ) => dc . name === ( item . metadata ?. name ?? '' ) ) ;
79+ const templateVersion = template ?. version ;
80+ let selectedVersion = template
81+ ? templateVersion && versions . includes ( templateVersion )
82+ ? templateVersion
83+ : ''
84+ : ( versions [ 0 ] ?? '' ) ;
85+ let isSelected = ! ! template ;
86+
87+ const initSel = initialSelection ?. [ item . metadata ?. name ?? '' ] ;
88+ if ( initSel ) {
89+ // Override selection and version from initial selection if provided
90+ isSelected = Boolean ( initSel . isSelected ) ;
91+ selectedVersion = initSel . version && versions . includes ( initSel . version ) ? initSel . version : '' ;
92+ }
93+ return {
94+ name : item . metadata ?. name ?? '' ,
95+ versions,
96+ selectedVersion,
97+ isSelected,
98+ documentationUrl : '' ,
99+ } ;
100+ } )
101+ . filter ( ( component ) => ! removeComponents . find ( ( item ) => item === component . name ) ) ;
102+ setInitialComponentsList ( newComponentsList ) ;
103+ setComponentsList ( newComponentsList ) ;
104+ initializedComponents . current = true ;
105+ // eslint-disable-next-line react-hooks/exhaustive-deps
106+ } , [ setComponentsList , defaultComponents , initialSelection , availableManagedComponentsListData ?. items ] ) ;
89107
90- if ( ! defaultComponents . length ) {
108+ useEffect ( ( ) => {
109+ const items = availableManagedComponentsListData ?. items ?? [ ] ;
110+ if ( items . length === 0 || ! defaultComponents . length ) {
91111 setTemplateDefaultsError ( null ) ;
92112 return ;
93113 }
94114
95115 const errors : string [ ] = [ ] ;
96116 defaultComponents . forEach ( ( dc : TemplateDefaultComponent ) => {
97117 if ( ! dc ?. name ) return ;
98- const item = items . find ( ( it ) => it . metadata . name === dc . name ) ;
118+ const item = items . find ( ( it ) => it . metadata ? .name === dc . name ) ;
99119 if ( ! item ) {
100120 errors . push ( `Component "${ dc . name } " from template is not available.` ) ;
101121 return ;
102122 }
103- const versions : string [ ] = Array . isArray ( item . status ?. versions ) ? item . status . versions : [ ] ;
123+ const versions : string [ ] = Array . isArray ( item . status ?. versions ) ? ( item . status ? .versions as string [ ] ) : [ ] ;
104124 if ( dc . version && ! versions . includes ( dc . version ) ) {
105125 errors . push ( `Component "${ dc . name } " version "${ dc . version } " from template is not available.` ) ;
106126 }
107127 } ) ;
108128
109129 setTemplateDefaultsError ( errors . length ? errors . join ( '\n' ) : null ) ;
110- } , [ availableManagedComponentsListData , defaultComponents , setComponentsList ] ) ;
130+ } , [ availableManagedComponentsListData , defaultComponents ] ) ;
131+
132+ useEffect ( ( ) => {
133+ if ( ! initializedComponents . current ) return ;
134+ if ( ! defaultComponents ?. length ) return ;
135+ if ( ! componentsList ?. length ) return ;
136+ // If initialSelection is provided, do not auto-apply template defaults
137+ if ( initialSelection && Object . keys ( initialSelection ) . length > 0 ) return ;
138+
139+ const anySelected = componentsList . some ( ( c ) => c . isSelected ) ;
140+ if ( anySelected ) return ;
141+
142+ const updated = componentsList . map ( ( c ) => {
143+ const template = defaultComponents . find ( ( dc ) => dc . name === c . name ) ;
144+ if ( ! template ) return c ;
145+ const templateVersion = template . version ;
146+ const selectedVersion =
147+ templateVersion && Array . isArray ( c . versions ) && c . versions . includes ( templateVersion ) ? templateVersion : '' ;
148+ return { ...c , isSelected : true , selectedVersion } ;
149+ } ) ;
150+
151+ setComponentsList ( updated ) ;
152+ // eslint-disable-next-line react-hooks/exhaustive-deps
153+ } , [ defaultComponents , componentsList , setComponentsList , initialSelection ] ) ;
111154
112155 if ( isLoading ) {
113156 return < Loading /> ;
@@ -117,7 +160,6 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
117160 return < IllustratedError compact = { true } /> ;
118161 }
119162
120- // Defensive: If the API returned no items, show error
121163 if ( ! componentsList || componentsList . length === 0 ) {
122164 return < IllustratedError title = { t ( 'componentsSelection.cannotLoad' ) } compact = { true } /> ;
123165 }
0 commit comments