V2Wizard: Add <ReleaseSelect> to Image Output step
The `<ReleaseSelect>` component now uses RTK instead of DDF. Some additional small changes were necessary due to Typescript - in particular, we use a Map() to store the releases (in order to ensure they appear in the correct order) and .tsconfig had to be modified to allow iteration over the Map() object.
This commit is contained in:
parent
2465ab4b84
commit
ad2bd7a31a
5 changed files with 70 additions and 48 deletions
|
|
@ -1,15 +1,11 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { ReactElement, useState } from 'react';
|
||||
|
||||
import { FormSpy } from '@data-driven-forms/react-form-renderer';
|
||||
import useFieldApi from '@data-driven-forms/react-form-renderer/use-field-api';
|
||||
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
|
||||
import { FormGroup } from '@patternfly/react-core';
|
||||
import {
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from '@patternfly/react-core/deprecated';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
RELEASES,
|
||||
|
|
@ -19,18 +15,27 @@ import {
|
|||
RHEL_9,
|
||||
RHEL_9_FULL_SUPPORT,
|
||||
RHEL_9_MAINTENANCE_SUPPORT,
|
||||
} from '../../../constants';
|
||||
import isRhel from '../../../Utilities/isRhel';
|
||||
import { toMonthAndYear } from '../../../Utilities/time';
|
||||
} from '../../../../constants';
|
||||
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
|
||||
import { Distributions } from '../../../../store/imageBuilderApi';
|
||||
import {
|
||||
changeDistribution,
|
||||
selectDistribution,
|
||||
} from '../../../../store/wizardSlice';
|
||||
import isRhel from '../../../../Utilities/isRhel';
|
||||
import { toMonthAndYear } from '../../../../Utilities/time';
|
||||
|
||||
const ImageOutputReleaseSelect = ({ label, isRequired, ...props }) => {
|
||||
const { change, getState } = useFormApi();
|
||||
const { input } = useFieldApi(props);
|
||||
const ReleaseSelect = () => {
|
||||
// What the UI refers to as the "release" is referred to as the "distribution" in the API.
|
||||
// The Redux store follows the API convention, and data read from or to the store will use
|
||||
// the word "Distribution" instead of "Release".
|
||||
const distribution = useAppSelector((state) => selectDistribution(state));
|
||||
const dispatch = useAppDispatch();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [showDevelopmentOptions, setShowDevelopmentOptions] = useState(false);
|
||||
|
||||
const setRelease = (_, selection) => {
|
||||
change(input.name, selection);
|
||||
const handleSelect = (_event: React.MouseEvent, selection: Distributions) => {
|
||||
dispatch(changeDistribution(selection));
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
|
|
@ -38,7 +43,7 @@ const ImageOutputReleaseSelect = ({ label, isRequired, ...props }) => {
|
|||
setShowDevelopmentOptions(true);
|
||||
};
|
||||
|
||||
const setDescription = (key) => {
|
||||
const setDescription = (key: Distributions) => {
|
||||
let fullSupportEnd = '';
|
||||
let maintenanceSupportEnd = '';
|
||||
|
||||
|
|
@ -58,7 +63,7 @@ const ImageOutputReleaseSelect = ({ label, isRequired, ...props }) => {
|
|||
};
|
||||
|
||||
const setSelectOptions = () => {
|
||||
var options = [];
|
||||
const options: ReactElement[] = [];
|
||||
const filteredRhel = new Map(
|
||||
[...RELEASES].filter(([key]) => {
|
||||
// Only show non-RHEL distros if expanded
|
||||
|
|
@ -71,7 +76,11 @@ const ImageOutputReleaseSelect = ({ label, isRequired, ...props }) => {
|
|||
|
||||
filteredRhel.forEach((value, key) => {
|
||||
options.push(
|
||||
<SelectOption key={value} value={key} description={setDescription(key)}>
|
||||
<SelectOption
|
||||
key={value}
|
||||
value={key}
|
||||
description={setDescription(key as Distributions)}
|
||||
>
|
||||
{RELEASES.get(key)}
|
||||
</SelectOption>
|
||||
);
|
||||
|
|
@ -81,34 +90,25 @@ const ImageOutputReleaseSelect = ({ label, isRequired, ...props }) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<FormSpy>
|
||||
{() => (
|
||||
<FormGroup isRequired={isRequired} label={label}>
|
||||
<Select
|
||||
ouiaId="release_select"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setIsOpen(!isOpen)}
|
||||
onSelect={setRelease}
|
||||
selections={RELEASES.get(getState()?.values?.[input.name])}
|
||||
isOpen={isOpen}
|
||||
{...(!showDevelopmentOptions && {
|
||||
loadingVariant: {
|
||||
text: 'Show options for further development of RHEL',
|
||||
onClick: handleExpand,
|
||||
},
|
||||
})}
|
||||
>
|
||||
{setSelectOptions()}
|
||||
</Select>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FormSpy>
|
||||
<FormGroup isRequired={true} label="Release">
|
||||
<Select
|
||||
ouiaId="release_select"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setIsOpen(!isOpen)}
|
||||
onSelect={handleSelect}
|
||||
selections={RELEASES.get(distribution)}
|
||||
isOpen={isOpen}
|
||||
{...(!showDevelopmentOptions && {
|
||||
loadingVariant: {
|
||||
text: 'Show options for further development of RHEL',
|
||||
onClick: handleExpand,
|
||||
},
|
||||
})}
|
||||
>
|
||||
{setSelectOptions()}
|
||||
</Select>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
ImageOutputReleaseSelect.propTypes = {
|
||||
label: PropTypes.node,
|
||||
isRequired: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default ImageOutputReleaseSelect;
|
||||
export default ReleaseSelect;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import React from 'react';
|
|||
|
||||
import { Text, Form, Title } from '@patternfly/react-core';
|
||||
|
||||
import ReleaseSelect from './ReleaseSelect';
|
||||
|
||||
import DocumentationButton from '../../../sharedComponents/DocumentationButton';
|
||||
|
||||
const ImageOutputStep = () => {
|
||||
|
|
@ -14,6 +16,7 @@ const ImageOutputStep = () => {
|
|||
<br />
|
||||
<DocumentationButton />
|
||||
</Text>
|
||||
<ReleaseSelect />
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export const UNIT_KIB = 1024 ** 1;
|
|||
export const UNIT_MIB = 1024 ** 2;
|
||||
export const UNIT_GIB = 1024 ** 3;
|
||||
|
||||
// Use a Map() to ensure order is preserved (order is not gauranteed by an Object())
|
||||
export const RELEASES = new Map([
|
||||
[RHEL_9, 'Red Hat Enterprise Linux (RHEL) 9'],
|
||||
[RHEL_8, 'Red Hat Enterprise Linux (RHEL) 8'],
|
||||
|
|
|
|||
|
|
@ -1,16 +1,33 @@
|
|||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
type wizardState = {};
|
||||
import { Distributions } from './imageBuilderApi';
|
||||
|
||||
const initialState: wizardState = {};
|
||||
import { RHEL_9 } from '../constants';
|
||||
|
||||
import { RootState } from '.';
|
||||
|
||||
type wizardState = {
|
||||
distribution: Distributions;
|
||||
};
|
||||
|
||||
const initialState: wizardState = {
|
||||
distribution: RHEL_9,
|
||||
};
|
||||
|
||||
export const selectDistribution = (state: RootState) => {
|
||||
return state.wizard.distribution;
|
||||
};
|
||||
|
||||
export const wizardSlice = createSlice({
|
||||
name: 'wizard',
|
||||
initialState,
|
||||
reducers: {
|
||||
initializeWizard: () => initialState,
|
||||
changeDistribution: (state, action: PayloadAction<Distributions>) => {
|
||||
state.distribution = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { initializeWizard } = wizardSlice.actions;
|
||||
export const { initializeWizard, changeDistribution } = wizardSlice.actions;
|
||||
export default wizardSlice.reducer;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
"noImplicitAny": true,
|
||||
"module": "es6",
|
||||
"target": "es5",
|
||||
"downlevelIteration": true, // Needed to allow iteration over some objects like Map() while target is es5
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue