@openshift-assisted/ui-lib 2.53.0 → 2.54.0

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.
Files changed (202) hide show
  1. package/build/@types/cim/components/ClusterDeployment/clusterDetails/ACMClusterDeploymentDetailsStep.d.ts.map +1 -1
  2. package/build/@types/cim/components/ClusterDeployment/clusterDetails/ClusterDeploymentDetailsStep.d.ts +0 -17
  3. package/build/@types/cim/components/ClusterDeployment/clusterDetails/ClusterDeploymentDetailsStep.d.ts.map +1 -1
  4. package/build/@types/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.d.ts.map +1 -1
  5. package/build/@types/cim/components/ClusterDeployment/clusterDetails/useDetailsFormik.d.ts +19 -0
  6. package/build/@types/cim/components/ClusterDeployment/clusterDetails/useDetailsFormik.d.ts.map +1 -0
  7. package/build/@types/cim/components/common/CpuArchitectureDropdown.d.ts.map +1 -1
  8. package/build/@types/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.d.ts +2 -1
  9. package/build/@types/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.d.ts.map +1 -1
  10. package/build/@types/common/components/clusterConfiguration/ExternalPlatformsDropdown.d.ts.map +1 -1
  11. package/build/@types/common/components/clusterWizard/ReviewValidations.d.ts.map +1 -1
  12. package/build/@types/common/components/clusterWizard/clusterDetailsValidation.d.ts.map +1 -1
  13. package/build/@types/common/components/clusterWizard/validationsInfoUtils.d.ts +0 -1
  14. package/build/@types/common/components/clusterWizard/validationsInfoUtils.d.ts.map +1 -1
  15. package/build/@types/common/components/hosts/HostsTable.d.ts.map +1 -1
  16. package/build/@types/common/components/ui/WizardFooter.d.ts +0 -1
  17. package/build/@types/common/components/ui/WizardFooter.d.ts.map +1 -1
  18. package/build/@types/common/selectors/clusterSelectors.d.ts +0 -1
  19. package/build/@types/common/selectors/clusterSelectors.d.ts.map +1 -1
  20. package/build/@types/common/types/clusters.d.ts +2 -2
  21. package/build/@types/common/types/clusters.d.ts.map +1 -1
  22. package/build/@types/ocm/components/clusterConfiguration/DiscoveryImageForm.d.ts.map +1 -1
  23. package/build/@types/ocm/components/clusterConfiguration/DiscoveryImageModal.d.ts +0 -1
  24. package/build/@types/ocm/components/clusterConfiguration/DiscoveryImageModal.d.ts.map +1 -1
  25. package/build/@types/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.d.ts.map +1 -1
  26. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.d.ts.map +1 -1
  27. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/components/CustomManifestsForm.d.ts.map +1 -1
  28. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/components/utils.d.ts +4 -0
  29. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/components/utils.d.ts.map +1 -1
  30. package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.d.ts.map +1 -1
  31. package/build/@types/ocm/components/clusterConfiguration/operators/OperatorCheckbox.d.ts.map +1 -1
  32. package/build/@types/ocm/components/clusterConfiguration/operators/bundleSpecs.d.ts.map +1 -1
  33. package/build/@types/ocm/components/clusterConfiguration/operators/utils.d.ts +2 -2
  34. package/build/@types/ocm/components/clusterConfiguration/operators/utils.d.ts.map +1 -1
  35. package/build/@types/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.d.ts.map +1 -1
  36. package/build/@types/ocm/components/clusterConfiguration/review/ReviewSummary.d.ts.map +1 -1
  37. package/build/@types/ocm/components/clusterConfiguration/review/TableSummaryExpandable.d.ts +1 -0
  38. package/build/@types/ocm/components/clusterConfiguration/review/TableSummaryExpandable.d.ts.map +1 -1
  39. package/build/@types/ocm/components/clusterConfiguration/staticIp/components/StaticIpForm.d.ts.map +1 -1
  40. package/build/@types/ocm/components/clusterConfiguration/staticIp/components/StaticIpPage.d.ts.map +1 -1
  41. package/build/@types/ocm/components/clusterWizard/ClusterDetails.d.ts.map +1 -1
  42. package/build/@types/ocm/components/clusterWizard/ClusterWizardContextProvider.d.ts.map +1 -1
  43. package/build/@types/ocm/components/clusterWizard/HostDiscovery.d.ts.map +1 -1
  44. package/build/@types/ocm/components/clusterWizard/NewClusterWizard.d.ts.map +1 -1
  45. package/build/@types/ocm/components/clusterWizard/Operators.d.ts.map +1 -1
  46. package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts +3 -3
  47. package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts.map +1 -1
  48. package/build/@types/ocm/components/clusterWizard/OptionalOperatorsDropdown.d.ts +13 -0
  49. package/build/@types/ocm/components/clusterWizard/OptionalOperatorsDropdown.d.ts.map +1 -0
  50. package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts +2 -3
  51. package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts.map +1 -1
  52. package/build/@types/ocm/components/clusters/ClustersListToolbar.d.ts +1 -2
  53. package/build/@types/ocm/components/clusters/ClustersListToolbar.d.ts.map +1 -1
  54. package/build/@types/ocm/components/hosts/HostsTableEmptyState.d.ts.map +1 -1
  55. package/build/@types/ocm/services/InfraEnvsService.d.ts.map +1 -1
  56. package/build/@types/ocm/store/slices/current-cluster/slice.d.ts +2 -0
  57. package/build/@types/ocm/store/slices/current-cluster/slice.d.ts.map +1 -1
  58. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ACMClusterDeploymentDetailsStep.js +4 -2
  59. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ACMClusterDeploymentDetailsStep.js.map +1 -1
  60. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ClusterDeploymentDetailsStep.js +5 -31
  61. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ClusterDeploymentDetailsStep.js.map +1 -1
  62. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.js +1 -11
  63. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.js.map +1 -1
  64. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/useDetailsFormik.js +41 -0
  65. package/build/cjs/cim/components/ClusterDeployment/clusterDetails/useDetailsFormik.js.map +1 -0
  66. package/build/cjs/cim/components/common/CpuArchitectureDropdown.js +1 -1
  67. package/build/cjs/cim/components/common/CpuArchitectureDropdown.js.map +1 -1
  68. package/build/cjs/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.js +9 -3
  69. package/build/cjs/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.js.map +1 -1
  70. package/build/cjs/common/components/clusterConfiguration/ExternalPlatformsDropdown.js +1 -1
  71. package/build/cjs/common/components/clusterConfiguration/ExternalPlatformsDropdown.js.map +1 -1
  72. package/build/cjs/common/components/clusterWizard/ReviewValidations.js +16 -0
  73. package/build/cjs/common/components/clusterWizard/ReviewValidations.js.map +1 -1
  74. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js +34 -19
  75. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js.map +1 -1
  76. package/build/cjs/common/components/clusterWizard/networkingSteps/ManagedNetworkingControlGroup.js +3 -3
  77. package/build/cjs/common/components/clusterWizard/validationsInfoUtils.js +1 -17
  78. package/build/cjs/common/components/clusterWizard/validationsInfoUtils.js.map +1 -1
  79. package/build/cjs/common/components/hosts/HostsTable.js +1 -2
  80. package/build/cjs/common/components/hosts/HostsTable.js.map +1 -1
  81. package/build/cjs/common/components/ui/WizardFooter.js +1 -6
  82. package/build/cjs/common/components/ui/WizardFooter.js.map +1 -1
  83. package/build/cjs/common/selectors/clusterSelectors.js +2 -8
  84. package/build/cjs/common/selectors/clusterSelectors.js.map +1 -1
  85. package/build/cjs/common/types/clusters.js.map +1 -1
  86. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageForm.js +5 -2
  87. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageForm.js.map +1 -1
  88. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageModal.js +2 -2
  89. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageModal.js.map +1 -1
  90. package/build/cjs/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.js +6 -2
  91. package/build/cjs/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.js.map +1 -1
  92. package/build/cjs/ocm/components/clusterConfiguration/OcmDiscoveryImageConfigForm.js +1 -1
  93. package/build/cjs/ocm/components/clusterConfiguration/OcmDiscoveryImageConfigForm.js.map +1 -1
  94. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.js +3 -1
  95. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.js.map +1 -1
  96. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/CustomManifestsForm.js +3 -1
  97. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/CustomManifestsForm.js.map +1 -1
  98. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/utils.js +11 -8
  99. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/utils.js.map +1 -1
  100. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js +5 -6
  101. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js.map +1 -1
  102. package/build/cjs/ocm/components/clusterConfiguration/operators/OperatorCheckbox.js +33 -13
  103. package/build/cjs/ocm/components/clusterConfiguration/operators/OperatorCheckbox.js.map +1 -1
  104. package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js +1 -2
  105. package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js.map +1 -1
  106. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js +3 -3
  107. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js.map +1 -1
  108. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.js +75 -20
  109. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.js.map +1 -1
  110. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewSummary.js +2 -2
  111. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewSummary.js.map +1 -1
  112. package/build/cjs/ocm/components/clusterConfiguration/review/TableSummaryExpandable.css +3 -0
  113. package/build/cjs/ocm/components/clusterConfiguration/review/TableSummaryExpandable.js +2 -3
  114. package/build/cjs/ocm/components/clusterConfiguration/review/TableSummaryExpandable.js.map +1 -1
  115. package/build/cjs/ocm/components/clusterConfiguration/review/utils.js +1 -1
  116. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/StaticIpForm.js +10 -1
  117. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/StaticIpForm.js.map +1 -1
  118. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/StaticIpPage.js +5 -5
  119. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/StaticIpPage.js.map +1 -1
  120. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js +2 -9
  121. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js.map +1 -1
  122. package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js +4 -4
  123. package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js.map +1 -1
  124. package/build/cjs/ocm/components/clusterWizard/HostDiscovery.js +1 -4
  125. package/build/cjs/ocm/components/clusterWizard/HostDiscovery.js.map +1 -1
  126. package/build/cjs/ocm/components/clusterWizard/NewClusterWizard.js +6 -3
  127. package/build/cjs/ocm/components/clusterWizard/NewClusterWizard.js.map +1 -1
  128. package/build/cjs/ocm/components/clusterWizard/Operators.js +36 -8
  129. package/build/cjs/ocm/components/clusterWizard/Operators.js.map +1 -1
  130. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js +34 -15
  131. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js.map +1 -1
  132. package/build/cjs/ocm/components/clusterWizard/OperatorsSelect.test.js +11 -5
  133. package/build/cjs/ocm/components/clusterWizard/OperatorsSelect.test.js.map +1 -1
  134. package/build/cjs/ocm/components/clusterWizard/OperatorsStep.js +1 -1
  135. package/build/cjs/ocm/components/clusterWizard/OperatorsStep.js.map +1 -1
  136. package/build/cjs/ocm/components/clusterWizard/OptionalOperatorsDropdown.js +34 -0
  137. package/build/cjs/ocm/components/clusterWizard/OptionalOperatorsDropdown.js.map +1 -0
  138. package/build/cjs/ocm/components/clusterWizard/wizardTransition.js +67 -28
  139. package/build/cjs/ocm/components/clusterWizard/wizardTransition.js.map +1 -1
  140. package/build/cjs/ocm/components/clusters/ClustersListToolbar.js +2 -2
  141. package/build/cjs/ocm/components/clusters/ClustersListToolbar.js.map +1 -1
  142. package/build/cjs/ocm/components/clusters/ClustersTable.js +1 -1
  143. package/build/cjs/ocm/components/clusters/ClustersTable.js.map +1 -1
  144. package/build/cjs/ocm/components/featureSupportLevels/featureStateUtils.js +1 -1
  145. package/build/cjs/ocm/components/hosts/HostsTableEmptyState.js +1 -2
  146. package/build/cjs/ocm/components/hosts/HostsTableEmptyState.js.map +1 -1
  147. package/build/cjs/ocm/hooks/useInfraEnvId.js +2 -2
  148. package/build/cjs/ocm/hooks/useInfraEnvId.js.map +1 -1
  149. package/build/cjs/ocm/services/InfraEnvsService.js +4 -1
  150. package/build/cjs/ocm/services/InfraEnvsService.js.map +1 -1
  151. package/lib/cim/components/ClusterDeployment/clusterDetails/ACMClusterDeploymentDetailsStep.tsx +3 -1
  152. package/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDeploymentDetailsStep.tsx +5 -86
  153. package/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.tsx +1 -12
  154. package/lib/cim/components/ClusterDeployment/clusterDetails/useDetailsFormik.tsx +97 -0
  155. package/lib/cim/components/common/CpuArchitectureDropdown.tsx +2 -1
  156. package/lib/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.tsx +18 -8
  157. package/lib/common/components/clusterConfiguration/ExternalPlatformsDropdown.tsx +3 -1
  158. package/lib/common/components/clusterWizard/ReviewValidations.tsx +24 -0
  159. package/lib/common/components/clusterWizard/clusterDetailsValidation.ts +38 -12
  160. package/lib/common/components/clusterWizard/networkingSteps/ManagedNetworkingControlGroup.tsx +3 -3
  161. package/lib/common/components/clusterWizard/validationsInfoUtils.ts +0 -20
  162. package/lib/common/components/hosts/HostsTable.tsx +0 -2
  163. package/lib/common/components/ui/WizardFooter.tsx +0 -10
  164. package/lib/common/selectors/clusterSelectors.ts +2 -9
  165. package/lib/common/types/clusters.ts +3 -1
  166. package/lib/ocm/components/clusterConfiguration/DiscoveryImageForm.tsx +11 -2
  167. package/lib/ocm/components/clusterConfiguration/DiscoveryImageModal.tsx +13 -3
  168. package/lib/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.tsx +9 -1
  169. package/lib/ocm/components/clusterConfiguration/OcmDiscoveryImageConfigForm.tsx +1 -1
  170. package/lib/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.tsx +8 -1
  171. package/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/CustomManifestsForm.tsx +3 -1
  172. package/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/utils.tsx +12 -6
  173. package/lib/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.tsx +7 -9
  174. package/lib/ocm/components/clusterConfiguration/operators/OperatorCheckbox.tsx +37 -17
  175. package/lib/ocm/components/clusterConfiguration/operators/bundleSpecs.tsx +2 -3
  176. package/lib/ocm/components/clusterConfiguration/operators/utils.tsx +5 -4
  177. package/lib/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.tsx +114 -24
  178. package/lib/ocm/components/clusterConfiguration/review/ReviewSummary.tsx +1 -4
  179. package/lib/ocm/components/clusterConfiguration/review/TableSummaryExpandable.css +3 -0
  180. package/lib/ocm/components/clusterConfiguration/review/TableSummaryExpandable.tsx +1 -1
  181. package/lib/ocm/components/clusterConfiguration/review/utils.tsx +1 -1
  182. package/lib/ocm/components/clusterConfiguration/staticIp/components/StaticIpForm.tsx +10 -1
  183. package/lib/ocm/components/clusterConfiguration/staticIp/components/StaticIpPage.tsx +9 -6
  184. package/lib/ocm/components/clusterWizard/ClusterDetails.tsx +2 -14
  185. package/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx +5 -13
  186. package/lib/ocm/components/clusterWizard/HostDiscovery.tsx +0 -4
  187. package/lib/ocm/components/clusterWizard/NewClusterWizard.tsx +7 -3
  188. package/lib/ocm/components/clusterWizard/Operators.tsx +45 -10
  189. package/lib/ocm/components/clusterWizard/OperatorsBundle.tsx +72 -26
  190. package/lib/ocm/components/clusterWizard/OperatorsSelect.test.ts +11 -5
  191. package/lib/ocm/components/clusterWizard/OperatorsStep.tsx +1 -1
  192. package/lib/ocm/components/clusterWizard/OptionalOperatorsDropdown.tsx +106 -0
  193. package/lib/ocm/components/clusterWizard/wizardTransition.ts +90 -36
  194. package/lib/ocm/components/clusters/ClustersListToolbar.tsx +3 -5
  195. package/lib/ocm/components/clusters/ClustersTable.tsx +1 -1
  196. package/lib/ocm/components/featureSupportLevels/featureStateUtils.ts +1 -1
  197. package/lib/ocm/components/hosts/HostsTableEmptyState.tsx +0 -2
  198. package/lib/ocm/hooks/useInfraEnvId.ts +2 -2
  199. package/lib/ocm/services/InfraEnvsService.ts +4 -1
  200. package/package.json +11 -11
  201. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageModal.css +0 -3
  202. package/lib/ocm/components/clusterConfiguration/DiscoveryImageModal.css +0 -3
@@ -24,7 +24,6 @@ import {
24
24
  UISettingService,
25
25
  } from '../../services';
26
26
  import { Cluster, InfraEnv } from '@openshift-assisted/types/assisted-installer-service';
27
- import BundleService from '../../services/BundleService';
28
27
  import { useFeature } from '../../hooks/use-feature';
29
28
 
30
29
  type ClusterDetailsProps = {
@@ -80,21 +79,10 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => {
80
79
  try {
81
80
  const searchParams = new URLSearchParams(location.search);
82
81
  const isAssistedMigration = searchParams.get('source') === 'assisted_migration';
83
- //For Assisted Migration we need the LVMs operator and also the virtualization bundle operators
82
+ // For Assisted Migration we need LVM as standalone and the virtualization bundle.
84
83
  if (isAssistedMigration) {
85
84
  params.olmOperators = [{ name: 'lvm' }];
86
- const selectedBundle = (
87
- await BundleService.listBundles(
88
- params.openshiftVersion,
89
- params.cpuArchitecture,
90
- params.platform?.type,
91
- )
92
- ).find((b) => b.id === 'virtualization');
93
- const virtOperators = selectedBundle?.operators;
94
- params.olmOperators = [
95
- ...params.olmOperators,
96
- ...(virtOperators ? virtOperators.map((op) => ({ name: op })) : []),
97
- ];
85
+ params.operatorBundles = [{ id: 'virtualization', optionalOperators: [] }];
98
86
  }
99
87
  const cluster = await ClustersService.create(
100
88
  params,
@@ -66,8 +66,8 @@ const getWizardStepIds = (
66
66
  stepsCopy = removeStepFromClusterWizard(stepsCopy, 'static-ip-network-wide-configurations', 2);
67
67
  }
68
68
 
69
- if (isSingleClusterFeatureEnabled) {
70
- stepsCopy = addStepToClusterWizard(stepsCopy, 'networking', ['credentials-download']);
69
+ if (isSingleClusterFeatureEnabled && !stepsCopy.includes('credentials-download')) {
70
+ stepsCopy = addStepToClusterWizard(stepsCopy, 'custom-manifests', ['credentials-download']);
71
71
  }
72
72
 
73
73
  return stepsCopy;
@@ -116,13 +116,11 @@ const ClusterWizardContextProvider = ({
116
116
  locationState,
117
117
  staticIpInfo,
118
118
  cluster?.status,
119
- cluster?.hosts,
120
- customManifestsStepNeedsToBeFilled,
119
+ cluster,
121
120
  );
122
121
  const firstStepIds = getWizardStepIds(
123
122
  wizardStepIds,
124
123
  staticIpInfo?.view,
125
-
126
124
  isSingleClusterFeatureEnabled,
127
125
  );
128
126
 
@@ -150,7 +148,7 @@ const ClusterWizardContextProvider = ({
150
148
  }
151
149
 
152
150
  // eslint-disable-next-line react-hooks/exhaustive-deps
153
- }, [uiSettings, UISettingsLoading, UISettingsError]);
151
+ }, [uiSettings, UISettingsLoading, UISettingsError, isSingleClusterFeatureEnabled]);
154
152
 
155
153
  const contextValue = React.useMemo<ClusterWizardContextType | null>(() => {
156
154
  if (!wizardStepIds || !currentStepId) {
@@ -167,7 +165,6 @@ const ClusterWizardContextProvider = ({
167
165
  const newStepIds = getWizardStepIds(
168
166
  wizardStepIds,
169
167
  staticIpInfo.view,
170
-
171
168
  isSingleClusterFeatureEnabled,
172
169
  );
173
170
  setWizardStepIds(newStepIds);
@@ -207,12 +204,7 @@ const ClusterWizardContextProvider = ({
207
204
  onUpdateHostNetworkConfigType(type: HostsNetworkConfigurationType): void {
208
205
  if (type === HostsNetworkConfigurationType.STATIC) {
209
206
  setWizardStepIds(
210
- getWizardStepIds(
211
- wizardStepIds,
212
- StaticIpView.FORM,
213
-
214
- isSingleClusterFeatureEnabled,
215
- ),
207
+ getWizardStepIds(wizardStepIds, StaticIpView.FORM, isSingleClusterFeatureEnabled),
216
208
  );
217
209
  } else {
218
210
  setWizardStepIds(
@@ -32,7 +32,6 @@ const HostDiscoveryForm = ({ cluster }: { cluster: Cluster }) => {
32
32
  const errorFields = getFormikErrorFields(errors, touched);
33
33
  const isBinding = useLateBinding(cluster);
34
34
 
35
- const hasHosts = (cluster.hosts?.length ?? 0) > 0;
36
35
  const isNextDisabled =
37
36
  !isValid ||
38
37
  !!alerts.length ||
@@ -41,15 +40,12 @@ const HostDiscoveryForm = ({ cluster }: { cluster: Cluster }) => {
41
40
  isBinding ||
42
41
  !canNextHostDiscovery({ cluster });
43
42
 
44
- const isWaitingForHosts = hasHosts && (isBinding || !canNextHostDiscovery({ cluster }));
45
-
46
43
  const footer = (
47
44
  <ClusterWizardFooter
48
45
  cluster={cluster}
49
46
  errorFields={errorFields}
50
47
  isSubmitting={isSubmitting}
51
48
  isNextDisabled={isNextDisabled}
52
- isWaitingForHosts={isWaitingForHosts}
53
49
  onNext={() => clusterWizardContext.moveNext()}
54
50
  onBack={() => clusterWizardContext.moveBack()}
55
51
  isBackDisabled={isSubmitting || isAutoSaveRunning}
@@ -5,24 +5,28 @@ import { useClusterWizardContext } from './ClusterWizardContext';
5
5
  import ReviewStep from './disconnected/ReviewStep';
6
6
  import BasicStep from './disconnected/BasicStep';
7
7
  import { ClusterWizardStepsType } from './wizardTransition';
8
+ import { useInfraEnv } from '../../hooks';
9
+ import { CpuArchitecture } from '../../../common/types';
10
+ import { InfraEnv } from '@openshift-assisted/types/assisted-installer-service';
8
11
 
9
- const getCurrentStep = (currentStepId: ClusterWizardStepsType) => {
12
+ const getCurrentStep = (currentStepId: ClusterWizardStepsType, infraEnv?: InfraEnv) => {
10
13
  switch (currentStepId) {
11
14
  case 'disconnected-review':
12
15
  return <ReviewStep />;
13
16
  case 'disconnected-basic':
14
17
  return <BasicStep />;
15
18
  default:
16
- return <ClusterDetails />;
19
+ return <ClusterDetails infraEnv={infraEnv} />;
17
20
  }
18
21
  };
19
22
 
20
23
  const NewClusterWizard: React.FC = () => {
24
+ const { infraEnv } = useInfraEnv('', CpuArchitecture.USE_DAY1_ARCHITECTURE);
21
25
  const { currentStepId } = useClusterWizardContext();
22
26
 
23
27
  return (
24
28
  <div className={classNames('pf-v6-c-wizard', 'cluster-wizard')}>
25
- {getCurrentStep(currentStepId)}
29
+ {getCurrentStep(currentStepId, infraEnv)}
26
30
  </div>
27
31
  );
28
32
  };
@@ -29,9 +29,31 @@ const getOperatorsInitialValues = (
29
29
  uiSettings: UISettingsValues | undefined,
30
30
  cluster: Cluster,
31
31
  ): OperatorsValues => {
32
+ const olmOperators = selectOlmOperators(cluster);
33
+ const selectedOperators = olmOperators
34
+ .filter((operator) => operator.name && !operator.sourceBundles?.length)
35
+ .map(({ name }) => name as string);
36
+
37
+ const selectedBundlesFromOperatorBundles = (cluster.operatorBundles || []).map(
38
+ ({ id, optionalOperators }) => ({
39
+ id,
40
+ optionalOperators: optionalOperators || [],
41
+ }),
42
+ );
43
+
44
+ // Backward compatibility: old clusters can miss `operatorBundles`.
45
+ const selectedBundlesFromUiSettings = (uiSettings?.bundlesSelected || []).map((id) => ({
46
+ id,
47
+ optionalOperators: [],
48
+ }));
49
+
50
+ const selectedBundles = !!cluster.operatorBundles?.length
51
+ ? selectedBundlesFromOperatorBundles
52
+ : selectedBundlesFromUiSettings;
53
+
32
54
  return {
33
- selectedBundles: uiSettings?.bundlesSelected || [],
34
- selectedOperators: selectOlmOperators(cluster).map((o) => o.name || ''),
55
+ selectedBundles,
56
+ selectedOperators,
35
57
  };
36
58
  };
37
59
 
@@ -81,22 +103,35 @@ const Operators = ({ cluster }: { cluster: Cluster }) => {
81
103
  const dispatch = useDispatch();
82
104
  const { updateUISettings, uiSettings } = useClusterWizardContext();
83
105
  const { addAlert, clearAlerts } = useAlerts();
106
+ const initialValues = React.useMemo(
107
+ () => getOperatorsInitialValues(uiSettings, cluster),
108
+ [cluster, uiSettings],
109
+ );
84
110
 
85
111
  const handleSubmit: FormikConfig<OperatorsValues>['onSubmit'] = async (values) => {
86
112
  clearAlerts();
87
113
 
88
- const enabledOperators = values.selectedOperators.map((so) => ({
89
- name: so,
90
- }));
91
-
92
114
  try {
93
115
  const { data: updatedCluster } = await ClustersService.update(cluster.id, cluster.tags, {
94
- olmOperators: enabledOperators,
116
+ operatorBundles: values.selectedBundles,
117
+ olmOperators: values.selectedOperators.map((name) => ({ name })),
95
118
  });
96
119
 
97
- await updateUISettings({ bundlesSelected: values.selectedBundles });
98
-
99
120
  dispatch(updateCluster(updatedCluster));
121
+
122
+ // Backward compatibility: old clusters used uiSettings.bundlesSelected, keep operatorBundles as source of truth.
123
+ if (uiSettings?.bundlesSelected?.length) {
124
+ try {
125
+ await updateUISettings({ bundlesSelected: undefined });
126
+ } catch (uiSettingsError) {
127
+ handleApiError(uiSettingsError, () =>
128
+ addAlert({
129
+ title: 'Failed to update UI settings',
130
+ message: getApiErrorMessage(uiSettingsError),
131
+ }),
132
+ );
133
+ }
134
+ }
100
135
  } catch (e) {
101
136
  handleApiError(e, () =>
102
137
  addAlert({ title: 'Failed to update the cluster', message: getApiErrorMessage(e) }),
@@ -108,7 +143,7 @@ const Operators = ({ cluster }: { cluster: Cluster }) => {
108
143
  };
109
144
 
110
145
  return (
111
- <Formik initialValues={getOperatorsInitialValues(uiSettings, cluster)} onSubmit={handleSubmit}>
146
+ <Formik initialValues={initialValues} onSubmit={handleSubmit}>
112
147
  <OperatorsForm cluster={cluster} />
113
148
  </Formik>
114
149
  );
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import {
3
+ Alert,
3
4
  Card,
4
5
  CardBody,
5
6
  CardHeader,
@@ -13,21 +14,24 @@ import {
13
14
  Title,
14
15
  Tooltip,
15
16
  } from '@patternfly/react-core';
17
+ import { Bundle, Cluster } from '@openshift-assisted/types/assisted-installer-service';
16
18
  import {
17
- Bundle,
18
- PreflightHardwareRequirements,
19
- } from '@openshift-assisted/types/assisted-installer-service';
20
- import { ExternalLink, OperatorsValues, PopoverIcon, singleClusterBundles } from '../../../common';
19
+ ExternalLink,
20
+ OperatorsValues,
21
+ PopoverIcon,
22
+ selectClusterValidationsInfo,
23
+ singleClusterBundles,
24
+ } from '../../../common';
21
25
  import { useFormikContext } from 'formik';
22
26
  import { useNewFeatureSupportLevel } from '../../../common/components/newFeatureSupportLevels';
23
27
  import { useFeature } from '../../hooks/use-feature';
24
- import { getNewBundleOperators } from '../clusterConfiguration/operators/utils';
25
28
  import { bundleSpecs } from '../clusterConfiguration/operators/bundleSpecs';
26
29
  import {
27
30
  highlightMatch,
28
31
  useOperatorSpecs,
29
32
  } from '../../../common/components/operators/operatorSpecs';
30
33
  import { useClusterWizardContext } from './ClusterWizardContext';
34
+ import OptionalOperatorsDropdown from './OptionalOperatorsDropdown';
31
35
  import './OperatorsBundle.css';
32
36
 
33
37
  const BundleLabel = ({ bundle, searchTerm }: { bundle: Bundle; searchTerm?: string }) => {
@@ -73,13 +77,13 @@ const BundleLabel = ({ bundle, searchTerm }: { bundle: Bundle; searchTerm?: stri
73
77
  const BundleCard = ({
74
78
  bundle,
75
79
  bundles,
76
- preflightRequirements,
77
80
  searchTerm,
81
+ informationalMessage,
78
82
  }: {
79
83
  bundle: Bundle;
80
84
  bundles: Bundle[];
81
- preflightRequirements: PreflightHardwareRequirements | undefined;
82
85
  searchTerm?: string;
86
+ informationalMessage?: string;
83
87
  }) => {
84
88
  const { values, setFieldValue } = useFormikContext<OperatorsValues>();
85
89
  const { isFeatureSupported } = useNewFeatureSupportLevel();
@@ -97,7 +101,7 @@ const BundleCard = ({
97
101
  const bundleSpec = bundleSpecs[bundle.id || ''];
98
102
 
99
103
  const incompatibleBundle = bundleSpec?.incompatibleBundles?.find((b) =>
100
- values.selectedBundles.includes(b),
104
+ values.selectedBundles.some((bundleSelection) => bundleSelection.id === b),
101
105
  );
102
106
  const isAssistedMigration = uiSettings?.isAssistedMigration;
103
107
  const disabledReason = hasUnsupportedOperators
@@ -112,23 +116,30 @@ const BundleCard = ({
112
116
  ? 'This bundle is not available for the current configuration, you might be able to use the standalone operators instead.'
113
117
  : undefined;
114
118
 
119
+ const addBundle = (
120
+ selectedBundles: OperatorsValues['selectedBundles'],
121
+ bundle: Bundle,
122
+ ): OperatorsValues['selectedBundles'] => [
123
+ ...selectedBundles,
124
+ { id: bundle.id || '', optionalOperators: bundle.optionalOperators || [] },
125
+ ];
126
+
127
+ const removeBundle = (
128
+ selectedBundles: OperatorsValues['selectedBundles'],
129
+ bundleId: Bundle['id'],
130
+ ): OperatorsValues['selectedBundles'] =>
131
+ selectedBundles.filter((selectedBundle) => selectedBundle.id !== bundleId);
132
+
115
133
  const onSelect = (checked: boolean) => {
116
- const newBundles = checked
117
- ? [...values.selectedBundles, bundle.id || '']
118
- : values.selectedBundles.filter((sb) => sb !== bundle.id);
119
- setFieldValue('selectedBundles', newBundles);
120
- const newOperators = getNewBundleOperators(
121
- values.selectedOperators,
122
- newBundles,
123
- bundles,
124
- bundle,
125
- preflightRequirements,
126
- checked,
127
- );
128
- setFieldValue('selectedOperators', newOperators);
134
+ const nextBundles = checked
135
+ ? addBundle(values.selectedBundles, bundle)
136
+ : removeBundle(values.selectedBundles, bundle.id);
137
+ setFieldValue('selectedBundles', nextBundles);
129
138
  };
130
139
 
131
- const isSelected = values.selectedBundles.includes(bundle.id || '');
140
+ const isSelected = values.selectedBundles.some(
141
+ (selectedBundle) => selectedBundle.id === bundle.id,
142
+ );
132
143
  const checkboxId = `bundle-${bundle.id || ''}`;
133
144
  return (
134
145
  <Tooltip content={disabledReason} hidden={!disabledReason}>
@@ -145,7 +156,7 @@ const BundleCard = ({
145
156
  selectableActionId: checkboxId,
146
157
  selectableActionAriaLabelledby: checkboxId,
147
158
  name: checkboxId,
148
- onChange: (_, checked) => onSelect(checked),
159
+ onChange: (_, checked) => onSelect(!!checked),
149
160
  isChecked: isSelected,
150
161
  }}
151
162
  >
@@ -158,6 +169,25 @@ const BundleCard = ({
158
169
  <StackItem isFilled>
159
170
  <div>{highlightMatch(bundle.description || '', searchTerm)}</div>
160
171
  </StackItem>
172
+ {!!bundle.optionalOperators?.length && (
173
+ <StackItem onClick={(e) => e.stopPropagation()}>
174
+ <OptionalOperatorsDropdown
175
+ bundleId={bundle.id || ''}
176
+ optionalOperatorIds={bundle.optionalOperators}
177
+ selectedBundles={values.selectedBundles}
178
+ setSelectedBundles={(selectedBundles) =>
179
+ setFieldValue('selectedBundles', selectedBundles)
180
+ }
181
+ isDisabled={!isSelected || !!disabledReason}
182
+ getOperatorLabel={(operatorId) => opSpecs[operatorId]?.title || operatorId}
183
+ />
184
+ </StackItem>
185
+ )}
186
+ {informationalMessage && (
187
+ <StackItem>
188
+ <Alert isInline variant="info" title={informationalMessage} />
189
+ </StackItem>
190
+ )}
161
191
  </Stack>
162
192
  </CardBody>
163
193
  </Card>
@@ -168,15 +198,29 @@ const BundleCard = ({
168
198
  const OperatorsBundle = ({
169
199
  bundles,
170
200
  allBundles,
171
- preflightRequirements,
172
201
  searchTerm,
202
+ cluster,
173
203
  }: {
174
204
  bundles: Bundle[];
175
205
  allBundles: Bundle[];
176
- preflightRequirements: PreflightHardwareRequirements | undefined;
177
206
  searchTerm?: string;
207
+ cluster: Cluster;
178
208
  }) => {
179
209
  const isSingleClusterFeatureEnabled = useFeature('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
210
+ const openshiftAiGpuInfoMessage = React.useMemo(() => {
211
+ const validationsInfo = selectClusterValidationsInfo(cluster);
212
+ if (!validationsInfo) {
213
+ return undefined;
214
+ }
215
+ return Object.values(validationsInfo)
216
+ .flat()
217
+ .find(
218
+ (validation) =>
219
+ validation?.id === 'openshift-ai-gpu-requirements-satisfied' &&
220
+ validation?.status === 'success' &&
221
+ !!validation.message,
222
+ )?.message;
223
+ }, [cluster]);
180
224
 
181
225
  return (
182
226
  <Stack hasGutter>
@@ -195,8 +239,10 @@ const OperatorsBundle = ({
195
239
  <BundleCard
196
240
  bundle={bundles.find((b) => b.id === bundle.id) || bundle}
197
241
  bundles={bundles}
198
- preflightRequirements={preflightRequirements}
199
242
  searchTerm={searchTerm}
243
+ informationalMessage={
244
+ bundle.id === 'openshift-ai' ? openshiftAiGpuInfoMessage : undefined
245
+ }
200
246
  />
201
247
  </GalleryItem>
202
248
  ))}
@@ -10,7 +10,7 @@ function calculateSelectedOperators(
10
10
  ): string[] {
11
11
  // Calculate all selected operators (direct selections + bundle selections)
12
12
  const bundleOperators = values.selectedBundles.flatMap(
13
- (bundleId) => bundles.find((b) => b.id === bundleId)?.operators || [],
13
+ (bundle) => bundles.find((b) => b.id === bundle.id)?.operators || [],
14
14
  );
15
15
 
16
16
  const allSelectedOperators = values.selectedOperators
@@ -62,7 +62,7 @@ describe('OperatorsSelect counting logic', () => {
62
62
  it('should count bundle operators when a bundle is selected', () => {
63
63
  const values: OperatorsValues = {
64
64
  selectedOperators: ['lvm'], // 1 manually selected
65
- selectedBundles: ['virtualization'], // bundle with 3 operators: cnv, nmstate, mtv
65
+ selectedBundles: [{ id: 'virtualization', optionalOperators: [] }], // bundle with 3 operators: cnv, nmstate, mtv
66
66
  };
67
67
 
68
68
  const result = calculateSelectedOperators(values, mockBundles, mockOpSpecs);
@@ -77,7 +77,7 @@ describe('OperatorsSelect counting logic', () => {
77
77
  it('should not double-count operators that are both manually selected and in a bundle', () => {
78
78
  const values: OperatorsValues = {
79
79
  selectedOperators: ['lvm', 'cnv'], // cnv is also in the bundle
80
- selectedBundles: ['virtualization'], // bundle with: cnv, nmstate, mtv
80
+ selectedBundles: [{ id: 'virtualization', optionalOperators: [] }], // bundle with: cnv, nmstate, mtv
81
81
  };
82
82
 
83
83
  const result = calculateSelectedOperators(values, mockBundles, mockOpSpecs);
@@ -107,7 +107,10 @@ describe('OperatorsSelect counting logic', () => {
107
107
  it('should handle multiple bundles correctly', () => {
108
108
  const values: OperatorsValues = {
109
109
  selectedOperators: ['lvm'],
110
- selectedBundles: ['virtualization', 'openshift-ai'], // Two bundles
110
+ selectedBundles: [
111
+ { id: 'virtualization', optionalOperators: [] },
112
+ { id: 'openshift-ai', optionalOperators: [] },
113
+ ], // Two bundles
111
114
  };
112
115
 
113
116
  const result = calculateSelectedOperators(values, mockBundles, mockOpSpecs);
@@ -125,7 +128,10 @@ describe('OperatorsSelect counting logic', () => {
125
128
  it('should handle overlapping operators in multiple bundles', () => {
126
129
  const values: OperatorsValues = {
127
130
  selectedOperators: [],
128
- selectedBundles: ['virtualization', 'openshift-ai'], // Both bundles have 'odf' (but only virtualization has it in our mock)
131
+ selectedBundles: [
132
+ { id: 'virtualization', optionalOperators: [] },
133
+ { id: 'openshift-ai', optionalOperators: [] },
134
+ ], // Both bundles have 'odf' (but only virtualization has it in our mock)
129
135
  };
130
136
 
131
137
  // Let's modify the virtualization bundle to include odf to test overlap
@@ -92,9 +92,9 @@ export const OperatorsStep = ({ cluster }: ClusterOperatorProps) => {
92
92
  <StackItem>
93
93
  <OperatorsBundle
94
94
  bundles={filteredBundles}
95
- preflightRequirements={preflightRequirements}
96
95
  searchTerm={searchTerm}
97
96
  allBundles={allBundles}
97
+ cluster={cluster}
98
98
  />
99
99
  </StackItem>
100
100
  <StackItem>
@@ -0,0 +1,106 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Badge,
4
+ MenuToggle,
5
+ MenuToggleElement,
6
+ Select,
7
+ SelectList,
8
+ SelectOption,
9
+ } from '@patternfly/react-core';
10
+ import { OperatorsValues } from '../../../common';
11
+
12
+ type OptionalOperatorsDropdownProps = {
13
+ bundleId: string;
14
+ optionalOperatorIds: string[];
15
+ selectedBundles: OperatorsValues['selectedBundles'];
16
+ setSelectedBundles: (selectedBundles: OperatorsValues['selectedBundles']) => void;
17
+ isDisabled: boolean;
18
+ getOperatorLabel: (operatorId: string) => string;
19
+ };
20
+
21
+ const OptionalOperatorsDropdown = ({
22
+ bundleId,
23
+ optionalOperatorIds,
24
+ selectedBundles,
25
+ setSelectedBundles,
26
+ isDisabled,
27
+ getOperatorLabel,
28
+ }: OptionalOperatorsDropdownProps) => {
29
+ const [isOpen, setIsOpen] = React.useState(false);
30
+ const toggleLabel = bundleId === 'openshift-ai' ? 'GPU operators' : 'Optional operators';
31
+ const selectedBundleEntry = selectedBundles.find(
32
+ (bundleSelection) => bundleSelection.id === bundleId,
33
+ );
34
+ const selectedOptionalOperators = selectedBundleEntry?.optionalOperators || [];
35
+
36
+ const updateBundleOptionalOperators = (operatorId: string) => {
37
+ if (selectedBundleEntry) {
38
+ const isCurrentlySelected = selectedOptionalOperators.includes(operatorId);
39
+ const nextOptionalOperators = isCurrentlySelected
40
+ ? selectedOptionalOperators.filter((optionalOperator) => optionalOperator !== operatorId)
41
+ : [...selectedOptionalOperators, operatorId];
42
+
43
+ const updatedBundles = selectedBundles.map((bundleSelection) =>
44
+ bundleSelection.id === bundleId
45
+ ? {
46
+ ...bundleSelection,
47
+ optionalOperators: nextOptionalOperators,
48
+ }
49
+ : bundleSelection,
50
+ );
51
+
52
+ setSelectedBundles(updatedBundles);
53
+ }
54
+ };
55
+
56
+ const onSelect = (
57
+ _event: React.MouseEvent | React.ChangeEvent | undefined,
58
+ value?: string | number,
59
+ ) => {
60
+ const operatorId = value as string;
61
+ updateBundleOptionalOperators(operatorId);
62
+ };
63
+
64
+ return (
65
+ <Select
66
+ role="menu"
67
+ isOpen={isOpen}
68
+ onSelect={onSelect}
69
+ selected={selectedOptionalOperators}
70
+ onOpenChange={(nextIsOpen) => setIsOpen(nextIsOpen)}
71
+ toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
72
+ <MenuToggle
73
+ ref={toggleRef}
74
+ onClick={() => setIsOpen((prevIsOpen) => !prevIsOpen)}
75
+ isExpanded={isOpen}
76
+ isDisabled={isDisabled}
77
+ style={{ minWidth: '190px' }}
78
+ >
79
+ {toggleLabel}
80
+ {selectedOptionalOperators.length > 0 && (
81
+ <>
82
+ {' '}
83
+ <Badge isRead>{selectedOptionalOperators.length}</Badge>
84
+ </>
85
+ )}
86
+ </MenuToggle>
87
+ )}
88
+ >
89
+ <SelectList>
90
+ {optionalOperatorIds.map((operatorId) => (
91
+ <SelectOption
92
+ id={`optional-operator-${bundleId}-${operatorId}`}
93
+ key={operatorId}
94
+ value={operatorId}
95
+ hasCheckbox
96
+ isSelected={selectedOptionalOperators.includes(operatorId)}
97
+ >
98
+ {getOperatorLabel(operatorId)}
99
+ </SelectOption>
100
+ ))}
101
+ </SelectList>
102
+ </Select>
103
+ );
104
+ };
105
+
106
+ export default OptionalOperatorsDropdown;