foreman_remote_execution 13.2.4 → 13.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72be28962ab121fc6ffc3541a26a48690c0d55afb36dfc2ae99d6b4fa3535cb1
4
- data.tar.gz: aeca3e51bee086c4d6b88ef77ed75663727ef44241e6f34d645f84da51f1715a
3
+ metadata.gz: f9049b84ffeb17c5603ee539e395f8de3180211896386064769bdec137a55aa2
4
+ data.tar.gz: 819932602c95357b78f56a1b04ed837c6f10ada81d653e0c621f832f594c6749
5
5
  SHA512:
6
- metadata.gz: 71f5695fb253fc5f90133161536dee9593b9b31105928c2c1d97eb0c3d8e3ad654a4cf550d29cd9bc113888507efc03b0cd7384155047965ceed00220c3b740a
7
- data.tar.gz: d4dd8722f3ee5ae0c5091d96db0c0dbf68ef7e554fd8926bce6017b4cd974b634182c776166a023f94fd1b98af73478ac941316475ae51f360fab885c68217bb
6
+ metadata.gz: bd6873c9f48b728cb4d7627c57bade8f1693355ef87d1ec2e7ece5af689fff10b2990edf8da0ae24a438afc0effab6de27be4db0c28908e340ea51dd1cc2bb4a
7
+ data.tar.gz: 6f56b251e5678619ae91cc0627096a468c04f3c28ad87e0f76adb3978d213d75bf7889d71e4f1228810f52f25a913f6e026e3828f5b5f45d721bd588de0c566e
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '13.2.4'.freeze
2
+ VERSION = '13.2.5'.freeze
3
3
  end
@@ -1,16 +1,33 @@
1
+ import React, { useState, useEffect } from 'react';
1
2
  import PropTypes from 'prop-types';
2
- import React from 'react';
3
3
  import URI from 'urijs';
4
- import { Alert, Button, Divider, Skeleton } from '@patternfly/react-core';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import {
6
+ Alert,
7
+ Divider,
8
+ Skeleton,
9
+ Button,
10
+ Title,
11
+ EmptyState,
12
+ EmptyStateVariant,
13
+ EmptyStateIcon,
14
+ EmptyStateBody,
15
+ } from '@patternfly/react-core';
16
+ import { ExclamationCircleIcon } from '@patternfly/react-icons';
17
+ import { global_palette_red_200 as exclamationColor } from '@patternfly/react-tokens';
18
+ import { get } from 'foremanReact/redux/API';
19
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
20
+ import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
21
+ import { STATUS } from 'foremanReact/constants';
5
22
  import {
6
23
  useForemanLocation,
7
24
  useForemanOrganization,
8
25
  } from 'foremanReact/Root/Context/ForemanContext';
9
- import { translate as __, sprintf } from 'foremanReact/common/I18n';
10
- import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
11
- import { STATUS } from 'foremanReact/constants';
12
- import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
13
26
  import { JobWizard } from './JobWizard';
27
+ import {
28
+ selectRerunJobInvocationResponse,
29
+ selectRerunJobInvocationStatus,
30
+ } from './JobWizardSelectors';
14
31
  import { JOB_API_KEY } from './JobWizardConstants';
15
32
 
16
33
  const JobWizardPageRerun = ({
@@ -19,6 +36,7 @@ const JobWizardPageRerun = ({
19
36
  },
20
37
  location: { search },
21
38
  }) => {
39
+ const dispatch = useDispatch();
22
40
  const uri = new URI(search);
23
41
  const { failed_only: failedOnly } = uri.search(true);
24
42
  const { succeeded_only: succeededOnly } = uri.search(true);
@@ -28,11 +46,6 @@ const JobWizardPageRerun = ({
28
46
  } else if (succeededOnly) {
29
47
  queryParams = '&succeeded_only=1';
30
48
  }
31
- const { response, status } = useAPI(
32
- 'get',
33
- `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
34
- JOB_API_KEY
35
- );
36
49
  const title = __('Run job');
37
50
  const breadcrumbOptions = {
38
51
  breadcrumbItems: [
@@ -41,11 +54,55 @@ const JobWizardPageRerun = ({
41
54
  ],
42
55
  };
43
56
 
44
- const jobOrganization = response.job_organization;
45
- const jobLocation = response.job_location;
57
+ const [errorMessage, setErrorMessage] = useState('');
58
+ const jobInvocationResponse = useSelector(selectRerunJobInvocationResponse);
59
+ const jobInvocationStatus = useSelector(selectRerunJobInvocationStatus);
60
+ const jobOrganization = jobInvocationResponse.job_organization;
61
+ const jobLocation = jobInvocationResponse.job_location;
46
62
  const currentOrganization = useForemanOrganization();
47
63
  const currentLocation = useForemanLocation();
48
64
 
65
+ const emptyStateLarge = (
66
+ <EmptyState variant={EmptyStateVariant.large}>
67
+ <EmptyStateIcon
68
+ icon={ExclamationCircleIcon}
69
+ color={exclamationColor.value}
70
+ />
71
+ <Title ouiaId="job-wizard-empty-state-header" headingLevel="h4" size="lg">
72
+ {__('Unable to run job')}
73
+ </Title>
74
+ <EmptyStateBody>{sprintf(errorMessage)}</EmptyStateBody>
75
+ <Button
76
+ ouiaId="job-wizard-run-job-button"
77
+ component="a"
78
+ href="/job_invocations/new"
79
+ variant="primary"
80
+ >
81
+ {__('Create job')}
82
+ </Button>
83
+ </EmptyState>
84
+ );
85
+
86
+ useEffect(() => {
87
+ let isMounted = true;
88
+ if (id !== undefined) {
89
+ dispatch(
90
+ get({
91
+ key: JOB_API_KEY,
92
+ url: `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
93
+ handleError: ({ response }) => {
94
+ if (isMounted) {
95
+ setErrorMessage(response?.data?.error?.message);
96
+ }
97
+ },
98
+ })
99
+ );
100
+ }
101
+ return () => {
102
+ isMounted = false;
103
+ };
104
+ }, [dispatch, id, failedOnly, queryParams]);
105
+
49
106
  return (
50
107
  <PageLayout
51
108
  header={title}
@@ -66,14 +123,16 @@ const JobWizardPageRerun = ({
66
123
  <React.Fragment>
67
124
  <Divider component="div" />
68
125
  </React.Fragment>
69
- {!status || status === STATUS.PENDING ? (
126
+ {jobInvocationStatus === STATUS.ERROR && emptyStateLarge}
127
+ {(!jobInvocationStatus || jobInvocationStatus === STATUS.PENDING) && (
70
128
  <div style={{ height: '400px' }}>
71
129
  <Skeleton
72
130
  height="100%"
73
131
  screenreaderText="Loading large rectangle contents"
74
132
  />
75
133
  </div>
76
- ) : (
134
+ )}
135
+ {jobInvocationStatus === STATUS.RESOLVED && (
77
136
  <React.Fragment>
78
137
  {jobOrganization?.id !== currentOrganization?.id && (
79
138
  <Alert
@@ -107,7 +166,12 @@ const JobWizardPageRerun = ({
107
166
  )}
108
167
  <Divider component="div" />
109
168
  <JobWizard
110
- rerunData={{ ...response?.job, inputs: response?.inputs } || null}
169
+ rerunData={
170
+ {
171
+ ...jobInvocationResponse?.job,
172
+ inputs: jobInvocationResponse?.inputs,
173
+ } || null
174
+ }
111
175
  />
112
176
  </React.Fragment>
113
177
  )}
@@ -14,8 +14,15 @@ import {
14
14
  JOB_TEMPLATE,
15
15
  HOSTS_API,
16
16
  JOB_INVOCATION,
17
+ JOB_API_KEY,
17
18
  } from './JobWizardConstants';
18
19
 
20
+ export const selectRerunJobInvocationResponse = state =>
21
+ selectAPIResponse(state, JOB_API_KEY) || {};
22
+
23
+ export const selectRerunJobInvocationStatus = state =>
24
+ selectAPIStatus(state, JOB_API_KEY);
25
+
19
26
  export const selectJobTemplatesStatus = state =>
20
27
  selectAPIStatus(state, JOB_TEMPLATES);
21
28
 
@@ -114,6 +114,8 @@ export const jobCategories = ['Services', 'Ansible Commands', 'Puppet'];
114
114
 
115
115
  export const testSetup = (selectors, api) => {
116
116
  jest.spyOn(api, 'get');
117
+ jest.spyOn(selectors, 'selectRerunJobInvocationResponse');
118
+ jest.spyOn(selectors, 'selectRerunJobInvocationStatus');
117
119
  jest.spyOn(selectors, 'selectJobTemplate');
118
120
  jest.spyOn(selectors, 'selectJobTemplates');
119
121
  jest.spyOn(selectors, 'selectJobCategories');
@@ -123,6 +125,10 @@ export const testSetup = (selectors, api) => {
123
125
 
124
126
  jest.spyOn(selectors, 'selectTemplateInputs');
125
127
  jest.spyOn(selectors, 'selectAdvancedTemplateInputs');
128
+ selectors.selectRerunJobInvocationResponse.mockImplementation(
129
+ () => jobInvocation
130
+ );
131
+ selectors.selectRerunJobInvocationStatus.mockImplementation(() => 'RESOLVED');
126
132
  selectors.selectWithKatello.mockImplementation(() => true);
127
133
  selectors.selectTemplateInputs.mockImplementation(
128
134
  () => jobTemplateResponse.template_inputs
@@ -14,16 +14,17 @@ import {
14
14
  jobInvocation,
15
15
  } from '../../__tests__/fixtures';
16
16
 
17
+ jest.useFakeTimers();
17
18
  const store = testSetup(selectors, api);
18
19
  mockApi(api);
19
20
  jest.spyOn(APIHooks, 'useAPI');
21
+ store.dispatch = jest.fn();
20
22
  APIHooks.useAPI.mockImplementation((action, url) => {
21
23
  if (url === '/ui_job_wizard/job_invocation?id=57') {
22
24
  return { response: jobInvocation, status: 'RESOLVED' };
23
25
  }
24
26
  return {};
25
27
  });
26
- jest.useFakeTimers();
27
28
 
28
29
  describe('ReviewDetails', () => {
29
30
  it('should call goToStepByName function when StepButton is clicked', async () => {
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: 13.2.4
4
+ version: 13.2.5
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: 2024-08-01 00:00:00.000000000 Z
11
+ date: 2024-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface