@openshift-assisted/ui-lib 2.42.2 → 2.43.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 (161) hide show
  1. package/build/@types/cim/components/ClusterDeployment/ClusterDeploymentDetailsStep.d.ts.map +1 -1
  2. package/build/@types/cim/components/ClusterDeployment/ClusterDetailsFormFields.d.ts.map +1 -1
  3. package/build/@types/common/components/clusterConfiguration/index.d.ts +0 -2
  4. package/build/@types/common/components/clusterConfiguration/index.d.ts.map +1 -1
  5. package/build/@types/common/components/clusterWizard/clusterDetailsValidation.d.ts +1 -4
  6. package/build/@types/common/components/clusterWizard/clusterDetailsValidation.d.ts.map +1 -1
  7. package/build/@types/common/components/clusterWizard/types.d.ts +0 -2
  8. package/build/@types/common/components/clusterWizard/types.d.ts.map +1 -1
  9. package/build/@types/common/components/hosts/DiskRole.d.ts.map +1 -1
  10. package/build/@types/common/components/hosts/TableToolbar.d.ts.map +1 -1
  11. package/build/@types/common/components/operators/operatorSpecs.d.ts.map +1 -1
  12. package/build/@types/common/components/ui/SimpleDropdown.d.ts.map +1 -1
  13. package/build/@types/common/components/ui/formik/index.d.ts +0 -1
  14. package/build/@types/common/components/ui/formik/index.d.ts.map +1 -1
  15. package/build/@types/common/config/constants.d.ts.map +1 -1
  16. package/build/@types/common/config/docs_links.d.ts +3 -3
  17. package/build/@types/common/config/docs_links.d.ts.map +1 -1
  18. package/build/@types/common/selectors/clusterSelectors.d.ts +1 -1
  19. package/build/@types/common/selectors/clusterSelectors.d.ts.map +1 -1
  20. package/build/@types/common/types/cpuArchitecture.d.ts.map +1 -1
  21. package/build/@types/ocm/components/Routes.d.ts +2 -1
  22. package/build/@types/ocm/components/Routes.d.ts.map +1 -1
  23. package/build/@types/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.d.ts.map +1 -1
  24. package/build/@types/ocm/components/clusterConfiguration/OcmSNODisclaimer.d.ts +1 -4
  25. package/build/@types/ocm/components/clusterConfiguration/OcmSNODisclaimer.d.ts.map +1 -1
  26. package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.d.ts.map +1 -1
  27. package/build/@types/ocm/components/clusterWizard/ClusterDetailsForm.d.ts.map +1 -1
  28. package/build/@types/ocm/components/clusterWizard/CredentialsDownload.d.ts.map +1 -1
  29. package/build/@types/ocm/components/clusterWizard/Operators.d.ts.map +1 -1
  30. package/build/@types/ocm/components/clusters/AssistedInstallerHeader.d.ts.map +1 -1
  31. package/build/@types/ocm/components/clusters/ClusterPage.d.ts.map +1 -1
  32. package/build/@types/ocm/components/clusters/NewClusterPage.d.ts.map +1 -1
  33. package/build/@types/ocm/components/hosts/use-hosts-table.d.ts.map +1 -1
  34. package/build/@types/ocm/services/OperatorsService.d.ts.map +1 -1
  35. package/build/@types/ocm/store/slices/current-cluster/selectors.d.ts.map +1 -1
  36. package/build/@types/ocm/store/slices/current-cluster/slice.d.ts +1 -1
  37. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsStep.js +1 -4
  38. package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsStep.js.map +1 -1
  39. package/build/cjs/cim/components/ClusterDeployment/ClusterDetailsFormFields.js +9 -1
  40. package/build/cjs/cim/components/ClusterDeployment/ClusterDetailsFormFields.js.map +1 -1
  41. package/build/cjs/common/components/clusterConfiguration/index.js +1 -5
  42. package/build/cjs/common/components/clusterConfiguration/index.js.map +1 -1
  43. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js +3 -23
  44. package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js.map +1 -1
  45. package/build/cjs/common/components/hosts/DiskRole.js +1 -1
  46. package/build/cjs/common/components/hosts/DiskRole.js.map +1 -1
  47. package/build/cjs/common/components/hosts/TableToolbar.js +3 -3
  48. package/build/cjs/common/components/hosts/TableToolbar.js.map +1 -1
  49. package/build/cjs/common/components/operators/operatorSpecs.js +10 -8
  50. package/build/cjs/common/components/operators/operatorSpecs.js.map +1 -1
  51. package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js +6 -7
  52. package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js.map +1 -1
  53. package/build/cjs/common/components/ui/SimpleDropdown.js +1 -1
  54. package/build/cjs/common/components/ui/SimpleDropdown.js.map +1 -1
  55. package/build/cjs/common/components/ui/formik/index.js +1 -3
  56. package/build/cjs/common/components/ui/formik/index.js.map +1 -1
  57. package/build/cjs/common/config/constants.js +0 -4
  58. package/build/cjs/common/config/constants.js.map +1 -1
  59. package/build/cjs/common/config/docs_links.js +13 -9
  60. package/build/cjs/common/config/docs_links.js.map +1 -1
  61. package/build/cjs/common/selectors/clusterSelectors.js +1 -1
  62. package/build/cjs/common/selectors/clusterSelectors.js.map +1 -1
  63. package/build/cjs/common/types/cpuArchitecture.js +3 -5
  64. package/build/cjs/common/types/cpuArchitecture.js.map +1 -1
  65. package/build/cjs/ocm/components/Routes.js +3 -2
  66. package/build/cjs/ocm/components/Routes.js.map +1 -1
  67. package/build/cjs/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.js +2 -4
  68. package/build/cjs/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.js.map +1 -1
  69. package/build/cjs/ocm/components/clusterConfiguration/OcmSNODisclaimer.js +5 -21
  70. package/build/cjs/ocm/components/clusterConfiguration/OcmSNODisclaimer.js.map +1 -1
  71. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.js +12 -18
  72. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.js.map +1 -1
  73. package/build/cjs/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.js +1 -1
  74. package/build/cjs/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.js.map +1 -1
  75. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/FormViewNetworkWide/FormViewNetworkWideFields.js +1 -1
  76. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/FormViewNetworkWide/FormViewNetworkWideFields.js.map +1 -1
  77. package/build/cjs/ocm/components/clusterConfiguration/staticIp/components/staticIp.css +3 -3
  78. package/build/cjs/ocm/components/clusterConfiguration/staticIp/data/formDataToInfraEnvField.js +1 -1
  79. package/build/cjs/ocm/components/clusterConfiguration/staticIp/data/formDataToInfraEnvField.js.map +1 -1
  80. package/build/cjs/ocm/components/clusterDetail/ProgressBarAlerts.js +1 -1
  81. package/build/cjs/ocm/components/clusterDetail/ProgressBarAlerts.js.map +1 -1
  82. package/build/cjs/ocm/components/clusterWizard/ClusterDetailsForm.js +0 -1
  83. package/build/cjs/ocm/components/clusterWizard/ClusterDetailsForm.js.map +1 -1
  84. package/build/cjs/ocm/components/clusterWizard/CredentialsDownload.js +2 -1
  85. package/build/cjs/ocm/components/clusterWizard/CredentialsDownload.js.map +1 -1
  86. package/build/cjs/ocm/components/clusterWizard/Operators.js +4 -1
  87. package/build/cjs/ocm/components/clusterWizard/Operators.js.map +1 -1
  88. package/build/cjs/ocm/components/clusters/AssistedInstallerHeader.js +3 -0
  89. package/build/cjs/ocm/components/clusters/AssistedInstallerHeader.js.map +1 -1
  90. package/build/cjs/ocm/components/clusters/ClusterPage.js +2 -0
  91. package/build/cjs/ocm/components/clusters/ClusterPage.js.map +1 -1
  92. package/build/cjs/ocm/components/clusters/NewClusterPage.js +6 -7
  93. package/build/cjs/ocm/components/clusters/NewClusterPage.js.map +1 -1
  94. package/build/cjs/ocm/components/hosts/use-hosts-table.js +8 -1
  95. package/build/cjs/ocm/components/hosts/use-hosts-table.js.map +1 -1
  96. package/build/cjs/ocm/services/DiskEncryptionService.js +1 -1
  97. package/build/cjs/ocm/services/DiskEncryptionService.js.map +1 -1
  98. package/build/cjs/ocm/services/OperatorsService.js +12 -2
  99. package/build/cjs/ocm/services/OperatorsService.js.map +1 -1
  100. package/build/cjs/ocm/store/slices/current-cluster/selectors.js +1 -1
  101. package/build/cjs/ocm/store/slices/current-cluster/selectors.js.map +1 -1
  102. package/lib/cim/components/ClusterDeployment/ClusterDeploymentDetailsStep.tsx +1 -5
  103. package/lib/cim/components/ClusterDeployment/ClusterDetailsFormFields.tsx +11 -2
  104. package/lib/common/components/clusterConfiguration/index.ts +0 -2
  105. package/lib/common/components/clusterWizard/clusterDetailsValidation.ts +2 -33
  106. package/lib/common/components/clusterWizard/types.ts +0 -2
  107. package/lib/common/components/hosts/DiskRole.tsx +0 -1
  108. package/lib/common/components/hosts/TableToolbar.tsx +9 -10
  109. package/lib/common/components/operators/operatorSpecs.tsx +11 -8
  110. package/lib/common/components/ui/OpenShiftVersionDropdown.tsx +10 -10
  111. package/lib/common/components/ui/SimpleDropdown.tsx +0 -1
  112. package/lib/common/components/ui/formik/index.tsx +0 -1
  113. package/lib/common/config/constants.ts +0 -4
  114. package/lib/common/config/docs_links.ts +15 -15
  115. package/lib/common/selectors/clusterSelectors.ts +1 -2
  116. package/lib/common/types/cpuArchitecture.ts +3 -9
  117. package/lib/ocm/components/Routes.tsx +3 -0
  118. package/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx +3 -16
  119. package/lib/ocm/components/clusterConfiguration/OcmSNODisclaimer.tsx +14 -60
  120. package/lib/ocm/components/clusterConfiguration/networkConfiguration/SubnetsDropdown.tsx +18 -25
  121. package/lib/ocm/components/clusterConfiguration/staticIp/commonValidationSchemas.tsx +1 -1
  122. package/lib/ocm/components/clusterConfiguration/staticIp/components/FormViewNetworkWide/FormViewNetworkWideFields.tsx +2 -2
  123. package/lib/ocm/components/clusterConfiguration/staticIp/components/staticIp.css +3 -3
  124. package/lib/ocm/components/clusterConfiguration/staticIp/data/formDataToInfraEnvField.ts +1 -1
  125. package/lib/ocm/components/clusterDetail/ProgressBarAlerts.tsx +1 -1
  126. package/lib/ocm/components/clusterWizard/ClusterDetailsForm.tsx +0 -1
  127. package/lib/ocm/components/clusterWizard/CredentialsDownload.tsx +2 -1
  128. package/lib/ocm/components/clusterWizard/Operators.tsx +5 -1
  129. package/lib/ocm/components/clusters/AssistedInstallerHeader.tsx +9 -1
  130. package/lib/ocm/components/clusters/ClusterPage.tsx +3 -0
  131. package/lib/ocm/components/clusters/NewClusterPage.tsx +9 -13
  132. package/lib/ocm/components/hosts/use-hosts-table.tsx +8 -1
  133. package/lib/ocm/services/DiskEncryptionService.ts +1 -1
  134. package/lib/ocm/services/OperatorsService.tsx +18 -2
  135. package/lib/ocm/store/slices/current-cluster/selectors.ts +1 -1
  136. package/package.json +3 -3
  137. package/build/@types/common/components/clusterConfiguration/SNOControlGroup.d.ts +0 -10
  138. package/build/@types/common/components/clusterConfiguration/SNOControlGroup.d.ts.map +0 -1
  139. package/build/@types/common/components/clusterConfiguration/SNODisclaimer.d.ts +0 -10
  140. package/build/@types/common/components/clusterConfiguration/SNODisclaimer.d.ts.map +0 -1
  141. package/build/@types/common/components/operators/test.d.ts +0 -50
  142. package/build/@types/common/components/operators/test.d.ts.map +0 -1
  143. package/build/@types/common/components/ui/formik/SingleNodeCheckbox.d.ts +0 -9
  144. package/build/@types/common/components/ui/formik/SingleNodeCheckbox.d.ts.map +0 -1
  145. package/build/@types/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.d.ts +0 -11
  146. package/build/@types/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.d.ts.map +0 -1
  147. package/build/cjs/common/components/clusterConfiguration/SNOControlGroup.js +0 -20
  148. package/build/cjs/common/components/clusterConfiguration/SNOControlGroup.js.map +0 -1
  149. package/build/cjs/common/components/clusterConfiguration/SNODisclaimer.js +0 -31
  150. package/build/cjs/common/components/clusterConfiguration/SNODisclaimer.js.map +0 -1
  151. package/build/cjs/common/components/operators/test.js +0 -323
  152. package/build/cjs/common/components/operators/test.js.map +0 -1
  153. package/build/cjs/common/components/ui/formik/SingleNodeCheckbox.js +0 -45
  154. package/build/cjs/common/components/ui/formik/SingleNodeCheckbox.js.map +0 -1
  155. package/build/cjs/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.js +0 -51
  156. package/build/cjs/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.js.map +0 -1
  157. package/lib/common/components/clusterConfiguration/SNOControlGroup.tsx +0 -41
  158. package/lib/common/components/clusterConfiguration/SNODisclaimer.tsx +0 -79
  159. package/lib/common/components/operators/test.tsx +0 -469
  160. package/lib/common/components/ui/formik/SingleNodeCheckbox.tsx +0 -98
  161. package/lib/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.tsx +0 -107
