foreman_remote_execution 4.5.5 → 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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby_ci.yml +7 -0
  3. data/.rubocop_todo.yml +1 -0
  4. data/app/controllers/api/v2/job_invocations_controller.rb +7 -1
  5. data/app/graphql/types/job_invocation.rb +16 -0
  6. data/app/lib/actions/remote_execution/run_host_job.rb +2 -1
  7. data/app/lib/actions/remote_execution/run_hosts_job.rb +57 -3
  8. data/app/mailers/rex_job_mailer.rb +15 -0
  9. data/app/models/job_invocation.rb +4 -0
  10. data/app/models/job_invocation_composer.rb +21 -13
  11. data/app/models/job_template.rb +1 -1
  12. data/app/models/remote_execution_provider.rb +17 -2
  13. data/app/models/rex_mail_notification.rb +13 -0
  14. data/app/models/setting/remote_execution.rb +7 -1
  15. data/app/services/ui_notifications/remote_execution_jobs/base_job_finish.rb +2 -1
  16. data/app/views/dashboard/_latest-jobs.html.erb +21 -0
  17. data/app/views/rex_job_mailer/job_finished.html.erb +24 -0
  18. data/app/views/rex_job_mailer/job_finished.text.erb +9 -0
  19. data/app/views/template_invocations/show.html.erb +2 -1
  20. data/db/seeds.d/50-notification_blueprints.rb +14 -0
  21. data/db/seeds.d/95-mail_notifications.rb +24 -0
  22. data/foreman_remote_execution.gemspec +2 -4
  23. data/lib/foreman_remote_execution/engine.rb +4 -0
  24. data/lib/foreman_remote_execution/version.rb +1 -1
  25. data/package.json +6 -6
  26. data/test/functional/api/v2/job_invocations_controller_test.rb +10 -0
  27. data/test/graphql/queries/job_invocation_query_test.rb +31 -0
  28. data/test/graphql/queries/job_invocations_query_test.rb +35 -0
  29. data/test/unit/actions/run_hosts_job_test.rb +99 -4
  30. data/test/unit/concerns/host_extensions_test.rb +4 -4
  31. data/test/unit/input_template_renderer_test.rb +1 -89
  32. data/test/unit/job_invocation_composer_test.rb +1 -12
  33. data/test/unit/job_invocation_report_template_test.rb +15 -12
  34. data/test/unit/remote_execution_provider_test.rb +34 -0
  35. data/webpack/JobWizard/JobWizard.js +53 -20
  36. data/webpack/JobWizard/JobWizard.scss +33 -4
  37. data/webpack/JobWizard/JobWizardConstants.js +17 -0
  38. data/webpack/JobWizard/__tests__/fixtures.js +8 -0
  39. data/webpack/JobWizard/__tests__/integration.test.js +3 -7
  40. data/webpack/JobWizard/steps/AdvancedFields/AdvancedFields.js +16 -5
  41. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +48 -1
  42. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +29 -14
  43. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +4 -2
  44. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js +3 -2
  45. data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +25 -0
  46. data/webpack/JobWizard/steps/HostsAndInputs/TemplateInputs.js +23 -0
  47. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/SelectedChips.test.js +37 -0
  48. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/TemplateInputs.test.js +50 -0
  49. data/webpack/JobWizard/steps/HostsAndInputs/index.js +66 -0
  50. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +24 -21
  51. data/webpack/JobWizard/steps/Schedule/StartEndDates.js +36 -21
  52. data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +155 -0
  53. data/webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js +9 -8
  54. data/webpack/JobWizard/steps/Schedule/index.js +89 -28
  55. data/webpack/JobWizard/steps/form/DateTimePicker.js +93 -0
  56. data/webpack/JobWizard/steps/form/Formatter.js +10 -9
  57. data/webpack/JobWizard/steps/form/NumberInput.js +2 -0
  58. data/webpack/JobWizard/steps/form/WizardTitle.js +14 -0
  59. data/webpack/react_app/components/RecentJobsCard/JobStatusIcon.js +43 -0
  60. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +73 -66
  61. data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +98 -0
  62. data/webpack/react_app/components/RecentJobsCard/constants.js +11 -0
  63. data/webpack/react_app/components/RecentJobsCard/styles.scss +11 -0
  64. data/webpack/react_app/extend/fillRecentJobsCard.js +1 -1
  65. metadata +26 -19
  66. data/webpack/react_app/components/RecentJobsCard/styles.css +0 -15
