|
1 | 1 | import React from 'react';
|
2 |
| -import { HelperText, FormGroup, FormHelperText, HelperTextItem } from '@patternfly/react-core'; |
| 2 | +import { |
| 3 | + HelperText, |
| 4 | + FormGroup, |
| 5 | + FormHelperText, |
| 6 | + HelperTextItem, |
| 7 | + Button, |
| 8 | +} from '@patternfly/react-core'; |
3 | 9 | import {
|
4 | 10 | DropdownItem,
|
5 | 11 | DropdownToggle,
|
6 | 12 | Dropdown,
|
| 13 | + DropdownGroup, |
7 | 14 | DropdownSeparator,
|
8 | 15 | } from '@patternfly/react-core/deprecated';
|
9 | 16 | import { CaretDownIcon } from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
|
10 | 17 |
|
11 | 18 | import { OpenshiftVersionOptionType } from '../../types';
|
12 | 19 | import { TFunction } from 'i18next';
|
13 | 20 | import { useTranslation } from '../../hooks/use-translation-wrapper';
|
14 |
| -import { useField } from 'formik'; |
| 21 | +import { useField, useFormikContext } from 'formik'; |
15 | 22 | import { getFieldId } from './formik';
|
16 | 23 | import ExternalLink from './ExternalLink';
|
17 | 24 | import { OCP_RELEASES_PAGE } from '../../config';
|
| 25 | +import { ClusterDetailsValues, ItemDropdown } from '../clusterWizard'; |
18 | 26 |
|
19 | 27 | export type HelperTextType = (
|
20 | 28 | versions: OpenshiftVersionOptionType[],
|
21 | 29 | value: string | undefined,
|
22 | 30 | t: TFunction,
|
| 31 | + isModal?: boolean, |
23 | 32 | ) => JSX.Element | null;
|
24 | 33 |
|
25 | 34 | type OpenShiftVersionDropdownProps = {
|
26 | 35 | name: string;
|
27 |
| - items: { |
28 |
| - label: string; |
29 |
| - value: string; |
30 |
| - }[]; |
| 36 | + items: ItemDropdown; |
31 | 37 | versions: OpenshiftVersionOptionType[];
|
32 | 38 | getHelperText: HelperTextType;
|
33 | 39 | showReleasesLink: boolean;
|
| 40 | + showOpenshiftVersionModal: () => void; |
| 41 | + customItems: ItemDropdown; |
34 | 42 | };
|
35 | 43 |
|
| 44 | +const getParsedVersions = (items: ItemDropdown) => { |
| 45 | + const versionsY = Array.from(new Set(items.map((val) => val.value.match(/^\d+\.(\d+)/)?.[1]))); |
| 46 | + const lastVersion = versionsY.slice(-1)[0]; |
| 47 | + |
| 48 | + const parsedVersions = versionsY.map((y) => ({ |
| 49 | + y: y, |
| 50 | + versions: items.filter((val) => val.value.match(/^\d+\.(\d+)/)?.[1] === y), |
| 51 | + })); |
| 52 | + return { parsedVersions: parsedVersions, lastVersion: lastVersion }; |
| 53 | +}; |
36 | 54 | export const OpenShiftVersionDropdown = ({
|
37 | 55 | name,
|
38 | 56 | items,
|
39 | 57 | versions,
|
40 | 58 | getHelperText,
|
41 | 59 | showReleasesLink,
|
| 60 | + showOpenshiftVersionModal, |
| 61 | + customItems, |
42 | 62 | }: OpenShiftVersionDropdownProps) => {
|
43 | 63 | const [field, , { setValue }] = useField(name);
|
44 | 64 | const [isOpen, setOpen] = React.useState(false);
|
45 | 65 | const { t } = useTranslation();
|
46 | 66 | const fieldId = getFieldId(name, 'input');
|
47 | 67 | const isDisabled = versions.length === 0;
|
48 |
| - |
| 68 | + const { |
| 69 | + values: { customOpenshiftSelect }, |
| 70 | + } = useFormikContext<ClusterDetailsValues>(); |
49 | 71 | const { defaultLabel, defaultValue } = React.useMemo(() => {
|
50 |
| - const defaultVersion = versions.find((item) => item.default); |
| 72 | + const defaultVersion = customOpenshiftSelect |
| 73 | + ? customOpenshiftSelect |
| 74 | + : versions.find((item) => item.default); |
51 | 75 | return {
|
52 | 76 | defaultLabel: defaultVersion?.label || '',
|
53 | 77 | defaultValue: defaultVersion?.value || '',
|
54 | 78 | };
|
55 |
| - }, [versions]); |
| 79 | + }, [customOpenshiftSelect, versions]); |
56 | 80 |
|
57 | 81 | const [helperText, setHelperText] = React.useState(getHelperText(versions, defaultValue, t));
|
58 |
| - const [current, setCurrent] = React.useState<string>(defaultLabel); |
| 82 | + const [current, setCurrent] = React.useState<string>(); |
59 | 83 |
|
60 |
| - const versionsY = Array.from(new Set(items.map((val) => val.value.match(/^\d+\.(\d+)/)?.[1]))); |
61 |
| - const lastVersion = versionsY.slice(-1)[0]; |
| 84 | + React.useEffect(() => { |
| 85 | + setCurrent(defaultLabel); |
| 86 | + }, [defaultLabel]); |
62 | 87 |
|
63 |
| - const parsedVersions = versionsY.map((y) => ({ |
64 |
| - y: y, |
65 |
| - versions: items.filter((val) => val.value.match(/^\d+\.(\d+)/)?.[1] === y), |
66 |
| - })); |
67 |
| - |
68 |
| - const dropdownItems = parsedVersions.map(({ y, versions }) => { |
| 88 | + const parsedVersionsForItems = getParsedVersions(items); |
| 89 | + const dropdownItems = parsedVersionsForItems.parsedVersions.map(({ y, versions }) => { |
69 | 90 | const items = versions.map(({ value, label }) => (
|
70 | 91 | <DropdownItem key={value} id={value}>
|
71 | 92 | {label}
|
72 | 93 | </DropdownItem>
|
73 | 94 | ));
|
74 | 95 |
|
75 |
| - if (y !== lastVersion) { |
| 96 | + if (y !== parsedVersionsForItems.lastVersion) { |
76 | 97 | items.push(<DropdownSeparator key={`separator-${y || ''}`} />);
|
77 | 98 | }
|
78 |
| - |
79 | 99 | return items;
|
80 | 100 | });
|
81 | 101 |
|
| 102 | + const parsedVersionsForCustomItems = getParsedVersions(customItems); |
| 103 | + const customDropdownItems = parsedVersionsForCustomItems.parsedVersions.map(({ y, versions }) => { |
| 104 | + const customItems = versions.map(({ value, label }) => ( |
| 105 | + <DropdownItem key={value} id={value}> |
| 106 | + {label} |
| 107 | + </DropdownItem> |
| 108 | + )); |
| 109 | + |
| 110 | + if (y !== parsedVersionsForCustomItems.lastVersion) { |
| 111 | + customItems.push(<DropdownSeparator key={`separator-${y || ''}`} />); |
| 112 | + } |
| 113 | + return customItems; |
| 114 | + }); |
| 115 | + |
| 116 | + const dropdownGroup = [ |
| 117 | + <DropdownGroup label="Latest releases" key="latest-releases"> |
| 118 | + {dropdownItems} |
| 119 | + </DropdownGroup>, |
| 120 | + <DropdownGroup |
| 121 | + label="Custom releases" |
| 122 | + key="custom-releases" |
| 123 | + hidden={customDropdownItems.length === 0} |
| 124 | + > |
| 125 | + {customDropdownItems} |
| 126 | + </DropdownGroup>, |
| 127 | + <DropdownGroup key="all-available-versions"> |
| 128 | + <DropdownItem key="all-versions" id="all-versions"> |
| 129 | + <Button |
| 130 | + variant="link" |
| 131 | + isInline |
| 132 | + onClick={() => showOpenshiftVersionModal()} |
| 133 | + id="show-all-versions" |
| 134 | + > |
| 135 | + Show all available versions |
| 136 | + </Button> |
| 137 | + </DropdownItem> |
| 138 | + </DropdownGroup>, |
| 139 | + ]; |
| 140 | + |
82 | 141 | const onSelect = React.useCallback(
|
83 | 142 | (event?: React.SyntheticEvent<HTMLDivElement>) => {
|
84 | 143 | const newLabel = event?.currentTarget.innerText;
|
85 | 144 | const newValue = event?.currentTarget.id;
|
86 |
| - if (newLabel && newValue) { |
| 145 | + if (newLabel && newValue !== 'all-versions') { |
87 | 146 | setCurrent(newLabel);
|
88 | 147 | setValue(newValue);
|
89 | 148 | setHelperText(getHelperText(versions, newValue, t));
|
90 | 149 | setOpen(false);
|
91 | 150 | }
|
92 | 151 | },
|
93 |
| - [setCurrent, setHelperText, setOpen, getHelperText, t, versions, setValue], |
| 152 | + [setValue, getHelperText, versions, t], |
94 | 153 | );
|
95 | 154 |
|
96 | 155 | const toggle = React.useMemo(
|
@@ -120,7 +179,7 @@ export const OpenShiftVersionDropdown = ({
|
120 | 179 | name={name}
|
121 | 180 | id={fieldId}
|
122 | 181 | onSelect={onSelect}
|
123 |
| - dropdownItems={dropdownItems} |
| 182 | + dropdownItems={dropdownGroup} |
124 | 183 | toggle={toggle}
|
125 | 184 | isOpen={isOpen}
|
126 | 185 | className="pf-v5-u-w-100"
|
|
0 commit comments