@@ -19,11 +19,13 @@ export const UILibRoutes = ({
19
19
  children,
20
20
  history,
21
21
  basename,
22
+ additionalComponents,
22
23
  }: {
23
24
  allEnabledFeatures: FeatureListType;
24
25
  children?: React.ReactNode;
25
26
  history?: HistoryRouterProps['history'];
26
27
  basename?: string;
28
+ additionalComponents?: React.ReactNode;
27
29
  }) => {
28
30
  useFeatureDetection(allEnabledFeatures);
29
31
 
@@ -49,6 +51,7 @@ export const UILibRoutes = ({
49
51
  ) : (
50
52
  routes
51
53
  )}
54
+ {additionalComponents}
52
55
  </Provider>
53
56
  );
54
57
  };
@@ -9,14 +9,15 @@ import {
9
9
  DropdownList,
10
10
  } from '@patternfly/react-core';
11
11
  import { useField } from 'formik';
12
+ import toNumber from 'lodash-es/toNumber';
12
13
  import { getFieldId, PopoverIcon, PreviewBadgePosition, TechnologyPreview } from '../../../common';
14
+
13
15
  import {
14
16
  NewFeatureSupportLevelMap,
15
17
  useNewFeatureSupportLevel,
16
18
  } from '../../../common/components/newFeatureSupportLevels';
