foreman-tasks 12.2.2 → 12.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79e3003ee203359edba19b75adac7c38435b94081969faba3ad211601c559345
4
- data.tar.gz: b3da633082735d6adf5a5d569744d3d5a6fa1d18d05568e7bc048b922205c674
3
+ metadata.gz: 200260a81901f7159c565c8188aa71de7b80bc0583b7cf3bf6432a2541130567
4
+ data.tar.gz: 3cb1afe2a7706fe328155ac0b32da0864155dfcb9e97a7b026283ba020f41489
5
5
  SHA512:
6
- metadata.gz: 6614edd5d7578167024f5df26bc5f950862dd9a2411a75cfd3f591b19755acbc40a1ca4321eff752800023923bb574d0095aa8c81ab4fa953e030999cf3d4547
7
- data.tar.gz: fcdd9f699f2a55d3e27bf014f8dbee0dd0e92e3d4f6b6b6921f0a4ba9841cf2cd8aa2392d0376667fa34a85ec41b53ad6e6ff25dae9443fcee9bd625350e82f2
6
+ metadata.gz: 26157491f3be0ce0e7386008c492476db1e49d28d28934f1139daec25771626d3e7813c3e858b501020f719930ad4fee3fcf6a54850bb661d4104b0628676993
7
+ data.tar.gz: d295b0470a35efb6a20801431614256612fdb16fb9f85f6c2c79ffdfaf0bd384656986d82f9d1bf0072b68366420884fbb552638152ccf9ca397f4c8a20a14c8
data/config/routes.rb CHANGED
@@ -36,7 +36,6 @@ Foreman::Application.routes.draw do
36
36
 
37
37
  match '/tasks', to: '/react#index', via: :get
38
38
  match '/tasks/:id/sub_tasks', to: '/react#index', via: :get
39
- match '/ex_tasks/:id', to: '/react#index', via: :get
40
39
 
41
40
  namespace :api do
42
41
  resources :recurring_logics, :only => [:index, :show, :update] do
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '12.2.2'.freeze
2
+ VERSION = '12.2.3'.freeze
3
3
  end
@@ -1,68 +1,174 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Alert, AlertVariant, Button } from '@patternfly/react-core';
3
+ import {
4
+ Alert,
5
+ AlertVariant,
6
+ Button,
7
+ EmptyState,
8
+ EmptyStateBody,
9
+ EmptyStateHeader,
10
+ EmptyStateIcon,
11
+ EmptyStateVariant,
12
+ Flex,
13
+ FlexItem,
14
+ Grid,
15
+ GridItem,
16
+ Stack,
17
+ StackItem,
18
+ } from '@patternfly/react-core';
19
+ import { HourglassStartIcon } from '@patternfly/react-icons';
4
20
  import { translate as __, sprintf } from 'foremanReact/common/I18n';
5
21
 
22
+ const RunningStepDetailBlock = ({ label, children }) => (
23
+ <GridItem span={12}>
24
+ <Flex
25
+ direction={{ default: 'column' }}
26
+ spaceItems={{ default: 'spaceItemsXs' }}
27
+ >
28
+ <FlexItem>
29
+ <strong>{label}</strong>
30
+ </FlexItem>
31
+ <FlexItem>{children}</FlexItem>
32
+ </Flex>
33
+ </GridItem>
34
+ );
35
+
36
+ RunningStepDetailBlock.propTypes = {
37
+ label: PropTypes.node.isRequired,
38
+ children: PropTypes.node.isRequired,
39
+ };
40
+
6
41
  const RunningSteps = ({
42
+ executionPlan,
43
+ result,
7
44
  runningSteps,
8
45
  id,
9
46
  cancelStep,
10
47
  taskReload,
11
48
  taskReloadStart,
12
49
  }) => {
13
- if (!runningSteps.length) return <span>{__('No running steps')}</span>;
14
- return (
15
- <div>
16
- {runningSteps.map((step, i) => (
50
+ const planState = executionPlan?.state;
51
+ const resultIsPending = String(result) === 'pending';
52
+
53
+ if (!runningSteps.length) {
54
+ if (planState === 'running' && resultIsPending) {
55
+ return (
17
56
  <Alert
18
57
  variant={AlertVariant.warning}
19
58
  isInline
20
- key={step.id || i}
21
- ouiaId={`running-step-${i}`}
22
- title={sprintf(__('Running step %s'), i + 1)}
59
+ ouiaId="running-steps-suspended-pending"
60
+ title={__('Temporarily suspended step(s)')}
23
61
  >
24
- {step.cancellable && (
25
- <p>
26
- <Button
27
- variant="danger"
28
- size="sm"
29
- ouiaId={`running-step-cancel-button-${i}`}
30
- onClick={() => {
31
- if (!taskReload) {
32
- taskReloadStart(id);
33
- }
34
- cancelStep(id, step.id);
35
- }}
36
- >
37
- {__('Cancel')}
38
- </Button>
39
- </p>
40
- )}
41
-
42
- <p>
43
- <span>{__('Action')}:</span>
44
- <span />
45
- </p>
46
- <pre>{step.action_class}</pre>
47
- <p>
48
- <span>{__('State')}:</span>
49
- <span>{step.state}</span>
50
- </p>
51
- <span>{__('Input')}:</span>
52
- <span>
53
- <pre>{step.input}</pre>
54
- </span>
55
- <span>{__('Output')}:</span>
56
- <span>
57
- <pre>{step.output}</pre>
58
- </span>
62
+ {__('The task is still being processed. Please wait.')}
59
63
  </Alert>
64
+ );
65
+ }
66
+
67
+ if (planState === 'planned' && resultIsPending) {
68
+ return (
69
+ <Grid>
70
+ <GridItem span={12}>
71
+ <Flex
72
+ direction={{ default: 'column' }}
73
+ alignItems={{ default: 'alignItemsCenter' }}
74
+ justifyContent={{ default: 'justifyContentCenter' }}
75
+ fullWidth={{ default: 'fullWidth' }}
76
+ >
77
+ <FlexItem>
78
+ <EmptyState variant={EmptyStateVariant.full}>
79
+ <EmptyStateHeader
80
+ titleText={__('Planned task')}
81
+ headingLevel="h2"
82
+ icon={<EmptyStateIcon icon={HourglassStartIcon} />}
83
+ />
84
+ <EmptyStateBody>
85
+ {__('The task has not started yet.')}
86
+ </EmptyStateBody>
87
+ </EmptyState>
88
+ </FlexItem>
89
+ </Flex>
90
+ </GridItem>
91
+ </Grid>
92
+ );
93
+ }
94
+
95
+ return <span>{__('No running steps')}</span>;
96
+ }
97
+
98
+ return (
99
+ <Stack hasGutter>
100
+ {runningSteps.map((step, i) => (
101
+ <StackItem key={step.id || i}>
102
+ <Alert
103
+ variant={AlertVariant.warning}
104
+ isInline
105
+ title={sprintf(__('Running step %s'), i + 1)}
106
+ ouiaId={`running-step-${i}`}
107
+ >
108
+ <Grid hasGutter>
109
+ {step.cancellable && (
110
+ <GridItem span={12}>
111
+ <Flex>
112
+ <FlexItem>
113
+ <Button
114
+ ouiaId={`running-step-${i}-cancel`}
115
+ variant="danger"
116
+ size="sm"
117
+ onClick={() => {
118
+ if (!taskReload) {
119
+ taskReloadStart(id);
120
+ }
121
+
122
+ cancelStep(id, step.id);
123
+ }}
124
+ >
125
+ {__('Cancel')}
126
+ </Button>
127
+ </FlexItem>
128
+ </Flex>
129
+ </GridItem>
130
+ )}
131
+ <GridItem span={12}>
132
+ <Flex
133
+ direction={{ default: 'row' }}
134
+ spaceItems={{ default: 'spaceItemsSm' }}
135
+ alignItems={{ default: 'alignItemsBaseline' }}
136
+ >
137
+ <FlexItem>
138
+ <strong>{`${__('Action')}:`}</strong>
139
+ </FlexItem>
140
+ <FlexItem>{step.action_class}</FlexItem>
141
+ </Flex>
142
+ </GridItem>
143
+ <GridItem span={12}>
144
+ <Flex
145
+ direction={{ default: 'row' }}
146
+ spaceItems={{ default: 'spaceItemsSm' }}
147
+ alignItems={{ default: 'alignItemsBaseline' }}
148
+ >
149
+ <FlexItem>
150
+ <strong>{`${__('State')}:`}</strong>
151
+ </FlexItem>
152
+ <FlexItem>{step.state}</FlexItem>
153
+ </Flex>
154
+ </GridItem>
155
+ <RunningStepDetailBlock label={__('Input')}>
156
+ <pre>{step.input}</pre>
157
+ </RunningStepDetailBlock>
158
+ <RunningStepDetailBlock label={__('Output')}>
159
+ <pre>{step.output}</pre>
160
+ </RunningStepDetailBlock>
161
+ </Grid>
162
+ </Alert>
163
+ </StackItem>
60
164
  ))}
61
- </div>
165
+ </Stack>
62
166
  );
63
167
  };
64
168
 
65
169
  RunningSteps.propTypes = {
170
+ executionPlan: PropTypes.shape({ state: PropTypes.string }),
171
+ result: PropTypes.string,
66
172
  runningSteps: PropTypes.array,
67
173
  id: PropTypes.string.isRequired,
68
174
  cancelStep: PropTypes.func.isRequired,
@@ -72,6 +178,8 @@ RunningSteps.propTypes = {
72
178
 
73
179
  RunningSteps.defaultProps = {
74
180
  runningSteps: [],
181
+ executionPlan: {},
182
+ result: undefined,
75
183
  };
76
184
 
77
185
  export default RunningSteps;
@@ -27,6 +27,45 @@ describe('RunningSteps', () => {
27
27
  expect(screen.getByText(/no running steps/i)).toBeInTheDocument();
28
28
  });
29
29
 
30
+ it('shows suspended warning when plan is running, result pending, no steps', () => {
31
+ render(
32
+ <RunningSteps
33
+ {...baseProps}
34
+ runningSteps={[]}
35
+ executionPlan={{ state: 'running', cancellable: false }}
36
+ result="pending"
37
+ />
38
+ );
39
+
40
+ expect(
41
+ screen.getByRole('heading', {
42
+ level: 4,
43
+ name: /temporarily suspended step/i,
44
+ })
45
+ ).toBeInTheDocument();
46
+ expect(
47
+ screen.getByText(/the task is still being processed/i)
48
+ ).toBeInTheDocument();
49
+ });
50
+
51
+ it('shows planned empty state when plan is planned, result pending, no steps', () => {
52
+ render(
53
+ <RunningSteps
54
+ {...baseProps}
55
+ runningSteps={[]}
56
+ executionPlan={{ state: 'planned', cancellable: false }}
57
+ result="pending"
58
+ />
59
+ );
60
+
61
+ expect(
62
+ screen.getByRole('heading', { level: 2, name: /planned task/i })
63
+ ).toBeInTheDocument();
64
+ expect(
65
+ screen.getByText(/the task has not started yet/i)
66
+ ).toBeInTheDocument();
67
+ });
68
+
30
69
  it('renders running step fields and Cancel when step is cancellable', () => {
31
70
  const cancelStep = jest.fn();
32
71
  render(
@@ -30,7 +30,7 @@ const TaskDetails = ({
30
30
  ...props
31
31
  }) => {
32
32
  const id = getTaskID();
33
- const { taskReload, status, isLoading } = props;
33
+ const { taskReload, status, isLoading, result } = props;
34
34
  const [activeTabKey, setActiveTabKey] = useState(1);
35
35
 
36
36
  useEffect(() => {
@@ -96,6 +96,8 @@ const TaskDetails = ({
96
96
  ouiaId="task-details-tab-running-steps"
97
97
  >
98
98
  <RunningSteps
99
+ executionPlan={executionPlan}
100
+ result={result}
99
101
  runningSteps={runningSteps}
100
102
  id={id}
101
103
  cancelStep={cancelStep}
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import TasksTableIndexPage from '../ForemanTasks/Components/TasksTable/TasksIndexPage';
3
- import ShowTask from '../ForemanTasks/Routes/ShowTask/ShowTask';
4
3
 
5
4
  const ForemanTasksRoutes = [
6
5
  {
@@ -13,10 +12,6 @@ const ForemanTasksRoutes = [
13
12
  exact: true,
14
13
  render: props => <TasksTableIndexPage {...props} />,
15
14
  },
16
- {
17
- path: '/foreman_tasks/ex_tasks/:id',
18
- render: props => <ShowTask {...props} />,
19
- },
20
15
  ];
21
16
 
22
17
  export default ForemanTasksRoutes;
@@ -12,14 +12,6 @@ jest.mock(
12
12
  }
13
13
  );
14
14
 
15
- jest.mock(
16
- '../ForemanTasks/Routes/ShowTask/ShowTask',
17
- () =>
18
- function ShowTaskStub() {
19
- return <div data-testid="show-task-stub" />;
20
- }
21
- );
22
-
23
15
  const routerProps = {
24
16
  history: { push: jest.fn(), replace: jest.fn(), go: jest.fn() },
25
17
  location: {
@@ -43,7 +35,6 @@ describe('ForemanTasks routes', () => {
43
35
  ).toEqual([
44
36
  { path: '/foreman_tasks/tasks', exact: true },
45
37
  { path: '/foreman_tasks/tasks/:id/sub_tasks', exact: true },
46
- { path: '/foreman_tasks/ex_tasks/:id', exact: undefined },
47
38
  ]);
48
39
  });
49
40
 
@@ -67,15 +58,6 @@ describe('ForemanTasks routes', () => {
67
58
  url: '/foreman_tasks/tasks/7/sub_tasks',
68
59
  },
69
60
  },
70
- {
71
- ...routerProps,
72
- match: {
73
- ...routerProps.match,
74
- params: { id: '42' },
75
- path: '/foreman_tasks/ex_tasks/:id',
76
- url: '/foreman_tasks/ex_tasks/42',
77
- },
78
- },
79
61
  ];
80
62
 
81
63
  ForemanTasksRoutes.forEach((route, index) => {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.2.2
4
+ version: 12.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
@@ -478,11 +478,6 @@ files:
478
478
  - webpack/ForemanTasks/Components/common/urlHelpers.js
479
479
  - webpack/ForemanTasks/ForemanTasksReducers.js
480
480
  - webpack/ForemanTasks/ForemanTasksSelectors.js
481
- - webpack/ForemanTasks/Routes/ShowTask/ShowTask.js
482
- - webpack/ForemanTasks/Routes/ShowTask/__tests__/ShowTask.test.js
483
- - webpack/ForemanTasks/Routes/ShowTask/__tests__/__snapshots__/ShowTask.test.js.snap
484
- - webpack/ForemanTasks/Routes/ShowTask/index.js
485
- - webpack/ForemanTasks/Routes/ShowTask/showTask.scss
486
481
  - webpack/Routes/routes.js
487
482
  - webpack/Routes/routes.test.js
488
483
  - webpack/global_index.js
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
-
3
- const ShowTask = () => (
4
- <div>
5
- <h1>Hello Foreman Tasks</h1>
6
- <h2>show-task-page</h2>
7
- </div>
8
- );
9
-
10
- export default ShowTask;
@@ -1,14 +0,0 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
-
3
- import ShowTask from '../ShowTask';
4
-
5
- const fixtures = {
6
- 'render without Props': {
7
- history: {
8
- push: jest.fn(),
9
- },
10
- },
11
- };
12
-
13
- describe('ShowTask', () =>
14
- testComponentSnapshotsWithFixtures(ShowTask, fixtures));
@@ -1,12 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`ShowTask render without Props 1`] = `
4
- <div>
5
- <h1>
6
- Hello Foreman Tasks
7
- </h1>
8
- <h2>
9
- show-task-page
10
- </h2>
11
- </div>
12
- `;
@@ -1 +0,0 @@
1
- export { default } from './ShowTask';
File without changes