@openshift-assisted/ui-lib 2.41.2 → 2.42.1

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 (217) hide show
  1. package/build/@types/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.d.ts.map +1 -1
  2. package/build/@types/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.d.ts.map +1 -1
  3. package/build/@types/cim/components/ClusterDeployment/LabelsSelector.d.ts.map +1 -1
  4. package/build/@types/cim/components/ClusterDeployment/ScaleUpForm.d.ts +1 -0
  5. package/build/@types/cim/components/ClusterDeployment/ScaleUpForm.d.ts.map +1 -1
  6. package/build/@types/cim/components/InfraEnv/AddHostDropdown.d.ts.map +1 -1
  7. package/build/@types/cim/components/InfraEnv/EnvironmentDetails.d.ts.map +1 -1
  8. package/build/@types/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.d.ts.map +1 -1
  9. package/build/@types/cim/components/common/CpuArchitectureDropdown.d.ts.map +1 -1
  10. package/build/@types/cim/components/helpers/versions.d.ts.map +1 -1
  11. package/build/@types/cim/components/modals/ScaleUpModal.d.ts +1 -0
  12. package/build/@types/cim/components/modals/ScaleUpModal.d.ts.map +1 -1
  13. package/build/@types/common/components/clusterConfiguration/ControlPlaneNodesDropdown.d.ts.map +1 -1
  14. package/build/@types/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.d.ts.map +1 -1
  15. package/build/@types/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionValues.d.ts +1 -0
  16. package/build/@types/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionValues.d.ts.map +1 -1
  17. package/build/@types/common/components/clusterWizard/clusterDetailsValidation.d.ts.map +1 -1
  18. package/build/@types/common/components/clusterWizard/types.d.ts +1 -0
  19. package/build/@types/common/components/clusterWizard/types.d.ts.map +1 -1
  20. package/build/@types/common/components/hosts/DiskRole.d.ts.map +1 -1
  21. package/build/@types/common/components/hosts/TableToolbar.d.ts.map +1 -1
  22. package/build/@types/common/components/newFeatureSupportLevels/types.d.ts +1 -1
  23. package/build/@types/common/components/newFeatureSupportLevels/types.d.ts.map +1 -1
  24. package/build/@types/common/components/operators/operatorDescriptions.d.ts +23 -0
  25. package/build/@types/common/components/operators/operatorDescriptions.d.ts.map +1 -0
  26. package/build/@types/common/components/operators/operatorSpecs.d.ts +25 -4
  27. package/build/@types/common/components/operators/operatorSpecs.d.ts.map +1 -1
  28. package/build/@types/common/components/ui/ClusterEventsToolbar.d.ts.map +1 -1
  29. package/build/@types/common/components/ui/OpenShiftVersionDropdown.d.ts +0 -1
  30. package/build/@types/common/components/ui/OpenShiftVersionDropdown.d.ts.map +1 -1
  31. package/build/@types/common/components/ui/SimpleDropdown.d.ts +2 -2
  32. package/build/@types/common/components/ui/SimpleDropdown.d.ts.map +1 -1
  33. package/build/@types/common/config/constants.d.ts.map +1 -1
  34. package/build/@types/common/config/docs_links.d.ts +1 -2
  35. package/build/@types/common/config/docs_links.d.ts.map +1 -1
  36. package/build/@types/common/index.d.ts +1 -0
  37. package/build/@types/common/index.d.ts.map +1 -1
  38. package/build/@types/common/types/ui-settings.d.ts +1 -0
  39. package/build/@types/common/types/ui-settings.d.ts.map +1 -1
  40. package/build/@types/common/utils.d.ts +8 -0
  41. package/build/@types/common/utils.d.ts.map +1 -1
  42. package/build/@types/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.d.ts +2 -0
  43. package/build/@types/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.d.ts.map +1 -1
  44. package/build/@types/ocm/components/clusterConfiguration/CpuArchitectureDropdown.d.ts.map +1 -1
  45. package/build/@types/ocm/components/clusterConfiguration/DiscoveryImageTypeDropdown.d.ts.map +1 -1
  46. package/build/@types/ocm/components/clusterConfiguration/OcmBaseDomainField.d.ts.map +1 -1
  47. package/build/@types/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.d.ts.map +1 -1
  48. package/build/@types/ocm/components/clusterConfiguration/OcmTNADisclaimer.d.ts +4 -0
  49. package/build/@types/ocm/components/clusterConfiguration/OcmTNADisclaimer.d.ts.map +1 -0
  50. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/components/FolderDropdown.d.ts.map +1 -1
  51. package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.d.ts.map +1 -1
  52. package/build/@types/ocm/components/clusterConfiguration/operators/utils.d.ts.map +1 -1
  53. package/build/@types/ocm/components/clusterConfiguration/platformIntegration/ExternalPlatformDropdown.d.ts.map +1 -1
  54. package/build/@types/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.d.ts.map +1 -1
  55. package/build/@types/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.d.ts.map +1 -1
  56. package/build/@types/ocm/components/clusterWizard/ClusterDetails.d.ts.map +1 -1
  57. package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts.map +1 -1
  58. package/build/@types/ocm/components/clusterWizard/OperatorsSelect.d.ts.map +1 -1
  59. package/build/@types/ocm/components/featureSupportLevels/featureStateUtils.d.ts.map +1 -1
  60. package/build/@types/ocm/components/hosts/use-hosts-table.d.ts.map +1 -1
  61. package/build/@types/ocm/services/DiskEncryptionService.d.ts +1 -1
  62. package/build/@types/ocm/services/DiskEncryptionService.d.ts.map +1 -1
  63. package/build/@types/ocm/store/slices/current-cluster/slice.d.ts +1 -1
  64. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.js +2 -2
  65. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.js.map +1 -1
  66. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.js +2 -1
  67. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.js.map +1 -1
  68. package/build/cjs/cim/components/ClusterDeployment/LabelsSelector.js +5 -5
  69. package/build/cjs/cim/components/ClusterDeployment/LabelsSelector.js.map +1 -1
  70. package/build/cjs/cim/components/ClusterDeployment/ScaleUpForm.js +2 -2
  71. package/build/cjs/cim/components/ClusterDeployment/ScaleUpForm.js.map +1 -1
  72. package/build/cjs/cim/components/InfraEnv/AddHostDropdown.js +29 -28
  73. package/build/cjs/cim/components/InfraEnv/AddHostDropdown.js.map +1 -1
  74. package/build/cjs/cim/components/InfraEnv/EnvironmentDetails.js +16 -14
  75. package/build/cjs/cim/components/InfraEnv/EnvironmentDetails.js.map +1 -1
  76. package/build/cjs/cim/components/InfraEnv/InfraEnvAgentTable.js +2 -2
  77. package/build/cjs/cim/components/InfraEnv/InfraEnvAgentTable.js.map +1 -1
  78. package/build/cjs/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.js +4 -8
  79. package/build/cjs/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.js.map +1 -1
  80. package/build/cjs/cim/components/common/CpuArchitectureDropdown.js +3 -3
  81. package/build/cjs/cim/components/common/CpuArchitectureDropdown.js.map +1 -1
  82. package/build/cjs/cim/components/helpers/versions.js +1 -1
  83. package/build/cjs/cim/components/helpers/versions.js.map +1 -1
  84. package/build/cjs/cim/components/modals/MassApproveAction.js +2 -2
  85. package/build/cjs/cim/components/modals/MassApproveAction.js.map +1 -1
  86. package/build/cjs/cim/components/modals/ScaleUpModal.js +3 -3
  87. package/build/cjs/cim/components/modals/ScaleUpModal.js.map +1 -1
  88. package/build/cjs/common/components/clusterConfiguration/ControlPlaneNodesDropdown.js +5 -6
  89. package/build/cjs/common/components/clusterConfiguration/ControlPlaneNodesDropdown.js.map +1 -1
  90. package/build/cjs/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.js +11 -6
  91. package/build/cjs/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.js.map +1 -1
  92. package/build/cjs/common/components/clusterDetail/OperatorsProgressItem.js +1 -1
  93. package/build/cjs/common/components/clusterDetail/OperatorsProgressItem.js.map +1 -1
  94. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js +2 -1
  95. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js.map +1 -1
  96. package/build/cjs/common/components/hosts/DiskRole.js +5 -5
  97. package/build/cjs/common/components/hosts/DiskRole.js.map +1 -1
  98. package/build/cjs/common/components/hosts/HostToolbarActions.js +3 -3
  99. package/build/cjs/common/components/hosts/HostToolbarActions.js.map +1 -1
  100. package/build/cjs/common/components/hosts/TableToolbar.js +15 -15
  101. package/build/cjs/common/components/hosts/TableToolbar.js.map +1 -1
  102. package/build/cjs/common/components/operators/operatorDescriptions.js +26 -0
  103. package/build/cjs/common/components/operators/operatorDescriptions.js.map +1 -0
  104. package/build/cjs/common/components/operators/operatorSpecs.js +332 -189
  105. package/build/cjs/common/components/operators/operatorSpecs.js.map +1 -1
  106. package/build/cjs/common/components/ui/ClusterEventsToolbar.js +1 -1
  107. package/build/cjs/common/components/ui/ClusterEventsToolbar.js.map +1 -1
  108. package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js +13 -16
  109. package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js.map +1 -1
  110. package/build/cjs/common/components/ui/SimpleDropdown.js +4 -5
  111. package/build/cjs/common/components/ui/SimpleDropdown.js.map +1 -1
  112. package/build/cjs/common/config/constants.js +10 -0
  113. package/build/cjs/common/config/constants.js.map +1 -1
  114. package/build/cjs/common/config/docs_links.js +41 -25
  115. package/build/cjs/common/config/docs_links.js.map +1 -1
  116. package/build/cjs/common/index.js +1 -0
  117. package/build/cjs/common/index.js.map +1 -1
  118. package/build/cjs/common/utils.js +27 -1
  119. package/build/cjs/common/utils.js.map +1 -1
  120. package/build/cjs/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.js +23 -13
  121. package/build/cjs/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.js.map +1 -1
  122. package/build/cjs/ocm/components/clusterConfiguration/CpuArchitectureDropdown.js +3 -5
  123. package/build/cjs/ocm/components/clusterConfiguration/CpuArchitectureDropdown.js.map +1 -1
  124. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageTypeDropdown.js +15 -17
  125. package/build/cjs/ocm/components/clusterConfiguration/DiscoveryImageTypeDropdown.js.map +1 -1
  126. package/build/cjs/ocm/components/clusterConfiguration/OcmBaseDomainField.js +5 -7
  127. package/build/cjs/ocm/components/clusterConfiguration/OcmBaseDomainField.js.map +1 -1
  128. package/build/cjs/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.js +16 -0
  129. package/build/cjs/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.js.map +1 -1
  130. package/build/cjs/ocm/components/clusterConfiguration/OcmOperatorProgressItem.js +1 -1
  131. package/build/cjs/ocm/components/clusterConfiguration/OcmOperatorProgressItem.js.map +1 -1
  132. package/build/cjs/ocm/components/clusterConfiguration/OcmTNADisclaimer.js +14 -0
  133. package/build/cjs/ocm/components/clusterConfiguration/OcmTNADisclaimer.js.map +1 -0
  134. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/FolderDropdown.js +6 -8
  135. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/components/FolderDropdown.js.map +1 -1
  136. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.js +7 -10
  137. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.js.map +1 -1
  138. package/build/cjs/ocm/components/clusterConfiguration/operators/OperatorCheckbox.js +1 -1
  139. package/build/cjs/ocm/components/clusterConfiguration/operators/OperatorCheckbox.js.map +1 -1
  140. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js +2 -1
  141. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js.map +1 -1
  142. package/build/cjs/ocm/components/clusterConfiguration/platformIntegration/ExternalPlatformDropdown.js +11 -13
  143. package/build/cjs/ocm/components/clusterConfiguration/platformIntegration/ExternalPlatformDropdown.js.map +1 -1
  144. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.js +1 -1
  145. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.js.map +1 -1
  146. package/build/cjs/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.js +4 -0
  147. package/build/cjs/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.js.map +1 -1
  148. package/build/cjs/ocm/components/clusterDetail/ProgressBarAlerts.js +1 -1
  149. package/build/cjs/ocm/components/clusterDetail/ProgressBarAlerts.js.map +1 -1
  150. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js +7 -4
  151. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js.map +1 -1
  152. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js +14 -10
  153. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js.map +1 -1
  154. package/build/cjs/ocm/components/clusterWizard/OperatorsSelect.js +13 -15
  155. package/build/cjs/ocm/components/clusterWizard/OperatorsSelect.js.map +1 -1
  156. package/build/cjs/ocm/components/featureSupportLevels/featureStateUtils.js +5 -15
  157. package/build/cjs/ocm/components/featureSupportLevels/featureStateUtils.js.map +1 -1
  158. package/build/cjs/ocm/components/hosts/use-hosts-table.js +9 -2
  159. package/build/cjs/ocm/components/hosts/use-hosts-table.js.map +1 -1
  160. package/build/cjs/ocm/services/DiskEncryptionService.js +11 -3
  161. package/build/cjs/ocm/services/DiskEncryptionService.js.map +1 -1
  162. package/lib/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.tsx +4 -2
  163. package/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx +8 -6
  164. package/lib/cim/components/ClusterDeployment/LabelsSelector.tsx +27 -14
  165. package/lib/cim/components/ClusterDeployment/ScaleUpForm.tsx +3 -0
  166. package/lib/cim/components/InfraEnv/AddHostDropdown.tsx +60 -47
  167. package/lib/cim/components/InfraEnv/EnvironmentDetails.tsx +7 -10
  168. package/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx +1 -1
  169. package/lib/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.tsx +34 -22
  170. package/lib/cim/components/common/CpuArchitectureDropdown.tsx +6 -3
  171. package/lib/cim/components/helpers/versions.ts +2 -2
  172. package/lib/cim/components/modals/MassApproveAction.tsx +1 -1
  173. package/lib/cim/components/modals/ScaleUpModal.tsx +5 -2
  174. package/lib/common/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx +30 -17
  175. package/lib/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionControlGroup.tsx +20 -5
  176. package/lib/common/components/clusterConfiguration/DiskEncryptionFields/DiskEncryptionValues.ts +1 -0
  177. package/lib/common/components/clusterDetail/OperatorsProgressItem.tsx +1 -1
  178. package/lib/common/components/clusterWizard/clusterDetailsValidation.ts +3 -0
  179. package/lib/common/components/clusterWizard/types.ts +1 -0
  180. package/lib/common/components/hosts/DiskRole.tsx +23 -17
  181. package/lib/common/components/hosts/HostToolbarActions.tsx +1 -1
  182. package/lib/common/components/hosts/TableToolbar.tsx +54 -48
  183. package/lib/common/components/newFeatureSupportLevels/types.ts +1 -0
  184. package/lib/common/components/operators/operatorDescriptions.tsx +58 -0
  185. package/lib/common/components/operators/operatorSpecs.tsx +425 -257
  186. package/lib/common/components/ui/ClusterEventsToolbar.tsx +1 -0
  187. package/lib/common/components/ui/OpenShiftVersionDropdown.tsx +38 -44
  188. package/lib/common/components/ui/SimpleDropdown.tsx +23 -22
  189. package/lib/common/config/constants.ts +11 -0
  190. package/lib/common/config/docs_links.ts +44 -30
  191. package/lib/common/index.ts +1 -0
  192. package/lib/common/types/ui-settings.ts +1 -0
  193. package/lib/common/utils.ts +30 -0
  194. package/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx +46 -15
  195. package/lib/ocm/components/clusterConfiguration/CpuArchitectureDropdown.tsx +26 -20
  196. package/lib/ocm/components/clusterConfiguration/DiscoveryImageTypeDropdown.tsx +47 -46
  197. package/lib/ocm/components/clusterConfiguration/OcmBaseDomainField.tsx +16 -13
  198. package/lib/ocm/components/clusterConfiguration/OcmClusterDetailsFormFields.tsx +33 -1
  199. package/lib/ocm/components/clusterConfiguration/OcmOperatorProgressItem.tsx +1 -1
  200. package/lib/ocm/components/clusterConfiguration/OcmTNADisclaimer.tsx +23 -0
  201. package/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/FolderDropdown.tsx +26 -26
  202. package/lib/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.tsx +26 -30
  203. package/lib/ocm/components/clusterConfiguration/operators/OperatorCheckbox.tsx +1 -1
  204. package/lib/ocm/components/clusterConfiguration/operators/utils.tsx +2 -1
  205. package/lib/ocm/components/clusterConfiguration/platformIntegration/ExternalPlatformDropdown.tsx +34 -33
  206. package/lib/ocm/components/clusterConfiguration/review/ReviewOperatorsTable.tsx +2 -1
  207. package/lib/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.tsx +4 -0
  208. package/lib/ocm/components/clusterDetail/ProgressBarAlerts.tsx +1 -1
  209. package/lib/ocm/components/clusterWizard/ClusterDetails.tsx +15 -5
  210. package/lib/ocm/components/clusterWizard/OperatorsBundle.tsx +15 -17
  211. package/lib/ocm/components/clusterWizard/OperatorsSelect.tsx +33 -27
  212. package/lib/ocm/components/featureSupportLevels/featureStateUtils.ts +7 -18
  213. package/lib/ocm/components/hosts/use-hosts-table.tsx +9 -3
  214. package/lib/ocm/services/DiskEncryptionService.ts +7 -1
  215. package/package.json +3 -3
  216. package/build/cjs/common/components/ui/OpenShiftVersionDropdown.css +0 -9
  217. package/lib/common/components/ui/OpenShiftVersionDropdown.css +0 -9
@@ -1,7 +1,14 @@
1
1
  import React from 'react';
2
- import { FormGroup, Split, SplitItem, Tooltip } from '@patternfly/react-core';
3
- import { Dropdown, DropdownItem, DropdownToggle } from '@patternfly/react-core/deprecated';
4
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
2
+ import {
3
+ FormGroup,
4
+ Split,
5
+ SplitItem,
6
+ Tooltip,
7
+ Dropdown,
8
+ DropdownItem,
9
+ MenuToggle,
10
+ MenuToggleElement,
11
+ } from '@patternfly/react-core';
5
12
  import { useField } from 'formik';
6
13
  import {
7
14
  architectureData,
@@ -119,7 +126,7 @@ const CpuArchitectureDropdown = ({
119
126
  ]);
120
127
 
121
128
  const onSelect = React.useCallback(
122
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
129
+ (event?: React.MouseEvent<Element, MouseEvent>): void => {
123
130
  const selectedCpuArch = event?.currentTarget.id as SupportedCpuArchitecture;
124
131
  setValue(selectedCpuArch);
125
132
  setOpen(false);
@@ -146,31 +153,30 @@ const CpuArchitectureDropdown = ({
146
153
  // eslint-disable-next-line react-hooks/exhaustive-deps
147
154
  }, [cpuArchitectures, openshiftVersion, selectedCpuArchitecture]);
148
155
 
149
- const toggle = React.useMemo(
150
- () => (
151
- <DropdownToggle
152
- onToggle={(_event, val: boolean) => setOpen(val)}
153
- toggleIndicator={CaretDownIcon}
154
- isText
155
- className="pf-v5-u-w-100"
156
- >
157
- {currentCpuArch}
158
- </DropdownToggle>
159
- ),
160
- [setOpen, currentCpuArch],
156
+ const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
157
+ <MenuToggle
158
+ id={fieldId}
159
+ ref={toggleRef}
160
+ onClick={() => setOpen(!isOpen)}
161
+ isExpanded={isOpen}
162
+ className="pf-v5-u-w-100"
163
+ >
164
+ {currentCpuArch}
165
+ </MenuToggle>
161
166
  );
162
167
 
163
168
  return (
164
169
  <FormGroup id={`form-control__${fieldId}`} fieldId={fieldId} label={'CPU architecture'}>
165
170
  <Dropdown
166
171
  {...field}
167
- id={fieldId}
168
- dropdownItems={enabledItems}
172
+ id={`${fieldId}-dropdown`}
169
173
  toggle={toggle}
170
174
  isOpen={isOpen}
171
- className="pf-v5-u-w-100"
172
175
  onSelect={onSelect}
173
- />
176
+ onOpenChange={() => setOpen(!isOpen)}
177
+ >
178
+ {enabledItems}
179
+ </Dropdown>
174
180
  </FormGroup>
175
181
  );
176
182
  };
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
- import { FormGroup } from '@patternfly/react-core';
2
+ import { FormGroup, Tooltip } from '@patternfly/react-core';
3
3
  import {
4
4
  DropdownItem,
5
- DropdownToggle,
5
+ Divider,
6
6
  Dropdown,
7
- DropdownSeparator,
8
- } from '@patternfly/react-core/deprecated';
9
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
7
+ MenuToggle,
8
+ MenuToggleElement,
9
+ DropdownList,
10
+ } from '@patternfly/react-core';
10
11
  import { useField } from 'formik';
11
12
  import {
12
13
  CpuArchitecture,
@@ -47,74 +48,74 @@ export const DiscoveryImageTypeDropdown = ({
47
48
  key="full-iso"
48
49
  id="full-iso"
49
50
  description={'Use when configuring custom networking for easier debugging'}
51
+ value={discoveryImageTypes['full-iso']}
50
52
  >
51
53
  {discoveryImageTypes['full-iso']}
52
54
  </DropdownItem>,
53
- <DropdownSeparator key="separator1" />,
54
- <DropdownItem
55
- key="minimal-iso"
56
- id="minimal-iso"
57
- description={'Use when provisioning with default networking options'}
58
- tooltip={
55
+ <Divider component="li" key="separator1" />,
56
+ <Tooltip
57
+ key="minimal-iso-tooltip"
58
+ content={
59
59
  isMinimalISODisabled ? (
60
60
  <p>{'This provisioning type is not supported when using s390x architecture'}</p>
61
61
  ) : undefined
62
62
  }
63
- isAriaDisabled={!!isMinimalISODisabled}
64
63
  >
65
- {discoveryImageTypes['minimal-iso']}
66
- </DropdownItem>,
67
- <DropdownSeparator key="separator2" />,
64
+ <DropdownItem
65
+ key="minimal-iso"
66
+ id="minimal-iso"
67
+ description={'Use when provisioning with default networking options'}
68
+ isAriaDisabled={!!isMinimalISODisabled}
69
+ value={discoveryImageTypes['minimal-iso']}
70
+ >
71
+ {discoveryImageTypes['minimal-iso']}
72
+ </DropdownItem>
73
+ </Tooltip>,
74
+ <Divider component="li" key="separator2" />,
68
75
  <DropdownItem
69
76
  key="discovery-image-ipxe"
70
77
  id="discovery-image-ipxe"
71
78
  description={'Use when your platform does not support booting from ISO'}
79
+ value={discoveryImageTypes['discovery-image-ipxe']}
72
80
  >
73
81
  {discoveryImageTypes['discovery-image-ipxe']}
74
82
  </DropdownItem>,
75
83
  ];
76
84
 
77
- const onSelect = React.useCallback(
78
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
79
- const imageTypeSelection = event?.currentTarget.id as DiscoveryImageType;
80
- const currentValue = imageTypeSelection
81
- ? discoveryImageTypes[imageTypeSelection]
82
- : defaultValue;
83
- setCurrent(currentValue ? currentValue : '');
84
- setValue(imageTypeSelection);
85
- setOpen(false);
86
- onChange(imageTypeSelection === 'discovery-image-ipxe');
87
- },
88
- [setCurrent, setOpen, defaultValue, setValue, onChange],
89
- );
85
+ const onSelect = (event?: React.MouseEvent<Element, MouseEvent>, value?: string | number) => {
86
+ const imageTypeSelection = value as string;
87
+ setCurrent(imageTypeSelection ? imageTypeSelection : '');
88
+ setValue(event?.currentTarget.id as DiscoveryImageType);
89
+ setOpen(false);
90
+ onChange(imageTypeSelection === 'discovery-image-ipxe');
91
+ };
90
92
 
91
- const toggle = React.useMemo(
92
- () => (
93
- <DropdownToggle
94
- onToggle={(_event, val) => setOpen(val)}
95
- toggleIndicator={CaretDownIcon}
96
- isText
97
- className="pf-v5-u-w-100"
98
- isDisabled={isDisabled}
99
- >
100
- {current || value}
101
- </DropdownToggle>
102
- ),
103
- [setOpen, current, value, isDisabled],
93
+ const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
94
+ <MenuToggle
95
+ id={fieldId}
96
+ className="pf-v5-u-w-100"
97
+ ref={toggleRef}
98
+ isFullWidth
99
+ onClick={() => setOpen(!isOpen)}
100
+ isExpanded={isOpen}
101
+ isDisabled={isDisabled}
102
+ >
103
+ {current || value}
104
+ </MenuToggle>
104
105
  );
105
106
 
106
107
  return (
107
108
  <FormGroup fieldId={fieldId} label={'Provisioning type'}>
108
109
  <Dropdown
109
110
  {...field}
110
- name={name}
111
- id={fieldId}
112
- dropdownItems={dropdownItems}
111
+ id={`${fieldId}-dropdown`}
113
112
  toggle={toggle}
114
113
  isOpen={isOpen}
115
- className="pf-v5-u-w-100"
116
114
  onSelect={onSelect}
117
- />
115
+ onOpenChange={() => setOpen(!isOpen)}
116
+ >
117
+ <DropdownList>{dropdownItems}</DropdownList>
118
+ </Dropdown>
118
119
  </FormGroup>
119
120
  );
120
121
  };
@@ -5,11 +5,13 @@ import {
5
5
  HelperText,
6
6
  HelperTextItem,
7
7
  Tooltip,
8
+ Dropdown,
9
+ DropdownItem,
10
+ MenuToggle,
11
+ MenuToggleElement,
8
12
  } from '@patternfly/react-core';
9
- import { Dropdown, DropdownItem, DropdownToggle } from '@patternfly/react-core/deprecated';
10
13
  import { useField, useFormikContext } from 'formik';
11
14
  import { ClusterDetailsValues, getFieldId } from '../../../common';
12
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
13
15
  import { OcmCheckboxField, OcmInputField } from '../ui/OcmFormFields';
14
16
  import { ManagedDomain } from '@openshift-assisted/types/assisted-installer-service';
15
17
  import { clusterExistsReason } from '../featureSupportLevels/featureStateUtils';
@@ -62,25 +64,25 @@ export const OcmBaseDomainField = ({
62
64
  ));
63
65
  }, [managedDomains]);
64
66
 
65
- const dropdownToggle = React.useMemo(() => {
67
+ const dropdownToggle = (toggleRef: React.Ref<MenuToggleElement>) => {
66
68
  const selectedDomain = managedDomains.find((d) => d.domain === value);
67
69
  return (
68
- <DropdownToggle
69
- onToggle={(_event, val) => setOpen(val)}
70
- toggleIndicator={CaretDownIcon}
71
- isText
70
+ <MenuToggle
71
+ ref={toggleRef}
72
+ onClick={() => setOpen(!isOpen)}
73
+ isExpanded={isOpen}
72
74
  className="pf-v5-u-w-100"
73
75
  >
74
76
  {selectedDomain ? getManagedDomainLabel(selectedDomain) : 'Base domain'}
75
- </DropdownToggle>
77
+ </MenuToggle>
76
78
  );
77
- }, [managedDomains, value]);
79
+ };
78
80
 
79
81
  const toggleRedHatDnsService = (checked: boolean) =>
80
82
  setValue((checked && managedDomains.map((d) => d.domain)[0]) || '');
81
83
 
82
84
  const onSelect = React.useCallback(
83
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
85
+ (event?: React.MouseEvent<Element, MouseEvent>): void => {
84
86
  const selectedDomain = event?.currentTarget.id || '';
85
87
  setValue(selectedDomain);
86
88
  setOpen(false);
@@ -111,11 +113,12 @@ export const OcmBaseDomainField = ({
111
113
  {useRedHatDnsService ? (
112
114
  <Dropdown
113
115
  toggle={dropdownToggle}
114
- dropdownItems={dropdownItems}
115
116
  isOpen={isOpen}
116
117
  onSelect={onSelect}
117
- className="pf-v5-u-w-100"
118
- />
118
+ onOpenChange={() => setOpen(!isOpen)}
119
+ >
120
+ {dropdownItems}
121
+ </Dropdown>
119
122
  ) : (
120
123
  <OcmInputField
121
124
  name={INPUT_NAME}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-console */
1
2
  import * as React from 'react';
2
3
  import { Form } from '@patternfly/react-core';
3
4
  import { useFormikContext } from 'formik';
@@ -32,7 +33,11 @@ import { ExternalPlatformLabels } from './platformIntegration/constants';
32
33
  import { ManagedDomain, PlatformType } from '@openshift-assisted/types/assisted-installer-service';
33
34
  import { useClusterWizardContext } from '../clusterWizard/ClusterWizardContext';
34
35
  import { useFeature } from '../../hooks/use-feature';
35
- import ControlPlaneNodesDropdown, { ControlPlaneNodesLabel } from './ControlPlaneNodesDropdown';
36
+ import ControlPlaneNodesDropdown, {
37
+ ControlPlaneNodesLabel,
38
+ DEFAULT_VALUE_CPN,
39
+ isCPNDropdownItemEnabled,
40
+ } from './ControlPlaneNodesDropdown';
36
41
 
37
42
  export type OcmClusterDetailsFormFieldsProps = {
38
43
  forceOpenshiftVersion?: string;
@@ -115,6 +120,33 @@ export const OcmClusterDetailsFormFields = ({
115
120
  );
116
121
  }, [setFieldValue, featureSupportLevelContext, featureSupportLevelData]);
117
122
 
123
+ React.useEffect(() => {
124
+ const currentCount = values.controlPlaneCount;
125
+ const isNonStandardControlPlaneEnabled = featureSupportLevelContext.isFeatureSupported(
126
+ 'NON_STANDARD_HA_CONTROL_PLANE',
127
+ featureSupportLevelData ?? undefined,
128
+ );
129
+ const isTnaEnabled = featureSupportLevelContext.isFeatureSupported(
130
+ 'TNA',
131
+ featureSupportLevelData ?? undefined,
132
+ );
133
+
134
+ const isItemEnabled = isCPNDropdownItemEnabled(
135
+ currentCount,
136
+ isNonStandardControlPlaneEnabled,
137
+ isTnaEnabled,
138
+ );
139
+
140
+ if (!isItemEnabled) {
141
+ setFieldValue('controlPlaneCount', DEFAULT_VALUE_CPN, false);
142
+ }
143
+ }, [
144
+ values.openshiftVersion,
145
+ featureSupportLevelData,
146
+ featureSupportLevelContext,
147
+ values.controlPlaneCount,
148
+ setFieldValue,
149
+ ]);
118
150
  return (
119
151
  <Form id="wizard-cluster-details__form">
120
152
  <OcmRichInputField
@@ -80,7 +80,7 @@ type OperatorsPopoverProps = OperatorListProps & {
80
80
 
81
81
  const OperatorsPopover = ({ operators, children }: OperatorsPopoverProps) => {
82
82
  const { t } = useTranslation();
83
- const opSpecs = useOperatorSpecs();
83
+ const { byKey: opSpecs } = useOperatorSpecs();
84
84
 
85
85
  return (
86
86
  <Popover
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { Alert, AlertVariant, List, ListItem } from '@patternfly/react-core';
3
+ import { useTranslation } from '../../../common/hooks/use-translation-wrapper';
4
+
5
+ const OcmTNADisclaimer = () => {
6
+ const { t } = useTranslation();
7
+
8
+ return (
9
+ <Alert
10
+ variant={AlertVariant.info}
11
+ title={t('ai:Requirements for Two Node control plane OpenShift')}
12
+ isInline
13
+ >
14
+ <List>
15
+ <ListItem>
16
+ {t('ai:Two nodes control plane OpenShift must include an additional arbiter node.')}
17
+ </ListItem>
18
+ </List>
19
+ </Alert>
20
+ );
21
+ };
22
+
23
+ export default OcmTNADisclaimer;
@@ -1,7 +1,12 @@
1
1
  import React from 'react';
2
- import { HelperText, FormGroup } from '@patternfly/react-core';
3
- import { DropdownItem, DropdownToggle, Dropdown } from '@patternfly/react-core/deprecated';
4
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
2
+ import {
3
+ HelperText,
4
+ FormGroup,
5
+ Dropdown,
6
+ DropdownItem,
7
+ MenuToggle,
8
+ MenuToggleElement,
9
+ } from '@patternfly/react-core';
5
10
  import { useField } from 'formik';
6
11
  import { getFieldId } from '../../../../../common/components/ui/formik';
7
12
  import { PopoverIcon } from '../../../../../common';
@@ -40,40 +45,35 @@ export const FolderDropdown = ({ name }: FolderDropdownProps) => {
40
45
  const [isOpen, setOpen] = React.useState(false);
41
46
  const fieldId = getFieldId(name, 'input');
42
47
 
43
- const onSelect = React.useCallback(
44
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
45
- setValue(event?.currentTarget.id as string);
46
- setOpen(false);
47
- },
48
- [setOpen, setValue],
49
- );
48
+ const onSelect = (event?: React.MouseEvent<Element, MouseEvent>): void => {
49
+ setValue(event?.currentTarget.id as string);
50
+ setOpen(false);
51
+ };
50
52
 
51
- const toggle = React.useMemo(
52
- () => (
53
- <DropdownToggle
54
- onToggle={(_event, val) => setOpen(val)}
55
- toggleIndicator={CaretDownIcon}
56
- isText
57
- className="pf-v5-u-w-100"
58
- >
59
- {value || 'manifests'}
60
- </DropdownToggle>
61
- ),
62
- [setOpen, value],
53
+ const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
54
+ <MenuToggle
55
+ ref={toggleRef}
56
+ onClick={() => setOpen(!isOpen)}
57
+ isExpanded={isOpen}
58
+ className="pf-v5-u-w-100"
59
+ id={fieldId}
60
+ >
61
+ {value || 'manifests'}
62
+ </MenuToggle>
63
63
  );
64
64
 
65
65
  return (
66
66
  <FormGroup fieldId={fieldId} label={<FolderLabel />} isRequired>
67
67
  <Dropdown
68
68
  {...field}
69
- name={name}
70
69
  id={fieldId}
70
+ onOpenChange={() => setOpen(!isOpen)}
71
71
  onSelect={onSelect}
72
- dropdownItems={dropdownItems}
73
72
  toggle={toggle}
74
73
  isOpen={isOpen}
75
- className="pf-v5-u-w-100"
76
- />
74
+ >
75
+ {dropdownItems}
76
+ </Dropdown>
77
77
  <HelperText style={{ display: 'inherit' }}>
78
78
  {'Manifests can be placed in "manifests" or "openshift" directories.'}
79
79
  </HelperText>
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import { DropdownItem, DropdownToggle, Dropdown } from '@patternfly/react-core/deprecated';
3
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
2
+ import { Dropdown, DropdownItem, MenuToggle, MenuToggleElement } from '@patternfly/react-core';
4
3
  import { useField } from 'formik';
5
4
  import { getFieldId, HostSubnet, NO_SUBNET_SET } from '../../../../common';
6
5
 
@@ -64,46 +63,43 @@ export const SubnetsDropdown = ({ name, machineSubnets, isDisabled }: SubnetsDro
64
63
  }, []);
65
64
 
66
65
  const dropdownItems = itemsSubnets.map(({ value, label, isDisabled }) => (
67
- <DropdownItem key={value} id={value} isDisabled={isDisabled}>
66
+ <DropdownItem key={value} id={value} isDisabled={isDisabled} value={value}>
68
67
  {label}
69
68
  </DropdownItem>
70
69
  ));
71
70
 
72
- const onSelect = React.useCallback(
73
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
74
- const currentValue = event?.currentTarget.innerText ?? currentDisplayValue;
75
- setCurrentDisplayValue(currentValue);
76
- setValue(event?.currentTarget.id);
77
- setOpen(false);
78
- },
79
- [currentDisplayValue, setValue],
80
- );
71
+ const onSelect = (
72
+ event?: React.MouseEvent<Element, MouseEvent>,
73
+ value?: string | number,
74
+ ): void => {
75
+ setCurrentDisplayValue(value as string);
76
+ setValue(event?.currentTarget.id);
77
+ setOpen(false);
78
+ };
81
79
 
82
- const toggle = React.useMemo(
83
- () => (
84
- <DropdownToggle
85
- onToggle={(_event, val) => setOpen(!isDisabled && val)}
86
- toggleIndicator={CaretDownIcon}
87
- isDisabled={isDisabled}
88
- isText
89
- className="pf-v5-u-w-100"
90
- >
91
- {currentDisplayValue}
92
- </DropdownToggle>
93
- ),
94
- [setOpen, currentDisplayValue, isDisabled],
80
+ const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
81
+ <MenuToggle
82
+ ref={toggleRef}
83
+ onClick={() => setOpen(!isOpen)}
84
+ isExpanded={isOpen}
85
+ isDisabled={isDisabled}
86
+ className="pf-v5-u-w-100"
87
+ id={fieldId}
88
+ >
89
+ {currentDisplayValue}
90
+ </MenuToggle>
95
91
  );
96
92
 
97
93
  return (
98
94
  <Dropdown
99
95
  {...field}
100
- name={name}
101
- id={fieldId}
96
+ id={`${fieldId}-dropdown`}
97
+ onOpenChange={() => setOpen(!isOpen)}
102
98
  onSelect={onSelect}
103
- dropdownItems={dropdownItems}
104
99
  toggle={toggle}
105
100
  isOpen={isOpen}
106
- className="pf-v5-u-w-100"
107
- />
101
+ >
102
+ {dropdownItems}
103
+ </Dropdown>
108
104
  );
109
105
  };
@@ -126,7 +126,7 @@ const OperatorCheckbox = ({
126
126
  preflightRequirements: PreflightHardwareRequirements | undefined;
127
127
  } & OperatorSpec) => {
128
128
  const { getFeatureSupportLevel, getFeatureDisabledReason } = useNewFeatureSupportLevel();
129
- const opSpecs = useOperatorSpecs();
129
+ const { byKey: opSpecs } = useOperatorSpecs();
130
130
 
131
131
  const { isViewerMode } = useSelector(selectCurrentClusterPermissionsState);
132
132
  const { values, setFieldValue } = useFormikContext<OperatorsValues>();
@@ -35,7 +35,8 @@ export const getNewOperators = (
35
35
  const dependencies = getOperatorDependencies(operatorId, preflightRequirements);
36
36
 
37
37
  if (add) {
38
- return [...new Set([...currentOperators, ...dependencies, operatorId])];
38
+ const uniqueOps = new Set([...currentOperators, ...dependencies, operatorId]);
39
+ return Array.from(uniqueOps);
39
40
  }
40
41
 
41
42
  const newOperators = currentOperators.filter((op) => op !== operatorId);
@@ -6,9 +6,12 @@ import {
6
6
  Split,
7
7
  SplitItem,
8
8
  Tooltip,
9
+ Dropdown,
10
+ DropdownItem,
11
+ MenuToggle,
12
+ MenuToggleElement,
13
+ DropdownList,
9
14
  } from '@patternfly/react-core';
10
- import { Dropdown, DropdownItem, DropdownToggle } from '@patternfly/react-core/deprecated';
11
- import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
12
15
  import { useField } from 'formik';
13
16
  import {
14
17
  CpuArchitecture,
@@ -199,7 +202,12 @@ export const ExternalPlatformDropdown = ({
199
202
  ] as ExternalPlatformInfo;
200
203
 
201
204
  return (
202
- <DropdownItem key={platform} id={platform} isAriaDisabled={disabledReason !== undefined}>
205
+ <DropdownItem
206
+ value={platform}
207
+ key={platform}
208
+ id={platform}
209
+ isAriaDisabled={disabledReason !== undefined}
210
+ >
203
211
  <Split>
204
212
  <SplitItem>
205
213
  <Tooltip hidden={!disabledReason} content={disabledReason} position="top">
@@ -234,29 +242,17 @@ export const ExternalPlatformDropdown = ({
234
242
  );
235
243
  });
236
244
 
237
- const onSelect = React.useCallback(
238
- (event?: React.SyntheticEvent<HTMLDivElement>) => {
239
- const selectedPlatform = event?.currentTarget.id as PlatformType;
240
- setValue(selectedPlatform);
241
- setOpen(false);
242
- onChange(selectedPlatform);
243
- },
244
- [setOpen, setValue, onChange],
245
- );
246
-
247
- const toggle = React.useMemo(
248
- () => (
249
- <DropdownToggle
250
- onToggle={(_event, val) => setOpen(val)}
251
- toggleIndicator={CaretDownIcon}
252
- isText
253
- className="pf-v5-u-w-100"
254
- isDisabled={dropdownIsDisabled}
255
- >
256
- {externalPlatformTypes[field.value as PlatformType]?.label}
257
- </DropdownToggle>
258
- ),
259
- [externalPlatformTypes, field, dropdownIsDisabled],
245
+ const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
246
+ <MenuToggle
247
+ id={fieldId}
248
+ className="pf-v5-u-w-100"
249
+ ref={toggleRef}
250
+ onClick={() => setOpen(!isOpen)}
251
+ isDisabled={dropdownIsDisabled}
252
+ isExpanded={isOpen}
253
+ >
254
+ {externalPlatformTypes[field.value as PlatformType]?.label}
255
+ </MenuToggle>
260
256
  );
261
257
 
262
258
  return (
@@ -272,15 +268,20 @@ export const ExternalPlatformDropdown = ({
272
268
  distance={7}
273
269
  >
274
270
  <Dropdown
275
- {...field}
276
- id={fieldId}
277
- dropdownItems={enabledItems}
271
+ id={`${fieldId}-dropdown`}
278
272
  toggle={toggle}
279
273
  isOpen={isOpen}
280
- className="pf-v5-u-w-100"
281
- onSelect={onSelect}
282
- disabled={dropdownIsDisabled}
283
- />
274
+ onOpenChange={() => setOpen(!isOpen)}
275
+ onSelect={(event) => {
276
+ const selectedPlatform = event?.currentTarget.id as PlatformType;
277
+ setValue(selectedPlatform);
278
+ setOpen(false);
279
+ onChange(selectedPlatform);
280
+ }}
281
+ shouldFocusToggleOnSelect
282
+ >
283
+ <DropdownList>{enabledItems}</DropdownList>
284
+ </Dropdown>
284
285
  </Tooltip>
285
286
  </FormGroup>
286
287
  );
@@ -6,7 +6,8 @@ import { TableSummaryExpandable } from './TableSummaryExpandable';
6
6
  import { useOperatorSpecs } from '../../../../common/components/operators/operatorSpecs';
7
7
 
8
8
  export const ReviewOperatorsTable = ({ cluster }: { cluster: Cluster }) => {
9
- const opSpecs = useOperatorSpecs();
9
+ const { byKey: opSpecs } = useOperatorSpecs();
10
+
10
11
  const rows = React.useMemo(
11
12
  () =>
12
13
  cluster.monitoredOperators
@@ -232,6 +232,10 @@ export const getIpIsNotNetworkOrBroadcastAddressSchema = (
232
232
  'is-not-network-or-broadcast',
233
233
  `The IP address must not match the network or broadcast address`,
234
234
  (value) => {
235
+ // Allow both addresses for IPv4 /31 subnets (RFC 3021)
236
+ if (protocolVersion === ProtocolVersion.ipv4 && subnet.endsWith('/31')) {
237
+ return true;
238
+ }
235
239
  const subnetAddr = getAddressObject(subnet, protocolVersion);
236
240
  if (!subnetAddr) {
237
241
  return true;
@@ -66,7 +66,7 @@ export const HostInstallationWarning = ({
66
66
  message,
67
67
  }: InstallationProgressWarningProps) => {
68
68
  const { addAlert, clearAlerts } = useAlerts();
69
- const opSpecs = useOperatorSpecs();
69
+ const { byKey: opSpecs } = useOperatorSpecs();
70
70
 
71
71
  return (
72
72
  <>