foreman-tasks 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ });