foreman_remote_execution 4.7.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +1 -0
- data/app/controllers/api/v2/job_invocations_controller.rb +7 -1
- data/app/lib/actions/remote_execution/run_host_job.rb +2 -1
- data/app/lib/actions/remote_execution/run_hosts_job.rb +57 -3
- data/app/mailers/rex_job_mailer.rb +15 -0
- data/app/models/job_invocation.rb +4 -0
- data/app/models/job_invocation_composer.rb +20 -12
- data/app/models/remote_execution_provider.rb +18 -2
- data/app/models/rex_mail_notification.rb +13 -0
- data/app/models/setting/remote_execution.rb +7 -1
- data/app/services/ui_notifications/remote_execution_jobs/base_job_finish.rb +2 -1
- data/app/views/dashboard/_latest-jobs.html.erb +21 -0
- data/app/views/rex_job_mailer/job_finished.html.erb +24 -0
- data/app/views/rex_job_mailer/job_finished.text.erb +9 -0
- data/app/views/template_invocations/show.html.erb +2 -1
- data/db/seeds.d/50-notification_blueprints.rb +14 -0
- data/db/seeds.d/95-mail_notifications.rb +24 -0
- data/foreman_remote_execution.gemspec +1 -1
- data/lib/foreman_remote_execution/engine.rb +1 -0
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/package.json +6 -6
- data/test/functional/api/v2/job_invocations_controller_test.rb +10 -0
- data/test/unit/actions/run_hosts_job_test.rb +99 -4
- data/test/unit/job_invocation_report_template_test.rb +15 -12
- data/test/unit/remote_execution_provider_test.rb +46 -0
- data/webpack/JobWizard/JobWizard.js +53 -20
- data/webpack/JobWizard/JobWizard.scss +33 -4
- data/webpack/JobWizard/JobWizardConstants.js +17 -0
- data/webpack/JobWizard/__tests__/fixtures.js +8 -0
- data/webpack/JobWizard/__tests__/integration.test.js +3 -7
- data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +16 -5
- data/webpack/JobWizard/steps/AdvancedFields/Fields.js +48 -1
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +29 -14
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +4 -2
- data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +3 -2
- data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +25 -0
- data/webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js +23 -0
- data/webpack/JobWizard/steps/HostsAndInputs/__tests__/SelectedChips.test.js +37 -0
- data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +50 -0
- data/webpack/JobWizard/steps/HostsAndInputs/index.js +66 -0
- data/webpack/JobWizard/steps/Schedule/ScheduleType.js +24 -21
- data/webpack/JobWizard/steps/Schedule/StartEndDates.js +36 -21
- data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +155 -0
- data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +9 -8
- data/webpack/JobWizard/steps/Schedule/index.js +89 -28
- data/webpack/JobWizard/steps/form/DateTimePicker.js +93 -0
- data/webpack/JobWizard/steps/form/Formatter.js +10 -9
- data/webpack/JobWizard/steps/form/NumberInput.js +2 -0
- data/webpack/JobWizard/steps/form/WizardTitle.js +14 -0
- data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +2 -1
- metadata +18 -4
@@ -1,41 +1,102 @@
|
|
1
|
-
import React
|
2
|
-
import
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { Button, Form } from '@patternfly/react-core';
|
3
4
|
import { translate as __ } from 'foremanReact/common/I18n';
|
4
5
|
import { ScheduleType } from './ScheduleType';
|
5
6
|
import { RepeatOn } from './RepeatOn';
|
6
7
|
import { QueryType } from './QueryType';
|
7
8
|
import { StartEndDates } from './StartEndDates';
|
8
|
-
import {
|
9
|
+
import { WIZARD_TITLES } from '../../JobWizardConstants';
|
10
|
+
import { WizardTitle } from '../form/WizardTitle';
|
9
11
|
|
10
|
-
const Schedule = () => {
|
11
|
-
const
|
12
|
-
const [repeatAmount, setRepeatAmount] = useState('');
|
13
|
-
const [starts, setStarts] = useState('');
|
14
|
-
const [ends, setEnds] = useState('');
|
12
|
+
const Schedule = ({ scheduleValue, setScheduleValue }) => {
|
13
|
+
const { repeatType, repeatAmount, starts, ends, isNeverEnds } = scheduleValue;
|
15
14
|
|
16
15
|
return (
|
17
|
-
|
18
|
-
<
|
19
|
-
<
|
16
|
+
<>
|
17
|
+
<WizardTitle title={WIZARD_TITLES.schedule} />
|
18
|
+
<Form className="schedule-tab">
|
19
|
+
<ScheduleType
|
20
|
+
isFuture={scheduleValue.isFuture}
|
21
|
+
setIsFuture={newValue => {
|
22
|
+
if (!newValue) {
|
23
|
+
// if schedule type is execute now
|
24
|
+
setScheduleValue(current => ({
|
25
|
+
...current,
|
26
|
+
starts: '',
|
27
|
+
}));
|
28
|
+
}
|
29
|
+
setScheduleValue(current => ({
|
30
|
+
...current,
|
31
|
+
isFuture: newValue,
|
32
|
+
}));
|
33
|
+
}}
|
34
|
+
/>
|
20
35
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
<RepeatOn
|
37
|
+
repeatType={repeatType}
|
38
|
+
setRepeatType={newValue => {
|
39
|
+
setScheduleValue(current => ({
|
40
|
+
...current,
|
41
|
+
repeatType: newValue,
|
42
|
+
}));
|
43
|
+
}}
|
44
|
+
repeatAmount={repeatAmount}
|
45
|
+
setRepeatAmount={newValue => {
|
46
|
+
setScheduleValue(current => ({
|
47
|
+
...current,
|
48
|
+
repeatAmount: newValue,
|
49
|
+
}));
|
50
|
+
}}
|
51
|
+
/>
|
52
|
+
<StartEndDates
|
53
|
+
starts={starts}
|
54
|
+
setStarts={newValue => {
|
55
|
+
if (!scheduleValue.isFuture) {
|
56
|
+
setScheduleValue(current => ({
|
57
|
+
...current,
|
58
|
+
isFuture: true,
|
59
|
+
}));
|
60
|
+
}
|
61
|
+
setScheduleValue(current => ({
|
62
|
+
...current,
|
63
|
+
starts: newValue,
|
64
|
+
}));
|
65
|
+
}}
|
66
|
+
ends={ends}
|
67
|
+
setEnds={newValue => {
|
68
|
+
setScheduleValue(current => ({
|
69
|
+
...current,
|
70
|
+
ends: newValue,
|
71
|
+
}));
|
72
|
+
}}
|
73
|
+
isNeverEnds={isNeverEnds}
|
74
|
+
setIsNeverEnds={newValue => {
|
75
|
+
setScheduleValue(current => ({
|
76
|
+
...current,
|
77
|
+
isNeverEnds: newValue,
|
78
|
+
}));
|
79
|
+
}}
|
80
|
+
/>
|
81
|
+
<Button variant="link" className="advanced-scheduling-button" isInline>
|
82
|
+
{__('Advanced scheduling')}
|
83
|
+
</Button>
|
84
|
+
<QueryType />
|
85
|
+
</Form>
|
86
|
+
</>
|
38
87
|
);
|
39
88
|
};
|
40
89
|
|
90
|
+
Schedule.propTypes = {
|
91
|
+
scheduleValue: PropTypes.shape({
|
92
|
+
repeatType: PropTypes.string.isRequired,
|
93
|
+
repeatAmount: PropTypes.string,
|
94
|
+
starts: PropTypes.string,
|
95
|
+
ends: PropTypes.string,
|
96
|
+
isFuture: PropTypes.bool,
|
97
|
+
isNeverEnds: PropTypes.bool,
|
98
|
+
}).isRequired,
|
99
|
+
setScheduleValue: PropTypes.func.isRequired,
|
100
|
+
};
|
101
|
+
|
41
102
|
export default Schedule;
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { DatePicker, TimePicker } from '@patternfly/react-core';
|
4
|
+
import { debounce } from 'lodash';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
|
7
|
+
export const DateTimePicker = ({ dateTime, setDateTime, isDisabled }) => {
|
8
|
+
const dateFormat = date =>
|
9
|
+
`${date.getFullYear()}/${(date.getMonth() + 1)
|
10
|
+
.toString()
|
11
|
+
.padStart(2, '0')}/${date
|
12
|
+
.getDate()
|
13
|
+
.toString()
|
14
|
+
.padStart(2, '0')}`;
|
15
|
+
|
16
|
+
const dateObject = dateTime ? new Date(dateTime) : new Date();
|
17
|
+
const formattedDate = dateTime ? dateFormat(dateObject) : '';
|
18
|
+
const dateParse = date =>
|
19
|
+
new Date(`${date} ${dateObject.getHours()}:${dateObject.getMinutes()}`);
|
20
|
+
|
21
|
+
const isValidDate = date => date && !Number.isNaN(date.getTime());
|
22
|
+
|
23
|
+
const isValidTime = time => {
|
24
|
+
if (!time) return false;
|
25
|
+
const split = time.split(':');
|
26
|
+
if (!(split[0].length === 2 && split[1].length === 2)) return false;
|
27
|
+
if (isValidDate(new Date(`${formattedDate} ${time}`))) return true;
|
28
|
+
if (!formattedDate.length && isValidDate(new Date(`01/01/2020 ${time}`))) {
|
29
|
+
const today = new Date();
|
30
|
+
today.setHours(split[0]);
|
31
|
+
today.setMinutes(split[1]);
|
32
|
+
setDateTime(today.toString());
|
33
|
+
}
|
34
|
+
return false;
|
35
|
+
};
|
36
|
+
|
37
|
+
const onDateChange = newDate => {
|
38
|
+
const parsedNewDate = new Date(newDate);
|
39
|
+
|
40
|
+
if (isValidDate(parsedNewDate)) {
|
41
|
+
parsedNewDate.setHours(dateObject.getHours());
|
42
|
+
parsedNewDate.setMinutes(dateObject.getMinutes());
|
43
|
+
setDateTime(parsedNewDate.toString());
|
44
|
+
}
|
45
|
+
};
|
46
|
+
|
47
|
+
const onTimeChange = newTime => {
|
48
|
+
if (isValidTime(newTime)) {
|
49
|
+
const parsedNewTime = new Date(`${formattedDate} ${newTime}`);
|
50
|
+
setDateTime(parsedNewTime.toString());
|
51
|
+
}
|
52
|
+
};
|
53
|
+
return (
|
54
|
+
<>
|
55
|
+
<DatePicker
|
56
|
+
value={formattedDate}
|
57
|
+
placeholder="yyyy/mm/dd"
|
58
|
+
onChange={debounce(onDateChange, 1000, {
|
59
|
+
leading: false,
|
60
|
+
trailing: true,
|
61
|
+
})}
|
62
|
+
dateFormat={dateFormat}
|
63
|
+
dateParse={dateParse}
|
64
|
+
isDisabled={isDisabled}
|
65
|
+
invalidFormatText={__('Invalid date')}
|
66
|
+
/>
|
67
|
+
<TimePicker
|
68
|
+
className="time-picker"
|
69
|
+
time={dateTime ? dateObject.toString() : ''}
|
70
|
+
inputProps={dateTime ? {} : { value: '' }}
|
71
|
+
placeholder="hh:mm"
|
72
|
+
onChange={debounce(onTimeChange, 1000, {
|
73
|
+
leading: false,
|
74
|
+
trailing: true,
|
75
|
+
})}
|
76
|
+
is24Hour
|
77
|
+
isDisabled={isDisabled}
|
78
|
+
invalidFormatErrorMessage={__('Invalid time format')}
|
79
|
+
menuAppendTo={() => document.body}
|
80
|
+
/>
|
81
|
+
</>
|
82
|
+
);
|
83
|
+
};
|
84
|
+
|
85
|
+
DateTimePicker.propTypes = {
|
86
|
+
dateTime: PropTypes.string,
|
87
|
+
setDateTime: PropTypes.func.isRequired,
|
88
|
+
isDisabled: PropTypes.bool,
|
89
|
+
};
|
90
|
+
DateTimePicker.defaultProps = {
|
91
|
+
dateTime: null,
|
92
|
+
isDisabled: false,
|
93
|
+
};
|
@@ -22,11 +22,12 @@ const TemplateSearchField = ({
|
|
22
22
|
setValue({ ...values, [name]: searchQuery });
|
23
23
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
24
24
|
}, [searchQuery]);
|
25
|
+
const id = name.replace(/ /g, '-');
|
25
26
|
return (
|
26
27
|
<FormGroup
|
27
28
|
label={name}
|
28
29
|
labelIcon={helpLabel(labelText, name)}
|
29
|
-
fieldId={
|
30
|
+
fieldId={id}
|
30
31
|
isRequired={required}
|
31
32
|
className="foreman-search-field"
|
32
33
|
>
|
@@ -54,16 +55,16 @@ export const formatter = (input, values, setValue) => {
|
|
54
55
|
const { name, required, hidden_value: hidden } = input;
|
55
56
|
const labelText = input.description;
|
56
57
|
const value = values[name];
|
57
|
-
|
58
|
+
const id = name.replace(/ /g, '-');
|
58
59
|
if (isSelectType) {
|
59
60
|
const options = input.options.split(/\r?\n/).map(option => option.trim());
|
60
61
|
return (
|
61
62
|
<SelectField
|
62
63
|
aria-label={name}
|
63
|
-
key={
|
64
|
+
key={id}
|
64
65
|
isRequired={required}
|
65
66
|
label={name}
|
66
|
-
fieldId={
|
67
|
+
fieldId={id}
|
67
68
|
options={options}
|
68
69
|
labelIcon={helpLabel(labelText, name)}
|
69
70
|
value={value}
|
@@ -77,7 +78,7 @@ export const formatter = (input, values, setValue) => {
|
|
77
78
|
key={name}
|
78
79
|
label={name}
|
79
80
|
labelIcon={helpLabel(labelText, name)}
|
80
|
-
fieldId={
|
81
|
+
fieldId={id}
|
81
82
|
isRequired={required}
|
82
83
|
>
|
83
84
|
<TextArea
|
@@ -85,7 +86,7 @@ export const formatter = (input, values, setValue) => {
|
|
85
86
|
className={hidden ? 'masked-input' : null}
|
86
87
|
required={required}
|
87
88
|
rows={2}
|
88
|
-
id={
|
89
|
+
id={id}
|
89
90
|
value={value}
|
90
91
|
onChange={newValue => setValue({ ...values, [name]: newValue })}
|
91
92
|
/>
|
@@ -98,7 +99,7 @@ export const formatter = (input, values, setValue) => {
|
|
98
99
|
key={name}
|
99
100
|
label={name}
|
100
101
|
labelIcon={helpLabel(labelText, name)}
|
101
|
-
fieldId={
|
102
|
+
fieldId={id}
|
102
103
|
isRequired={required}
|
103
104
|
>
|
104
105
|
<TextInput
|
@@ -106,7 +107,7 @@ export const formatter = (input, values, setValue) => {
|
|
106
107
|
placeholder="YYYY-mm-dd HH:MM"
|
107
108
|
className={hidden ? 'masked-input' : null}
|
108
109
|
required={required}
|
109
|
-
id={
|
110
|
+
id={id}
|
110
111
|
type="text"
|
111
112
|
value={value}
|
112
113
|
onChange={newValue => setValue({ ...values, [name]: newValue })}
|
@@ -119,7 +120,7 @@ export const formatter = (input, values, setValue) => {
|
|
119
120
|
// TODO: get text from redux autocomplete
|
120
121
|
return (
|
121
122
|
<TemplateSearchField
|
122
|
-
key={
|
123
|
+
key={id}
|
123
124
|
name={name}
|
124
125
|
defaultValue={value}
|
125
126
|
controller={controller}
|
@@ -5,6 +5,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
|
|
5
5
|
|
6
6
|
export const NumberInput = ({ formProps, inputProps }) => {
|
7
7
|
const [validated, setValidated] = useState();
|
8
|
+
const name = inputProps.id.replace(/-/g, ' ');
|
8
9
|
return (
|
9
10
|
<FormGroup
|
10
11
|
{...formProps}
|
@@ -12,6 +13,7 @@ export const NumberInput = ({ formProps, inputProps }) => {
|
|
12
13
|
validated={validated}
|
13
14
|
>
|
14
15
|
<TextInput
|
16
|
+
aria-label={name}
|
15
17
|
type="text"
|
16
18
|
{...inputProps}
|
17
19
|
onChange={newValue => {
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { Title } from '@patternfly/react-core';
|
4
|
+
|
5
|
+
export const WizardTitle = ({ title, ...props }) => (
|
6
|
+
<Title headingLevel="h2" className="wizard-title" {...props}>
|
7
|
+
{title}
|
8
|
+
</Title>
|
9
|
+
);
|
10
|
+
|
11
|
+
WizardTitle.propTypes = {
|
12
|
+
title: PropTypes.string.isRequired,
|
13
|
+
};
|
14
|
+
export default WizardTitle;
|
@@ -21,7 +21,8 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
|
|
21
21
|
|
22
22
|
return (
|
23
23
|
<CardTemplate
|
24
|
-
|
24
|
+
overrideGridProps={{ xl: 8, lg: 8, md: 12 }}
|
25
|
+
header={__('Recent jobs')}
|
25
26
|
dropdownItems={[
|
26
27
|
<DropdownItem
|
27
28
|
href={foremanUrl(`${JOB_BASE_URL}${name}`)}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_remote_execution
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Foreman Remote Execution team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 5.
|
53
|
+
version: 5.1.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 5.
|
60
|
+
version: 5.1.0
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: factory_bot_rails
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- app/lib/foreman_remote_execution/renderer/scope/input.rb
|
151
151
|
- app/lib/proxy_api/remote_execution_ssh.rb
|
152
152
|
- app/mailers/.gitkeep
|
153
|
+
- app/mailers/rex_job_mailer.rb
|
153
154
|
- app/models/concerns/api/v2/interfaces_controller_extensions.rb
|
154
155
|
- app/models/concerns/foreman_remote_execution/bookmark_extensions.rb
|
155
156
|
- app/models/concerns/foreman_remote_execution/errors_flattener.rb
|
@@ -177,6 +178,7 @@ files:
|
|
177
178
|
- app/models/job_template_effective_user.rb
|
178
179
|
- app/models/remote_execution_feature.rb
|
179
180
|
- app/models/remote_execution_provider.rb
|
181
|
+
- app/models/rex_mail_notification.rb
|
180
182
|
- app/models/setting/remote_execution.rb
|
181
183
|
- app/models/ssh_execution_provider.rb
|
182
184
|
- app/models/target_remote_execution_proxy.rb
|
@@ -216,6 +218,7 @@ files:
|
|
216
218
|
- app/views/api/v2/template_invocations/base.json.rabl
|
217
219
|
- app/views/api/v2/template_invocations/template_invocations.json.rabl
|
218
220
|
- app/views/dashboard/.gitkeep
|
221
|
+
- app/views/dashboard/_latest-jobs.html.erb
|
219
222
|
- app/views/job_invocation_task_groups/_job_invocation_task_groups.html.erb
|
220
223
|
- app/views/job_invocations/_card_results.html.erb
|
221
224
|
- app/views/job_invocations/_card_schedule.html.erb
|
@@ -249,6 +252,8 @@ files:
|
|
249
252
|
- app/views/remote_execution_features/_form.html.erb
|
250
253
|
- app/views/remote_execution_features/index.html.erb
|
251
254
|
- app/views/remote_execution_features/show.html.erb
|
255
|
+
- app/views/rex_job_mailer/job_finished.html.erb
|
256
|
+
- app/views/rex_job_mailer/job_finished.text.erb
|
252
257
|
- app/views/template_inputs/_foreign_input_set_form.html.erb
|
253
258
|
- app/views/template_invocations/_output_line_set.html.erb
|
254
259
|
- app/views/template_invocations/_refresh.js.erb
|
@@ -318,6 +323,7 @@ files:
|
|
318
323
|
- db/seeds.d/60-ssh_proxy_feature.rb
|
319
324
|
- db/seeds.d/70-job_templates.rb
|
320
325
|
- db/seeds.d/90-bookmarks.rb
|
326
|
+
- db/seeds.d/95-mail_notifications.rb
|
321
327
|
- extra/cockpit/cockpit.conf.example
|
322
328
|
- extra/cockpit/foreman-cockpit-session
|
323
329
|
- extra/cockpit/foreman-cockpit.service
|
@@ -405,17 +411,25 @@ files:
|
|
405
411
|
- webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js
|
406
412
|
- webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js
|
407
413
|
- webpack/JobWizard/steps/CategoryAndTemplate/index.js
|
414
|
+
- webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js
|
415
|
+
- webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js
|
416
|
+
- webpack/JobWizard/steps/HostsAndInputs/__tests__/SelectedChips.test.js
|
417
|
+
- webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js
|
418
|
+
- webpack/JobWizard/steps/HostsAndInputs/index.js
|
408
419
|
- webpack/JobWizard/steps/Schedule/QueryType.js
|
409
420
|
- webpack/JobWizard/steps/Schedule/RepeatOn.js
|
410
421
|
- webpack/JobWizard/steps/Schedule/ScheduleType.js
|
411
422
|
- webpack/JobWizard/steps/Schedule/StartEndDates.js
|
423
|
+
- webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js
|
412
424
|
- webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js
|
413
425
|
- webpack/JobWizard/steps/Schedule/index.js
|
426
|
+
- webpack/JobWizard/steps/form/DateTimePicker.js
|
414
427
|
- webpack/JobWizard/steps/form/FormHelpers.js
|
415
428
|
- webpack/JobWizard/steps/form/Formatter.js
|
416
429
|
- webpack/JobWizard/steps/form/GroupedSelectField.js
|
417
430
|
- webpack/JobWizard/steps/form/NumberInput.js
|
418
431
|
- webpack/JobWizard/steps/form/SelectField.js
|
432
|
+
- webpack/JobWizard/steps/form/WizardTitle.js
|
419
433
|
- webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example
|
420
434
|
- webpack/Routes/routes.js
|
421
435
|
- webpack/__mocks__/foremanReact/common/I18n.js
|