@openshift-assisted/ui-lib 2.12.3-cim → 2.12.5-cim
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.
- package/build/@types/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.d.ts +2 -1
- package/build/@types/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.d.ts.map +1 -1
- package/build/@types/cim/components/ClusterDeployment/ClusterDetailsFormFields.d.ts +1 -0
- package/build/@types/cim/components/ClusterDeployment/ClusterDetailsFormFields.d.ts.map +1 -1
- package/build/@types/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsForm.d.ts.map +1 -1
- package/build/@types/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsStep.d.ts.map +1 -1
- package/build/@types/cim/components/Hypershift/HostedClusterWizard/DetailsStep/types.d.ts +6 -1
- package/build/@types/cim/components/Hypershift/HostedClusterWizard/DetailsStep/types.d.ts.map +1 -1
- package/build/@types/cim/components/Hypershift/hooks/useSupportedOCPVersions.d.ts +1 -1
- package/build/@types/cim/components/Hypershift/hooks/useSupportedOCPVersions.d.ts.map +1 -1
- package/build/@types/cim/components/helpers/versions.d.ts +3 -3
- package/build/@types/cim/components/helpers/versions.d.ts.map +1 -1
- package/build/@types/cim/types/k8s/agent-service-config.d.ts +6 -0
- package/build/@types/cim/types/k8s/agent-service-config.d.ts.map +1 -1
- package/build/@types/common/components/clusterConfiguration/index.d.ts +0 -1
- package/build/@types/common/components/clusterConfiguration/index.d.ts.map +1 -1
- package/build/@types/common/components/clusterWizard/clusterDetailsValidation.d.ts.map +1 -1
- package/build/@types/common/components/clusterWizard/types.d.ts +6 -0
- package/build/@types/common/components/clusterWizard/types.d.ts.map +1 -1
- package/build/@types/common/components/ui/OpenShiftSelectWithSearch.d.ts +11 -0
- package/build/@types/common/components/ui/OpenShiftSelectWithSearch.d.ts.map +1 -0
- package/build/@types/common/components/ui/OpenShiftVersionDropdown.d.ts +8 -8
- package/build/@types/common/components/ui/OpenShiftVersionDropdown.d.ts.map +1 -1
- package/build/@types/common/components/ui/OpenShiftVersionModal.d.ts +11 -0
- package/build/@types/common/components/ui/OpenShiftVersionModal.d.ts.map +1 -0
- package/build/@types/ocm/components/clusterConfiguration/OcmOpenShiftVersionSelect.d.ts.map +1 -1
- package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.js +4 -3
- package/build/cjs/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.js.map +1 -1
- package/build/cjs/cim/components/ClusterDeployment/ClusterDetailsFormFields.js +37 -11
- package/build/cjs/cim/components/ClusterDeployment/ClusterDetailsFormFields.js.map +1 -1
- package/build/cjs/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsForm.js +23 -3
- package/build/cjs/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsForm.js.map +1 -1
- package/build/cjs/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsStep.js +3 -1
- package/build/cjs/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsStep.js.map +1 -1
- package/build/cjs/cim/components/Hypershift/hooks/useSupportedOCPVersions.js +3 -3
- package/build/cjs/cim/components/Hypershift/hooks/useSupportedOCPVersions.js.map +1 -1
- package/build/cjs/cim/components/helpers/versions.js +10 -5
- package/build/cjs/cim/components/helpers/versions.js.map +1 -1
- package/build/cjs/common/components/clusterConfiguration/index.js +1 -3
- package/build/cjs/common/components/clusterConfiguration/index.js.map +1 -1
- package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js +1 -0
- package/build/cjs/common/components/clusterWizard/clusterDetailsValidation.js.map +1 -1
- package/build/cjs/common/components/ui/OpenShiftSelectWithSearch.js +55 -0
- package/build/cjs/common/components/ui/OpenShiftSelectWithSearch.js.map +1 -0
- package/build/cjs/common/components/ui/OpenShiftVersionDropdown.css +7 -0
- package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js +50 -27
- package/build/cjs/common/components/ui/OpenShiftVersionDropdown.js.map +1 -1
- package/build/cjs/common/components/ui/OpenShiftVersionModal.css +7 -0
- package/build/cjs/common/components/ui/OpenShiftVersionModal.js +28 -0
- package/build/cjs/common/components/ui/OpenShiftVersionModal.js.map +1 -0
- package/build/cjs/ocm/components/clusterConfiguration/OcmOpenShiftVersionSelect.js +5 -1
- package/build/cjs/ocm/components/clusterConfiguration/OcmOpenShiftVersionSelect.js.map +1 -1
- package/lib/cim/components/ClusterDeployment/ClusterDeploymentDetailsForm.tsx +13 -5
- package/lib/cim/components/ClusterDeployment/ClusterDetailsFormFields.tsx +57 -13
- package/lib/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsForm.tsx +45 -3
- package/lib/cim/components/Hypershift/HostedClusterWizard/DetailsStep/DetailsStep.tsx +4 -0
- package/lib/cim/components/Hypershift/HostedClusterWizard/DetailsStep/types.ts +6 -1
- package/lib/cim/components/Hypershift/hooks/useSupportedOCPVersions.ts +3 -2
- package/lib/cim/components/helpers/versions.ts +19 -4
- package/lib/cim/types/k8s/agent-service-config.ts +7 -0
- package/lib/common/components/clusterConfiguration/index.ts +0 -1
- package/lib/common/components/clusterWizard/clusterDetailsValidation.ts +1 -0
- package/lib/common/components/clusterWizard/types.ts +7 -0
- package/lib/common/components/ui/OpenShiftSelectWithSearch.tsx +130 -0
- package/lib/common/components/ui/OpenShiftVersionDropdown.css +7 -0
- package/lib/common/components/ui/OpenShiftVersionDropdown.tsx +101 -56
- package/lib/common/components/ui/OpenShiftVersionModal.css +7 -0
- package/lib/common/components/ui/OpenShiftVersionModal.tsx +61 -0
- package/lib/ocm/components/clusterConfiguration/OcmOpenShiftVersionSelect.tsx +11 -1
- package/package.json +3 -3
- package/build/@types/common/components/clusterConfiguration/OpenShiftVersionSelect.d.ts +0 -10
- package/build/@types/common/components/clusterConfiguration/OpenShiftVersionSelect.d.ts.map +0 -1
- package/build/cjs/common/components/clusterConfiguration/OpenShiftVersionSelect.js +0 -55
- package/build/cjs/common/components/clusterConfiguration/OpenShiftVersionSelect.js.map +0 -1
- package/lib/common/components/clusterConfiguration/OpenShiftVersionSelect.tsx +0 -81
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { Form } from '@patternfly/react-core';
|
|
2
2
|
import { useFormikContext } from 'formik';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { InputField,
|
|
4
|
+
import { InputField, PullSecret } from '../../../../../common';
|
|
5
5
|
import { useTranslation } from '../../../../../common/hooks/use-translation-wrapper';
|
|
6
6
|
import { BaseDnsHelperText } from '../../../ClusterDeployment/ClusterDetailsFormFields';
|
|
7
7
|
import { useTemptiflySync } from '../../hooks/useTemptiflySync';
|
|
8
8
|
import { DetailsFormProps, DetailsFormValues } from './types';
|
|
9
|
+
import { OpenShiftVersionDropdown } from '../../../../../common/components/ui/OpenShiftVersionDropdown';
|
|
10
|
+
import { OpenShiftVersionModal } from '../../../../../common/components/ui/OpenShiftVersionModal';
|
|
9
11
|
|
|
10
12
|
const DetailsForm: React.FC<DetailsFormProps> = ({
|
|
11
13
|
onValuesChanged,
|
|
12
14
|
extensionAfter,
|
|
13
15
|
ocpVersions,
|
|
16
|
+
allVersions,
|
|
14
17
|
}) => {
|
|
18
|
+
const { t } = useTranslation();
|
|
19
|
+
const [openshiftVersionModalOpen, setOpenshiftVersionModalOpen] = React.useState(false);
|
|
15
20
|
const { values } = useFormikContext<DetailsFormValues>();
|
|
16
21
|
useTemptiflySync({ values, onValuesChanged });
|
|
17
22
|
|
|
@@ -20,7 +25,30 @@ const DetailsForm: React.FC<DetailsFormProps> = ({
|
|
|
20
25
|
nameInputRef.current?.focus();
|
|
21
26
|
}, []);
|
|
22
27
|
|
|
23
|
-
const
|
|
28
|
+
const selectOptions = React.useMemo(
|
|
29
|
+
() =>
|
|
30
|
+
ocpVersions.map((version) => ({
|
|
31
|
+
label: version.label,
|
|
32
|
+
value: version.value,
|
|
33
|
+
})),
|
|
34
|
+
[ocpVersions],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const additionalSelectOptions = React.useMemo(() => {
|
|
38
|
+
if (
|
|
39
|
+
values.customOpenshiftSelect &&
|
|
40
|
+
!selectOptions.some((option) => option.value === values.customOpenshiftSelect?.value)
|
|
41
|
+
) {
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
value: values.customOpenshiftSelect.value,
|
|
45
|
+
label: values.customOpenshiftSelect.label,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
return [];
|
|
50
|
+
}, [selectOptions, values.customOpenshiftSelect]);
|
|
51
|
+
|
|
24
52
|
return (
|
|
25
53
|
<Form>
|
|
26
54
|
<InputField
|
|
@@ -38,7 +66,21 @@ const DetailsForm: React.FC<DetailsFormProps> = ({
|
|
|
38
66
|
placeholder="example.com"
|
|
39
67
|
isRequired
|
|
40
68
|
/>
|
|
41
|
-
<
|
|
69
|
+
<OpenShiftVersionDropdown
|
|
70
|
+
name="openshiftVersion"
|
|
71
|
+
items={selectOptions}
|
|
72
|
+
versions={ocpVersions}
|
|
73
|
+
showReleasesLink={false}
|
|
74
|
+
showOpenshiftVersionModal={() => setOpenshiftVersionModalOpen(true)}
|
|
75
|
+
customItems={additionalSelectOptions}
|
|
76
|
+
/>
|
|
77
|
+
{openshiftVersionModalOpen && (
|
|
78
|
+
<OpenShiftVersionModal
|
|
79
|
+
allVersions={allVersions}
|
|
80
|
+
setOpenshiftVersionModalOpen={setOpenshiftVersionModalOpen}
|
|
81
|
+
/>
|
|
82
|
+
)}
|
|
83
|
+
|
|
42
84
|
<PullSecret />
|
|
43
85
|
</Form>
|
|
44
86
|
);
|
|
@@ -26,6 +26,7 @@ const useDetailsFormik: UseDetailsFormik = ({
|
|
|
26
26
|
openshiftVersion: getDefaultOpenShiftVersion(ocpVersions),
|
|
27
27
|
pullSecret: initPullSecret,
|
|
28
28
|
baseDnsDomain: initBaseDomain,
|
|
29
|
+
customOpenshiftSelect: null,
|
|
29
30
|
}),
|
|
30
31
|
[], // eslint-disable-line react-hooks/exhaustive-deps
|
|
31
32
|
);
|
|
@@ -53,6 +54,8 @@ const DetailsStep: React.FC<DetailsStepProps> = ({
|
|
|
53
54
|
supportedVersionsCM,
|
|
54
55
|
}) => {
|
|
55
56
|
const ocpVersions = useSupportedOCPVersions(clusterImages, supportedVersionsCM);
|
|
57
|
+
const allVersions = useSupportedOCPVersions(clusterImages, supportedVersionsCM, true);
|
|
58
|
+
|
|
56
59
|
const [initialValues, validationSchema] = useDetailsFormik({
|
|
57
60
|
ocpVersions,
|
|
58
61
|
usedClusterNames,
|
|
@@ -70,6 +73,7 @@ const DetailsStep: React.FC<DetailsStepProps> = ({
|
|
|
70
73
|
<DetailsForm
|
|
71
74
|
onValuesChanged={onValuesChanged}
|
|
72
75
|
ocpVersions={ocpVersions}
|
|
76
|
+
allVersions={allVersions}
|
|
73
77
|
extensionAfter={extensionAfter}
|
|
74
78
|
/>
|
|
75
79
|
</Formik>
|
|
@@ -8,6 +8,7 @@ export type DetailsFormValues = {
|
|
|
8
8
|
openshiftVersion: string;
|
|
9
9
|
pullSecret: string;
|
|
10
10
|
baseDnsDomain: string;
|
|
11
|
+
customOpenshiftSelect: OpenshiftVersionOptionType | null;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
type UseDetailsFormikArgs = {
|
|
@@ -19,7 +20,10 @@ type UseDetailsFormikArgs = {
|
|
|
19
20
|
|
|
20
21
|
export type UseDetailsFormik = (
|
|
21
22
|
args: UseDetailsFormikArgs,
|
|
22
|
-
) => [
|
|
23
|
+
) => [
|
|
24
|
+
DetailsFormValues,
|
|
25
|
+
ObjectSchema<Omit<DetailsFormValues, 'openshiftVersion' | 'customOpenshiftSelect'>>,
|
|
26
|
+
];
|
|
23
27
|
|
|
24
28
|
export type DetailsStepProps = {
|
|
25
29
|
usedClusterNames: string[];
|
|
@@ -35,4 +39,5 @@ export type DetailsStepProps = {
|
|
|
35
39
|
|
|
36
40
|
export type DetailsFormProps = Pick<DetailsStepProps, 'onValuesChanged' | 'extensionAfter'> & {
|
|
37
41
|
ocpVersions: OpenshiftVersionOptionType[];
|
|
42
|
+
allVersions: OpenshiftVersionOptionType[];
|
|
38
43
|
};
|
|
@@ -11,9 +11,10 @@ export const getSupportedCM = (configMaps: ConfigMapK8sResource[]) =>
|
|
|
11
11
|
export const useSupportedOCPVersions = (
|
|
12
12
|
clusterImages: ClusterImageSetK8sResource[],
|
|
13
13
|
supportedVersionsCM?: ConfigMapK8sResource,
|
|
14
|
+
extended?: boolean,
|
|
14
15
|
) => {
|
|
15
16
|
return React.useMemo(() => {
|
|
16
|
-
const ocpVersions = getOCPVersions(clusterImages, false);
|
|
17
|
+
const ocpVersions = getOCPVersions(clusterImages, false, undefined, extended);
|
|
17
18
|
const supportedVersionsString = supportedVersionsCM?.data?.['supported-versions'];
|
|
18
19
|
if (supportedVersionsString) {
|
|
19
20
|
try {
|
|
@@ -25,5 +26,5 @@ export const useSupportedOCPVersions = (
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
return ocpVersions;
|
|
28
|
-
}, [clusterImages, supportedVersionsCM]);
|
|
29
|
+
}, [clusterImages, extended, supportedVersionsCM?.data]);
|
|
29
30
|
};
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AgentClusterInstallK8sResource,
|
|
5
5
|
ClusterImageSetK8sResource,
|
|
6
6
|
ClusterVersionK8sResource,
|
|
7
|
+
OsImage,
|
|
7
8
|
} from '../../types';
|
|
8
9
|
import { OpenshiftVersionOptionType } from '../../../common';
|
|
9
10
|
import { OpenshiftVersion } from '@openshift-assisted/types/assisted-installer-service';
|
|
@@ -36,8 +37,12 @@ const getSupportLevelFromChannel = (
|
|
|
36
37
|
|
|
37
38
|
export const supportedNutanixPlatforms = ['x86_64', 'x86-64'];
|
|
38
39
|
|
|
39
|
-
export const isValidImageSet = (
|
|
40
|
-
|
|
40
|
+
export const isValidImageSet = (
|
|
41
|
+
cis: ClusterImageSetK8sResource,
|
|
42
|
+
architectures?: string[],
|
|
43
|
+
extended?: boolean,
|
|
44
|
+
) => {
|
|
45
|
+
if (!extended && cis.metadata?.labels?.visible !== 'true') {
|
|
41
46
|
return false;
|
|
42
47
|
}
|
|
43
48
|
if (!architectures) {
|
|
@@ -51,10 +56,15 @@ export const isValidImageSet = (cis: ClusterImageSetK8sResource, architectures?:
|
|
|
51
56
|
export const getOCPVersions = (
|
|
52
57
|
clusterImageSets: ClusterImageSetK8sResource[],
|
|
53
58
|
isNutanix?: boolean | undefined,
|
|
59
|
+
osImages?: OsImage[],
|
|
60
|
+
extended?: boolean,
|
|
54
61
|
): OpenshiftVersionOptionType[] => {
|
|
62
|
+
const ocpImageVersions = Array.from(
|
|
63
|
+
new Set(osImages?.map((osImage) => osImage.openshiftVersion)),
|
|
64
|
+
);
|
|
55
65
|
const versions = clusterImageSets
|
|
56
66
|
.filter((clusterImageSet) =>
|
|
57
|
-
isValidImageSet(clusterImageSet, isNutanix ? supportedNutanixPlatforms : undefined),
|
|
67
|
+
isValidImageSet(clusterImageSet, isNutanix ? supportedNutanixPlatforms : undefined, extended),
|
|
58
68
|
)
|
|
59
69
|
.map((clusterImageSet): OpenshiftVersionOptionType => {
|
|
60
70
|
const version = getVersionFromReleaseImage(clusterImageSet.spec?.releaseImage);
|
|
@@ -67,6 +77,10 @@ export const getOCPVersions = (
|
|
|
67
77
|
supportLevel: 'production', // getSupportLevelFromChannel(clusterImageSet.metadata?.labels?.channel),
|
|
68
78
|
};
|
|
69
79
|
})
|
|
80
|
+
.filter((ocpVersion) => {
|
|
81
|
+
const ver = ocpVersion.version.split('.').slice(0, 2).join('.');
|
|
82
|
+
return !!ocpImageVersions.length ? ocpImageVersions.includes(ver) : true;
|
|
83
|
+
})
|
|
70
84
|
.sort(
|
|
71
85
|
(versionA, versionB) => /* descending */ -1 * versionA.label.localeCompare(versionB.label),
|
|
72
86
|
);
|
|
@@ -86,8 +100,9 @@ export const getSelectedVersion = (
|
|
|
86
100
|
const selectedClusterImage = clusterImages.find(
|
|
87
101
|
(ci) => ci.metadata?.name === agentClusterInstall?.spec?.imageSetRef?.name,
|
|
88
102
|
);
|
|
103
|
+
|
|
89
104
|
return selectedClusterImage
|
|
90
|
-
? getOCPVersions([selectedClusterImage])?.[0]?.version
|
|
105
|
+
? getOCPVersions([selectedClusterImage], undefined, undefined, true)?.[0]?.version
|
|
91
106
|
: agentClusterInstall?.spec?.imageSetRef?.name;
|
|
92
107
|
};
|
|
93
108
|
|
|
@@ -11,6 +11,13 @@ type StorageConfig = {
|
|
|
11
11
|
};
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
export type OsImage = {
|
|
15
|
+
cpuArchitecture: string;
|
|
16
|
+
openshiftVersion: string;
|
|
17
|
+
url: string;
|
|
18
|
+
version: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
14
21
|
export type AgentServiceConfigConditionType = 'DeploymentsHealthy' | 'ReconcileCompleted';
|
|
15
22
|
|
|
16
23
|
export type AgentServiceConfigK8sResource = K8sResourceCommon & {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { default as SNOControlGroup } from './SNOControlGroup';
|
|
2
2
|
export { default as SNODisclaimer } from './SNODisclaimer';
|
|
3
|
-
export { default as OpenShiftVersionSelect } from './OpenShiftVersionSelect';
|
|
4
3
|
export { default as UploadSSH } from './UploadSSH';
|
|
5
4
|
export { default as ProxyFields, ProxyInputFields } from './ProxyFields';
|
|
6
5
|
export { default as DownloadIsoModal } from './DownloadIsoModal';
|
|
@@ -76,6 +76,7 @@ export const getClusterDetailsInitialValues = ({
|
|
|
76
76
|
diskEncryption: cluster?.diskEncryption ?? {},
|
|
77
77
|
cpuArchitecture: cluster?.cpuArchitecture || getDefaultCpuArchitecture(),
|
|
78
78
|
platform: cluster?.platform?.type || 'none',
|
|
79
|
+
customOpenshiftSelect: null,
|
|
79
80
|
userManagedNetworking: cluster?.userManagedNetworking || false,
|
|
80
81
|
};
|
|
81
82
|
};
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '../../types/hosts';
|
|
16
16
|
import { TangServer } from '../clusterConfiguration/DiskEncryptionFields/DiskEncryptionValues';
|
|
17
17
|
import { WizardStepsValidationMap } from './validationsInfoUtils';
|
|
18
|
+
import { OpenshiftVersionOptionType } from '../../types';
|
|
18
19
|
|
|
19
20
|
export type ClusterDetailsValues = {
|
|
20
21
|
name: string;
|
|
@@ -31,6 +32,7 @@ export type ClusterDetailsValues = {
|
|
|
31
32
|
diskEncryption: DiskEncryption;
|
|
32
33
|
cpuArchitecture: string;
|
|
33
34
|
platform: PlatformType;
|
|
35
|
+
customOpenshiftSelect: OpenshiftVersionOptionType | null;
|
|
34
36
|
userManagedNetworking: boolean;
|
|
35
37
|
};
|
|
36
38
|
|
|
@@ -67,3 +69,8 @@ export type ValidationActionLinkProps<S extends string> = {
|
|
|
67
69
|
};
|
|
68
70
|
|
|
69
71
|
export type ClusterOperatorProps = Pick<Cluster, 'openshiftVersion'> & { clusterId: Cluster['id'] };
|
|
72
|
+
|
|
73
|
+
export type ItemDropdown = {
|
|
74
|
+
label: string;
|
|
75
|
+
value: string;
|
|
76
|
+
}[];
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { Dispatch, SetStateAction } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
FormHelperText,
|
|
4
|
+
Select,
|
|
5
|
+
SelectOption,
|
|
6
|
+
SelectOptionObject,
|
|
7
|
+
SelectVariant,
|
|
8
|
+
} from '@patternfly/react-core';
|
|
9
|
+
import { OpenshiftVersionOptionType } from '../../types';
|
|
10
|
+
import { HelperTextType } from './OpenShiftVersionDropdown';
|
|
11
|
+
import { useTranslation } from '../../hooks/use-translation-wrapper';
|
|
12
|
+
|
|
13
|
+
type OpenshiftSelectWithSearchProps = {
|
|
14
|
+
versions: OpenshiftVersionOptionType[];
|
|
15
|
+
getHelperText?: HelperTextType;
|
|
16
|
+
setCustomOpenshiftSelect: Dispatch<SetStateAction<OpenshiftVersionOptionType | undefined>>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const OpenShiftSelectWithSearch: React.FunctionComponent<OpenshiftSelectWithSearchProps> = ({
|
|
20
|
+
versions,
|
|
21
|
+
getHelperText,
|
|
22
|
+
setCustomOpenshiftSelect,
|
|
23
|
+
}: OpenshiftSelectWithSearchProps) => {
|
|
24
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
25
|
+
const [selected, setSelected] = React.useState<string>('');
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
|
|
28
|
+
const selectOptions = React.useMemo(
|
|
29
|
+
() =>
|
|
30
|
+
versions.map((version) => ({
|
|
31
|
+
value: version.value,
|
|
32
|
+
label:
|
|
33
|
+
version.supportLevel === 'beta'
|
|
34
|
+
? version.label + ' - ' + t('ai:Developer preview release')
|
|
35
|
+
: version.label,
|
|
36
|
+
version: version,
|
|
37
|
+
})),
|
|
38
|
+
[versions, t],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const onToggle = (isOpen: boolean) => {
|
|
42
|
+
setIsOpen(isOpen);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const onSelect = (
|
|
46
|
+
_event: React.MouseEvent | React.ChangeEvent,
|
|
47
|
+
selection: string | SelectOptionObject,
|
|
48
|
+
) => {
|
|
49
|
+
const value = typeof selection === 'string' ? selection : selection.toString();
|
|
50
|
+
const selectedOption = selectOptions.find((option) => option.value === value);
|
|
51
|
+
|
|
52
|
+
if (selectedOption) {
|
|
53
|
+
setSelected(value);
|
|
54
|
+
setCustomOpenshiftSelect(selectedOption.version);
|
|
55
|
+
setIsOpen(false);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const onClear = () => {
|
|
60
|
+
setSelected('');
|
|
61
|
+
setCustomOpenshiftSelect(undefined);
|
|
62
|
+
setIsOpen(false);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const onFilter = (e: React.ChangeEvent<HTMLInputElement> | null, value: string) => {
|
|
66
|
+
if (!value || value === '') {
|
|
67
|
+
return selectOptions.map((option) => (
|
|
68
|
+
<SelectOption key={option.value} value={option.value}>
|
|
69
|
+
{option.label}
|
|
70
|
+
</SelectOption>
|
|
71
|
+
));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const filteredOptions = selectOptions.filter((option) =>
|
|
75
|
+
option.label.toLowerCase().includes(value.toLowerCase()),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (filteredOptions.length === 0) {
|
|
79
|
+
return [
|
|
80
|
+
<SelectOption key="no-results" isDisabled>
|
|
81
|
+
{t('ai:No results found for "{{value}}"', { value })}
|
|
82
|
+
</SelectOption>,
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return filteredOptions.map((option) => (
|
|
87
|
+
<SelectOption key={option.value} value={option.value}>
|
|
88
|
+
{option.label}
|
|
89
|
+
</SelectOption>
|
|
90
|
+
));
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const helperText = getHelperText && getHelperText(selected, true);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
<Select
|
|
98
|
+
id="customOpenshiftSelect"
|
|
99
|
+
variant={SelectVariant.typeahead}
|
|
100
|
+
typeAheadAriaLabel={t('ai:Select OpenShift version')}
|
|
101
|
+
placeholderText={t('ai:Select an OpenShift version')}
|
|
102
|
+
isOpen={isOpen}
|
|
103
|
+
onToggle={onToggle}
|
|
104
|
+
onSelect={onSelect}
|
|
105
|
+
onClear={onClear}
|
|
106
|
+
selections={selected}
|
|
107
|
+
onFilter={onFilter}
|
|
108
|
+
className="pf-u-w-100"
|
|
109
|
+
maxHeight="300px"
|
|
110
|
+
isCreatable={false}
|
|
111
|
+
>
|
|
112
|
+
{selectOptions.map((option) => (
|
|
113
|
+
<SelectOption key={option.value} value={option.value}>
|
|
114
|
+
{option.label}
|
|
115
|
+
</SelectOption>
|
|
116
|
+
))}
|
|
117
|
+
</Select>
|
|
118
|
+
|
|
119
|
+
{helperText && <FormHelperText>{helperText}</FormHelperText>}
|
|
120
|
+
|
|
121
|
+
{!helperText && (
|
|
122
|
+
<FormHelperText>
|
|
123
|
+
{t(
|
|
124
|
+
'ai:Select an OpenShift version from the list or use the type ahead to narrow down the list.',
|
|
125
|
+
)}
|
|
126
|
+
</FormHelperText>
|
|
127
|
+
)}
|
|
128
|
+
</>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
@@ -1,114 +1,159 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import {
|
|
3
|
+
FormGroup,
|
|
4
|
+
FormHelperText,
|
|
5
|
+
Button,
|
|
3
6
|
DropdownItem,
|
|
4
7
|
DropdownToggle,
|
|
5
8
|
Dropdown,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
DropdownSeparator,
|
|
9
|
+
DropdownGroup,
|
|
10
|
+
Divider,
|
|
9
11
|
} from '@patternfly/react-core';
|
|
10
12
|
import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
|
|
11
13
|
|
|
12
14
|
import { OpenshiftVersionOptionType } from '../../types';
|
|
13
|
-
import { TFunction } from 'i18next';
|
|
14
15
|
import { useTranslation } from '../../hooks/use-translation-wrapper';
|
|
15
|
-
import { useField } from 'formik';
|
|
16
|
+
import { useField, useFormikContext } from 'formik';
|
|
16
17
|
import { getFieldId } from './formik';
|
|
17
18
|
import ExternalLink from './ExternalLink';
|
|
18
19
|
import { OCP_RELEASES_PAGE } from '../../config';
|
|
20
|
+
import { ClusterDetailsValues, ItemDropdown } from '../clusterWizard';
|
|
21
|
+
import './OpenShiftVersionDropdown.css';
|
|
19
22
|
|
|
20
|
-
export type HelperTextType = (
|
|
21
|
-
versions: OpenshiftVersionOptionType[],
|
|
22
|
-
value: string | undefined,
|
|
23
|
-
t: TFunction,
|
|
24
|
-
) => JSX.Element | null;
|
|
23
|
+
export type HelperTextType = (value: string | undefined, inModal?: boolean) => JSX.Element | null;
|
|
25
24
|
|
|
26
25
|
type OpenShiftVersionDropdownProps = {
|
|
27
26
|
name: string;
|
|
28
|
-
items:
|
|
29
|
-
label: string;
|
|
30
|
-
value: string;
|
|
31
|
-
}[];
|
|
27
|
+
items: ItemDropdown;
|
|
32
28
|
versions: OpenshiftVersionOptionType[];
|
|
33
|
-
getHelperText
|
|
29
|
+
getHelperText?: HelperTextType;
|
|
34
30
|
showReleasesLink: boolean;
|
|
31
|
+
showOpenshiftVersionModal: () => void;
|
|
32
|
+
customItems: ItemDropdown;
|
|
35
33
|
};
|
|
36
34
|
|
|
35
|
+
const getParsedVersions = (items: ItemDropdown) => {
|
|
36
|
+
const versionsY = Array.from(new Set(items.map((val) => val.value.match(/^\d+\.(\d+)/)?.[1])));
|
|
37
|
+
|
|
38
|
+
const parsedVersions = versionsY.map((y) => ({
|
|
39
|
+
y: y,
|
|
40
|
+
versions: items.filter((val) => val.value.match(/^\d+\.(\d+)/)?.[1] === y),
|
|
41
|
+
}));
|
|
42
|
+
return { parsedVersions: parsedVersions.reverse() };
|
|
43
|
+
};
|
|
37
44
|
export const OpenShiftVersionDropdown = ({
|
|
38
45
|
name,
|
|
39
46
|
items,
|
|
40
47
|
versions,
|
|
41
48
|
getHelperText,
|
|
42
49
|
showReleasesLink,
|
|
50
|
+
showOpenshiftVersionModal,
|
|
51
|
+
customItems,
|
|
43
52
|
}: OpenShiftVersionDropdownProps) => {
|
|
44
|
-
const [field, , { setValue }] = useField(name);
|
|
53
|
+
const [field, , { setValue }] = useField<string>(name);
|
|
45
54
|
const [isOpen, setOpen] = React.useState(false);
|
|
46
55
|
const { t } = useTranslation();
|
|
47
56
|
const fieldId = getFieldId(name, 'input');
|
|
48
|
-
const
|
|
57
|
+
const {
|
|
58
|
+
values: { customOpenshiftSelect },
|
|
59
|
+
} = useFormikContext<ClusterDetailsValues>();
|
|
60
|
+
const [current, setCurrent] = React.useState<string>();
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
const defaultVersion =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
React.useEffect(() => {
|
|
63
|
+
const defaultVersion = customOpenshiftSelect
|
|
64
|
+
? customOpenshiftSelect
|
|
65
|
+
: versions.find((item) => item.default);
|
|
66
|
+
setCurrent(defaultVersion?.label || '');
|
|
67
|
+
setValue(defaultVersion?.value || '');
|
|
68
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
69
|
+
}, [customOpenshiftSelect]);
|
|
57
70
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const versionsY = Array.from(new Set(items.map((val) => val.value.match(/^\d+\.(\d+)/)?.[1])));
|
|
62
|
-
const lastVersion = versionsY.slice(-1)[0];
|
|
63
|
-
|
|
64
|
-
const parsedVersions = versionsY.map((y) => ({
|
|
65
|
-
y: y,
|
|
66
|
-
versions: items.filter((val) => val.value.match(/^\d+\.(\d+)/)?.[1] === y),
|
|
67
|
-
}));
|
|
68
|
-
|
|
69
|
-
const dropdownItems = parsedVersions.map(({ y, versions }) => {
|
|
71
|
+
const parsedVersionsForItems = getParsedVersions(items);
|
|
72
|
+
let lastY: string | undefined = '';
|
|
73
|
+
const dropdownItems = parsedVersionsForItems.parsedVersions.map(({ y, versions }) => {
|
|
70
74
|
const items = versions.map(({ value, label }) => (
|
|
71
|
-
<DropdownItem key={value} id={value}>
|
|
75
|
+
<DropdownItem key={value} id={value} value={value}>
|
|
72
76
|
{label}
|
|
73
77
|
</DropdownItem>
|
|
74
78
|
));
|
|
75
79
|
|
|
76
|
-
if (y !==
|
|
77
|
-
items.push(<
|
|
80
|
+
if (lastY !== null && y !== lastY) {
|
|
81
|
+
items.push(<Divider key={`separator-${y || ''}`} />);
|
|
78
82
|
}
|
|
79
|
-
|
|
83
|
+
lastY = y;
|
|
80
84
|
return items;
|
|
81
85
|
});
|
|
82
86
|
|
|
87
|
+
const parsedVersionsForCustomItems = getParsedVersions(customItems);
|
|
88
|
+
let lastCustomY: string | undefined = '';
|
|
89
|
+
const customDropdownItems = parsedVersionsForCustomItems.parsedVersions.map(({ y, versions }) => {
|
|
90
|
+
const customItems = versions.map(({ value, label }) => (
|
|
91
|
+
<DropdownItem key={value} id={value} value={value}>
|
|
92
|
+
{label}
|
|
93
|
+
</DropdownItem>
|
|
94
|
+
));
|
|
95
|
+
if (lastCustomY !== null && y !== lastCustomY) {
|
|
96
|
+
customItems.push(<Divider key={`separator-${y || ''}`} />);
|
|
97
|
+
}
|
|
98
|
+
lastCustomY = y;
|
|
99
|
+
return customItems;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const dropdownGroup = [
|
|
103
|
+
dropdownItems.length && (
|
|
104
|
+
<DropdownGroup label="Latest releases" key="latest-releases">
|
|
105
|
+
{dropdownItems}
|
|
106
|
+
</DropdownGroup>
|
|
107
|
+
),
|
|
108
|
+
customDropdownItems.length && (
|
|
109
|
+
<DropdownGroup label="Custom releases" key="custom-releases">
|
|
110
|
+
{customDropdownItems}
|
|
111
|
+
</DropdownGroup>
|
|
112
|
+
),
|
|
113
|
+
<DropdownGroup key="all-available-versions">
|
|
114
|
+
<DropdownItem key="all-versions" id="all-versions" onSelect={(e) => e.preventDefault()}>
|
|
115
|
+
<Button
|
|
116
|
+
variant="link"
|
|
117
|
+
isInline
|
|
118
|
+
onClick={() => showOpenshiftVersionModal()}
|
|
119
|
+
id="show-all-versions"
|
|
120
|
+
>
|
|
121
|
+
{t('ai:Show all available versions')}
|
|
122
|
+
</Button>
|
|
123
|
+
</DropdownItem>
|
|
124
|
+
</DropdownGroup>,
|
|
125
|
+
].filter(Boolean);
|
|
126
|
+
|
|
83
127
|
const onSelect = React.useCallback(
|
|
84
128
|
(event?: React.SyntheticEvent<HTMLDivElement>) => {
|
|
85
|
-
const newLabel = event?.currentTarget.
|
|
129
|
+
const newLabel = event?.currentTarget.textContent;
|
|
86
130
|
const newValue = event?.currentTarget.id;
|
|
87
|
-
if (newLabel && newValue) {
|
|
131
|
+
if (newLabel && newValue && event.currentTarget.id !== 'all-versions') {
|
|
88
132
|
setCurrent(newLabel);
|
|
89
133
|
setValue(newValue);
|
|
90
|
-
setHelperText(getHelperText(versions, newValue, t));
|
|
91
134
|
setOpen(false);
|
|
92
135
|
}
|
|
93
136
|
},
|
|
94
|
-
[
|
|
137
|
+
[setValue],
|
|
95
138
|
);
|
|
96
139
|
|
|
97
|
-
const
|
|
140
|
+
const dropdownToggle = React.useMemo(
|
|
98
141
|
() => (
|
|
99
142
|
<DropdownToggle
|
|
100
|
-
|
|
143
|
+
id={fieldId}
|
|
144
|
+
className="pf-u-w-100"
|
|
145
|
+
onToggle={(val) => setOpen(val)}
|
|
101
146
|
toggleIndicator={CaretDownIcon}
|
|
102
|
-
isDisabled={isDisabled}
|
|
103
147
|
isText
|
|
104
|
-
className="pf-u-w-100"
|
|
105
148
|
>
|
|
106
|
-
{current}
|
|
149
|
+
{current || t('ai:OpenShift version')}
|
|
107
150
|
</DropdownToggle>
|
|
108
151
|
),
|
|
109
|
-
[
|
|
152
|
+
[fieldId, current, t],
|
|
110
153
|
);
|
|
111
154
|
|
|
155
|
+
const helperText = getHelperText && getHelperText(field.value);
|
|
156
|
+
|
|
112
157
|
return (
|
|
113
158
|
<FormGroup
|
|
114
159
|
id={`form-control__${fieldId}`}
|
|
@@ -118,15 +163,15 @@ export const OpenShiftVersionDropdown = ({
|
|
|
118
163
|
>
|
|
119
164
|
<Dropdown
|
|
120
165
|
{...field}
|
|
121
|
-
|
|
122
|
-
id={fieldId}
|
|
123
|
-
onSelect={onSelect}
|
|
124
|
-
dropdownItems={dropdownItems}
|
|
125
|
-
toggle={toggle}
|
|
166
|
+
id={`${fieldId}-dropdown`}
|
|
126
167
|
isOpen={isOpen}
|
|
168
|
+
onSelect={onSelect}
|
|
169
|
+
toggle={dropdownToggle}
|
|
170
|
+
dropdownItems={dropdownGroup}
|
|
127
171
|
className="pf-u-w-100"
|
|
128
172
|
/>
|
|
129
|
-
|
|
173
|
+
|
|
174
|
+
{helperText && <FormHelperText>{helperText}</FormHelperText>}
|
|
130
175
|
{showReleasesLink && (
|
|
131
176
|
<ExternalLink href={`${window.location.origin}/${OCP_RELEASES_PAGE}`}>
|
|
132
177
|
<span data-ouia-id="openshift-releases-link">
|