Skip to content

Commit 0f32950

Browse files
authored
Merge pull request #436 from rvsia/refactorPf4wizard
fix(pf4): refactor wizard, validating disable nav
2 parents 7641bff + a0b9d8c commit 0f32950

File tree

9 files changed

+348
-481
lines changed

9 files changed

+348
-481
lines changed

packages/common/src/wizard/reducer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ const handleNext = (state, nextStep, formOptions, fields) => {
6565
export const findCurrentStep = (activeStep, fields) => fields.find(({ name }) => name === activeStep);
6666

6767
const jumpToStep = (state, index, valid, fields, crossroads, formOptions) => {
68+
if (index === state.activeStepIndex) {
69+
return state;
70+
}
71+
6872
const clickOnPreviousStep = state.prevSteps[index];
6973

7074
if (clickOnPreviousStep) {

packages/pf4-component-mapper/demo/demo-schemas/wizard-schema.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ ValidateButtons.propTypes = {
4343
renderNextButton: PropTypes.func.isRequired
4444
};
4545

46+
const asyncValidator = () => new Promise((res) => setTimeout(() => res(), 1000));
47+
4648
export const wizardSchema = {
4749
fields: [
4850
{
@@ -70,7 +72,8 @@ export const wizardSchema = {
7072
component: componentTypes.TEXTAREA,
7173
name: 'source.source-name',
7274
type: 'text',
73-
label: 'Source name'
75+
label: 'Source name',
76+
validate: [asyncValidator]
7477
},
7578
{
7679
component: componentTypes.SELECT,

packages/pf4-component-mapper/src/files/wizard.js

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { cloneElement, useReducer, useEffect } from 'react';
1+
import React, { useReducer, useEffect } from 'react';
22
import { createPortal } from 'react-dom';
33
import PropTypes from 'prop-types';
44
import { FormSpy } from '@data-driven-forms/react-form-renderer';
@@ -72,10 +72,6 @@ const WizardInternal = ({
7272
return null;
7373
}
7474

75-
const step = (
76-
<WizardStep {...currentStep} formOptions={formOptions} buttonLabels={buttonLabels} buttonsClassName={buttonsClassName} showTitles={showTitles} />
77-
);
78-
7975
return (
8076
<Modal inModal={inModal} container={state.container}>
8177
<div
@@ -89,27 +85,33 @@ const WizardInternal = ({
8985
{title && <WizardHeader title={title} description={description} onClose={formOptions.onCancel} />}
9086
<div className="pf-c-wizard__outer-wrap">
9187
<WizardNav>
92-
<FormSpy>
93-
{({ values }) => (
88+
<FormSpy subscription={{ values: true, valid: true, validating: true }}>
89+
{({ values, valid, validating }) => (
9490
<WizardNavigation
9591
navSchema={navSchema}
9692
activeStepIndex={activeStepIndex}
97-
formOptions={formOptions}
93+
valid={valid}
9894
maxStepIndex={maxStepIndex}
9995
jumpToStep={jumpToStep}
10096
crossroads={crossroads}
10197
isDynamic={isDynamic}
10298
values={values}
10399
setPrevSteps={setPrevSteps}
100+
validating={validating}
104101
/>
105102
)}
106103
</FormSpy>
107104
</WizardNav>
108-
{cloneElement(step, {
109-
handleNext: (nextStep) => handleNext(nextStep),
110-
handlePrev,
111-
disableBack: activeStepIndex === 0
112-
})}
105+
<WizardStep
106+
{...currentStep}
107+
formOptions={formOptions}
108+
buttonLabels={buttonLabels}
109+
buttonsClassName={buttonsClassName}
110+
showTitles={showTitles}
111+
handleNext={(nextStep) => handleNext(nextStep)}
112+
handlePrev={handlePrev}
113+
disableBack={activeStepIndex === 0}
114+
/>
113115
</div>
114116
</div>
115117
</Modal>
@@ -126,11 +128,6 @@ WizardInternal.propTypes = {
126128
buttonsClassName: PropTypes.string,
127129
title: PropTypes.any,
128130
description: PropTypes.any,
129-
fields: PropTypes.arrayOf(
130-
PropTypes.shape({
131-
name: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
132-
})
133-
).isRequired,
134131
isCompactNav: PropTypes.bool,
135132
inModal: PropTypes.bool,
136133
setFullWidth: PropTypes.bool,

packages/pf4-component-mapper/src/files/wizard/step-buttons.js

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,25 @@ import { Button } from '@patternfly/react-core';
44
import selectNext from '@data-driven-forms/common/src/wizard/select-next';
55
import { FormSpy } from '@data-driven-forms/react-form-renderer';
66

7-
const SimpleNext = ({ nextStep, valid, handleNext, submit, nextLabel, getState }) => (
7+
const NextButton = ({ nextStep, valid, handleNext, nextLabel, getState, handleSubmit, submitLabel }) => (
88
<Button
99
variant="primary"
1010
type="button"
1111
isDisabled={!valid || getState().validating}
12-
onClick={() => (valid ? handleNext(selectNext(nextStep, getState)) : submit())}
12+
onClick={() => (nextStep ? handleNext(selectNext(nextStep, getState)) : handleSubmit())}
1313
>
14-
{nextLabel}
14+
{nextStep ? nextLabel : submitLabel}
1515
</Button>
1616
);
1717

18-
SimpleNext.propTypes = {
19-
valid: PropTypes.bool,
20-
handleNext: PropTypes.func.isRequired,
21-
submit: PropTypes.func.isRequired,
22-
nextLabel: PropTypes.string.isRequired,
23-
getState: PropTypes.func.isRequired,
24-
nextStep: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.func]).isRequired
25-
};
26-
27-
const SubmitButton = ({ handleSubmit, submitLabel }) => (
28-
<Button type="button" variant="primary" onClick={handleSubmit}>
29-
{submitLabel}
30-
</Button>
31-
);
32-
33-
SubmitButton.propTypes = {
34-
handleSubmit: PropTypes.func.isRequired,
35-
submitLabel: PropTypes.node.isRequired
36-
};
37-
38-
const NextButton = ({ nextStep, handleSubmit, submitLabel, ...rest }) =>
39-
nextStep ? <SimpleNext nextStep={nextStep} {...rest} /> : <SubmitButton handleSubmit={handleSubmit} submitLabel={submitLabel} />;
40-
4118
NextButton.propTypes = {
4219
nextStep: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object]),
4320
handleSubmit: PropTypes.func.isRequired,
44-
submitLabel: PropTypes.string.isRequired
21+
submitLabel: PropTypes.string.isRequired,
22+
valid: PropTypes.bool,
23+
handleNext: PropTypes.func.isRequired,
24+
nextLabel: PropTypes.string.isRequired,
25+
getState: PropTypes.func.isRequired
4526
};
4627

4728
const WizardStepButtons = ({
@@ -57,9 +38,6 @@ const WizardStepButtons = ({
5738
<footer className={`pf-c-wizard__footer ${buttonsClassName ? buttonsClassName : ''}`}>
5839
{Buttons ? (
5940
<Buttons
60-
ConditionalNext={SimpleNext}
61-
SubmitButton={SubmitButton}
62-
SimpleNext={SimpleNext}
6341
disableBack={disableBack}
6442
handlePrev={handlePrev}
6543
nextStep={nextStep}

packages/pf4-component-mapper/src/files/wizard/wizard-nav.js

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ const memoValues = (initialValue) => {
2020
};
2121

2222
const WizardNavigationInternal = React.memo(
23-
({ navSchema, activeStepIndex, maxStepIndex, jumpToStep, formOptions: { valid } }) =>
23+
({ navSchema, activeStepIndex, maxStepIndex, jumpToStep, valid, validating }) =>
2424
navSchema
2525
.filter((field) => field.primary)
2626
.map((step) => {
2727
const substeps = step.substepOf && navSchema.filter((field) => field.substepOf === step.substepOf);
2828

29+
const isValid = valid && !validating;
30+
2931
return (
3032
<WizardNavItem
3133
key={step.substepOf || step.title}
3234
text={step.substepOf || step.title}
3335
isCurrent={substeps ? activeStepIndex >= step.index && activeStepIndex < step.index + substeps.length : activeStepIndex === step.index}
34-
isDisabled={valid ? maxStepIndex < step.index : step.index > activeStepIndex}
35-
onNavItemClick={(ind) => jumpToStep(ind, valid)}
36+
isDisabled={isValid ? maxStepIndex < step.index : step.index > activeStepIndex}
37+
onNavItemClick={(ind) => jumpToStep(ind, isValid)}
3638
step={step.index}
3739
>
3840
{substeps && (
@@ -42,8 +44,8 @@ const WizardNavigationInternal = React.memo(
4244
key={substep.title}
4345
text={substep.title}
4446
isCurrent={activeStepIndex === substep.index}
45-
isDisabled={valid ? maxStepIndex < substep.index : substep.index > activeStepIndex}
46-
onNavItemClick={(ind) => jumpToStep(ind, valid)}
47+
isDisabled={isValid ? maxStepIndex < substep.index : substep.index > activeStepIndex}
48+
onNavItemClick={(ind) => jumpToStep(ind, isValid)}
4749
step={substep.index}
4850
/>
4951
))}
@@ -60,12 +62,11 @@ WizardNavigationInternal.propTypes = {
6062
maxStepIndex: PropTypes.number.isRequired,
6163
jumpToStep: PropTypes.func.isRequired,
6264
navSchema: PropTypes.array.isRequired,
63-
formOptions: PropTypes.shape({
64-
valid: PropTypes.bool.isRequired
65-
}).isRequired
65+
valid: PropTypes.bool.isRequired,
66+
validating: PropTypes.bool.isRequired
6667
};
6768

68-
const WizardNavigation = ({ activeStepIndex, maxStepIndex, jumpToStep, navSchema, formOptions, setPrevSteps, crossroads, values }) => {
69+
const WizardNavigation = ({ setPrevSteps, crossroads, values, ...props }) => {
6970
const [memoValue] = useState(() =>
7071
memoValues(
7172
crossroads
@@ -96,26 +97,13 @@ const WizardNavigation = ({ activeStepIndex, maxStepIndex, jumpToStep, navSchema
9697
}
9798
});
9899

99-
return (
100-
<WizardNavigationInternal
101-
navSchema={navSchema}
102-
activeStepIndex={activeStepIndex}
103-
maxStepIndex={maxStepIndex}
104-
jumpToStep={jumpToStep}
105-
formOptions={formOptions}
106-
/>
107-
);
100+
return <WizardNavigationInternal {...props} />;
108101
};
109102

110103
WizardNavigation.propTypes = {
111-
activeStepIndex: PropTypes.number.isRequired,
112-
maxStepIndex: PropTypes.number.isRequired,
113-
jumpToStep: PropTypes.func.isRequired,
114104
setPrevSteps: PropTypes.func.isRequired,
115-
navSchema: PropTypes.array.isRequired,
116105
values: PropTypes.object.isRequired,
117-
crossroads: PropTypes.arrayOf(PropTypes.string),
118-
formOptions: PropTypes.object.isRequired
106+
crossroads: PropTypes.arrayOf(PropTypes.string)
119107
};
120108

121109
export default WizardNavigation;

0 commit comments

Comments
 (0)