17
19
  import { isFeatureSupportedAndAvailable } from '../featureSupportLevels/featureStateUtils';
18
20
  import OcmTNADisclaimer from './OcmTNADisclaimer';
19
- import toNumber from 'lodash-es/toNumber';
20
21
  import OcmSNODisclaimer from './OcmSNODisclaimer';
21
22
 
22
23
  const INPUT_NAME = 'controlPlaneCount';
@@ -71,18 +72,10 @@ const ControlPlaneNodesDropdown: React.FC<ControlPlaneNodesDropdownProps> = ({
71
72
  const [isOpen, setOpen] = React.useState<boolean>(false);
72
73
  const newFeatureSupportLevelContext = useNewFeatureSupportLevel();
73
74
 
74
- const snoSupportLevel = newFeatureSupportLevelContext.getFeatureSupportLevel(
75
- 'SNO',
76
- featureSupportLevelData ?? undefined,
77
- );
78
75
  const snoExpansion = newFeatureSupportLevelContext.isFeatureSupported(
79
76
  'SINGLE_NODE_EXPANSION',
80
77
  featureSupportLevelData ?? undefined,
81
78
  );
82
- const isDisabled = newFeatureSupportLevelContext.isFeatureDisabled(
83
- 'SNO',
84
- featureSupportLevelData ?? undefined,
85
- );
86
79
 
87
80
  const disabledReason =
88
81
  'This option is not available with the current configurations. Make sure that OpenShift version is 4.19 or newer and no external platform integration is selected.';
@@ -171,13 +164,7 @@ const ControlPlaneNodesDropdown: React.FC<ControlPlaneNodesDropdownProps> = ({
171
164
  <DropdownList>{dropdownItems}</DropdownList>
172
165
  </Dropdown>
173
166
  </FormGroup>
174
- {field.value === 1 && (
175
- <OcmSNODisclaimer
176
- isDisabled={isDisabled}
177
- snoSupportLevel={snoSupportLevel || 'supported'}
178
- snoExpansionSupported={snoExpansion}
179
- />
180
- )}
167
+ {field.value === 1 && <OcmSNODisclaimer snoExpansionSupported={snoExpansion} />}
181
168
  {field.value === 2 && <OcmTNADisclaimer />}
182
169
  </>
183
170
  );
@@ -1,77 +1,31 @@
1
1
  import React from 'react';
2
- import { Alert, AlertVariant, List, ListItem, Stack, StackItem } from '@patternfly/react-core';
3
- import { CheckboxField } from '../../../common';
2
+ import { Alert, AlertVariant, List, ListItem } from '@patternfly/react-core';
4
3
  import { useTranslation } from '../../../common/hooks/use-translation-wrapper';
5
- import { SupportLevel } from '@openshift-assisted/types/assisted-installer-service';
6
4
 
7
5
  type OcmSNODisclaimerProps = {
8
- snoSupportLevel: SupportLevel;
9
- isDisabled?: boolean;
10
6
  snoExpansionSupported?: boolean;
11
7
  };
12
- const OcmSNODisclaimer = ({
13
- snoSupportLevel,
14
- isDisabled = false,
15
- snoExpansionSupported = false,
16
- }: OcmSNODisclaimerProps) => {
8
+ const OcmSNODisclaimer = ({ snoExpansionSupported = false }: OcmSNODisclaimerProps) => {
17
9
  const { t } = useTranslation();
18
- if (!['dev-preview', 'supported'].includes(snoSupportLevel)) {
19
- //if tech preview or unsupported there's no definition which warning to show
20
- return null;
21
- }
22
- const isDevPreview = snoSupportLevel === 'dev-preview';
23
- const generalSNOFacts = (
24
- <>
25
- <ListItem>
26
- {t(
27
- 'ai:Installing SNO will result in an OpenShift deployment that is not highly available.',
28
- )}
29
- </ListItem>
30
- {!snoExpansionSupported && (
31
- <ListItem>
32
- {t('ai:Currently, adding additional machines to your cluster is not supported.')}
33
- </ListItem>
34
- )}
35
- </>
36
- );
37
- const unsupportedWarnings = (
38
- <>
39
- <ListItem>
40
- {t('ai:SNO is in a proof-of-concept stage and is not supported in any way.')}
41
- </ListItem>
42
- <ListItem>
43
- {t(
44
- "ai:OpenShift in-place upgrades aren't expected to work with SNO. If an upgrade is needed, your system will need a redeployment.",
45
- )}
46
- </ListItem>
47
- </>
48
- );
49
10
 
50
11
  return (
51
12
  <Alert
52
- variant={isDevPreview ? AlertVariant.warning : AlertVariant.info}
13
+ variant={AlertVariant.info}
53
14
  title={t('ai:Limitations for using Single Node OpenShift')}
54
15
  isInline
55
16
  >
56
- <Stack hasGutter>
57
- <StackItem>
58
- <List>
59
- {generalSNOFacts}
60
- {isDevPreview && unsupportedWarnings}
61
- </List>
62
- </StackItem>
63
- {isDevPreview && (
64
- <StackItem>
65
- <CheckboxField
66
- name="SNODisclaimer"
67
- label={t(
68
- 'ai:I understand, accept, and agree to the limitations associated with using Single Node OpenShift.',
69
- )}
70
- isDisabled={isDisabled}
71
- />
72
- </StackItem>
17
+ <List>
18
+ <ListItem>
19
+ {t(
20
+ 'ai:Installing SNO will result in an OpenShift deployment that is not highly available.',
21
+ )}
22
+ </ListItem>
23
+ {!snoExpansionSupported && (
24
+ <ListItem>
25
+ {t('ai:Currently, adding additional machines to your cluster is not supported.')}
26
+ </ListItem>
73
27
  )}
74
- </Stack>
28
+ </List>
75
29
  </Alert>
76
30
  );
77
31
  };
@@ -35,32 +35,29 @@ const noSubnetAvailableOption = {
35
35
  export const SubnetsDropdown = ({ name, machineSubnets, isDisabled }: SubnetsDropdownProps) => {
36
36
  const [field, , { setValue }] = useField(name);
37
37
  const [isOpen, setOpen] = React.useState(false);
38
- const [currentDisplayValue, setCurrentDisplayValue] = React.useState<string | undefined>();
39
38
  const fieldId = getFieldId(name, 'input');
40
39
 
41
- const itemsSubnets = React.useMemo(() => {
42
- return machineSubnets.length === 0
43
- ? [noSubnetAvailableOption]
44
- : [makeNoSubnetSelectedOption(machineSubnets.length)].concat(
45
- toFormSelectOptions(machineSubnets),
46
- );
47
- }, [machineSubnets]);
40
+ const { itemsSubnets, currentDisplayValue } = React.useMemo(() => {
41
+ const itemsSubnets =
42
+ machineSubnets.length === 0
43
+ ? [noSubnetAvailableOption]
44
+ : [makeNoSubnetSelectedOption(machineSubnets.length)].concat(
45
+ toFormSelectOptions(machineSubnets),
46
+ );
48
47
 
49
- React.useEffect(() => {
48
+ let currentDisplayValue = itemsSubnets[0].label; // The placeholder is the fallback
50
49
  if (field.value) {
51
- // If the field already has a value then it must have been assigned from one of the entries in the `itemsSubnets`
52
50
  const subnetItem = itemsSubnets.find((item) => item.value === field.value);
53
- setCurrentDisplayValue(subnetItem?.label ?? itemsSubnets[0].label);
54
- } else {
55
- // When `itemsSubnets.length === 2`, there is a placeholder at index 0 and only one subnet at index 1.
56
- // In all the other cases the user should see the placeholder saying that either there is no subnet available
57
- // or there is more than one option they can choose from.
58
- const defaultValue =
59
- itemsSubnets.length === 2 ? itemsSubnets[1].label : itemsSubnets[0].label;
60
- setCurrentDisplayValue(defaultValue);
51
+ if (subnetItem) {
52
+ currentDisplayValue = subnetItem.label;
53
+ }
54
+ } else if (machineSubnets.length === 1) {
55
+ // When there is only one subnet, it's selected by default. We skip the placeholder at index 0.
56
+ currentDisplayValue = itemsSubnets[1].label;
61
57
  }
62
- // eslint-disable-next-line react-hooks/exhaustive-deps
63
- }, []);
58
+
59
+ return { itemsSubnets, currentDisplayValue: currentDisplayValue };
60
+ }, [machineSubnets, field.value]);
64
61
 
65
62
  const dropdownItems = itemsSubnets.map(({ value, label, isDisabled }) => (
66
63
  <DropdownItem key={value} id={value} isDisabled={isDisabled} value={value}>
@@ -68,11 +65,7 @@ export const SubnetsDropdown = ({ name, machineSubnets, isDisabled }: SubnetsDro
68
65
  </DropdownItem>
69
66
  ));
70
67
 
71
- const onSelect = (
72
- event?: React.MouseEvent<Element, MouseEvent>,
73
- value?: string | number,
74
- ): void => {
75
- setCurrentDisplayValue(value as string);
68
+ const onSelect = (event?: React.MouseEvent<Element, MouseEvent>): void => {
76
69
  setValue(event?.currentTarget.id);
77
70
  setOpen(false);
78
71
  };
@@ -201,7 +201,7 @@ export const getIpAddressInSubnetValidationSchema = (
201
201
  ) => {
202
202
  return Yup.string().test(
203
203
  'is-in-subnet',
204
- `IP Address is outside of the machine network ${subnet}`,
204
+ `IP Address is outside of the subnet ${subnet}`,
205
205
  (value, testContext: Yup.TestContext) => {
206
206
  if (!value) {
207
207
  return true;
@@ -82,10 +82,10 @@ const MachineNetwork: React.FC<{ fieldName: string; protocolVersion: ProtocolVer
82
82
  labelIcon={
83
83
  <PopoverIcon noVerticalAlign bodyContent="The range of IP addresses of the hosts." />
84
84
  }
85
- label="Machine network"
85
+ label="Subnet"
86
86
  fieldId={fieldId}
87
87
  isRequired
88
- className="machine-network"
88
+ className="subnet"
89
89
  >
90
90
  <Flex>
91
91
  <FlexItem spacer={{ default: 'spacerSm' }}>
@@ -16,14 +16,14 @@
16
16
  font-weight: unset;
17
17
  }
18
18
 
19
- .machine-network .pf-l-flex > div:nth-child(1) {
19
+ .subnet .pf-l-flex > div:nth-child(1) {
20
20
  flex: 0 0 24rem;
21
21
  }
22
22
 
23
- .machine-network .pf-l-flex > div:nth-child(3) {
23
+ .subnet .pf-l-flex > div:nth-child(3) {
24
24
  flex: 0 0 6rem;
25
25
  }
26
26
 
27
- .machine-network .pf-v5-c-form__helper-text.pf-m-error {
27
+ .subnet .pf-v5-c-form__helper-text.pf-m-error {
28
28
  margin-top: unset;
29
29
  }
@@ -44,7 +44,7 @@ const getPrefixLength = (
44
44
  ): number => {
45
45
  const machineNetwork = networkWide.ipConfigs[protocolVersion].machineNetwork;
46
46
  if (machineNetwork.prefixLength === '') {
47
- throw 'Machine network prefix length not configured';
47
+ throw 'Subnet prefix length not configured';
48
48
  }
49
49
  return machineNetwork.prefixLength;
50
50
  };
@@ -114,7 +114,7 @@ export const HostsInstallationFailed = ({
114
114
  const { resetClusterDialog } = useModalDialogsContext();
115
115
  const getID = (suffix: string) => `cluster-install-error-${suffix}`;
116
116
  let title, message;
117
- if (cluster.highAvailabilityMode === 'None' || failedHosts > 0) {
117
+ if (cluster.controlPlaneCount === 1 || failedHosts > 0) {
118
118
  title = 'Control plane was not installed';
119
119
  message = `${failedHosts}/${totalHosts} control plane nodes failed to install. Please check the installation logs for more information.`;
120
120
  } else if (isCriticalNumberOfWorkersFailed) {
@@ -136,7 +136,6 @@ const ClusterDetailsForm = (props: ClusterDetailsFormProps) => {
136
136
  const validationSchema = getClusterDetailsValidationSchema({
137
137
  usedClusterNames,
138
138
  pullSecretSet: cluster?.pullSecretSet,
139
- ocpVersions,
140
139
  isOcm: true,
141
140
  t,
142
141
  });
@@ -22,7 +22,7 @@ const CredentialsDownload: React.FC<{ cluster: Cluster }> = ({ cluster }) => {
22
22
  const clusterWizardContext = useClusterWizardContext();
23
23
  const [isChecked, setIsChecked] = React.useState<boolean>(false);
24
24
  const [isDownloading, setIsDownloading] = React.useState(false);
25
- const { addAlert } = useAlerts();
25
+ const { addAlert, clearAlerts } = useAlerts();
26
26
  const { t } = useTranslation();
27
27
 
28
28
  const downloadSingleFile = async (fileName: string) => {
@@ -42,6 +42,7 @@ const CredentialsDownload: React.FC<{ cluster: Cluster }> = ({ cluster }) => {
42
42
  };
43
43
 
44
44
  const handleDownloadClick = async () => {
45
+ clearAlerts();
45
46
  setIsDownloading(true);
46
47
 
47
48
  const configSuccess = await downloadSingleFile('kubeconfig');
@@ -21,6 +21,10 @@ import { setServerUpdateError, updateCluster } from '../../store/slices/current-
21
21
  import { getApiErrorMessage, handleApiError, isUnknownServerError } from '../../../common/api';
22
22
  import { canNextOperators } from './wizardTransition';
23
23
 
24
+ // Balance debounce time: fast clicks should trigger a single API call,
25
+ // but making it shorter will allow us to disable navigation buttons while changes are pending
26
+ const operatorsAutoSaveDebounce = 500;
27
+
24
28
  const getOperatorsInitialValues = (
25
29
  uiSettings: UISettingsValues | undefined,
26
30
  cluster: Cluster,
@@ -34,7 +38,7 @@ const getOperatorsInitialValues = (
34
38
  const OperatorsForm = ({ cluster }: { cluster: Cluster }) => {
35
39
  const { alerts } = useAlerts();
36
40
  const clusterWizardContext = useClusterWizardContext();
37
- const isAutoSaveRunning = useFormikAutoSave();
41
+ const isAutoSaveRunning = useFormikAutoSave(operatorsAutoSaveDebounce);
38
42
  const { errors, touched, isSubmitting, isValid } = useFormikContext<OperatorsValues>();
39
43
  const navigate = useNavigate();
40
44
  const { pathname } = useLocation();
@@ -1,13 +1,21 @@
1
1
  import React from 'react';
2
2
  import { TextContent, Text, Split, SplitItem } from '@patternfly/react-core';
3
- import { ASSISTED_INSTALLER_DOCUMENTATION_LINK, ExternalLink, isInOcm } from '../../../common';
3
+ import {
4
+ ASSISTED_INSTALLER_DOCUMENTATION_LINK,
5
+ DeveloperPreview,
6
+ ExternalLink,
7
+ isInOcm,
8
+ } from '../../../common';
9
+ import { useFeature } from '../../hooks/use-feature';
4
10
 
5
11
  export const AssistedInstallerHeader = () => {
12
+ const isSingleClusterFeatureEnabled = useFeature('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
6
13
  return (
7
14
  <TextContent>
8
15
  <Text component="h1" className="pf-v5-u-display-inline">
9
16
  Install OpenShift with the Assisted Installer
10
17
  </Text>
18
+ {isSingleClusterFeatureEnabled && <DeveloperPreview />}
11
19
  <Split hasGutter>
12
20
  <SplitItem>
13
21
  <ExternalLink href={ASSISTED_INSTALLER_DOCUMENTATION_LINK}>
@@ -205,6 +205,9 @@ export const SingleClusterPage = ({
205
205
  resetModal: React.ReactNode;
206
206
  }) => (
207
207
  <AlertsContextProvider>
208
+ <PageSection variant={PageSectionVariants.light}>
209
+ <AssistedInstallerHeader />
210
+ </PageSection>
208
211
  <ClusterPageGeneric clusterId={clusterId} resetModal={resetModal} />
209
212
  </AlertsContextProvider>
210
213
  );
@@ -1,4 +1,4 @@
1
- import React, { ReactNode } from 'react';
1
+ import React from 'react';
2
2
  import { PageSectionVariants, PageSection } from '@patternfly/react-core';
3
3
  import { AlertsContextProvider } from '../../../common';
4
4
  import ClusterBreadcrumbs from './ClusterBreadcrumbs';
@@ -13,7 +13,7 @@ import { AssistedInstallerHeader } from './AssistedInstallerHeader';
13
13
  import { ModalDialogsContextProvider } from '../hosts/ModalDialogsContext';
14
14
  import { OpenShiftVersionsContextProvider } from '../clusterWizard/OpenShiftVersionsContext';
15
15
 
16
- const NewClusterPageGeneric = ({ pageTitleSection }: { pageTitleSection?: ReactNode }) => {
16
+ const NewClusterPageGeneric = ({ children }: React.PropsWithChildren<unknown>) => {
17
17
  return (
18
18
  <AlertsContextProvider>
19
19
  <SentryErrorMonitorContextProvider>
@@ -24,7 +24,10 @@ const NewClusterPageGeneric = ({ pageTitleSection }: { pageTitleSection?: ReactN
24
24
  >
25
25
  <OpenShiftVersionsContextProvider>
26
26
  <NewFeatureSupportLevelProvider loadingUi={<ClusterLoading />}>
27
- {pageTitleSection}
27
+ {children}
28
+ <PageSection variant={PageSectionVariants.light}>
29
+ <AssistedInstallerHeader />
30
+ </PageSection>
28
31
  <PageSection variant={PageSectionVariants.light} isFilled>
29
32
  <ClusterWizardContextProvider>
30
33
  <NewClusterWizard />
@@ -39,16 +42,9 @@ const NewClusterPageGeneric = ({ pageTitleSection }: { pageTitleSection?: ReactN
39
42
  );
40
43
  };
41
44
 
42
- const NewClusterTitleSection = () => (
43
- <>
44
- <ClusterBreadcrumbs clusterName="New cluster" />
45
- <PageSection variant={PageSectionVariants.light}>
46
- <AssistedInstallerHeader />
47
- </PageSection>
48
- </>
49
- );
50
-
51
45
  export const NewSingleClusterPage = () => <NewClusterPageGeneric />;
52
46
  export const NewClusterPage = () => (
53
- <NewClusterPageGeneric pageTitleSection={<NewClusterTitleSection />} />
47
+ <NewClusterPageGeneric>
48
+ <ClusterBreadcrumbs clusterName="New cluster" />
49
+ </NewClusterPageGeneric>
54
50
  );
@@ -326,7 +326,14 @@ export const useHostsTable = (cluster: Cluster) => {
326
326
  throw new Error(`Failed to edit role in host: ${host.id}.\nMissing cluster_id`);
327
327
  }
328
328
  const { data } = await HostsService.updateRole(host, role);
329
- resetCluster ? void resetCluster() : dispatch(updateHost(data));
329
+
330
+ if (resetCluster) {
331
+ void resetCluster();
332
+ } else {
333
+ dispatch(updateHost(data));
334
+ // Reload to obtain cluster-level validations that may be affected by role change
335
+ dispatch(forceReload());
336
+ }
330
337
  } catch (e) {
331
338
  handleApiError(e, () =>
332
339
  addAlert({ title: 'Failed to set role', message: getApiErrorMessage(e) }),
@@ -26,7 +26,7 @@ const DiskEncryptionService = {
26
26
  return {
27
27
  mode: values.diskEncryptionMode,
28
28
  enableOn:
29
- values.highAvailabilityMode === 'None'
29
+ values.controlPlaneCount === 1
30
30
  ? values.enableDiskEncryptionOnMasters
31
31
  ? 'all'
32
32
  : 'none'
@@ -1,9 +1,25 @@
1
1
  import OperatorsAPI from '../../common/api/assisted-service/OperatorsAPI';
2
+ import { getOperatorSpecs } from '../../common/components/operators/operatorSpecs';
3
+
4
+ const getAllKnownOperatorKeys = (): Set<string> => {
5
+ const allSpecsByCategory = getOperatorSpecs(() => undefined);
6
+
7
+ const allKeys = Object.values(allSpecsByCategory)
8
+ .flat()
9
+ .map((spec) => spec.operatorKey);
10
+
11
+ return new Set(allKeys);
12
+ };
2
13
 
3
14
  const OperatorsService = {
4
15
  getSupportedOperators: async (): Promise<string[]> => {
5
- const { data: operators } = await OperatorsAPI.list();
6
- return operators;
16
+ const knownOperatorKeys = getAllKnownOperatorKeys();
17
+ const { data: operatorsFromAPI } = await OperatorsAPI.list();
18
+ const filteredOperators = operatorsFromAPI.filter((operatorName) =>
19
+ knownOperatorKeys.has(operatorName),
20
+ );
21
+
22
+ return filteredOperators;
7
23
  },
8
24
  };
9
25
  export default OperatorsService;
@@ -5,7 +5,7 @@ export const selectCurrentClusterState = (state: RootStateDay1) => state.current
5
5
  export const selectCurrentCluster = (state: RootStateDay1) => state.currentCluster.data;
6
6
  export const selectCurrentClusterUIState = (state: RootStateDay1) => state.currentCluster.uiState;
7
7
  export const selectIsCurrentClusterSNO = (state: RootStateDay1) =>
8
- state.currentCluster.data?.highAvailabilityMode === 'None';
8
+ state.currentCluster.data?.controlPlaneCount === 1;
9
9
  export const selectCurrentClusterPermissionsState = (
10
10
  state: RootStateDay1,
11
11
  ): AssistedInstallerPermissionTypesListType => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dependencies": {
3
- "@openshift-assisted/locales": "2.42.2",
4
- "@openshift-assisted/types": "2.42.2",
3
+ "@openshift-assisted/locales": "2.43.0",
4
+ "@openshift-assisted/types": "2.43.0",
5
5
  "@openshift-console/dynamic-plugin-sdk": "0.0.3",
6
6
  "@patternfly/patternfly": "5.2.0",
7
7
  "@patternfly/react-code-editor": "5.2.0",
@@ -140,5 +140,5 @@
140
140
  ]
141
141
  }
142
142
  },
143
- "version": "2.42.2"
143
+ "version": "2.43.0"
144
144
  }
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- import { ClusterDetailsValues } from '../../../common/components/clusterWizard/types';
3
- import { OpenshiftVersionOptionType } from '../../types';
4
- type SNOControlGroupProps = {
5
- versions: OpenshiftVersionOptionType[];
6
- highAvailabilityMode: ClusterDetailsValues['highAvailabilityMode'];
7
- };
8
- declare const SNOControlGroup: ({ versions, highAvailabilityMode }: SNOControlGroupProps) => React.JSX.Element;
9
- export default SNOControlGroup;
10
- //# sourceMappingURL=SNOControlGroup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SNOControlGroup.d.ts","sourceRoot":"","sources":["../../../../../lib/common/components/clusterConfiguration/SNOControlGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AAEtF,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAIzD,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,oBAAoB,EAAE,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;CACpE,CAAC;AAEF,QAAA,MAAM,eAAe,uCAAwC,oBAAoB,sBAyBhF,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- import { SupportLevel } from '@openshift-assisted/types/assisted-installer-service';
3
- type SNODisclaimerProps = {
4
- snoSupportLevel: SupportLevel;
5
- isDisabled?: boolean;
6
- snoExpansionSupported?: boolean;
7
- };
8
- declare const SNODisclaimer: ({ snoSupportLevel, isDisabled, snoExpansionSupported, }: SNODisclaimerProps) => React.JSX.Element | null;
9
- export default SNODisclaimer;
10
- //# sourceMappingURL=SNODisclaimer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SNODisclaimer.d.ts","sourceRoot":"","sources":["../../../../../lib/common/components/clusterConfiguration/SNODisclaimer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAC;AAEpF,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,YAAY,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AACF,QAAA,MAAM,aAAa,4DAIhB,kBAAkB,6BA6DpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -1,50 +0,0 @@
1
- import React from 'react';
2
- import { Cluster, SupportLevel } from '@openshift-assisted/types/assisted-installer-service';
3
- import { FeatureId } from '../../types';
4
- import { GetFeatureSupportLevel } from '../newFeatureSupportLevels';
5
- export declare const isOCPVersionEqualsOrMore: (openshiftVersion: string, ocpVersionToCompare: string) => boolean;
6
- export declare const highlightMatch: (text: string, searchTerm?: string) => React.ReactNode;
7
- export declare const HighlightedText: ({ text, searchTerm }: {
8
- text: string;
9
- searchTerm?: string | undefined;
10
- }) => React.JSX.Element;
11
- export type OperatorSpec = {
12
- operatorKey: string;
13
- title: string;
14
- featureId: FeatureId;
15
- descriptionText?: string;
16
- Description?: React.ComponentType<{
17
- openshiftVersion?: string;
18
- searchTerm?: string;
19
- }>;
20
- notStandalone?: boolean;
21
- Requirements?: React.ComponentType<{
22
- cluster: Cluster;
23
- }>;
24
- supportLevel?: SupportLevel | undefined;
25
- };
26
- export declare const getOperatorSpecs: (getFeatureSupportLevel: GetFeatureSupportLevel, useLVMS?: boolean) => {
27
- [category: string]: OperatorSpec[];
28
- };
29
- export declare const useOperatorSpecs: () => {
30
- byCategory: {
31
- [category: string]: OperatorSpec[];
32
- };
33
- byKey: Record<string, OperatorSpec>;
34
- };
35
- export declare const getOperatorTitleByFeatureId: (featureId: FeatureId) => string | undefined;
36
- declare enum Category {
37
- STORAGE = 0,
38
- VIRT = 1,
39
- AI = 2,
40
- NETWORK = 3,
41
- CI_CD = 4,
42
- PLATFORM = 5,
43
- SECURITY = 6,
44
- SCHEDULING = 7
45
- }
46
- export declare const categories: {
47
- [key in Category]: string;
48
- };
49
- export {};
50
- //# sourceMappingURL=test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../../../lib/common/components/operators/test.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA+CxC,OAAO,EAAE,sBAAsB,EAA6B,MAAM,4BAA4B,CAAC;AAwB/F,eAAO,MAAM,wBAAwB,qBACjB,MAAM,uBACH,MAAM,KAC1B,OAOF,CAAC;AAEF,eAAO,MAAM,cAAc,SAAU,MAAM,eAAe,MAAM,KAAG,MAAM,SAUxE,CAAC;AAEF,eAAO,MAAM,eAAe;UAAkC,MAAM;;uBAEnE,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,gBAAgB,2BACH,sBAAsB,YACpC,OAAO;;CAwSlB,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;CAqB5B,CAAC;AAEF,eAAO,MAAM,2BAA2B,cAAe,SAAS,KAAG,MAAM,GAAG,SAW3E,CAAC;AAEF,aAAK,QAAQ;IACX,OAAO,IAAA;IACP,IAAI,IAAA;IACJ,EAAE,IAAA;IACF,OAAO,IAAA;IACP,KAAK,IAAA;IACL,QAAQ,IAAA;IACR,QAAQ,IAAA;IACR,UAAU,IAAA;CACX;AAED,eAAO,MAAM,UAAU,EAAE;KAAG,GAAG,IAAI,QAAQ,GAAG,MAAM;CASnD,CAAC"}
@@ -1,9 +0,0 @@
1
- import * as React from 'react';
2
- import { OpenshiftVersionOptionType } from '../../../types';
3
- import { CheckboxFieldProps } from './types';
4
- type SingleNodeCheckboxProps = CheckboxFieldProps & {
5
- versions: OpenshiftVersionOptionType[];
6
- };
7
- declare const SingleNodeCheckbox: React.FC<SingleNodeCheckboxProps>;
8
- export default SingleNodeCheckbox;
9
- //# sourceMappingURL=SingleNodeCheckbox.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SingleNodeCheckbox.d.ts","sourceRoot":"","sources":["../../../../../../lib/common/components/ui/formik/SingleNodeCheckbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAK7C,KAAK,uBAAuB,GAAG,kBAAkB,GAAG;IAAE,QAAQ,EAAE,0BAA0B,EAAE,CAAA;CAAE,CAAC;AAE/F,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4EzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1,11 +0,0 @@
1
- import * as React from 'react';
2
- import { CheckboxFieldProps } from '../../../common/components/ui/formik/types';
3
- import { SupportLevel } from '@openshift-assisted/types/assisted-installer-service';
4
- export interface OcmCheckboxProps extends CheckboxFieldProps {
5
- disabledReason?: string;
6
- isSupportedVersionAvailable?: boolean;
7
- supportLevel?: SupportLevel;
8
- }
9
- declare const OcmSingleNodeCheckbox: React.FC<OcmCheckboxProps>;
10
- export default OcmSingleNodeCheckbox;
11
- //# sourceMappingURL=OcmSingleNodeCheckbox.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OcmSingleNodeCheckbox.d.ts","sourceRoot":"","sources":["../../../../../lib/ocm/components/clusterConfiguration/OcmSingleNodeCheckbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAGhF,OAAO,EAEL,YAAY,EACb,MAAM,sDAAsD,CAAC;AAE9D,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA8ErD,CAAC;AAEF,eAAe,qBAAqB,CAAC"}