@@ -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;
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ CheckCircleIcon,
5
+ ExclamationCircleIcon,
6
+ QuestionCircleIcon,
7
+ } from '@patternfly/react-icons';
8
+ import { JOB_SUCCESS_STATUS, JOB_ERROR_STATUS } from './constants';
9
+ import './styles.scss';
10
+
11
+ const JobStatusIcon = ({ status, children, ...props }) => {
12
+ switch (status) {
13
+ case JOB_SUCCESS_STATUS:
14
+ return (
15
+ <span className="job-success">
16
+ <CheckCircleIcon {...props} /> {children}
17
+ </span>
18
+ );
19
+ case JOB_ERROR_STATUS:
20
+ return (
21
+ <span className="job-error">
22
+ <ExclamationCircleIcon {...props} /> {children}
23
+ </span>
24
+ );
25
+ default:
26
+ return (
27
+ <span className="job-info">
28
+ <QuestionCircleIcon {...props} /> {children}
29
+ </span>
30
+ );
31
+ }
32
+ };
33
+
34
+ JobStatusIcon.propTypes = {
35
+ status: PropTypes.number,
36
+ children: PropTypes.string.isRequired,
37
+ };
38
+
39
+ JobStatusIcon.defaultProps = {
40
+ status: undefined,
41
+ };
42
+
43
+ export default JobStatusIcon;
@@ -1,76 +1,78 @@
1
- /* eslint-disable camelcase */
2
-
3
1
  import PropTypes from 'prop-types';
4
- import React from 'react';
5
- import Skeleton from 'react-loading-skeleton';
6
- import ElipsisWithTooltip from 'react-ellipsis-with-tooltip';
7
-
8
- import { Grid, GridItem } from '@patternfly/react-core';
9
- import {
10
- PropertiesSidePanel,
11
- PropertyItem,
12
- } from '@patternfly/react-catalog-view-extension';
13
- import { ArrowIcon, ErrorCircleOIcon, OkIcon } from '@patternfly/react-icons';
2
+ import React, { useState } from 'react';
14
3
 
15
- import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
16
- import CardItem from 'foremanReact/components/HostDetails/Templates/CardItem/CardTemplate';
17
- import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
4
+ import { DropdownItem, Tabs, Tab, TabTitleText } from '@patternfly/react-core';
5
+ import CardTemplate from 'foremanReact/components/HostDetails/Templates/CardItem/CardTemplate';
18
6
  import { translate as __ } from 'foremanReact/common/I18n';
19
- import './styles.css';
7
+ import { foremanUrl } from 'foremanReact/common/helpers';
20
8
 
