foreman-tasks 1.1.3 → 1.2.0

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_tasks/api/tasks_controller.rb +29 -1
  3. data/app/controllers/foreman_tasks/tasks_controller.rb +3 -11
  4. data/app/models/foreman_tasks/task.rb +4 -0
  5. data/app/models/setting/foreman_tasks.rb +1 -1
  6. data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
  7. data/app/views/foreman_tasks/api/tasks/details.json.rabl +0 -1
  8. data/config/routes.rb +1 -0
  9. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
  10. data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
  11. data/db/seeds.d/30-notification_blueprints.rb +7 -0
  12. data/lib/foreman_tasks/engine.rb +1 -1
  13. data/lib/foreman_tasks/tasks/cleanup.rake +2 -2
  14. data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
  15. data/lib/foreman_tasks/version.rb +1 -1
  16. data/locale/action_names.rb +1 -1
  17. data/locale/en/foreman_tasks.po +227 -41
  18. data/locale/foreman_tasks.pot +579 -288
  19. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
  20. data/webpack/ForemanTasks/Components/{TasksTable/TasksTableActionHelpers.js → TaskActions/TaskActionHelpers.js} +21 -6
  21. data/webpack/ForemanTasks/Components/{TasksTable/__tests__/TasksTableActionHelpers.test.js → TaskActions/TaskActionHelpers.test.js} +2 -2
  22. data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
  23. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
  24. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
  25. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
  26. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
  27. data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
  28. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +130 -152
  29. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +67 -3
  30. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +0 -1
  31. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +101 -70
  32. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +0 -15
  33. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +0 -5
  34. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -6
  35. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +0 -9
  36. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
  37. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +5 -0
  38. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -7
  39. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +4 -0
  40. data/webpack/ForemanTasks/Components/TaskDetails/index.js +4 -8
  41. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
  42. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
  43. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
  44. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
  45. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +45 -0
  46. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
  47. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
  48. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
  49. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +54 -0
  50. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
  51. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
  52. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +30 -0
  53. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
  54. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -0
  55. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
  56. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +113 -30
  57. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +13 -9
  58. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +23 -63
  59. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +10 -12
  60. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +24 -94
  61. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
  62. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +7 -4
  63. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +35 -0
  64. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +2 -12
  65. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +22 -26
  66. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +2 -14
  67. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +107 -0
  68. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +2 -14
  69. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +17 -124
  70. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +24 -128
  71. data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -2
  72. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +47 -19
  73. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +61 -14
  74. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +80 -21
  75. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
  76. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
  77. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
  78. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
  79. data/webpack/ForemanTasks/Components/common/{ToastTypesConstants.js → ToastsHelpers/ToastTypesConstants.js} +0 -0
  80. data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
  81. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  82. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -1
  83. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +2 -2
  84. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +17 -3
  85. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  86. metadata +32 -22
  87. data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +0 -9
  88. data/lib/foreman_tasks/tasks/dynflow.rake +0 -6
  89. data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +0 -53
  90. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +0 -56
  91. data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +0 -52
  92. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +0 -26
  93. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +0 -24
  94. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +0 -26
  95. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +0 -65
  96. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +0 -30
  97. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +0 -63
  98. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
  99. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -26
  100. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
  101. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
  102. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
  103. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
@@ -1 +1,6 @@
1
- export const getTaskID = () => window.location.pathname.split('/').slice(-1)[0];
1
+ // Get Task ID from URL. Split url by '/', filter non-empty values and get Task ID.
2
+ export const getTaskID = () =>
3
+ window.location.pathname
4
+ .split('/')
5
+ .filter(i => i)
6
+ .slice(-1)[0];
@@ -6,6 +6,11 @@ const fixtures = {
6
6
  'render without Props': {},
7
7
  };
8
8
 
9
+ delete window.location;
10
+ window.location = new URL(
11
+ 'https://foreman.com/foreman_tasks/tasks/a15dd820-32f1-4ced-9ab7-c0fab8234c47/'
12
+ );
13
+
9
14
  describe('TaskDetails', () => {
10
15
  describe('rendering', () =>
11
16
  testComponentSnapshotsWithFixtures(TaskDetails, fixtures));
@@ -15,7 +15,6 @@ exports[`TaskDetails rendering render without Props 1`] = `
15
15
  >
16
16
  <Task
17
17
  action=""
18
- allowDangerousActions={false}
19
18
  cancelTaskRequest={[Function]}
20
19
  cancellable={false}
21
20
  dynflowEnableConsole={false}
@@ -27,7 +26,7 @@ exports[`TaskDetails rendering render without Props 1`] = `
27
26
  fetchTaskDetails={[Function]}
28
27
  hasSubTasks={false}
29
28
  help=""
30
- id=""
29
+ id="a15dd820-32f1-4ced-9ab7-c0fab8234c47"
31
30
  input={Array []}
32
31
  label=""
33
32
  locks={Array []}
@@ -39,8 +38,6 @@ exports[`TaskDetails rendering render without Props 1`] = `
39
38
  resumable={false}
40
39
  resumeTaskRequest={[Function]}
41
40
  runningSteps={Array []}
42
- showForceUnlockModal={false}
43
- showUnlockModal={false}
44
41
  startAt=""
45
42
  startBefore=""
46
43
  startedAt=""
@@ -49,8 +46,6 @@ exports[`TaskDetails rendering render without Props 1`] = `
49
46
  taskReloadStart={[Function]}
50
47
  taskReloadStop={[Function]}
51
48
  timeoutId={null}
52
- toggleForceUnlockModal={[Function]}
53
- toggleUnlockModal={[Function]}
54
49
  username=""
55
50
  usernamePath=""
56
51
  />
@@ -88,7 +83,7 @@ exports[`TaskDetails rendering render without Props 1`] = `
88
83
  <Raw
89
84
  endedAt=""
90
85
  externalId=""
91
- id=""
86
+ id="a15dd820-32f1-4ced-9ab7-c0fab8234c47"
92
87
  input={Array []}
93
88
  label=""
94
89
  output={Object {}}
@@ -15,6 +15,10 @@ describe('TaskDetails integration test', () => {
15
15
  const expectedIntervalId = 1;
16
16
  jest.useFakeTimers();
17
17
  setInterval.mockImplementation(() => expectedIntervalId);
18
+ delete window.location;
19
+ window.location = new URL(
20
+ 'https://foreman.com/foreman_tasks/tasks/a15dd820-32f1-4ced-9ab7-c0fab8234c47/'
21
+ );
18
22
  });
19
23
  it('should flow', async () => {
20
24
  window.location.reload = jest.fn();
@@ -1,7 +1,8 @@
1
1
  import { bindActionCreators } from 'redux';
2
2
  import { connect } from 'react-redux';
3
3
  import TaskDetails from './TaskDetails';
4
- import * as actions from './TaskDetailsActions';
4
+ import * as taskDetailsActions from './TaskDetailsActions';
5
+ import * as taskActions from '../TaskActions';
5
6
  import reducer from './TaskDetailsReducer';
6
7
  import {
7
8
  selectEndedAt,
@@ -22,7 +23,6 @@ import {
22
23
  selectFailedSteps,
23
24
  selectRunningSteps,
24
25
  selectHasSubTasks,
25
- selectAllowDangerousActions,
26
26
  selectUsernamePath,
27
27
  selectAction,
28
28
  selectState,
@@ -30,8 +30,6 @@ import {
30
30
  selectTimeoutId,
31
31
  selectTaskReload,
32
32
  selectParentTask,
33
- selectShowUnlockModal,
34
- selectShowForceUnlockModal,
35
33
  selectExternalId,
36
34
  selectDynflowEnableConsole,
37
35
  } from './TaskDetailsSelectors';
@@ -54,7 +52,6 @@ const mapStateToProps = state => ({
54
52
  runningSteps: selectRunningSteps(state),
55
53
  help: selectHelp(state),
56
54
  hasSubTasks: selectHasSubTasks(state),
57
- allowDangerousActions: selectAllowDangerousActions(state),
58
55
  locks: selectLocks(state),
59
56
  usernamePath: selectUsernamePath(state),
60
57
  action: selectAction(state),
@@ -63,13 +60,12 @@ const mapStateToProps = state => ({
63
60
  timeoutId: selectTimeoutId(state),
64
61
  taskReload: selectTaskReload(state),
65
62
  parentTask: selectParentTask(state),
66
- showUnlockModal: selectShowUnlockModal(state),
67
- showForceUnlockModal: selectShowForceUnlockModal(state),
68
63
  externalId: selectExternalId(state),
69
64
  dynflowEnableConsole: selectDynflowEnableConsole(state),
70
65
  });
71
66
 
72
- const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
67
+ const mapDispatchToProps = dispatch =>
68
+ bindActionCreators({ ...taskActions, ...taskDetailsActions }, dispatch);
73
69
 
74
70
  export const reducers = { taskDetails: reducer };
75
71
 
@@ -3,7 +3,12 @@ import { DropdownButton, MenuItem } from 'patternfly-react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
 
6
- export const ActionSelectButton = ({ onCancel, onResume, disabled }) => (
6
+ export const ActionSelectButton = ({
7
+ onCancel,
8
+ onResume,
9
+ onForceCancel,
10
+ disabled,
11
+ }) => (
7
12
  <DropdownButton
8
13
  title={__('Select Action')}
9
14
  disabled={disabled}
@@ -23,6 +28,13 @@ export const ActionSelectButton = ({ onCancel, onResume, disabled }) => (
23
28
  >
24
29
  {__('Resume Selected')}
25
30
  </MenuItem>
31
+ <MenuItem
32
+ title={__('Force Cancel selected tasks')}
33
+ onClick={onForceCancel}
34
+ eventKey="3"
35
+ >
36
+ {__('Force Cancel Selected')}
37
+ </MenuItem>
26
38
  </DropdownButton>
27
39
  );
28
40
 
@@ -30,6 +42,7 @@ ActionSelectButton.propTypes = {
30
42
  disabled: PropTypes.bool,
31
43
  onCancel: PropTypes.func.isRequired,
32
44
  onResume: PropTypes.func.isRequired,
45
+ onForceCancel: PropTypes.func.isRequired,
33
46
  };
34
47
 
35
48
  ActionSelectButton.defaultProps = {
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { startCase } from 'lodash';
4
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
5
+ import { Button } from 'patternfly-react';
6
+ import ForemanModal from 'foremanReact/components/ForemanModal';
7
+ import { FORCE_UNLOCK_MODAL } from '../../../TaskActions/TaskActionsConstants';
8
+ import { FORCE_UNLOCK_SELECTED_MODAL } from '../../TasksTableConstants';
9
+ import { ForceUnlockModal } from '../../../TaskActions/UnlockModals';
10
+
11
+ export const ConfirmModal = ({
12
+ actionText,
13
+ actionState,
14
+ actionType,
15
+ selectedRowsLen,
16
+ id,
17
+ parentTaskID,
18
+ url,
19
+ uriQuery: query,
20
+ setModalClosed,
21
+ ...props
22
+ }) => {
23
+ if ([FORCE_UNLOCK_MODAL, FORCE_UNLOCK_SELECTED_MODAL].includes(actionType)) {
24
+ return (
25
+ <ForceUnlockModal
26
+ onClick={() => {
27
+ props[actionType]({ url, query, parentTaskID });
28
+ setModalClosed();
29
+ }}
30
+ id={id}
31
+ selectedRowsLen={selectedRowsLen}
32
+ />
33
+ );
34
+ }
35
+ return (
36
+ <ForemanModal
37
+ title={sprintf(__('%s Selected Tasks'), startCase(actionText))}
38
+ id={id}
39
+ >
40
+ {sprintf(
41
+ __(
42
+ `This will %(action)s %(number)s task(s), putting them in the %(state)s state. Are you sure?`
43
+ ),
44
+ { action: actionText, number: selectedRowsLen, state: actionState }
45
+ )}
46
+ <ForemanModal.Footer>
47
+ <Button onClick={setModalClosed}>{__('No')}</Button>
48
+ <Button
49
+ className="confirm-button"
50
+ bsStyle="primary"
51
+ onClick={() => {
52
+ props[actionType]({ url, query, parentTaskID });
53
+ setModalClosed();
54
+ }}
55
+ >
56
+ {__('Yes')}
57
+ </Button>
58
+ </ForemanModal.Footer>
59
+ </ForemanModal>
60
+ );
61
+ };
62
+
63
+ ConfirmModal.propTypes = {
64
+ actionText: PropTypes.string,
65
+ actionState: PropTypes.string,
66
+ selectedRowsLen: PropTypes.number.isRequired,
67
+ actionType: PropTypes.string,
68
+ id: PropTypes.string.isRequired,
69
+ parentTaskID: PropTypes.string,
70
+ url: PropTypes.string.isRequired,
71
+ uriQuery: PropTypes.object,
72
+ setModalClosed: PropTypes.func.isRequired,
73
+ };
74
+
75
+ ConfirmModal.defaultProps = {
76
+ actionType: '',
77
+ actionText: '',
78
+ actionState: '',
79
+ parentTaskID: '',
80
+ uriQuery: {},
81
+ };
82
+
83
+ export default ConfirmModal;
@@ -0,0 +1,106 @@
1
+ import {
2
+ resumeTask,
3
+ cancelTask,
4
+ forceCancelTask,
5
+ } from '../../TasksTableActions';
6
+ import {
7
+ bulkCancelBySearch,
8
+ bulkCancelById,
9
+ bulkResumeBySearch,
10
+ bulkResumeById,
11
+ bulkForceCancelBySearch,
12
+ bulkForceCancelById,
13
+ } from '../../TasksBulkActions';
14
+ import { selectClicked, selectSelectedTasks } from './ConfirmModalSelectors';
15
+ import { selectAllRowsSelected } from '../../TasksTableSelectors';
16
+ import {
17
+ CANCEL_MODAL,
18
+ RESUME_MODAL,
19
+ CANCEL_SELECTED_MODAL,
20
+ RESUME_SELECTED_MODAL,
21
+ FORCE_UNLOCK_SELECTED_MODAL,
22
+ } from '../../TasksTableConstants';
23
+ import { FORCE_UNLOCK_MODAL } from '../../../TaskActions/TaskActionsConstants';
24
+
25
+ export default {
26
+ [CANCEL_SELECTED_MODAL]: ({ url, query, parentTaskID }) => (
27
+ dispatch,
28
+ getState
29
+ ) => {
30
+ if (selectAllRowsSelected(getState())) {
31
+ return dispatch(bulkCancelBySearch({ query, parentTaskID }));
32
+ }
33
+ return dispatch(
34
+ bulkCancelById({
35
+ selected: selectSelectedTasks(getState()),
36
+ url,
37
+ parentTaskID,
38
+ })
39
+ );
40
+ },
41
+ [CANCEL_MODAL]: ({ url, parentTaskID }) => (dispatch, getState) => {
42
+ const { taskId, taskName } = selectClicked(getState());
43
+ return dispatch(
44
+ cancelTask({
45
+ taskId,
46
+ taskName,
47
+ url,
48
+ parentTaskID,
49
+ })
50
+ );
51
+ },
52
+ [RESUME_SELECTED_MODAL]: ({ url, query, parentTaskID }) => (
53
+ dispatch,
54
+ getState
55
+ ) => {
56
+ if (selectAllRowsSelected(getState())) {
57
+ return dispatch(bulkResumeBySearch({ query, parentTaskID }));
58
+ }
59
+ return dispatch(
60
+ bulkResumeById({
61
+ selected: selectSelectedTasks(getState()),
62
+ url,
63
+ parentTaskID,
64
+ })
65
+ );
66
+ },
67
+
68
+ [RESUME_MODAL]: ({ url, parentTaskID }) => (dispatch, getState) => {
69
+ const { taskId, taskName } = selectClicked(getState());
70
+ return dispatch(
71
+ resumeTask({
72
+ taskId,
73
+ taskName,
74
+ url,
75
+ parentTaskID,
76
+ })
77
+ );
78
+ },
79
+
80
+ [FORCE_UNLOCK_MODAL]: ({ url, parentTaskID }) => (dispatch, getState) => {
81
+ const { taskId, taskName } = selectClicked(getState());
82
+ return dispatch(
83
+ forceCancelTask({
84
+ taskId,
85
+ taskName,
86
+ url,
87
+ parentTaskID,
88
+ })
89
+ );
90
+ },
91
+ [FORCE_UNLOCK_SELECTED_MODAL]: ({ url, query, parentTaskID }) => (
92
+ dispatch,
93
+ getState
94
+ ) => {
95
+ if (selectAllRowsSelected(getState())) {
96
+ return dispatch(bulkForceCancelBySearch({ query, parentTaskID }));
97
+ }
98
+ return dispatch(
99
+ bulkForceCancelById({
100
+ selected: selectSelectedTasks(getState()),
101
+ url,
102
+ parentTaskID,
103
+ })
104
+ );
105
+ },
106
+ };
@@ -0,0 +1,38 @@
1
+ import Immutable from 'seamless-immutable';
2
+ import {
3
+ UPDATE_MODAL,
4
+ CANCEL_SELECTED_MODAL,
5
+ RESUME_SELECTED_MODAL,
6
+ RESUME_MODAL,
7
+ CANCEL_MODAL,
8
+ } from '../../TasksTableConstants';
9
+
10
+ const initialState = Immutable({});
11
+
12
+ export const ConfirmModalReducer = (state = initialState, action) => {
13
+ const { type, payload } = action;
14
+ switch (type) {
15
+ case UPDATE_MODAL:
16
+ switch (payload.modalID) {
17
+ case CANCEL_SELECTED_MODAL:
18
+ case CANCEL_MODAL:
19
+ return state.merge({
20
+ actionText: 'cancel',
21
+ actionState: 'stopped',
22
+ actionType: payload.modalID,
23
+ });
24
+ case RESUME_SELECTED_MODAL:
25
+ case RESUME_MODAL:
26
+ return state.merge({
27
+ actionText: 'resume',
28
+ actionState: 'running',
29
+ actionType: payload.modalID,
30
+ });
31
+ default:
32
+ return state.set('actionType', payload.modalID);
33
+ }
34
+ default:
35
+ return state;
36
+ }
37
+ };
38
+ export default ConfirmModalReducer;
@@ -0,0 +1,45 @@
1
+ import { selectForemanTasks } from '../../../../ForemanTasksSelectors';
2
+ import {
3
+ selectTasksTableQuery,
4
+ selectResults,
5
+ selectSelectedRows,
6
+ selectItemCount,
7
+ selectAllRowsSelected,
8
+ } from '../../TasksTableSelectors';
9
+ import { RESUME_MODAL, CANCEL_MODAL } from '../../TasksTableConstants';
10
+ import { FORCE_UNLOCK_MODAL } from '../../../TaskActions/TaskActionsConstants';
11
+
12
+ export const selectCofirmModal = state =>
13
+ selectForemanTasks(state).confirmModal || {};
14
+
15
+ export const selectActionType = state => selectCofirmModal(state).actionType;
16
+ export const selectActionText = state => selectCofirmModal(state).actionText;
17
+ export const selectActionState = state => selectCofirmModal(state).actionState;
18
+ export const selectClicked = state =>
19
+ selectTasksTableQuery(state).clicked || {};
20
+
21
+ export const selectSelectedTasks = state => {
22
+ const selectedIDs = selectResults(state).filter(item =>
23
+ selectSelectedRows(state).includes(item.id)
24
+ );
25
+ return selectedIDs.map(item => ({
26
+ name: item.action,
27
+ id: item.id,
28
+ isCancellable: item.availableActions.cancellable,
29
+ isResumable: item.availableActions.resumable,
30
+ }));
31
+ };
32
+
33
+ export const selectSelectedRowsLen = state => {
34
+ if (
35
+ [CANCEL_MODAL, RESUME_MODAL, FORCE_UNLOCK_MODAL].includes(
36
+ selectActionType(state)
37
+ )
38
+ ) {
39
+ return 1;
40
+ }
41
+ if (selectAllRowsSelected(state)) {
42
+ return selectItemCount(state);
43
+ }
44
+ return selectSelectedRows(state).length;
45
+ };
@@ -0,0 +1,36 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import { ConfirmModal } from '../ConfirmModal';
3
+ import { RESUME_SELECTED_MODAL } from '../../../TasksTableConstants';
4
+ import { FORCE_UNLOCK_MODAL } from '../../../../TaskActions/TaskActionsConstants';
5
+
6
+ const fixtures = {
7
+ 'renders ConfirmModal': {
8
+ actionType: RESUME_SELECTED_MODAL,
9
+ actionText: 'some text',
10
+ actionState: 'some state',
11
+ selectedRowsLen: 1,
12
+ id: 'modalID',
13
+ parentTaskID: 'parent-id',
14
+ allRowsSelected: true,
15
+ url: 'some-url',
16
+ uriQuery: { state: 'stopped' },
17
+ setModalClosed: jest.fn(),
18
+ },
19
+
20
+ 'renders ConfirmModal for unlock ': {
21
+ actionType: FORCE_UNLOCK_MODAL,
22
+ actionText: 'some text',
23
+ actionState: 'some state',
24
+ selectedRowsLen: 1,
25
+ id: 'modalID',
26
+ parentTaskID: 'parent-id',
27
+ allRowsSelected: true,
28
+ url: 'some-url',
29
+ uriQuery: { state: 'stopped' },
30
+ setModalClosed: jest.fn(),
31
+ },
32
+ };
33
+
34
+ describe('ConfirmModal', () => {
35
+ testComponentSnapshotsWithFixtures(ConfirmModal, fixtures);
36
+ });