Skip to content

Commit df2a1a3

Browse files
committed
feat(wizard): enable conditional submit step conversion
1 parent ac3b770 commit df2a1a3

File tree

26 files changed

+548
-102
lines changed

26 files changed

+548
-102
lines changed

packages/ant-component-mapper/src/tests/wizard.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { mount } from 'enzyme';
55
import { Button } from 'antd';
66

77
import { componentMapper, FormTemplate } from '../index';
8+
import { CONDITIONAL_SUBMIT_FLAG } from '@data-driven-forms/common/wizard';
89

910
describe('wizard', () => {
1011
let initialProps;
@@ -379,4 +380,51 @@ describe('wizard', () => {
379380
aws: 'something'
380381
});
381382
});
383+
384+
it('conditional submit step', () => {
385+
const submit = jest.fn();
386+
schema = {
387+
fields: [
388+
{
389+
component: componentTypes.WIZARD,
390+
name: 'wizard',
391+
fields: [
392+
{
393+
name: 'first-step',
394+
nextStep: {
395+
when: 'name',
396+
stepMapper: {
397+
aws: 'summary',
398+
submit: CONDITIONAL_SUBMIT_FLAG
399+
}
400+
},
401+
fields: [
402+
{
403+
component: componentTypes.TEXT_FIELD,
404+
name: 'name',
405+
validate: [{ type: validatorTypes.REQUIRED }]
406+
}
407+
]
408+
}
409+
]
410+
}
411+
]
412+
};
413+
414+
const wrapper = mount(<FormRenderer {...initialProps} onSubmit={submit} schema={schema} />);
415+
416+
wrapper.find('input').instance().value = 'bla';
417+
wrapper.find('input').simulate('change');
418+
wrapper.update();
419+
420+
expect(wrapper.find('button.ant-btn.ant-btn-primary').text()).toEqual('Next');
421+
422+
wrapper.find('input').instance().value = 'submit';
423+
wrapper.find('input').simulate('change');
424+
wrapper.update();
425+
426+
expect(wrapper.find('button.ant-btn.ant-btn-primary').text()).toEqual('Submit');
427+
wrapper.find('button.ant-btn.ant-btn-primary').simulate('click');
428+
expect(submit).toHaveBeenCalledWith({ name: 'submit' }, expect.any(Object), expect.any(Object));
429+
});
382430
});

packages/ant-component-mapper/src/wizard/step-buttons.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,28 @@ import PropTypes from 'prop-types';
33
import { Button } from 'antd';
44
import selectNext from '@data-driven-forms/common/wizard/select-next';
55

6-
const NextButton = ({ nextStep, handleNext, handleSubmit, buttonLabels, getState, valid, NextButtonProps, SubmitButtonProps }) => {
6+
const NextButton = ({
7+
nextStep,
8+
handleNext,
9+
handleSubmit,
10+
buttonLabels,
11+
getState,
12+
valid,
13+
NextButtonProps,
14+
SubmitButtonProps,
15+
conditionalSubmitFlag
16+
}) => {
17+
const nextResult = nextStep ? selectNext(nextStep, getState) : nextStep;
18+
const progressNext = nextResult !== conditionalSubmitFlag && nextStep;
719
return (
820
<Button
921
type="primary"
1022
htmlType="button"
11-
onClick={() => (nextStep ? handleNext(selectNext(nextStep, getState)) : handleSubmit())}
23+
onClick={() => (progressNext ? handleNext(nextResult) : handleSubmit())}
1224
disabled={!valid}
13-
{...(nextStep ? NextButtonProps : SubmitButtonProps)}
25+
{...(progressNext ? NextButtonProps : SubmitButtonProps)}
1426
>
15-
{nextStep ? buttonLabels.next : buttonLabels.submit}
27+
{progressNext ? buttonLabels.next : buttonLabels.submit}
1628
</Button>
1729
);
1830
};
@@ -30,7 +42,8 @@ NextButton.propTypes = {
3042
next: PropTypes.node.isRequired
3143
}).isRequired,
3244
NextButtonProps: PropTypes.object,
33-
SubmitButtonProps: PropTypes.object
45+
SubmitButtonProps: PropTypes.object,
46+
conditionalSubmitFlag: PropTypes.string.isRequired
3447
};
3548

3649
const WizardStepButtons = ({
@@ -44,7 +57,8 @@ const WizardStepButtons = ({
4457
NextButtonProps,
4558
CancelButtonProps,
4659
BackButtonProps,
47-
SubmitButtonProps
60+
SubmitButtonProps,
61+
conditionalSubmitFlag
4862
}) => (
4963
<div {...ButtonProps}>
5064
{formOptions.onCancel && (
@@ -62,6 +76,7 @@ const WizardStepButtons = ({
6276
buttonLabels={buttonLabels}
6377
NextButtonProps={NextButtonProps}
6478
SubmitButtonProps={SubmitButtonProps}
79+
conditionalSubmitFlag={conditionalSubmitFlag}
6580
/>
6681
</div>
6782
);
@@ -70,6 +85,7 @@ WizardStepButtons.propTypes = {
7085
disableBack: PropTypes.bool,
7186
handlePrev: PropTypes.func.isRequired,
7287
handleNext: PropTypes.func.isRequired,
88+
conditionalSubmitFlag: PropTypes.string.isRequired,
7389
nextStep: PropTypes.oneOfType([
7490
PropTypes.string,
7591
PropTypes.shape({

packages/ant-component-mapper/src/wizard/wizard-step.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { Fragment } from 'react';
22
import PropTypes from 'prop-types';
3+
import FormSpy from '@data-driven-forms/react-form-renderer/form-spy';
34
import WizardStepButtons from './step-buttons';
45

56
import './wizard-step.css';
@@ -9,7 +10,7 @@ const WizardStep = ({ fields, formOptions, WizardStepProps, ...rest }) => (
910
<div className="ddorg__ant-component-mapper_wizard-step" {...WizardStepProps}>
1011
{fields.map((item) => formOptions.renderForm([item], formOptions))}
1112
</div>
12-
<WizardStepButtons formOptions={formOptions} {...rest} />
13+
<FormSpy>{() => <WizardStepButtons formOptions={formOptions} {...rest} />}</FormSpy>
1314
</Fragment>
1415
);
1516

packages/ant-component-mapper/src/wizard/wizard.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ const WizardInternal = ({
2626
NextButtonProps,
2727
BackButtonProps,
2828
CancelButtonProps,
29-
SubmitButtonProps
29+
SubmitButtonProps,
30+
conditionalSubmitFlag
3031
}) => {
3132
const { onKeyDown, formOptions, handleNext, handlePrev, prevSteps, currentStep, jumpToStep, activeStepIndex } = useContext(WizardContext);
3233

@@ -53,6 +54,7 @@ const WizardInternal = ({
5354
BackButtonProps={BackButtonProps}
5455
CancelButtonProps={CancelButtonProps}
5556
SubmitButtonProps={SubmitButtonProps}
57+
conditionalSubmitFlag={conditionalSubmitFlag}
5658
/>
5759
</div>
5860
);
@@ -70,7 +72,8 @@ WizardInternal.propTypes = {
7072
NextButtonProps: PropTypes.object,
7173
BackButtonProps: PropTypes.object,
7274
CancelButtonProps: PropTypes.object,
73-
SubmitButtonProps: PropTypes.object
75+
SubmitButtonProps: PropTypes.object,
76+
conditionalSubmitFlag: PropTypes.string.isRequired
7477
};
7578

7679
const WizardFinal = ({ buttonLabels, ...props }) => (

packages/blueprint-component-mapper/src/tests/wizard.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { mount } from 'enzyme';
44
import { Button } from '@blueprintjs/core';
55

66
import { componentMapper, FormTemplate } from '../index';
7+
import { CONDITIONAL_SUBMIT_FLAG } from '@data-driven-forms/common/wizard';
78

89
describe('wizard', () => {
910
let initialProps;
@@ -338,4 +339,51 @@ describe('wizard', () => {
338339
aws: 'something'
339340
});
340341
});
342+
343+
it('conditional submit step', () => {
344+
const submit = jest.fn();
345+
schema = {
346+
fields: [
347+
{
348+
component: componentTypes.WIZARD,
349+
name: 'wizard',
350+
fields: [
351+
{
352+
name: 'first-step',
353+
nextStep: {
354+
when: 'name',
355+
stepMapper: {
356+
aws: 'summary',
357+
submit: CONDITIONAL_SUBMIT_FLAG
358+
}
359+
},
360+
fields: [
361+
{
362+
component: componentTypes.TEXT_FIELD,
363+
name: 'name',
364+
validate: [{ type: validatorTypes.REQUIRED }]
365+
}
366+
]
367+
}
368+
]
369+
}
370+
]
371+
};
372+
373+
const wrapper = mount(<FormRenderer {...initialProps} onSubmit={submit} schema={schema} />);
374+
375+
wrapper.find('input').instance().value = 'bla';
376+
wrapper.find('input').simulate('change');
377+
wrapper.update();
378+
379+
expect(wrapper.find('button.bp3-button.bp3-intent-success').text()).toEqual('Nextarrow-right');
380+
381+
wrapper.find('input').instance().value = 'submit';
382+
wrapper.find('input').simulate('change');
383+
wrapper.update();
384+
385+
expect(wrapper.find('button.bp3-button.bp3-intent-success').text()).toEqual('Submitarrow-up');
386+
wrapper.find('button.bp3-button.bp3-intent-success').simulate('click');
387+
expect(submit).toHaveBeenCalledWith({ name: 'submit' }, expect.any(Object), expect.any(Object));
388+
});
341389
});

packages/blueprint-component-mapper/src/wizard/step-buttons.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@ import { createUseStyles } from 'react-jss';
66

77
import { Button, Intent } from '@blueprintjs/core';
88

9-
const NextButton = ({ nextStep, handleNext, buttonLabels, getState, handleSubmit, isDisabled, ...props }) => (
10-
<Button
11-
disabled={isDisabled}
12-
onClick={() => (nextStep ? handleNext(selectNext(nextStep, getState)) : handleSubmit())}
13-
rightIcon={nextStep ? 'arrow-right' : 'arrow-up'}
14-
intent={Intent.SUCCESS}
15-
{...props}
16-
>
17-
{nextStep ? buttonLabels.next : buttonLabels.submit}
18-
</Button>
19-
);
9+
const NextButton = ({ nextStep, handleNext, buttonLabels, getState, handleSubmit, isDisabled, conditionalSubmitFlag, ...props }) => {
10+
const nextResult = nextStep ? selectNext(nextStep, getState) : nextStep;
11+
const progressNext = nextResult !== conditionalSubmitFlag && nextStep;
12+
return (
13+
<Button
14+
disabled={isDisabled}
15+
onClick={() => (progressNext ? handleNext(nextResult) : handleSubmit())}
16+
rightIcon={progressNext ? 'arrow-right' : 'arrow-up'}
17+
intent={Intent.SUCCESS}
18+
{...props}
19+
>
20+
{progressNext ? buttonLabels.next : buttonLabels.submit}
21+
</Button>
22+
);
23+
};
2024

2125
NextButton.propTypes = {
2226
handleNext: PropTypes.func,
@@ -29,7 +33,8 @@ NextButton.propTypes = {
2933
nextStep: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object]),
3034
getState: PropTypes.func,
3135
handleSubmit: PropTypes.func,
32-
isDisabled: PropTypes.bool
36+
isDisabled: PropTypes.bool,
37+
conditionalSubmitFlag: PropTypes.string.isRequired
3338
};
3439

3540
const useStyles = createUseStyles({
@@ -57,7 +62,8 @@ const StepButtons = ({
5762
CancelButtonProps,
5863
BackButtonProps,
5964
NextButtonProps,
60-
SubmitButtonProps
65+
SubmitButtonProps,
66+
conditionalSubmitFlag
6167
}) => {
6268
const { buttonGroup } = useStyles();
6369

@@ -77,6 +83,7 @@ const StepButtons = ({
7783
handleNext={handleNext}
7884
isDisabled={!formOptions.valid || isNextDisabled}
7985
handleSubmit={formOptions.handleSubmit}
86+
conditionalSubmitFlag={conditionalSubmitFlag}
8087
{...(currentStep.nextStep ? NextButtonProps : SubmitButtonProps)}
8188
/>
8289
</div>
@@ -88,6 +95,7 @@ StepButtons.propTypes = {
8895
currentStep: PropTypes.object,
8996
handlePrev: PropTypes.func,
9097
handleNext: PropTypes.func,
98+
conditionalSubmitFlag: PropTypes.string.isRequired,
9199
formOptions: PropTypes.shape({
92100
onCancel: PropTypes.func,
93101
renderForm: PropTypes.func,

packages/blueprint-component-mapper/src/wizard/wizard.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const WizardInternal = ({ WizardProps, ...props }) => {
1111
return (
1212
<div onKeyDown={onKeyDown} {...WizardProps}>
1313
{currentStep.fields.map((item) => formOptions.renderForm([item], formOptions))}
14-
<FormSpy subscription={{ valid: true, submitting: true, validating: true }}>
14+
<FormSpy>
1515
{({ valid, submitting, validating }) => (
1616
<StepButtons isNextDisabled={!valid || submitting || validating} {...props} {...rest} currentStep={currentStep} formOptions={formOptions} />
1717
)}

packages/carbon-component-mapper/src/tests/wizard.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FormRenderer, componentTypes, validatorTypes } from '@data-driven-forms
33
import { mount } from 'enzyme';
44

55
import { componentMapper, FormTemplate } from '../index';
6+
import { CONDITIONAL_SUBMIT_FLAG } from '@data-driven-forms/common/wizard';
67

78
describe('wizard', () => {
89
let initialProps;
@@ -365,4 +366,51 @@ describe('wizard', () => {
365366
});
366367
onSubmit.mockClear();
367368
});
369+
370+
it('conditional submit step', () => {
371+
const submit = jest.fn();
372+
schema = {
373+
fields: [
374+
{
375+
component: componentTypes.WIZARD,
376+
name: 'wizard',
377+
fields: [
378+
{
379+
name: 'first-step',
380+
nextStep: {
381+
when: 'name',
382+
stepMapper: {
383+
aws: 'summary',
384+
submit: CONDITIONAL_SUBMIT_FLAG
385+
}
386+
},
387+
fields: [
388+
{
389+
component: componentTypes.TEXT_FIELD,
390+
name: 'name',
391+
validate: [{ type: validatorTypes.REQUIRED }]
392+
}
393+
]
394+
}
395+
]
396+
}
397+
]
398+
};
399+
400+
const wrapper = mount(<FormRenderer {...initialProps} onSubmit={submit} schema={schema} />);
401+
402+
wrapper.find('input').instance().value = 'bla';
403+
wrapper.find('input').simulate('change');
404+
wrapper.update();
405+
406+
expect(wrapper.find('button.bx--btn.bx--btn--primary').text()).toEqual('Next');
407+
408+
wrapper.find('input').instance().value = 'submit';
409+
wrapper.find('input').simulate('change');
410+
wrapper.update();
411+
412+
expect(wrapper.find('button.bx--btn.bx--btn--primary').text()).toEqual('Submit');
413+
wrapper.find('button.bx--btn.bx--btn--primary').simulate('click');
414+
expect(submit).toHaveBeenCalledWith({ name: 'submit' }, expect.any(Object), expect.any(Object));
415+
});
368416
});

0 commit comments

Comments
 (0)