foreman_remote_execution 4.5.5 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
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