foreman-tasks 0.16.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +4 -1
  3. data/.eslintrc +4 -13
  4. data/app/assets/stylesheets/foreman_tasks/application.css.scss +0 -37
  5. data/app/controllers/foreman_tasks/api/tasks_controller.rb +9 -5
  6. data/app/controllers/foreman_tasks/tasks_controller.rb +23 -19
  7. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +28 -29
  8. data/app/lib/actions/bulk_action.rb +1 -1
  9. data/app/models/foreman_tasks/task.rb +1 -1
  10. data/app/models/foreman_tasks/task/dynflow_task.rb +30 -0
  11. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +4 -0
  12. data/app/views/foreman_tasks/api/tasks/details.json.rabl +18 -0
  13. data/app/views/foreman_tasks/layouts/react.html.erb +1 -1
  14. data/app/views/foreman_tasks/tasks/index.html.erb +3 -0
  15. data/app/views/foreman_tasks/tasks/show.html.erb +10 -134
  16. data/config/routes.rb +3 -0
  17. data/lib/foreman_tasks/engine.rb +1 -1
  18. data/lib/foreman_tasks/tasks/export_tasks.rake +1 -2
  19. data/lib/foreman_tasks/version.rb +1 -1
  20. data/package.json +6 -20
  21. data/test/controllers/tasks_controller_test.rb +11 -0
  22. data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +39 -0
  23. data/test/unit/actions/bulk_action_test.rb +2 -0
  24. data/test/unit/task_test.rb +4 -0
  25. data/webpack/ForemanTasks/Components/TaskDetails/Components/Errors.js +60 -0
  26. data/webpack/ForemanTasks/Components/TaskDetails/Components/Locks.js +46 -0
  27. data/webpack/ForemanTasks/Components/TaskDetails/Components/Raw.js +73 -0
  28. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +55 -0
  29. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +202 -0
  30. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskHelper.js +38 -0
  31. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +238 -0
  32. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +36 -0
  33. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +28 -0
  34. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +27 -0
  35. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +29 -0
  36. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +18 -0
  37. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskHelper.test.js +77 -0
  38. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +60 -0
  39. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Errors.test.js.snap +77 -0
  40. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Locks.test.js.snap +108 -0
  41. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Raw.test.js.snap +174 -0
  42. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +62 -0
  43. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +282 -0
  44. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskHelper.test.js.snap +37 -0
  45. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +568 -0
  46. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +87 -0
  47. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +63 -0
  48. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.stories.js +5 -0
  49. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +109 -0
  50. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +18 -0
  51. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +44 -0
  52. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +83 -0
  53. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +1 -0
  54. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +12 -0
  55. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +20 -0
  56. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +33 -0
  57. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +97 -0
  58. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +43 -0
  59. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +26 -0
  60. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +122 -0
  61. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +63 -0
  62. data/webpack/ForemanTasks/Components/TaskDetails/index.js +77 -0
  63. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.js +6 -1
  64. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +2 -0
  65. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.js +6 -1
  66. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +2 -0
  67. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +3 -6
  68. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +0 -3
  69. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +3 -0
  70. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +2 -0
  71. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +0 -4
  72. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardHelper.js +3 -3
  73. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +495 -54
  74. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +1 -0
  75. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +6 -0
  76. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.scss +0 -3
  77. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +1 -1
  78. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +2 -2
  79. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +83 -0
  80. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  81. data/webpack/__mocks__/foremanReact/common/I18n.js +2 -0
  82. data/webpack/__mocks__/foremanReact/components/Layout/LayoutActions.js +2 -0
  83. data/webpack/index.js +5 -0
  84. metadata +46 -9
  85. data/app/views/foreman_tasks/tasks/_details.html.erb +0 -195
  86. data/app/views/foreman_tasks/tasks/_errors.html.erb +0 -42
  87. data/app/views/foreman_tasks/tasks/_locks.html.erb +0 -19
  88. data/app/views/foreman_tasks/tasks/_raw.html.erb +0 -28
  89. data/app/views/foreman_tasks/tasks/_running_steps.html.erb +0 -40
@@ -0,0 +1,87 @@
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Tab, Tabs } from 'patternfly-react';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+ import Task from './Components/Task';
6
+ import RunningSteps from './Components/RunningSteps';
7
+ import Errors from './Components/Errors';
8
+ import Locks from './Components/Locks';
9
+ import Raw from './Components/Raw';
10
+ import { getTaskID } from './TasksDetailsHelper';
11
+
12
+ import './TaskDetails.scss';
13
+
14
+ class TaskDetails extends Component {
15
+ componentDidMount() {
16
+ const { timeoutId, refetchTaskDetails, fetchTaskDetails } = this.props;
17
+
18
+ fetchTaskDetails(getTaskID(), timeoutId, refetchTaskDetails);
19
+ }
20
+ componentWillUnmount() {
21
+ this.props.taskReloadStop(this.props.timeoutId);
22
+ }
23
+ render() {
24
+ const {
25
+ externalId,
26
+ startedAt,
27
+ endedAt,
28
+ label,
29
+ input,
30
+ output,
31
+ executionPlan,
32
+ failedSteps,
33
+ runningSteps,
34
+ locks,
35
+ } = this.props;
36
+ const id = getTaskID();
37
+ const resumable = executionPlan ? executionPlan.state === 'paused' : false;
38
+ const cancellable = executionPlan ? executionPlan.cancellable : false;
39
+ return (
40
+ <div className="task-details-react well">
41
+ <Tabs defaultActiveKey={1} animation={false} id="task-details-tabs">
42
+ <Tab eventKey={1} title={__('Task')}>
43
+ <Task {...{ ...this.props, cancellable, resumable, id }} />
44
+ </Tab>
45
+ <Tab eventKey={2} title={__('Running Steps')}>
46
+ <RunningSteps
47
+ executionPlan={executionPlan}
48
+ runningSteps={runningSteps}
49
+ />
50
+ </Tab>
51
+ <Tab eventKey={3} title={__('Errors')}>
52
+ <Errors executionPlan={executionPlan} failedSteps={failedSteps} />
53
+ </Tab>
54
+ <Tab eventKey={4} title={__('Locks')}>
55
+ <Locks locks={locks} />
56
+ </Tab>
57
+ <Tab eventKey={5} title={__('Raw')}>
58
+ <Raw
59
+ {...{ id, label, startedAt, endedAt, input, output, externalId }}
60
+ />
61
+ </Tab>
62
+ </Tabs>
63
+ </div>
64
+ );
65
+ }
66
+ }
67
+
68
+ TaskDetails.propTypes = {
69
+ label: PropTypes.string,
70
+ fetchTaskDetails: PropTypes.func,
71
+ ...Task.propTypes,
72
+ ...RunningSteps.propTypes,
73
+ ...Errors.propTypes,
74
+ ...Locks.propTypes,
75
+ ...Raw.propTypes,
76
+ };
77
+ TaskDetails.defaultProps = {
78
+ label: '',
79
+ fetchTaskDetails: () => null,
80
+ ...Task.defaultProps,
81
+ ...RunningSteps.defaultProps,
82
+ ...Errors.defaultProps,
83
+ ...Locks.defaultProps,
84
+ ...Raw.defaultProps,
85
+ };
86
+
87
+ export default TaskDetails;
@@ -0,0 +1,63 @@
1
+ .task-details-react {
2
+ .progress-label-top-right {
3
+ font-size: 11px;
4
+ text-align: right;
5
+ }
6
+ a,
7
+ button {
8
+ margin-right: 3px;
9
+ }
10
+ .container {
11
+ margin: 0;
12
+ }
13
+ /*
14
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
15
+ * listed below.
16
+ *
17
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
18
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
19
+ *
20
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
21
+ * compiled file, but it's generally better to create a new file per style scope.
22
+ *
23
+ *= require_self
24
+ *= require_tree .
25
+ */
26
+
27
+ .spin {
28
+ -webkit-animation: spin 1s infinite linear;
29
+ -moz-animation: spin 1s infinite linear;
30
+ -o-animation: spin 1s infinite linear;
31
+ animation: spin 1s infinite linear;
32
+ -webkit-transform-origin: 50% 50%;
33
+ transform-origin: 50% 50%;
34
+ -ms-transform-origin: 50% 50%; /* IE 9 */
35
+ }
36
+
37
+ @-moz-keyframes spin {
38
+ from {
39
+ -moz-transform: rotate(0deg);
40
+ }
41
+ to {
42
+ -moz-transform: rotate(360deg);
43
+ }
44
+ }
45
+
46
+ @-webkit-keyframes spin {
47
+ from {
48
+ -webkit-transform: rotate(0deg);
49
+ }
50
+ to {
51
+ -webkit-transform: rotate(360deg);
52
+ }
53
+ }
54
+
55
+ @keyframes spin {
56
+ from {
57
+ transform: rotate(0deg);
58
+ }
59
+ to {
60
+ transform: rotate(360deg);
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import TaskDetails from './TaskDetails';
4
+
5
+ storiesOf('TaskDetails', module).add('TaskDetails', () => <TaskDetails />);
@@ -0,0 +1,109 @@
1
+ import API from 'foremanReact/API';
2
+ import {
3
+ showLoading,
4
+ hideLoading,
5
+ } from 'foremanReact/components/Layout/LayoutActions';
6
+ import {
7
+ FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST,
8
+ FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS,
9
+ FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE,
10
+ FOREMAN_TASK_DETAILS_STOP_POLLING,
11
+ FOREMAN_TASK_DETAILS_START_POLLING,
12
+ FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL,
13
+ FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL,
14
+ } from './TaskDetailsConstants';
15
+
16
+ export const taskReloadStop = timeoutId => {
17
+ if (timeoutId) {
18
+ clearTimeout(timeoutId);
19
+ }
20
+ return {
21
+ type: FOREMAN_TASK_DETAILS_STOP_POLLING,
22
+ payload: { timeoutId },
23
+ };
24
+ };
25
+
26
+ export const taskReloadStart = (
27
+ timeoutId,
28
+ refetchTaskDetails,
29
+ id,
30
+ loading = false
31
+ ) => {
32
+ if (!timeoutId) {
33
+ timeoutId = setInterval(() => refetchTaskDetails(id, loading), 5000);
34
+ }
35
+ return {
36
+ type: FOREMAN_TASK_DETAILS_START_POLLING,
37
+ payload: { timeoutId },
38
+ };
39
+ };
40
+
41
+ export const refetchTaskDetails = (id, loading) => dispatch => {
42
+ if (!loading) {
43
+ showLoading();
44
+ dispatch(startRequest());
45
+ reloadTasksDetails(id, dispatch);
46
+ }
47
+ };
48
+
49
+ const reloadTasksDetails = async (id, dispatch) => {
50
+ try {
51
+ const { data } = await API.get(`/foreman_tasks/api/tasks/${id}/details`);
52
+ dispatch(requestSuccess(data));
53
+ } catch (error) {
54
+ dispatch(requestFailure(error));
55
+ document.location.reload();
56
+ } finally {
57
+ hideLoading();
58
+ }
59
+ };
60
+
61
+ export const fetchTaskDetails = (
62
+ id,
63
+ timeoutId,
64
+ refetchTaskDetailsAction
65
+ ) => dispatch => {
66
+ showLoading();
67
+ dispatch(startRequest());
68
+ getTasksDetails(id, dispatch, timeoutId, refetchTaskDetailsAction);
69
+ };
70
+
71
+ const getTasksDetails = async (
72
+ id,
73
+ dispatch,
74
+ timeoutId,
75
+ refetchTaskDetailsAction
76
+ ) => {
77
+ try {
78
+ const { data } = await API.get(`/foreman_tasks/api/tasks/${id}/details`);
79
+ dispatch(requestSuccess(data));
80
+ if (data.state !== 'stopped') {
81
+ dispatch(taskReloadStart(timeoutId, refetchTaskDetailsAction, id));
82
+ }
83
+ } catch (error) {
84
+ dispatch(requestFailure(error));
85
+ } finally {
86
+ hideLoading();
87
+ }
88
+ };
89
+
90
+ const startRequest = () => ({
91
+ type: FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST,
92
+ });
93
+
94
+ const requestSuccess = data => ({
95
+ type: FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS,
96
+ payload: data,
97
+ });
98
+
99
+ const requestFailure = error => ({
100
+ type: FOREMAN_TASK_DETAILS_FETCH_TASK_FAILURE,
101
+ payload: error,
102
+ });
103
+
104
+ export const toggleUnlockModal = () => ({
105
+ type: FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL,
106
+ });
107
+ export const toggleForceUnlockModal = () => ({
108
+ type: FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL,
109
+ });
@@ -0,0 +1,18 @@
1
+ export const FOREMAN_TASK_DETAILS_INIT = 'FOREMAN_TASK_DETAILS_INIT';
2
+
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 FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL =
16
+ 'FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL';
17
+ export const FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL =
18
+ 'FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL';
@@ -0,0 +1,44 @@
1
+ import Immutable from 'seamless-immutable';
2
+ import {
3
+ FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST,
4
+ FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS,
5
+ FOREMAN_TASK_DETAILS_STOP_POLLING,
6
+ FOREMAN_TASK_DETAILS_START_POLLING,
7
+ FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL,
8
+ FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL,
9
+ } from './TaskDetailsConstants';
10
+
11
+ const initialState = Immutable({});
12
+
13
+ export default (state = initialState, action) => {
14
+ const { type, payload } = action;
15
+ let { taskReload, timeoutId } = state;
16
+
17
+ switch (type) {
18
+ case FOREMAN_TASK_DETAILS_FETCH_TASK_REQUEST:
19
+ return state.set('loading', true);
20
+ case FOREMAN_TASK_DETAILS_FETCH_TASK_SUCCESS:
21
+ if (payload.state === 'stopped') {
22
+ clearTimeout(state.timeoutId);
23
+ taskReload = false;
24
+ timeoutId = null;
25
+ }
26
+ return state.merge({
27
+ loading: false,
28
+ ...payload,
29
+ taskReload,
30
+ timeoutId,
31
+ });
32
+ case FOREMAN_TASK_DETAILS_STOP_POLLING:
33
+ return state.merge({ taskReload: false, timeoutId: null });
34
+ case FOREMAN_TASK_DETAILS_START_POLLING:
35
+ clearTimeout(state.timeoutId);
36
+ return state.merge({ taskReload: true, timeoutId: payload.timeoutId });
37
+ case FOREMAN_TASK_DETAILS_TOGGLE_UNLOCK_MODAL:
38
+ return state.set('showUnlockModal', !state.showUnlockModal);
39
+ case FOREMAN_TASK_DETAILS_TOGGLE_FORCE_UNLOCK_MODAL:
40
+ return state.set('showForceUnlockModal', !state.showForceUnlockModal);
41
+ default:
42
+ return state;
43
+ }
44
+ };
@@ -0,0 +1,83 @@
1
+ import { selectForemanTasks } from '../../ForemanTasksSelectors';
2
+
3
+ export const selectTaskDetails = state =>
4
+ selectForemanTasks(state).taskDetails || {};
5
+
6
+ export const selectStartAt = state => selectTaskDetails(state).start_at || null;
7
+
8
+ export const selectStartBefore = state =>
9
+ selectTaskDetails(state).start_before || null;
10
+
11
+ export const selectStartedAt = state =>
12
+ selectTaskDetails(state).started_at || null;
13
+
14
+ export const selectEndedAt = state => selectTaskDetails(state).ended_at || null;
15
+
16
+ export const selectInput = state => selectTaskDetails(state).input || [];
17
+
18
+ export const selectOutput = state => selectTaskDetails(state).output || {};
19
+
20
+ export const selectResumable = state =>
21
+ selectTaskDetails(state).resumable || false;
22
+
23
+ export const selectCancellable = state =>
24
+ selectTaskDetails(state).cancellable || false;
25
+
26
+ export const selectErrors = state => {
27
+ const { humanized } = selectTaskDetails(state);
28
+ return humanized ? humanized.errors : [];
29
+ };
30
+
31
+ export const selectProgress = state =>
32
+ selectTaskDetails(state).progress * 100 || 0;
33
+
34
+ export const selectUsername = state =>
35
+ selectTaskDetails(state).username || null;
36
+
37
+ export const selectLabel = state => selectTaskDetails(state).label || null;
38
+
39
+ export const selectExecutionPlan = state =>
40
+ selectTaskDetails(state).execution_plan || {};
41
+
42
+ export const selectFailedSteps = state =>
43
+ selectTaskDetails(state).failed_steps || [];
44
+
45
+ export const selectRunningSteps = state =>
46
+ selectTaskDetails(state).running_steps || [];
47
+
48
+ export const selectHelp = state => selectTaskDetails(state).help || null;
49
+
50
+ export const selectHasSubTasks = state =>
51
+ selectTaskDetails(state).has_sub_tasks || false;
52
+
53
+ export const selectAllowDangerousActions = state =>
54
+ selectTaskDetails(state).allowDangerousActions || false;
55
+
56
+ export const selectLocks = state => selectTaskDetails(state).locks || [];
57
+
58
+ export const selectUsernamePath = state =>
59
+ selectTaskDetails(state).username_path || null;
60
+
61
+ export const selectAction = state => selectTaskDetails(state).action || null;
62
+
63
+ export const selectState = state => selectTaskDetails(state).state || null;
64
+
65
+ export const selectResult = state => selectTaskDetails(state).result || null;
66
+
67
+ export const selectTimeoutId = state =>
68
+ selectTaskDetails(state).timeoutId || null;
69
+
70
+ export const selectTaskReload = state =>
71
+ selectTaskDetails(state).taskReload || false;
72
+
73
+ export const selectParentTask = state =>
74
+ selectTaskDetails(state).parent_task_id || '';
75
+
76
+ export const selectShowUnlockModal = state =>
77
+ selectTaskDetails(state).showUnlockModal || false;
78
+
79
+ export const selectShowForceUnlockModal = state =>
80
+ selectTaskDetails(state).showForceUnlockModal || false;
81
+
82
+ export const selectExternalId = state =>
83
+ selectTaskDetails(state).external_id || null;
@@ -0,0 +1 @@
1
+ export const getTaskID = () => window.location.pathname.split('/').slice(-1)[0];
@@ -0,0 +1,12 @@
1
+ import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
2
+
3
+ import TaskDetails from '../TaskDetails';
4
+
5
+ const fixtures = {
6
+ 'render without Props': {},
7
+ };
8
+
9
+ describe('TaskDetails', () => {
10
+ describe('rendering', () =>
11
+ testComponentSnapshotsWithFixtures(TaskDetails, fixtures));
12
+ });
@@ -0,0 +1,20 @@
1
+ import { testActionSnapshotWithFixtures } from 'react-redux-test-utils';
2
+ import API from 'foremanReact/API';
3
+ import {
4
+ taskReloadStop,
5
+ taskReloadStart,
6
+ fetchTaskDetails,
7
+ } from '../TaskDetailsActions';
8
+
9
+ jest.mock('foremanReact/API');
10
+
11
+ API.get.mockImplementation(async () => ({ data: 'some-data' }));
12
+
13
+ const fixtures = {
14
+ 'should start reload': () => taskReloadStart(1),
15
+ 'should stop reload': () => taskReloadStop(2),
16
+ 'should fetch-task-details and success': () => fetchTaskDetails(),
17
+ };
18
+
19
+ describe('TaskDetails - Actions', () =>
20
+ testActionSnapshotWithFixtures(fixtures));