21
- const RecentJobsCard = ({ hostDetails: { name } }) => {
22
- const jobsUrl =
23
- name && `/api/job_invocations?search=host%3D${name}&per_page=3`;
24
- const {
25
- response: { results: jobs },
26
- } = useAPI('get', jobsUrl);
9
+ import {
10
+ FINISHED_TAB,
11
+ RUNNING_TAB,
12
+ SCHEDULED_TAB,
13
+ JOB_BASE_URL,
14
+ } from './constants';
15
+ import RecentJobsTable from './RecentJobsTable';
27
16
 
28
- const iconMarkup = status => {
29
- if (status === 1) return <ErrorCircleOIcon color="#C9190B" />;
30
- return <OkIcon color="#3E8635" />;
31
- };
17
+ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
18
+ const [activeTab, setActiveTab] = useState(FINISHED_TAB);
19
+
20
+ const handleTabClick = (evt, tabIndex) => setActiveTab(tabIndex);
32
21
 
33
22
  return (
34
- <CardItem
35
- header={
36
- <span>
37
- {__('Recent Jobs')}{' '}
38
- <a href={`/job_invocations?search=host+%3D+${name}`}>
39
- <ArrowIcon />
40
- </a>
41
- </span>
42
- }
23
+ <CardTemplate
24
+ overrideGridProps={{ xl: 8, lg: 8, md: 12 }}
25
+ header={__('Recent jobs')}
26
+ dropdownItems={[
27
+ <DropdownItem
28
+ href={foremanUrl(`${JOB_BASE_URL}${name}`)}
29
+ key="link-to-all"
30
+ >
31
+ {__('View All Jobs')}
32
+ </DropdownItem>,
33
+ <DropdownItem
34
+ href={foremanUrl(
35
+ `${JOB_BASE_URL}${name}+and+status+%3D+failed+or+status%3D+succeeded`
36
+ )}
37
+ key="link-to-finished"
38
+ >
39
+ {__('View Finished Jobs')}
40
+ </DropdownItem>,
41
+ <DropdownItem
42
+ href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+running`)}
43
+ key="link-to-running"
44
+ >
45
+ {__('View Running Jobs')}
46
+ </DropdownItem>,
47
+ <DropdownItem
48
+ href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+queued`)}
49
+ key="link-to-scheduled"
50
+ >
51
+ {__('View Scheduled Jobs')}
52
+ </DropdownItem>,
53
+ ]}
43
54
  >
44
- <PropertiesSidePanel>
45
- {jobs?.map(({ status, status_label, id, start_at, description }) => (
46
- <PropertyItem
47
- key={id}
48
- label={
49
- description ? (
50
- <Grid>
51
- <GridItem span={8}>
52
- <ElipsisWithTooltip>{description}</ElipsisWithTooltip>
53
- </GridItem>
54
- <GridItem span={1}>{iconMarkup(status)}</GridItem>
55
- <GridItem span={3}>{status_label}</GridItem>
56
- </Grid>
57
- ) : (
58
- <Skeleton />
59
- )
60
- }
61
- value={
62
- start_at ? (
63
- <a href={`/job_invocations/${id}`}>
64
- <RelativeDateTime date={start_at} />
65
- </a>
66
- ) : (
67
- <Skeleton />
68
- )
69
- }
70
- />
71
- ))}
72
- </PropertiesSidePanel>
73
- </CardItem>
55
+ <Tabs mountOnEnter activeKey={activeTab} onSelect={handleTabClick}>
56
+ <Tab
57
+ eventKey={FINISHED_TAB}
58
+ title={<TabTitleText>{__('Finished')}</TabTitleText>}
59
+ >
60
+ <RecentJobsTable hostId={id} status="failed+or+status%3D+succeeded" />
61
+ </Tab>
62
+ <Tab
63
+ eventKey={RUNNING_TAB}
64
+ title={<TabTitleText>{__('Running')}</TabTitleText>}
65
+ >
66
+ <RecentJobsTable hostId={id} status="running" />
67
+ </Tab>
68
+ <Tab
69
+ eventKey={SCHEDULED_TAB}
70
+ title={<TabTitleText>{__('Scheduled')}</TabTitleText>}
71
+ >
72
+ <RecentJobsTable hostId={id} status="queued" />
73
+ </Tab>
74
+ </Tabs>
75
+ </CardTemplate>
74
76
  );
75
77
  };
76
78
 
@@ -79,5 +81,10 @@ export default RecentJobsCard;
79
81
  RecentJobsCard.propTypes = {
80
82
  hostDetails: PropTypes.shape({
81
83
  name: PropTypes.string,
82
- }).isRequired,
84
+ id: PropTypes.number,
85
+ }),
86
+ };
87
+
88
+ RecentJobsCard.defaultProps = {
89
+ hostDetails: {},
83
90
  };
@@ -0,0 +1,98 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import {
4
+ DataList,
5
+ DataListItem,
6
+ DataListItemRow,
7
+ DataListItemCells,
8
+ DataListCell,
9
+ DataListWrapModifier,
10
+ Text,
11
+ Bullseye,
12
+ } from '@patternfly/react-core';
13
+ import { STATUS } from 'foremanReact/constants';
14
+
15
+ import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
16
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
17
+ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
18
+ import { translate as __ } from 'foremanReact/common/I18n';
19
+ import { foremanUrl } from 'foremanReact/common/helpers';
20
+
21
+ import JobStatusIcon from './JobStatusIcon';
22
+ import { JOB_API_URL, JOBS_IN_CARD } from './constants';
23
+
24
+ const RecentJobsTable = ({ status, hostId }) => {
25
+ const jobsUrl =
26
+ hostId &&
27
+ foremanUrl(
28
+ `${JOB_API_URL}${hostId}+and+status%3D${status}&per_page=${JOBS_IN_CARD}`
29
+ );
30
+ const {
31
+ response: { results: jobs },
32
+ status: responseStatus,
33
+ } = useAPI('get', jobsUrl);
34
+
35
+ return (
36
+ <DataList aria-label="recent-jobs-table" isCompact>
37
+ <SkeletonLoader
38
+ skeletonProps={{ count: 3 }}
39
+ status={responseStatus || STATUS.PENDING}
40
+ emptyState={
41
+ <Bullseye>
42
+ <Text style={{ marginTop: '20px' }} component="p">
43
+ {__('No results found')}
44
+ </Text>
45
+ </Bullseye>
46
+ }
47
+ >
48
+ {jobs?.length &&
49
+ jobs.map(
50
+ ({
51
+ status: jobStatus,
52
+ status_label: label,
53
+ id,
54
+ start_at: startAt,
55
+ description,
56
+ }) => (
57
+ <DataListItem key={id}>
58
+ <DataListItemRow>
59
+ <DataListItemCells
60
+ dataListCells={[
61
+ <DataListCell
62
+ wrapModifier={DataListWrapModifier.truncate}
63
+ key={`name-${id}`}
64
+ >
65
+ <a href={foremanUrl(`/job_invocations/${id}`)}>
66
+ {description}
67
+ </a>
68
+ </DataListCell>,
69
+ <DataListCell key={`date-${id}`}>
70
+ <RelativeDateTime date={startAt} />
71
+ </DataListCell>,
72
+ <DataListCell key={`status-${id}`}>
73
+ <JobStatusIcon status={jobStatus}>
74
+ {label}
75
+ </JobStatusIcon>
76
+ </DataListCell>,
77
+ ]}
78
+ />
79
+ </DataListItemRow>
80
+ </DataListItem>
81
+ )
82
+ )}
83
+ </SkeletonLoader>
84
+ </DataList>
85
+ );
86
+ };
87
+
88
+ RecentJobsTable.propTypes = {
89
+ hostId: PropTypes.number,
90
+ status: PropTypes.string,
91
+ };
92
+
93
+ RecentJobsTable.defaultProps = {
94
+ hostId: undefined,
95
+ status: STATUS.PENDING,
96
+ };
97
+
98
+ export default RecentJobsTable;
@@ -1 +1,12 @@
1
1
  export const HOST_DETAILS_JOBS = 'HOST_DETAILS_JOBS';
2
+ export const FINISHED_TAB = 0;
3
+ export const RUNNING_TAB = 1;
4
+ export const SCHEDULED_TAB = 2;
5
+
6
+ export const JOB_SUCCESS_STATUS = 0;
7
+ export const JOB_ERROR_STATUS = 1;
8
+
9
+ export const JOB_BASE_URL = '/job_invocations?search=host+%3D+';
10
+ export const JOB_API_URL =
11
+ '/api/job_invocations?order=start_at+DESC&search=targeted_host_id%3D';
12
+ export const JOBS_IN_CARD = 3;
@@ -0,0 +1,11 @@
1
+ .job-success {
2
+ color: var(--pf-global--success-color--100);
3
+ }
4
+
5
+ .job-error {
6
+ color: var(--pf-global--danger-color--100);
7
+ }
8
+
9
+ .job-info {
10
+ color: var(--pf-global--info-color--200);
11
+ }
@@ -6,6 +6,6 @@ export default () =>
6
6
  addGlobalFill(
7
7
  'details-cards',
8
8
  'rex-host-details-latest-jobs',
9
- <RecentJobsCard />,
9
+ <RecentJobsCard key="rex-host-details-latest-jobs" />,
10
10
  1000
11
11
  );
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.5.5
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-08-17 00:00:00.000000000 Z
11
+ date: 2021-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -44,34 +44,20 @@ dependencies:
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
46
  version: 2.0.0
47
- - !ruby/object:Gem::Dependency
48
- name: foreman_remote_execution_core
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: foreman-tasks
63
49
  requirement: !ruby/object:Gem::Requirement
64
50
  requirements:
65
51
  - - ">="
66
52
  - !ruby/object:Gem::Version
67
- version: 4.1.0
53
+ version: 5.1.0
68
54
  type: :runtime
69
55
  prerelease: false
70
56
  version_requirements: !ruby/object:Gem::Requirement
71
57
  requirements:
72
58
  - - ">="
73
59
  - !ruby/object:Gem::Version
74
- version: 4.1.0
60
+ version: 5.1.0
75
61
  - !ruby/object:Gem::Dependency
76
62
  name: factory_bot_rails
77
63
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +136,7 @@ files:
150
136
  - app/controllers/remote_execution_features_controller.rb
151
137
  - app/controllers/template_invocations_controller.rb
152
138
  - app/controllers/ui_job_wizard_controller.rb
139
+ - app/graphql/types/job_invocation.rb
153
140
  - app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb
154
141
  - app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb
155
142
  - app/helpers/job_invocation_output_helper.rb
@@ -163,6 +150,7 @@ files:
163
150
  - app/lib/foreman_remote_execution/renderer/scope/input.rb
164
151
  - app/lib/proxy_api/remote_execution_ssh.rb
165
152
  - app/mailers/.gitkeep
153
+ - app/mailers/rex_job_mailer.rb
166
154
  - app/models/concerns/api/v2/interfaces_controller_extensions.rb
167
155
  - app/models/concerns/foreman_remote_execution/bookmark_extensions.rb
168
156
  - app/models/concerns/foreman_remote_execution/errors_flattener.rb
@@ -190,6 +178,7 @@ files:
190
178
  - app/models/job_template_effective_user.rb
191
179
  - app/models/remote_execution_feature.rb
192
180
  - app/models/remote_execution_provider.rb
181
+ - app/models/rex_mail_notification.rb
193
182
  - app/models/setting/remote_execution.rb
194
183
  - app/models/ssh_execution_provider.rb
195
184
  - app/models/target_remote_execution_proxy.rb
@@ -229,6 +218,7 @@ files:
229
218
  - app/views/api/v2/template_invocations/base.json.rabl
230
219
  - app/views/api/v2/template_invocations/template_invocations.json.rabl
231
220
  - app/views/dashboard/.gitkeep
221
+ - app/views/dashboard/_latest-jobs.html.erb
232
222
  - app/views/job_invocation_task_groups/_job_invocation_task_groups.html.erb
233
223
  - app/views/job_invocations/_card_results.html.erb
234
224
  - app/views/job_invocations/_card_schedule.html.erb
@@ -262,6 +252,8 @@ files:
262
252
  - app/views/remote_execution_features/_form.html.erb
263
253
  - app/views/remote_execution_features/index.html.erb
264
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
265
257
  - app/views/template_inputs/_foreign_input_set_form.html.erb
266
258
  - app/views/template_invocations/_output_line_set.html.erb
267
259
  - app/views/template_invocations/_refresh.js.erb
@@ -331,6 +323,7 @@ files:
331
323
  - db/seeds.d/60-ssh_proxy_feature.rb
332
324
  - db/seeds.d/70-job_templates.rb
333
325
  - db/seeds.d/90-bookmarks.rb
326
+ - db/seeds.d/95-mail_notifications.rb
334
327
  - extra/cockpit/cockpit.conf.example
335
328
  - extra/cockpit/foreman-cockpit-session
336
329
  - extra/cockpit/foreman-cockpit.service
@@ -380,6 +373,8 @@ files:
380
373
  - test/functional/job_invocations_controller_test.rb
381
374
  - test/functional/job_templates_controller_test.rb
382
375
  - test/functional/ui_job_wizard_controller_test.rb
376
+ - test/graphql/queries/job_invocation_query_test.rb
377
+ - test/graphql/queries/job_invocations_query_test.rb
383
378
  - test/helpers/remote_execution_helper_test.rb
384
379
  - test/support/remote_execution_helper.rb
385
380
  - test/test_plugin_helper.rb
@@ -416,17 +411,25 @@ files:
416
411
  - webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js
417
412
  - webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.test.js
418
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
419
419
  - webpack/JobWizard/steps/Schedule/QueryType.js
420
420
  - webpack/JobWizard/steps/Schedule/RepeatOn.js
421
421
  - webpack/JobWizard/steps/Schedule/ScheduleType.js
422
422
  - webpack/JobWizard/steps/Schedule/StartEndDates.js
423
+ - webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js
423
424
  - webpack/JobWizard/steps/Schedule/__tests__/StartEndDates.test.js
424
425
  - webpack/JobWizard/steps/Schedule/index.js
426
+ - webpack/JobWizard/steps/form/DateTimePicker.js
425
427
  - webpack/JobWizard/steps/form/FormHelpers.js
426
428
  - webpack/JobWizard/steps/form/Formatter.js
427
429
  - webpack/JobWizard/steps/form/GroupedSelectField.js
428
430
  - webpack/JobWizard/steps/form/NumberInput.js
429
431
  - webpack/JobWizard/steps/form/SelectField.js
432
+ - webpack/JobWizard/steps/form/WizardTitle.js
430
433
  - webpack/JobWizard/steps/form/__tests__/Formatter.test.js.example
431
434
  - webpack/Routes/routes.js
432
435
  - webpack/__mocks__/foremanReact/common/I18n.js
@@ -442,10 +445,12 @@ files:
442
445
  - webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js
443
446
  - webpack/global_index.js
444
447
  - webpack/index.js
448
+ - webpack/react_app/components/RecentJobsCard/JobStatusIcon.js
445
449
  - webpack/react_app/components/RecentJobsCard/RecentJobsCard.js
450
+ - webpack/react_app/components/RecentJobsCard/RecentJobsTable.js
446
451
  - webpack/react_app/components/RecentJobsCard/constants.js
447
452
  - webpack/react_app/components/RecentJobsCard/index.js
448
- - webpack/react_app/components/RecentJobsCard/styles.css
453
+ - webpack/react_app/components/RecentJobsCard/styles.scss
449
454
  - webpack/react_app/components/RegistrationExtension/RexInterface.js
450
455
  - webpack/react_app/components/RegistrationExtension/__tests__/RexInterface.test.js
451
456
  - webpack/react_app/components/RegistrationExtension/__tests__/__snapshots__/RexInterface.test.js.snap
@@ -520,6 +525,8 @@ test_files:
520
525
  - test/functional/job_invocations_controller_test.rb
521
526
  - test/functional/job_templates_controller_test.rb
522
527
  - test/functional/ui_job_wizard_controller_test.rb
528
+ - test/graphql/queries/job_invocation_query_test.rb
529
+ - test/graphql/queries/job_invocations_query_test.rb
523
530
  - test/helpers/remote_execution_helper_test.rb
524
531
  - test/support/remote_execution_helper.rb
525
532
  - test/test_plugin_helper.rb