Skip to content

Commit 357f963

Browse files
committed
Address initial wizard setup feedback
Signed-off-by: Jeff Puzzo <[email protected]>
1 parent a27e320 commit 357f963

File tree

9 files changed

+108
-111
lines changed

9 files changed

+108
-111
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.create-plan-wizard__form {
2+
width: 66%;
3+
}

packages/forklift-console-plugin/src/modules/Plans/views/create/CreatePlanWizard.tsx

+20-46
Original file line numberDiff line numberDiff line change
@@ -6,83 +6,67 @@ import { Form, Title, Wizard, WizardStep, WizardStepType } from '@patternfly/rea
66

77
import { CreatePlanWizardFooter } from './components/CreatePlanWizardFooter';
88
import { GeneralInformationForm } from './steps/GeneralInformationForm';
9-
import {
10-
defaultCurrentStep,
11-
getPlanWizardStepNames,
12-
planStepIndexes,
13-
PlanWizardStepId,
14-
} from './constants';
9+
import { defaultCurrentStep, planStepIndexes, planStepNames, PlanWizardStepId } from './constants';
10+
11+
import './CreatePlanWizard.style.css';
1512

1613
export const CreatePlanWizard: FC = () => {
1714
const { t } = useForkliftTranslation();
1815
const form = useForm({ mode: 'onChange' });
1916
const [currentStep, setCurrentStep] = useState<WizardStepType>(defaultCurrentStep);
2017
const { formState, getValues } = form;
2118
const formValues = getValues();
22-
const stepNames = getPlanWizardStepNames(t);
2319

2420
const onSubmit = () => console.log('SUBMITTED: ', formValues);
2521

26-
const isStepDisabled = (stepId: PlanWizardStepId) =>
27-
currentStep?.index < planStepIndexes[stepId] && Object.keys(formState?.errors).length > 0;
22+
const getStepProps = (id: PlanWizardStepId) => ({
23+
id,
24+
name: planStepNames[id],
25+
isDisabled:
26+
currentStep?.index < planStepIndexes[id] && Object.keys(formState?.errors).length > 0,
27+
});
2828

2929
return (
3030
<FormProvider {...form}>
3131
<Wizard
3232
isVisitRequired
3333
title={t('Create migration plan')}
34-
footer={({ id: stepId }) => (
35-
<CreatePlanWizardFooter canSkipToReview={stepId === PlanWizardStepId.MigrationType} />
36-
)}
34+
footer={<CreatePlanWizardFooter />}
3735
onStepChange={(_event, currentStep) => setCurrentStep(currentStep)}
3836
>
3937
<WizardStep
40-
name={t(stepNames[PlanWizardStepId.BasicSetUp])}
41-
id={PlanWizardStepId.BasicSetUp}
38+
{...getStepProps(PlanWizardStepId.BasicSetUp)}
4239
steps={[
43-
<WizardStep
44-
key={PlanWizardStepId.General}
45-
id={PlanWizardStepId.General}
46-
name={stepNames[PlanWizardStepId.General]}
47-
isDisabled={isStepDisabled(PlanWizardStepId.General)}
48-
>
40+
<WizardStep key={PlanWizardStepId.General} {...getStepProps(PlanWizardStepId.General)}>
4941
<GeneralInformationForm />
5042
</WizardStep>,
5143
<WizardStep
5244
key={PlanWizardStepId.VirtualMachines}
53-
id={PlanWizardStepId.VirtualMachines}
54-
name={stepNames[PlanWizardStepId.VirtualMachines]}
55-
isDisabled={isStepDisabled(PlanWizardStepId.VirtualMachines)}
45+
{...getStepProps(PlanWizardStepId.VirtualMachines)}
5646
>
5747
<Form>
5848
<Title headingLevel="h2">{t('Virtual machines')}</Title>
5949
</Form>
6050
</WizardStep>,
6151
<WizardStep
6252
key={PlanWizardStepId.NetworkMapping}
63-
id={PlanWizardStepId.NetworkMapping}
64-
name={stepNames[PlanWizardStepId.NetworkMapping]}
65-
isDisabled={isStepDisabled(PlanWizardStepId.NetworkMapping)}
53+
{...getStepProps(PlanWizardStepId.NetworkMapping)}
6654
>
6755
<Form>
6856
<Title headingLevel="h2">{t('Network mappings')}</Title>
6957
</Form>
7058
</WizardStep>,
7159
<WizardStep
7260
key={PlanWizardStepId.StorageMapping}
73-
id={PlanWizardStepId.StorageMapping}
74-
name={stepNames[PlanWizardStepId.StorageMapping]}
75-
isDisabled={isStepDisabled(PlanWizardStepId.StorageMapping)}
61+
{...getStepProps(PlanWizardStepId.StorageMapping)}
7662
>
7763
<Form>
7864
<Title headingLevel="h2">{t('Storage mappings')}</Title>
7965
</Form>
8066
</WizardStep>,
8167
<WizardStep
8268
key={PlanWizardStepId.MigrationType}
83-
id={PlanWizardStepId.MigrationType}
84-
name={stepNames[PlanWizardStepId.MigrationType]}
85-
isDisabled={isStepDisabled(PlanWizardStepId.MigrationType)}
69+
{...getStepProps(PlanWizardStepId.MigrationType)}
8670
>
8771
<Form>
8872
<Title headingLevel="h2">{t('Migration type')}</Title>
@@ -92,25 +76,17 @@ export const CreatePlanWizard: FC = () => {
9276
/>
9377

9478
<WizardStep
95-
name={stepNames[PlanWizardStepId.AdditionalSetUp]}
96-
id={PlanWizardStepId.AdditionalSetUp}
79+
{...getStepProps(PlanWizardStepId.AdditionalSetUp)}
9780
steps={[
9881
<WizardStep
9982
key={PlanWizardStepId.OtherSettings}
100-
id={PlanWizardStepId.OtherSettings}
101-
name={stepNames[PlanWizardStepId.OtherSettings]}
102-
isDisabled={isStepDisabled(PlanWizardStepId.OtherSettings)}
83+
{...getStepProps(PlanWizardStepId.OtherSettings)}
10384
>
10485
<Form>
10586
<Title headingLevel="h2">{t('Other settings')}</Title>
10687
</Form>
10788
</WizardStep>,
108-
<WizardStep
109-
key={PlanWizardStepId.Hooks}
110-
id={PlanWizardStepId.Hooks}
111-
name={stepNames[PlanWizardStepId.Hooks]}
112-
isDisabled={isStepDisabled(PlanWizardStepId.Hooks)}
113-
>
89+
<WizardStep key={PlanWizardStepId.Hooks} {...getStepProps(PlanWizardStepId.Hooks)}>
11490
<Form>
11591
<Title headingLevel="h2">{t('Hooks')}</Title>
11692
</Form>
@@ -119,10 +95,8 @@ export const CreatePlanWizard: FC = () => {
11995
/>
12096

12197
<WizardStep
122-
name={stepNames[PlanWizardStepId.ReviewAndCreate]}
123-
id={PlanWizardStepId.ReviewAndCreate}
12498
footer={<CreatePlanWizardFooter nextButtonText={t('Create plan')} onNext={onSubmit} />}
125-
isDisabled={isStepDisabled(PlanWizardStepId.ReviewAndCreate)}
99+
{...getStepProps(PlanWizardStepId.ReviewAndCreate)}
126100
>
127101
<pre>{JSON.stringify(formValues, null, 2)}</pre>
128102
</WizardStep>
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
import React, { FC } from 'react';
2+
import { useForkliftTranslation } from 'src/utils';
23

3-
import { PageSection, Title } from '@patternfly/react-core';
4+
import { PageSection, PageSectionTypes, PageSectionVariants, Title } from '@patternfly/react-core';
45

56
import { CreatePlanWizard } from './CreatePlanWizard';
67

78
import './PlanCreatePage.style.css';
89

9-
export const PlanCreatePageV2: FC = () => (
10-
<>
11-
<PageSection variant="light">
12-
<Title headingLevel="h2">{'Create migration plan'}</Title>
13-
</PageSection>
14-
<PageSection
15-
hasOverflowScroll={true}
16-
variant="light"
17-
className="forklift--create-plan--wizard-container"
18-
>
19-
<CreatePlanWizard />
20-
</PageSection>
21-
</>
22-
);
10+
export const PlanCreatePageV2: FC = () => {
11+
const { t } = useForkliftTranslation();
12+
13+
return (
14+
<>
15+
<PageSection variant={PageSectionVariants.light}>
16+
<Title headingLevel="h2">{t('Create migration plan')}</Title>
17+
</PageSection>
18+
19+
<PageSection
20+
hasOverflowScroll
21+
variant={PageSectionVariants.light}
22+
type={PageSectionTypes.wizard}
23+
className="forklift--create-plan--wizard-container"
24+
>
25+
<CreatePlanWizard />
26+
</PageSection>
27+
</>
28+
);
29+
};
2330

2431
export default PlanCreatePageV2;

packages/forklift-console-plugin/src/modules/Plans/views/create/components/CreatePlanWizardFooter.tsx

+12-8
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,17 @@ import { PlanModelRef } from '@kubev2v/types';
88
import { useActiveNamespace } from '@openshift-console/dynamic-plugin-sdk';
99
import {
1010
Button,
11+
ButtonVariant,
1112
useWizardContext,
1213
WizardFooterProps,
1314
WizardFooterWrapper,
1415
} from '@patternfly/react-core';
1516

1617
import { PlanWizardStepId } from '../constants';
1718

18-
type CreatePlanWizardFooterProps = Partial<Pick<WizardFooterProps, 'nextButtonText' | 'onNext'>> & {
19-
canSkipToReview?: boolean;
20-
};
19+
type CreatePlanWizardFooterProps = Partial<Pick<WizardFooterProps, 'nextButtonText' | 'onNext'>>;
2120

2221
export const CreatePlanWizardFooter: FC<CreatePlanWizardFooterProps> = ({
23-
canSkipToReview,
2422
nextButtonText,
2523
onNext,
2624
}) => {
@@ -29,6 +27,9 @@ export const CreatePlanWizardFooter: FC<CreatePlanWizardFooterProps> = ({
2927
const [activeNamespace] = useActiveNamespace();
3028
const { trigger } = useFormContext();
3129
const { activeStep, goToNextStep, goToPrevStep, goToStepById } = useWizardContext();
30+
const canSkipToReview =
31+
activeStep.id === PlanWizardStepId.MigrationType ||
32+
activeStep.id === PlanWizardStepId.OtherSettings;
3233

3334
const onNextClick =
3435
(event: MouseEvent<HTMLButtonElement>) => async (goToStep: () => void | Promise<void>) => {
@@ -54,26 +55,29 @@ export const CreatePlanWizardFooter: FC<CreatePlanWizardFooterProps> = ({
5455
return (
5556
<WizardFooterWrapper>
5657
<Button
57-
variant="secondary"
58+
variant={ButtonVariant.secondary}
5859
onClick={goToPrevStep}
5960
isDisabled={activeStep.id === PlanWizardStepId.General}
6061
>
6162
{t('Back')}
6263
</Button>
63-
<Button variant="primary" onClick={(event) => onNextClick(event)(() => goToNextStep())}>
64+
<Button
65+
variant={ButtonVariant.primary}
66+
onClick={(event) => onNextClick(event)(() => goToNextStep())}
67+
>
6468
{nextButtonText || t('Next')}
6569
</Button>
6670
{canSkipToReview && (
6771
<Button
68-
variant="tertiary"
72+
variant={ButtonVariant.tertiary}
6973
onClick={(event) =>
7074
onNextClick(event)(() => goToStepById(PlanWizardStepId.ReviewAndCreate))
7175
}
7276
>
7377
{t('Skip to review')}
7478
</Button>
7579
)}
76-
<Button variant="link" onClick={onCancel}>
80+
<Button variant={ButtonVariant.link} onClick={onCancel}>
7781
{t('Cancel')}
7882
</Button>
7983
</WizardFooterWrapper>

packages/forklift-console-plugin/src/modules/Plans/views/create/constants.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TFunction } from 'react-i18next';
1+
import { t } from 'src/utils/i18n';
22

33
export enum PlanWizardStepId {
44
BasicSetUp = 'basic-set-up',
@@ -13,7 +13,7 @@ export enum PlanWizardStepId {
1313
ReviewAndCreate = 'review-and-create',
1414
}
1515

16-
export const getPlanWizardStepNames = (t: TFunction): Record<PlanWizardStepId, string> => ({
16+
export const planStepNames: Record<PlanWizardStepId, string> = {
1717
[PlanWizardStepId.BasicSetUp]: t('Basic set up'),
1818
[PlanWizardStepId.General]: t('General'),
1919
[PlanWizardStepId.VirtualMachines]: t('Virtual machines'),
@@ -24,7 +24,7 @@ export const getPlanWizardStepNames = (t: TFunction): Record<PlanWizardStepId, s
2424
[PlanWizardStepId.OtherSettings]: t('Other settings (optional)'),
2525
[PlanWizardStepId.Hooks]: t('Hooks (optional)'),
2626
[PlanWizardStepId.ReviewAndCreate]: t('Review and create'),
27-
});
27+
};
2828

2929
export const planStepIndexes = Object.values(PlanWizardStepId).reduce(
3030
(acc, stepId, index) => ({ ...acc, [stepId]: index + 1 }),

packages/forklift-console-plugin/src/modules/Plans/views/create/steps/CreateMigrationPlan/index.ts

-3
This file was deleted.

packages/forklift-console-plugin/src/modules/Plans/views/create/steps/GeneralInformationForm.tsx

+35-32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Controller, useFormContext } from 'react-hook-form';
33
import { useForkliftTranslation } from 'src/utils';
44

55
import {
6+
Flex,
67
Form,
78
FormGroup,
89
FormSection,
@@ -13,48 +14,50 @@ import {
1314

1415
import { FormErrorHelperText } from '../components/FormErrorHelperText';
1516

16-
import { GeneralFormFieldId, getGeneralFormFieldLabels } from './constants';
17+
import { GeneralFormFieldId, generalFormFieldLabels } from './constants';
1718

1819
export const GeneralInformationForm: FC = () => {
1920
const { t } = useForkliftTranslation();
2021
const {
2122
control,
2223
formState: { errors },
2324
} = useFormContext();
24-
const fieldLabels = getGeneralFormFieldLabels(t);
2525

2626
return (
27-
<Form className="pf-v5-u-w-66">
27+
<Flex direction={{ default: 'column' }} spaceItems={{ default: 'spaceItemsLg' }}>
2828
<Title headingLevel="h2">{t('General')}</Title>
2929

30-
<FormSection title={t('Plan information')} titleElement="h3" className="pf-v5-u-mt-0">
31-
<p>{t('Name your plan and choose the project you would like it to be created in.')}</p>
32-
<FormGroup
33-
isRequired
34-
fieldId={GeneralFormFieldId.PlanName}
35-
label={fieldLabels[GeneralFormFieldId.PlanName]}
36-
>
37-
<Controller
38-
name={GeneralFormFieldId.PlanName}
39-
control={control}
40-
rules={{
41-
required: t('Plan name is required.'),
42-
}}
43-
render={({ field }) => (
44-
<TextInput
45-
{...field}
46-
validated={
47-
errors[GeneralFormFieldId.PlanName]
48-
? ValidatedOptions.error
49-
: ValidatedOptions.default
50-
}
51-
/>
52-
)}
53-
/>
54-
55-
<FormErrorHelperText error={errors[GeneralFormFieldId.PlanName]} />
56-
</FormGroup>
57-
</FormSection>
58-
</Form>
30+
<Form className="create-plan-wizard__form">
31+
<FormSection title={t('Plan information')} titleElement="h3">
32+
<p>{t('Name your plan and choose the project you would like it to be created in.')}</p>
33+
34+
<FormGroup
35+
isRequired
36+
fieldId={GeneralFormFieldId.PlanName}
37+
label={generalFormFieldLabels[GeneralFormFieldId.PlanName]}
38+
>
39+
<Controller
40+
name={GeneralFormFieldId.PlanName}
41+
control={control}
42+
rules={{
43+
required: t('Plan name is required.'),
44+
}}
45+
render={({ field }) => (
46+
<TextInput
47+
{...field}
48+
validated={
49+
errors[GeneralFormFieldId.PlanName]
50+
? ValidatedOptions.error
51+
: ValidatedOptions.default
52+
}
53+
/>
54+
)}
55+
/>
56+
57+
<FormErrorHelperText error={errors[GeneralFormFieldId.PlanName]} />
58+
</FormGroup>
59+
</FormSection>
60+
</Form>
61+
</Flex>
5962
);
6063
};
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { TFunction } from 'react-i18next';
1+
import { t } from 'src/utils/i18n';
22

33
export enum GeneralFormFieldId {
44
PlanName = 'plan-name',
55
}
66

7-
export const getGeneralFormFieldLabels = (t: TFunction): Record<GeneralFormFieldId, string> => ({
7+
export const generalFormFieldLabels: Record<GeneralFormFieldId, string> = {
88
[GeneralFormFieldId.PlanName]: t('Plan name'),
9-
});
9+
};

0 commit comments

Comments
 (0)