-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: fix continuous execution and cron expression dynamic
- Loading branch information
ismay
committed
Jan 13, 2021
1 parent
a95ba1f
commit 76d216f
Showing
10 changed files
with
164 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react' | ||
import { object } from 'prop-types' | ||
import { Radio as CoreRadio } from '@dhis2/ui-core' | ||
|
||
const Radio = ({ input, ...rest }) => { | ||
return <CoreRadio {...input} {...rest} /> | ||
} | ||
|
||
Radio.propTypes = { | ||
input: object.isRequired, | ||
} | ||
|
||
export default Radio |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react' | ||
import { shallow } from 'enzyme' | ||
import Radio from './Radio' | ||
|
||
describe('<Radio>', () => { | ||
it('renders correctly', () => { | ||
const props = { | ||
input: { | ||
onChange: () => {}, | ||
name: 'name', | ||
value: 'value', | ||
}, | ||
label: 'label', | ||
} | ||
const wrapper = shallow(<Radio {...props} />) | ||
|
||
expect(wrapper).toMatchSnapshot() | ||
}) | ||
}) |
10 changes: 10 additions & 0 deletions
10
src/components/FormBaseFields/__snapshots__/Radio.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`<Radio> renders correctly 1`] = ` | ||
<Radio | ||
label="label" | ||
name="name" | ||
onChange={[Function]} | ||
value="value" | ||
/> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import InputField from './InputField' | ||
import Radio from './Radio' | ||
import SelectField from './SelectField' | ||
import Switch from './Switch' | ||
|
||
export { InputField, SelectField, Switch } | ||
export { InputField, SelectField, Switch, Radio } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,49 @@ | ||
import React from 'react' | ||
import { Field } from 'react-final-form' | ||
import { Switch } from '../../components/FormBaseFields' | ||
import { Field, FormSpy } from 'react-final-form' | ||
import { Radio } from '../FormBaseFields' | ||
import CronField from './CronField' | ||
|
||
// The key under which this field will be sent to the backend | ||
export const FIELD_NAME = 'continuousExecution' | ||
|
||
/** | ||
* This field is slightly convoluted. For scheduling, the job can either be set to continuous | ||
* execution, or to a cron expression. The display of the cron is controlled by the value of | ||
* continuous execution. So this field actually has two purposes; set the value for continuous | ||
* execution, and control the display of the cron expression field. | ||
* It was designed as a radio button, which does not allow a boolean as a value. But the backend | ||
* expects a boolean for the continuousExecution field. So we're setting true or false as a string. | ||
* This does work as well, but eventually we'll have to revisit this design as this is hacky and | ||
* more likely to break. | ||
*/ | ||
|
||
const ContinuousExecutionField = () => ( | ||
<Field | ||
name={FIELD_NAME} | ||
component={Switch} | ||
label="Continuous Execution" | ||
type="checkbox" | ||
/> | ||
<FormSpy subscription={{ values: true }}> | ||
{({ values }) => { | ||
const continuousExecution = values[FIELD_NAME] | ||
|
||
return ( | ||
<React.Fragment> | ||
<p>When should the job run?</p> | ||
<Field | ||
label="At a set time/interval" | ||
component={Radio} | ||
name={FIELD_NAME} | ||
type="radio" | ||
value="false" | ||
/> | ||
{continuousExecution === 'false' && <CronField />} | ||
<Field | ||
label="Continuously" | ||
component={Radio} | ||
name={FIELD_NAME} | ||
type="radio" | ||
value="true" | ||
/> | ||
</React.Fragment> | ||
) | ||
}} | ||
</FormSpy> | ||
) | ||
|
||
export default ContinuousExecutionField |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,74 @@ | ||
import React from 'react' | ||
import { bool } from 'prop-types' | ||
import { Field } from 'react-final-form' | ||
import { func, string } from 'prop-types' | ||
import { connect } from 'react-redux' | ||
import { Field, FormSpy } from 'react-final-form' | ||
import cronstrue from 'cronstrue' | ||
import { getCronPreset } from '../../rootSelectors' | ||
import { selectors, actions } from '../../data/cron-preset' | ||
import { InputField } from '../../components/FormBaseFields' | ||
import { requiredCron } from '../../services/validators' | ||
import { ShowCronPresetButton } from '../Buttons' | ||
import { requiredCron, validateCron } from '../../services/validators' | ||
|
||
// The key under which this field will be sent to the backend | ||
export const FIELD_NAME = 'cronExpression' | ||
export const VALIDATOR = requiredCron | ||
|
||
const CronField = ({ disabled }) => ( | ||
<Field | ||
component={InputField} | ||
name={FIELD_NAME} | ||
validate={VALIDATOR} | ||
label="CRON Expression" | ||
type="text" | ||
required={!disabled} | ||
disabled={disabled} | ||
/> | ||
const DumbCronField = ({ cronPreset, clearPreset }) => ( | ||
<FormSpy subscription={{ values: true }}> | ||
{({ form, values }) => { | ||
let humanReadableCron = '' | ||
const cronExpression = values[FIELD_NAME] | ||
|
||
// Update the cron expression if a preset has been selected | ||
if (cronPreset && cronExpression !== cronPreset) { | ||
form.change(FIELD_NAME, cronPreset) | ||
|
||
// Clear the preset to prevent further updates | ||
clearPreset() | ||
} | ||
|
||
if (cronExpression && validateCron(cronExpression)) { | ||
humanReadableCron = cronstrue.toString(cronExpression) | ||
} | ||
|
||
return ( | ||
<React.Fragment> | ||
<Field | ||
component={InputField} | ||
name={FIELD_NAME} | ||
validate={VALIDATOR} | ||
label="CRON Expression" | ||
type="text" | ||
required | ||
/> | ||
<p>{humanReadableCron}</p> | ||
<ShowCronPresetButton /> | ||
</React.Fragment> | ||
) | ||
}} | ||
</FormSpy> | ||
) | ||
|
||
CronField.defaultProps = { | ||
disabled: false, | ||
DumbCronField.propTypes = { | ||
cronPreset: string.isRequired, | ||
clearPreset: func.isRequired, | ||
} | ||
|
||
const mapStateToProps = state => { | ||
/* istanbul ignore next */ | ||
const cronPreset = getCronPreset(state) | ||
|
||
/* istanbul ignore next */ | ||
return { | ||
cronPreset: selectors.getPreset(cronPreset), | ||
} | ||
} | ||
|
||
CronField.propTypes = { | ||
disabled: bool, | ||
const mapDispatchToProps = { | ||
clearPreset: actions.clearPreset, | ||
} | ||
|
||
export default CronField | ||
export default connect( | ||
mapStateToProps, | ||
mapDispatchToProps | ||
)(DumbCronField) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters