Skip to content

Commit

Permalink
Fixes #32045 - Add start-end date pickers to job wizard
Browse files Browse the repository at this point in the history
  • Loading branch information
MariaAga committed Jun 18, 2021
1 parent 88f1fb5 commit 97ed9a2
Show file tree
Hide file tree
Showing 13 changed files with 337 additions and 81 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
"@theforeman/eslint-plugin-foreman": "^4.14.0",
"@theforeman/stories": "^4.14.0",
"@theforeman/test": "^4.14.0",
"@theforeman/vendor-dev": "^4.14.0",
"@theforeman/vendor-dev": "^8.4.0",
"babel-eslint": "^10.0.0",
"eslint": "^6.8.0",
"prettier": "^1.19.1",
"@patternfly/react-catalog-view-extension": "^4.8.126",
"redux-mock-store": "^1.2.2"
},
"peerDependencies": {
"@theforeman/vendor": "^8.3.0"
"@theforeman/vendor": "^8.4.0"
}
}
18 changes: 16 additions & 2 deletions webpack/JobWizard/JobWizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
import history from 'foremanReact/history';
import CategoryAndTemplate from './steps/CategoryAndTemplate/';
import { AdvancedFields } from './steps/AdvancedFields/AdvancedFields';
import { JOB_TEMPLATE } from './JobWizardConstants';
import { JOB_TEMPLATE, repeatTypes } from './JobWizardConstants';
import { selectTemplateError } from './JobWizardSelectors';
import Schedule from './steps/Schedule/';
import './JobWizard.scss';
Expand All @@ -17,6 +17,15 @@ export const JobWizard = () => {
const [advancedValues, setAdvancedValues] = useState({});
const dispatch = useDispatch();

const [scheduleValue, setScheduleValue] = useState({
repeatType: repeatTypes.noRepeat,
repeatAmount: '',
starts: '',
ends: '',
isFuture: false,
isNeverEnds: false,
});

const setDefaults = useCallback(response => {
const responseJob = response.data;
setAdvancedValues({
Expand Down Expand Up @@ -73,7 +82,12 @@ export const JobWizard = () => {
},
{
name: __('Schedule'),
component: <Schedule />,
component: (
<Schedule
scheduleValue={scheduleValue}
setScheduleValue={setScheduleValue}
/>
),
canJumpTo: isTemplate,
},
{
Expand Down
14 changes: 14 additions & 0 deletions webpack/JobWizard/JobWizard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,18 @@
text-align: start;
}
}

.pf-c-date-picker {
vertical-align: top;
}

.time-picker {
width: 150px;
}

input[type='radio'],
input[type='checkbox'] {
// overwriting bootstrap/_forms.scss margin: 4px 0 0;
margin: 0;
}
}
6 changes: 6 additions & 0 deletions webpack/JobWizard/__tests__/JobWizard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import JobWizardPage from '../index';

jest.spyOn(patternfly, 'Wizard');
patternfly.Wizard.mockImplementation(props => <div>{props.navAriaLabel}</div>);
const mockDate = new Date(1466424490000);
const spy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);

afterAll(() => {
spy.mockRestore();
});

const fixtures = {
'renders ': {},
Expand Down
45 changes: 24 additions & 21 deletions webpack/JobWizard/steps/Schedule/ScheduleType.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import React, { useState } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { FormGroup, Radio } from '@patternfly/react-core';
import { translate as __ } from 'foremanReact/common/I18n';

export const ScheduleType = () => {
const [isFuture, setIsFuture] = useState(false);
return (
<FormGroup label={__('Schedule type')} fieldId="schedule-type">
<Radio
isChecked={!isFuture}
name="schedule-type"
onChange={() => setIsFuture(false)}
id="schedule-type-now"
label={__('Execute now')}
/>
<Radio
isChecked={isFuture}
name="schedule-type"
onChange={() => setIsFuture(true)}
id="schedule-type-future"
label={__('Schedule for future execution')}
/>
</FormGroup>
);
export const ScheduleType = ({ isFuture, setIsFuture }) => (
<FormGroup label={__('Schedule type')} fieldId="schedule-type">
<Radio
isChecked={!isFuture}
name="schedule-type"
onChange={() => setIsFuture(false)}
id="schedule-type-now"
label={__('Execute now')}
/>
<Radio
isChecked={isFuture}
name="schedule-type"
onChange={() => setIsFuture(true)}
id="schedule-type-future"
label={__('Schedule for future execution')}
/>
</FormGroup>
);

ScheduleType.propTypes = {
isFuture: PropTypes.bool.isRequired,
setIsFuture: PropTypes.func.isRequired,
};
57 changes: 36 additions & 21 deletions webpack/JobWizard/steps/Schedule/StartEndDates.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,48 @@
import React, { useState } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { FormGroup, TextInput, Checkbox } from '@patternfly/react-core';
import { FormGroup, Checkbox } from '@patternfly/react-core';
import { translate as __ } from 'foremanReact/common/I18n';
import { DateTimePicker } from '../form/DateTimePicker';

// TODO: change to datepicker
export const StartEndDates = ({ starts, setStarts, ends, setEnds }) => {
const [isNeverEnds, setIsNeverEnds] = useState(false);
export const StartEndDates = ({
starts,
setStarts,
ends,
setEnds,
isNeverEnds,
setIsNeverEnds,
}) => {
const toggleIsNeverEnds = (checked, event) => {
const value = event?.target?.checked;
setIsNeverEnds(value);
setEnds('');
};
const validateEndDate = () => {
if (isNeverEnds) return 'success';
if (!starts || !ends) return 'success';
if (new Date(starts).getTime() <= new Date(ends).getTime())
return 'success';
return 'error';
};
return (
<>
<FormGroup label={__('Starts')} fieldId="start-date">
<TextInput
id="start-date"
value={starts}
type="text"
onChange={newValue => setStarts(newValue)}
placeholder="mm/dd/yy, hh:mm UTC"
/>
<FormGroup
className="start-date"
label={__('Starts')}
fieldId="start-date"
>
<DateTimePicker dateTime={starts} setDateTime={setStarts} />
</FormGroup>
<FormGroup label={__('Ends')} fieldId="end-date">
<TextInput
<FormGroup
className="end-date"
label={__('Ends')}
fieldId="end-date"
helperTextInvalid={__('End time needs to be after start time')}
validated={validateEndDate()}
>
<DateTimePicker
dateTime={ends}
setDateTime={setEnds}
isDisabled={isNeverEnds}
id="end-date"
value={ends}
type="text"
onChange={newValue => setEnds(newValue)}
placeholder="mm/dd/yy, hh:mm UTC"
/>
<Checkbox
label={__('Never ends')}
Expand All @@ -48,4 +61,6 @@ StartEndDates.propTypes = {
setStarts: PropTypes.func.isRequired,
ends: PropTypes.string.isRequired,
setEnds: PropTypes.func.isRequired,
isNeverEnds: PropTypes.bool.isRequired,
setIsNeverEnds: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ScheduleType } from '../ScheduleType';
jest.spyOn(patternfly, 'FormGroup');
patternfly.FormGroup.mockImplementation(props => <div props={props} />);
const fixtures = {
renders: {},
renders: { isFuture: false, setIsFuture: jest.fn() },
};

describe('ScheduleType', () => {
Expand Down
20 changes: 11 additions & 9 deletions webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import React from 'react';
import * as patternfly from '@patternfly/react-core';
import { render, fireEvent, screen } from '@testing-library/react';
import { render, fireEvent, screen, act } from '@testing-library/react';
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
import { StartEndDates } from '../StartEndDates';

jest.spyOn(patternfly, 'FormGroup');
patternfly.FormGroup.mockImplementation(props => <div props={props} />);

const setEnds = jest.fn();
const setIsNeverEnds = jest.fn();
const props = {
starts: '',
setStarts: jest.fn(),
ends: 'some-end-date',
setEnds,
setIsNeverEnds,
isNeverEnds: false,
};
const fixtures = {
renders: props,
'renders isNeverEnds false': props,
'renders isNeverEnds true': { ...props, isNeverEnds: true },
};

describe('StartEndDates', () => {
testComponentSnapshotsWithFixtures(StartEndDates, fixtures);
it('never ends', () => {
it('never ends', async () => {
patternfly.FormGroup.mockRestore();
render(<StartEndDates {...props} />);
const neverEnds = screen.getByLabelText('Never ends', {
selector: 'input',
});
fireEvent.click(neverEnds);
expect(setEnds).toBeCalledWith('');
await act(async () => render(<StartEndDates {...props} />));
const neverEnds = screen.getByRole('checkbox', { name: 'Never ends' });
await act(async () => fireEvent.click(neverEnds));
expect(setIsNeverEnds).toBeCalledWith(true);
});
});
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`StartEndDates renders 1`] = `
exports[`StartEndDates renders isNeverEnds false 1`] = `
<Fragment>
<mockConstructor
className="start-date"
fieldId="start-date"
label="Starts"
>
<TextInput
id="start-date"
onChange={[Function]}
placeholder="mm/dd/yy, hh:mm UTC"
type="text"
value=""
<DateTimePicker
dateTime=""
isDisabled={false}
setDateTime={[MockFunction]}
/>
</mockConstructor>
<mockConstructor
className="end-date"
fieldId="end-date"
helperTextInvalid="End time needs to be after start time"
label="Ends"
validated="success"
>
<TextInput
id="end-date"
<DateTimePicker
dateTime="some-end-date"
isDisabled={false}
onChange={[Function]}
placeholder="mm/dd/yy, hh:mm UTC"
type="text"
value="some-end-date"
setDateTime={[MockFunction]}
/>
<Checkbox
className=""
Expand All @@ -39,3 +38,42 @@ exports[`StartEndDates renders 1`] = `
</mockConstructor>
</Fragment>
`;

exports[`StartEndDates renders isNeverEnds true 1`] = `
<Fragment>
<mockConstructor
className="start-date"
fieldId="start-date"
label="Starts"
>
<DateTimePicker
dateTime=""
isDisabled={false}
setDateTime={[MockFunction]}
/>
</mockConstructor>
<mockConstructor
className="end-date"
fieldId="end-date"
helperTextInvalid="End time needs to be after start time"
label="Ends"
validated="success"
>
<DateTimePicker
dateTime="some-end-date"
isDisabled={true}
setDateTime={[MockFunction]}
/>
<Checkbox
className=""
id="never-ends"
isChecked={true}
isDisabled={false}
isValid={true}
label="Never ends"
name="never-ends"
onChange={[Function]}
/>
</mockConstructor>
</Fragment>
`;

0 comments on commit 97ed9a2

Please sign in to comment.