foreman-tasks 2.0.3 → 3.0.4

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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/js_tests.yml +31 -0
  3. data/.github/workflows/ruby_tests.yml +74 -0
  4. data/.rubocop.yml +12 -4
  5. data/.rubocop_todo.yml +32 -25
  6. data/Gemfile +5 -0
  7. data/app/controllers/foreman_tasks/api/tasks_controller.rb +50 -63
  8. data/app/controllers/foreman_tasks/concerns/parameters/triggering.rb +1 -1
  9. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +7 -0
  10. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +3 -3
  11. data/app/models/foreman_tasks/recurring_logic.rb +1 -1
  12. data/app/models/foreman_tasks/task.rb +11 -0
  13. data/app/models/foreman_tasks/task/dynflow_task.rb +27 -33
  14. data/app/models/foreman_tasks/task/search.rb +1 -1
  15. data/app/models/foreman_tasks/task/status_explicator.rb +1 -1
  16. data/app/models/foreman_tasks/triggering.rb +1 -1
  17. data/app/models/setting/foreman_tasks.rb +9 -9
  18. data/app/services/foreman_tasks/dashboard_table_filter.rb +5 -1
  19. data/app/views/foreman_tasks/api/tasks/index.json.rabl +2 -0
  20. data/app/views/foreman_tasks/layouts/react.html.erb +1 -2
  21. data/app/views/foreman_tasks/recurring_logics/index.html.erb +3 -1
  22. data/app/views/foreman_tasks/tasks/dashboard/_latest_tasks_in_error_warning.html.erb +1 -1
  23. data/app/views/foreman_tasks/tasks/dashboard/_tasks_status.html.erb +1 -1
  24. data/app/views/foreman_tasks/tasks/show.html.erb +1 -6
  25. data/config/routes.rb +2 -1
  26. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +2 -2
  27. data/db/seeds.d/30-notification_blueprints.rb +7 -7
  28. data/db/seeds.d/61-foreman_tasks_bookmarks.rb +1 -1
  29. data/foreman-tasks.gemspec +1 -0
  30. data/lib/foreman_tasks/cleaner.rb +4 -6
  31. data/lib/foreman_tasks/dynflow/configuration.rb +1 -1
  32. data/lib/foreman_tasks/dynflow/persistence.rb +4 -6
  33. data/lib/foreman_tasks/engine.rb +2 -2
  34. data/lib/foreman_tasks/version.rb +1 -1
  35. data/package.json +0 -1
  36. data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
  37. data/test/controllers/api/tasks_controller_test.rb +17 -7
  38. data/test/controllers/tasks_controller_test.rb +6 -6
  39. data/test/core/unit/runner_test.rb +20 -20
  40. data/test/core/unit/task_launcher_test.rb +8 -8
  41. data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +7 -7
  42. data/test/helpers/foreman_tasks/tasks_helper_test.rb +3 -3
  43. data/test/lib/actions/middleware/keep_current_request_id_test.rb +3 -3
  44. data/test/support/history_tasks_builder.rb +1 -1
  45. data/test/tasks/generate_task_actions_test.rb +1 -1
  46. data/test/unit/actions/action_with_sub_plans_test.rb +2 -2
  47. data/test/unit/actions/bulk_action_test.rb +6 -6
  48. data/test/unit/actions/proxy_action_test.rb +20 -20
  49. data/test/unit/actions/recurring_action_test.rb +30 -32
  50. data/test/unit/cleaner_test.rb +24 -24
  51. data/test/unit/dashboard_table_filter_test.rb +5 -5
  52. data/test/unit/otp_manager_test.rb +2 -2
  53. data/test/unit/proxy_selector_test.rb +9 -9
  54. data/test/unit/recurring_logic_test.rb +32 -32
  55. data/test/unit/remote_task_test.rb +2 -2
  56. data/test/unit/task_groups_test.rb +4 -4
  57. data/test/unit/task_test.rb +26 -18
  58. data/test/unit/triggering_test.rb +8 -8
  59. data/test/unit/troubleshooting_help_generator_test.rb +6 -6
  60. data/test/unit/ui_notifications_test.rb +11 -11
  61. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +3 -3
  62. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -157
  63. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +168 -0
  64. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +6 -7
  65. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +48 -0
  66. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +1 -1
  67. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +12 -70
  68. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
  69. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +78 -225
  70. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +212 -0
  71. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +8 -4
  72. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +87 -70
  73. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +10 -0
  74. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +48 -125
  75. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -16
  76. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +55 -29
  77. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +2 -2
  78. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +6 -0
  79. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +2 -18
  80. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +77 -27
  81. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +14 -101
  82. data/webpack/ForemanTasks/Components/TaskDetails/index.js +6 -3
  83. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +4 -0
  84. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +53 -0
  85. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +14 -0
  86. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +27 -19
  87. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +14 -0
  88. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -34
  89. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/{StoppedTasksCardHelper.js → StoppedTasksCardTable.js} +28 -1
  90. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +54 -0
  91. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +48 -0
  92. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +60 -1367
  93. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +960 -0
  94. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +14 -11
  95. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +2 -0
  96. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +17 -11
  97. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +26 -14
  98. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +14 -11
  99. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +38 -22
  100. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +0 -8
  101. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +13 -4
  102. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +0 -10
  103. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +0 -2
  104. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +3 -1
  105. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +6 -1
  106. data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
  107. data/webpack/ForemanTasks/ForemanTasksReducers.js +0 -2
  108. data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
  109. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +10 -0
  110. data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
  111. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +5 -0
  112. metadata +21 -13
  113. data/.travis.yml +0 -7
  114. data/app/assets/stylesheets/foreman_tasks/tasks.scss +0 -9
  115. data/script/travis_run_js_tests.sh +0 -7
  116. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -38
  117. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +0 -33
  118. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +0 -26
  119. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +0 -122
  120. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +0 -72
  121. data/webpack/__mocks__/foremanReact/redux/API.js +0 -7
@@ -290,10 +290,14 @@ exports[`TaskInfo rendering render with Props 1`] = `
290
290
  </b>
291
291
  </span>
292
292
  </p>
293
- <p>
294
- A paused task represents a process that has not finished properly. Any task in paused state can lead to potential inconsistency and needs to be resolved.
295
- The recommended approach is to investigate the error messages below and in 'errors' tab, address the primary cause of the issue and resume the task.
296
- </p>
293
+ <p
294
+ dangerouslySetInnerHTML={
295
+ Object {
296
+ "__html": "A paused task represents a process that has not finished properly. Any task in paused state can lead to potential inconsistency and needs to be resolved.
297
+ The recommended approach is to investigate the error messages below and in 'errors' tab, address the primary cause of the issue and resume the task.",
298
+ }
299
+ }
300
+ />
297
301
  </Col>
298
302
  </Row>
299
303
  </Grid>
@@ -1,104 +1,119 @@
1
- import React, { Component } from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Tab, Tabs } from 'patternfly-react';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
+ import { STATUS } from 'foremanReact/constants';
6
+ import MessageBox from 'foremanReact/components/common/MessageBox';
5
7
  import Task from './Components/Task';
6
8
  import RunningSteps from './Components/RunningSteps';
7
9
  import Errors from './Components/Errors';
8
10
  import Locks from './Components/Locks';
9
11
  import Raw from './Components/Raw';
10
12
  import { getTaskID } from './TasksDetailsHelper';
13
+ import { TaskSkeleton } from './Components/TaskSkeleton';
11
14
 
12
15
  import './TaskDetails.scss';
13
16
 
14
- class TaskDetails extends Component {
15
- componentDidMount() {
16
- const { timeoutId, refetchTaskDetails, fetchTaskDetails } = this.props;
17
+ const TaskDetails = ({
18
+ executionPlan,
19
+ failedSteps,
20
+ runningSteps,
21
+ locks,
22
+ cancelStep,
23
+ taskReloadStart,
24
+ taskReloadStop,
25
+ APIerror,
26
+ ...props
27
+ }) => {
28
+ const id = getTaskID();
29
+ const { taskReload, status, isLoading } = props;
17
30
 
18
- fetchTaskDetails(getTaskID(), timeoutId, refetchTaskDetails);
19
- }
20
- componentWillUnmount() {
21
- this.props.taskReloadStop(this.props.timeoutId);
22
- }
23
- taskProgressToggle = () => {
24
- const {
25
- timeoutId,
26
- refetchTaskDetails,
27
- id,
28
- loading,
29
- taskReloadStop,
30
- taskReloadStart,
31
- } = this.props;
32
- if (timeoutId) {
33
- taskReloadStop(timeoutId);
31
+ useEffect(() => {
32
+ taskReloadStart(id);
33
+ return () => {
34
+ taskReloadStop();
35
+ };
36
+ }, [id, taskReloadStart, taskReloadStop]);
37
+
38
+ const taskProgressToggle = () => {
39
+ if (taskReload) {
40
+ taskReloadStop();
34
41
  } else {
35
- taskReloadStart(timeoutId, refetchTaskDetails, id, loading);
42
+ taskReloadStart(id);
36
43
  }
37
44
  };
38
45
 
39
- render() {
40
- const {
41
- externalId,
42
- startedAt,
43
- endedAt,
44
- label,
45
- input,
46
- output,
47
- executionPlan,
48
- failedSteps,
49
- runningSteps,
50
- locks,
51
- cancelStep,
52
- } = this.props;
53
- const id = getTaskID();
54
- const resumable = executionPlan ? executionPlan.state === 'paused' : false;
55
- const cancellable = executionPlan ? executionPlan.cancellable : false;
46
+ if (status === STATUS.ERROR) {
56
47
  return (
57
- <div className="task-details-react well">
58
- <Tabs defaultActiveKey={1} animation={false} id="task-details-tabs">
59
- <Tab eventKey={1} title={__('Task')}>
48
+ <MessageBox
49
+ key="task-details-error"
50
+ icontype="error-circle-o"
51
+ msg={__(`Could not receive data: ${APIerror && APIerror.message}`)}
52
+ />
53
+ );
54
+ }
55
+ const resumable = executionPlan ? executionPlan.state === 'paused' : false;
56
+ const cancellable = executionPlan ? executionPlan.cancellable : false;
57
+ return (
58
+ <div className="task-details-react well">
59
+ <Tabs defaultActiveKey={1} animation={false} id="task-details-tabs">
60
+ <Tab eventKey={1} title={__('Task')}>
61
+ {isLoading ? (
62
+ <TaskSkeleton />
63
+ ) : (
60
64
  <Task
61
65
  {...{
62
- ...this.props,
66
+ ...props,
63
67
  cancellable,
64
68
  resumable,
65
69
  id,
66
- taskProgressToggle: this.taskProgressToggle,
70
+ status,
71
+ taskProgressToggle,
72
+ taskReloadStart,
67
73
  }}
68
74
  />
69
- </Tab>
70
- <Tab eventKey={2} title={__('Running Steps')}>
71
- <RunningSteps
72
- runningSteps={runningSteps}
73
- id={id}
74
- cancelStep={cancelStep}
75
- taskReload={this.props.taskReload}
76
- taskProgressToggle={this.taskProgressToggle}
77
- />
78
- </Tab>
79
- <Tab eventKey={3} title={__('Errors')}>
80
- <Errors executionPlan={executionPlan} failedSteps={failedSteps} />
81
- </Tab>
82
- <Tab eventKey={4} title={__('Locks')}>
83
- <Locks locks={locks} />
84
- </Tab>
85
- <Tab eventKey={5} title={__('Raw')}>
86
- <Raw
87
- {...{ id, label, startedAt, endedAt, input, output, externalId }}
88
- />
89
- </Tab>
90
- </Tabs>
91
- </div>
92
- );
93
- }
94
- }
75
+ )}
76
+ </Tab>
77
+ <Tab eventKey={2} disabled={isLoading} title={__('Running Steps')}>
78
+ <RunningSteps
79
+ runningSteps={runningSteps}
80
+ id={id}
81
+ cancelStep={cancelStep}
82
+ taskReload={taskReload}
83
+ taskReloadStart={taskReloadStart}
84
+ />
85
+ </Tab>
86
+ <Tab eventKey={3} disabled={isLoading} title={__('Errors')}>
87
+ <Errors executionPlan={executionPlan} failedSteps={failedSteps} />
88
+ </Tab>
89
+ <Tab eventKey={4} disabled={isLoading} title={__('Locks')}>
90
+ <Locks locks={locks} />
91
+ </Tab>
92
+ <Tab eventKey={5} disabled={isLoading} title={__('Raw')}>
93
+ <Raw
94
+ id={id}
95
+ label={props.label}
96
+ startedAt={props.startedAt}
97
+ endedAt={props.endedAt}
98
+ input={props.input}
99
+ output={props.output}
100
+ externalId={props.externalId}
101
+ />
102
+ </Tab>
103
+ </Tabs>
104
+ </div>
105
+ );
106
+ };
95
107
 
96
108
  TaskDetails.propTypes = {
97
109
  label: PropTypes.string,
98
- fetchTaskDetails: PropTypes.func.isRequired,
99
110
  runningSteps: PropTypes.array,
100
111
  cancelStep: PropTypes.func.isRequired,
101
112
  taskReload: PropTypes.bool.isRequired,
113
+ status: PropTypes.oneOf(Object.keys(STATUS)),
114
+ APIerror: PropTypes.object,
115
+ taskReloadStop: PropTypes.func.isRequired,
116
+ taskReloadStart: PropTypes.func.isRequired,
102
117
  ...Task.propTypes,
103
118
  ...Errors.propTypes,
104
119
  ...Locks.propTypes,
@@ -107,6 +122,8 @@ TaskDetails.propTypes = {
107
122
  TaskDetails.defaultProps = {
108
123
  label: '',
109
124
  runningSteps: [],
125
+ APIerror: null,
126
+ status: STATUS.PENDING,
110
127
  ...Task.defaultProps,
111
128
  ...RunningSteps.defaultProps,
112
129
  ...Errors.defaultProps,
@@ -49,4 +49,14 @@
49
49
  .dynflow-button > span {
50
50
  pointer-events: auto;
51
51
  }
52
+
53
+ pre {
54
+ white-space: pre;
55
+ word-break: normal;
56
+ }
57
+
58
+ .param-name {
59
+ display: inline-block;
60
+ width: 10em;
61
+ }
52
62
  }
@@ -1,139 +1,62 @@
1
- import { API } from 'foremanReact/redux/API';
2
- import {
3
- showLoading,
4
- hideLoading,
5
- } from 'foremanReact/components/Layout/LayoutActions';
1
+ import { post, get } from 'foremanReact/redux/API';
6
2
  import { addToast } from 'foremanReact/redux/actions/toasts';
7
3
  import { translate as __ } from 'foremanReact/common/I18n';
8
4
  import {
9
- FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST,
10
- FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS,
11
- FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE,
12
- FOREMAN_TASK_DETAILS_STOP_POLLING,
13
- FOREMAN_TASK_DETAILS_START_POLLING,
14
- TASK_STEP_CANCEL_REQUEST,
15
- TASK_STEP_CANCEL_FAILURE,
16
- TASK_STEP_CANCEL_SUCCESS,
17
- } from './TaskDetailsConstants';
5
+ withInterval,
6
+ stopInterval,
7
+ } from 'foremanReact/redux/middlewares/IntervalMiddleware';
8
+ import { foremanTasksApiPath, foremanTasksPath } from '../common/urlHelpers';
9
+ import { TASK_STEP_CANCEL, FOREMAN_TASK_DETAILS } from './TaskDetailsConstants';
18
10
  import {
19
11
  errorToastData,
20
12
  infoToastData,
21
13
  successToastData,
22
14
  } from '../common/ToastsHelpers';
23
15
 
24
- export const taskReloadStop = timeoutId => {
25
- if (timeoutId) {
26
- clearTimeout(timeoutId);
27
- }
28
- return {
29
- type: FOREMAN_TASK_DETAILS_STOP_POLLING,
30
- payload: { timeoutId },
31
- };
32
- };
33
-
34
- export const taskReloadStart = (
35
- timeoutId,
36
- refetchTaskDetails,
37
- id,
38
- loading = false
39
- ) => {
40
- if (!timeoutId) {
41
- timeoutId = setInterval(() => refetchTaskDetails(id, loading), 5000);
42
- }
43
- return {
44
- type: FOREMAN_TASK_DETAILS_START_POLLING,
45
- payload: { timeoutId },
46
- };
47
- };
48
-
49
- export const refetchTaskDetails = (id, loading) => dispatch => {
50
- if (!loading) {
51
- showLoading();
52
- dispatch(startRequest());
53
- reloadTasksDetails(id, dispatch);
54
- }
55
- };
56
-
57
- const reloadTasksDetails = async (id, dispatch) => {
58
- try {
59
- const { data } = await API.get(
60
- `/foreman_tasks/api/tasks/${id}/details?include_permissions`
61
- );
62
- dispatch(requestSuccess(data));
63
- } catch (error) {
64
- dispatch(requestFailure(error));
65
- document.location.reload();
66
- } finally {
67
- hideLoading();
68
- }
16
+ export const taskReloadStop = () => stopInterval(FOREMAN_TASK_DETAILS);
17
+
18
+ export const taskReloadStart = id => dispatch => {
19
+ dispatch(
20
+ withInterval(
21
+ get({
22
+ key: FOREMAN_TASK_DETAILS,
23
+ url: foremanTasksApiPath(`${id}/details?include_permissions`),
24
+ handleSuccess: ({ data }) => {
25
+ if (data.state === 'stopped') {
26
+ dispatch(stopInterval(FOREMAN_TASK_DETAILS));
27
+ }
28
+ },
29
+ handleError: () => {
30
+ dispatch(stopInterval(FOREMAN_TASK_DETAILS));
31
+ },
32
+ }),
33
+ 5000
34
+ )
35
+ );
69
36
  };
70
37
 
71
- export const fetchTaskDetails = (
72
- id,
73
- timeoutId,
74
- refetchTaskDetailsAction
75
- ) => async dispatch => {
76
- showLoading();
77
- dispatch(startRequest());
78
- await getTasksDetails(id, dispatch, timeoutId, refetchTaskDetailsAction);
79
- };
80
-
81
- const getTasksDetails = async (
82
- id,
83
- dispatch,
84
- timeoutId,
85
- refetchTaskDetailsAction
86
- ) => {
87
- try {
88
- const { data } = await API.get(
89
- `/foreman_tasks/api/tasks/${id}/details?include_permissions`
90
- );
91
- dispatch(requestSuccess(data));
92
- if (data.state !== 'stopped') {
93
- dispatch(taskReloadStart(timeoutId, refetchTaskDetailsAction, id));
94
- }
95
- } catch (error) {
96
- dispatch(requestFailure(error));
97
- } finally {
98
- hideLoading();
99
- }
100
- };
101
-
102
- const startRequest = () => ({
103
- type: FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST,
104
- });
105
-
106
- const requestSuccess = data => ({
107
- type: FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS,
108
- payload: data,
109
- });
110
-
111
- const requestFailure = error => ({
112
- type: FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE,
113
- payload: error,
114
- });
115
-
116
38
  export const cancelStep = (taskId, stepId) => async dispatch => {
117
- dispatch({ type: TASK_STEP_CANCEL_REQUEST });
118
39
  dispatch(addToast(infoToastData(`${__('Trying to cancel step')} ${stepId}`)));
119
- try {
120
- await API.post(
121
- `/foreman_tasks/tasks/${taskId}/cancel_step?step_id=${stepId}`
122
- );
123
- dispatch({ type: TASK_STEP_CANCEL_SUCCESS });
124
- dispatch(addToast(successToastData(`${stepId} {__('Step Canceled')}`)));
125
- } catch (error) {
126
- dispatch({ type: TASK_STEP_CANCEL_FAILURE, payload: error });
127
- dispatch(
128
- addToast(
129
- errorToastData(
130
- `${__('Could not cancel step.')} ${__(
131
- 'Error:'
132
- )} ${stepId} ${error.response &&
133
- error.response.data &&
134
- error.response.data.error}`
135
- )
136
- )
137
- );
138
- }
40
+ dispatch(
41
+ post({
42
+ key: TASK_STEP_CANCEL,
43
+ url: foremanTasksPath(`${taskId}/cancel_step?step_id=${stepId}`),
44
+ handleSuccess: () => {
45
+ dispatch(addToast(successToastData(`${stepId} {__('Step Canceled')}`)));
46
+ },
47
+ handleError: error => {
48
+ dispatch(
49
+ addToast(
50
+ errorToastData(
51
+ `${__('Could not cancel step.')} ${__(
52
+ 'Error:'
53
+ )} ${stepId} ${error.response &&
54
+ error.response.data &&
55
+ error.response.data.error}`
56
+ )
57
+ )
58
+ );
59
+ },
60
+ })
61
+ );
139
62
  };
@@ -1,17 +1,4 @@
1
- export const FOREMAN_TASK_DETAILS_INIT = 'FOREMAN_TASK_DETAILS_INIT';
1
+ export const FOREMAN_TASK_DETAILS = 'FOREMAN_TASK_DETAILS';
2
+ export const FOREMAN_TASK_DETAILS_SUCCESS = 'FOREMAN_TASK_DETAILS_SUCCESS';
2
3
 
3
- export const FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST =
4
- 'FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST';
5
- export const FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS =
6
- 'FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS';
7
- export const FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE =
8
- 'FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE';
9
-
10
- export const FOREMAN_TASK_DETAILS_STOP_POLLING =
11
- 'FOREMAN_TASK_DETAILS_STOP_POLLING';
12
- export const FOREMAN_TASK_DETAILS_START_POLLING =
13
- 'FOREMAN_TASK_DETAILS_START_POLLING';
14
-
15
- export const TASK_STEP_CANCEL_REQUEST = 'TASK_STEP_CANCEL_REQUEST';
16
- export const TASK_STEP_CANCEL_FAILURE = 'TASK_STEP_CANCEL_FAILURE';
17
- export const TASK_STEP_CANCEL_SUCCESS = 'TASK_STEP_CANCEL_SUCCESS';
4
+ export const TASK_STEP_CANCEL = 'TASK_STEP_CANCEL';
@@ -1,82 +1,108 @@
1
+ /* eslint-disable camelcase */
2
+ import {
3
+ selectAPIResponse,
4
+ selectAPIByKey,
5
+ } from 'foremanReact/redux/API/APISelectors';
6
+ import { selectDoesIntervalExist } from 'foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors';
7
+ import { STATUS } from 'foremanReact/constants';
1
8
  import { selectForemanTasks } from '../../ForemanTasksSelectors';
9
+ import { FOREMAN_TASK_DETAILS } from './TaskDetailsConstants';
2
10
 
3
11
  export const selectTaskDetails = state =>
4
12
  selectForemanTasks(state).taskDetails || {};
5
13
 
6
- export const selectStartAt = state => selectTaskDetails(state).start_at || null;
14
+ export const selectTaskDetailsResponse = state =>
15
+ selectAPIResponse(state, FOREMAN_TASK_DETAILS);
16
+
17
+ export const selectStartAt = state =>
18
+ selectTaskDetailsResponse(state)?.start_at;
7
19
 
8
20
  export const selectStartBefore = state =>
9
- selectTaskDetails(state).start_before || null;
21
+ selectTaskDetailsResponse(state)?.start_before;
10
22
 
11
23
  export const selectStartedAt = state =>
12
- selectTaskDetails(state).started_at || null;
24
+ selectTaskDetailsResponse(state)?.started_at;
13
25
 
14
- export const selectEndedAt = state => selectTaskDetails(state).ended_at || null;
26
+ export const selectEndedAt = state =>
27
+ selectTaskDetailsResponse(state)?.ended_at;
15
28
 
16
- export const selectInput = state => selectTaskDetails(state).input || [];
29
+ export const selectInput = state =>
30
+ selectTaskDetailsResponse(state).input || [];
17
31
 
18
- export const selectOutput = state => selectTaskDetails(state).output || {};
32
+ export const selectOutput = state =>
33
+ selectTaskDetailsResponse(state).output || {};
19
34
 
20
35
  export const selectResumable = state =>
21
- selectTaskDetails(state).resumable || false;
36
+ selectTaskDetailsResponse(state).resumable || false;
22
37
 
23
38
  export const selectCancellable = state =>
24
- selectTaskDetails(state).cancellable || false;
39
+ selectTaskDetailsResponse(state).cancellable || false;
25
40
 
26
41
  export const selectErrors = state => {
27
- const { humanized } = selectTaskDetails(state);
42
+ const { humanized } = selectTaskDetailsResponse(state);
28
43
  return humanized ? humanized.errors : [];
29
44
  };
30
45
 
31
46
  export const selectProgress = state =>
32
- selectTaskDetails(state).progress
33
- ? Math.trunc(selectTaskDetails(state).progress * 100)
47
+ selectTaskDetailsResponse(state).progress
48
+ ? Math.trunc(selectTaskDetailsResponse(state).progress * 100)
34
49
  : 0;
35
50
 
36
51
  export const selectUsername = state =>
37
- selectTaskDetails(state).username || null;
52
+ selectTaskDetailsResponse(state)?.username;
38
53
 
39
- export const selectLabel = state => selectTaskDetails(state).label || null;
54
+ export const selectLabel = state => selectTaskDetailsResponse(state)?.label;
40
55
 
41
56
  export const selectExecutionPlan = state =>
42
- selectTaskDetails(state).execution_plan || {};
57
+ selectTaskDetailsResponse(state).execution_plan || {};
43
58
 
44
59
  export const selectFailedSteps = state =>
45
- selectTaskDetails(state).failed_steps || [];
60
+ selectTaskDetailsResponse(state).failed_steps || [];
46
61
 
47
62
  export const selectRunningSteps = state =>
48
- selectTaskDetails(state).running_steps || [];
63
+ selectTaskDetailsResponse(state).running_steps || [];
49
64
 
50
- export const selectHelp = state => selectTaskDetails(state).help || null;
65
+ export const selectHelp = state => selectTaskDetailsResponse(state)?.help;
51
66
 
52
67
  export const selectHasSubTasks = state =>
53
- selectTaskDetails(state).has_sub_tasks || false;
68
+ selectTaskDetailsResponse(state).has_sub_tasks || false;
54
69
 
55
- export const selectLocks = state => selectTaskDetails(state).locks || [];
70
+ export const selectLocks = state =>
71
+ selectTaskDetailsResponse(state).locks || [];
56
72
 
57
73
  export const selectUsernamePath = state =>
58
- selectTaskDetails(state).username_path || null;
74
+ selectTaskDetailsResponse(state)?.username_path;
59
75
 
60
- export const selectAction = state => selectTaskDetails(state).action || '';
76
+ export const selectAction = state =>
77
+ selectTaskDetailsResponse(state).action || '';
61
78
 
62
- export const selectState = state => selectTaskDetails(state).state || null;
79
+ export const selectState = state => selectTaskDetailsResponse(state)?.state;
63
80
 
64
- export const selectResult = state => selectTaskDetails(state).result || null;
81
+ export const selectResult = state => selectTaskDetailsResponse(state)?.result;
65
82
 
66
83
  export const selectTimeoutId = state =>
67
- selectTaskDetails(state).timeoutId || null;
84
+ selectTaskDetailsResponse(state)?.timeoutId;
68
85
 
69
86
  export const selectTaskReload = state =>
70
- selectTaskDetails(state).taskReload || false;
87
+ !!selectDoesIntervalExist(state, FOREMAN_TASK_DETAILS);
71
88
 
72
89
  export const selectParentTask = state =>
73
- selectTaskDetails(state).parent_task_id || '';
90
+ selectTaskDetailsResponse(state).parent_task_id || '';
74
91
 
75
92
  export const selectExternalId = state =>
76
- selectTaskDetails(state).external_id || null;
93
+ selectTaskDetailsResponse(state)?.external_id;
77
94
 
78
95
  export const selectDynflowEnableConsole = state =>
79
- selectTaskDetails(state).dynflow_enable_console || false;
96
+ selectTaskDetailsResponse(state).dynflow_enable_console || false;
80
97
 
81
98
  export const selectCanEdit = state =>
82
- selectTaskDetails(state).can_edit || false;
99
+ selectTaskDetailsResponse(state).can_edit || false;
100
+
101
+ export const selectStatus = state => selectTaskDetailsResponse(state).status;
102
+
103
+ export const selectAPIError = state =>
104
+ selectTaskDetailsResponse(state)?.APIerror;
105
+
106
+ export const selectIsLoading = state =>
107
+ !!selectAPIByKey(state, FOREMAN_TASK_DETAILS).response &&
108
+ selectStatus(state) === STATUS.PENDING;