foreman-tasks 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +2 -22
  3. data/.rubocop.yml +12 -12
  4. data/.rubocop_todo.yml +34 -116
  5. data/README.md +2 -0
  6. data/app/controllers/foreman_tasks/api/recurring_logics_controller.rb +20 -1
  7. data/app/controllers/foreman_tasks/api/tasks_controller.rb +66 -11
  8. data/app/controllers/foreman_tasks/concerns/hosts_controller_extension.rb +1 -1
  9. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +19 -0
  10. data/app/controllers/foreman_tasks/tasks_controller.rb +3 -11
  11. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +1 -3
  12. data/app/lib/actions/helpers/humanizer.rb +1 -3
  13. data/app/lib/actions/proxy_action.rb +33 -12
  14. data/app/lib/foreman_tasks/concerns/polling_action_extensions.rb +12 -0
  15. data/app/models/foreman_tasks/concerns/action_triggering.rb +1 -1
  16. data/app/models/foreman_tasks/recurring_logic.rb +1 -0
  17. data/app/models/foreman_tasks/remote_task.rb +1 -0
  18. data/app/models/foreman_tasks/task.rb +8 -0
  19. data/app/models/foreman_tasks/task/dynflow_task.rb +1 -1
  20. data/app/models/foreman_tasks/task/search.rb +11 -1
  21. data/app/models/setting/foreman_tasks.rb +7 -2
  22. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +0 -4
  23. data/app/services/ui_notifications/tasks/task_bulk_cancel.rb +36 -0
  24. data/app/services/ui_notifications/tasks/task_bulk_resume.rb +38 -0
  25. data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
  26. data/app/views/foreman_tasks/api/recurring_logics/base.json.rabl +2 -1
  27. data/app/views/foreman_tasks/api/tasks/details.json.rabl +1 -1
  28. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
  29. data/app/views/foreman_tasks/recurring_logics/index.html.erb +30 -0
  30. data/app/views/foreman_tasks/tasks/show.html.erb +3 -0
  31. data/{.babelrc.js → babel.config.js} +0 -0
  32. data/config/routes.rb +8 -0
  33. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
  34. data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
  35. data/db/seeds.d/30-notification_blueprints.rb +21 -0
  36. data/foreman-tasks.gemspec +5 -6
  37. data/gemfile.d/foreman-tasks.rb +1 -0
  38. data/lib/foreman_tasks/dynflow/console_authorizer.rb +2 -2
  39. data/lib/foreman_tasks/engine.rb +17 -14
  40. data/lib/foreman_tasks/tasks/cleanup.rake +1 -1
  41. data/lib/foreman_tasks/tasks/export_tasks.rake +2 -2
  42. data/lib/foreman_tasks/test_extensions.rb +1 -1
  43. data/lib/foreman_tasks/version.rb +1 -1
  44. data/locale/action_names.rb +2 -2
  45. data/locale/en/foreman_tasks.po +227 -41
  46. data/locale/foreman_tasks.pot +579 -288
  47. data/package.json +18 -71
  48. data/script/rails +2 -2
  49. data/script/travis_run_js_tests.sh +2 -2
  50. data/test/controllers/api/tasks_controller_test.rb +9 -0
  51. data/test/factories/task_factory.rb +34 -2
  52. data/test/foreman_tasks_test_helper.rb +4 -0
  53. data/test/lib/concerns/polling_action_extensions_test.rb +34 -0
  54. data/test/unit/actions/action_with_sub_plans_test.rb +1 -1
  55. data/test/unit/task_test.rb +160 -74
  56. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
  57. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +67 -0
  58. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.test.js +46 -0
  59. data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
  60. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
  61. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
  62. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
  63. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
  64. data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
  65. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +132 -150
  66. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +3 -12
  67. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +1 -1
  68. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +1 -1
  69. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +1 -1
  70. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +1 -1
  71. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +68 -3
  72. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +1 -2
  73. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +104 -71
  74. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +3 -9
  75. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.stories.js +6 -2
  76. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +0 -15
  77. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +0 -5
  78. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -6
  79. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +4 -10
  80. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
  81. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +6 -1
  82. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +1 -1
  83. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +1 -1
  84. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +3 -7
  85. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +5 -1
  86. data/webpack/ForemanTasks/Components/TaskDetails/index.js +6 -8
  87. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.stories.js +44 -40
  88. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +1 -1
  89. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.stories.js +45 -40
  90. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +1 -1
  91. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.stories.js +27 -22
  92. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +1 -1
  93. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.stories.js +61 -56
  94. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -1
  95. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.stories.js +40 -35
  96. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +1 -1
  97. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.stories.js +21 -20
  98. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +1 -1
  99. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.stories.js +40 -39
  100. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +1 -1
  101. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.stories.js +16 -17
  102. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +1 -2
  103. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.mdx +57 -0
  104. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +1 -1
  105. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.stories.js +36 -18
  106. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.test.js +1 -1
  107. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +5 -0
  108. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +3 -2
  109. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +1 -1
  110. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +1 -1
  111. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js +1 -1
  112. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +1 -1
  113. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
  114. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
  115. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
  116. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
  117. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +45 -0
  118. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
  119. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
  120. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
  121. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +54 -0
  122. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
  123. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
  124. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +30 -0
  125. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
  126. data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +43 -0
  127. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +2 -1
  128. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +29 -0
  129. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionCell.test.js +1 -1
  130. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionHeaderCell.test.js +1 -1
  131. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
  132. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +75 -0
  133. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +4 -1
  134. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +247 -0
  135. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +50 -22
  136. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +62 -101
  137. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +21 -9
  138. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +4 -3
  139. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +65 -38
  140. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +26 -9
  141. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
  142. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +27 -16
  143. data/webpack/ForemanTasks/Components/TasksTable/__tests__/SubTasksPage.test.js +1 -1
  144. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +147 -0
  145. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksIndexPage.test.js +1 -1
  146. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +4 -7
  147. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.test.js +1 -1
  148. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +46 -74
  149. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +17 -1
  150. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +10 -2
  151. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +28 -8
  152. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +5 -7
  153. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +336 -0
  154. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +4 -7
  155. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +22 -158
  156. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +64 -42
  157. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +43 -16
  158. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
  159. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +2 -2
  160. data/webpack/ForemanTasks/Components/TasksTable/index.js +11 -4
  161. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +49 -21
  162. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +61 -14
  163. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +80 -21
  164. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
  165. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
  166. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
  167. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
  168. data/webpack/ForemanTasks/Components/common/ToastsHelpers/ToastTypesConstants.js +11 -0
  169. data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
  170. data/webpack/ForemanTasks/ForemanTasks.test.js +1 -1
  171. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  172. data/webpack/ForemanTasks/Routes/ForemanTasksRouter.test.js +1 -1
  173. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +4 -4
  174. data/webpack/ForemanTasks/Routes/ShowTask/__tests__/ShowTask.test.js +1 -1
  175. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
  176. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +10 -0
  177. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +18 -0
  178. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  179. metadata +71 -30
  180. data/.storybook/addons.js +0 -2
  181. data/.storybook/config.js +0 -7
  182. data/.storybook/webpack.config.js +0 -84
  183. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.js +0 -23
  184. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionConfirmation.js +0 -49
  185. data/webpack/ForemanTasks/Components/TasksTable/Components/CancelResumeConfirm.js +0 -51
  186. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionConfirmation.test.js +0 -18
  187. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelResumeConfirm.test.js +0 -28
  188. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionConfirmation.test.js.snap +0 -89
  189. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelResumeConfirm.test.js.snap +0 -37
  190. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
  191. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -27
  192. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
  193. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
  194. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
  195. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
  196. data/webpack/stories/index.js +0 -10
  197. data/webpack/stories/index.scss +0 -7
  198. data/webpack/test_setup.js +0 -7
@@ -0,0 +1,29 @@
1
+ import { connect } from 'react-redux';
2
+ import { bindActionCreators } from 'redux';
3
+ import { ConfirmModal } from './ConfirmModal';
4
+ import reducer from './ConfirmModalReducer';
5
+ import tasksActions from './ConfirmModalActions';
6
+ import {
7
+ selectActionText,
8
+ selectActionState,
9
+ selectActionType,
10
+ selectClicked,
11
+ selectSelectedRowsLen,
12
+ } from './ConfirmModalSelectors';
13
+ import { selectAllRowsSelected } from '../../TasksTableSelectors';
14
+
15
+ const mapStateToProps = state => ({
16
+ actionText: selectActionText(state),
17
+ actionType: selectActionType(state),
18
+ actionState: selectActionState(state),
19
+ allRowsSelected: selectAllRowsSelected(state),
20
+ clicked: selectClicked(state),
21
+ selectedRowsLen: selectSelectedRowsLen(state),
22
+ });
23
+
24
+ const mapDispatchToProps = dispatch =>
25
+ bindActionCreators(tasksActions, dispatch);
26
+
27
+ export const reducers = { confirmModal: reducer };
28
+
29
+ export default connect(mapStateToProps, mapDispatchToProps)(ConfirmModal);
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Alert, Button } from 'patternfly-react';
4
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
5
+
6
+ export const SelectAllAlert = ({
7
+ itemCount,
8
+ perPage,
9
+ selectAllRows,
10
+ unselectAllRows,
11
+ allRowsSelected,
12
+ }) => {
13
+ const selectAllText = (
14
+ <React.Fragment>
15
+ {sprintf(
16
+ 'All %s tasks on this page are selected',
17
+ Math.min(itemCount, perPage)
18
+ )}
19
+ <Button bsStyle="link" onClick={selectAllRows}>
20
+ {__('Select All')}
21
+ <b> {itemCount} </b> {__('tasks.')}
22
+ </Button>
23
+ </React.Fragment>
24
+ );
25
+ const undoSelectText = (
26
+ <React.Fragment>
27
+ {sprintf(__(`All %s tasks are selected. `), itemCount)}
28
+ <Button bsStyle="link" onClick={unselectAllRows}>
29
+ {__('Undo selection')}
30
+ </Button>
31
+ </React.Fragment>
32
+ );
33
+ const selectAlertText = allRowsSelected ? undoSelectText : selectAllText;
34
+ return <Alert type="info">{selectAlertText}</Alert>;
35
+ };
36
+
37
+ SelectAllAlert.propTypes = {
38
+ allRowsSelected: PropTypes.bool.isRequired,
39
+ itemCount: PropTypes.number.isRequired,
40
+ perPage: PropTypes.number.isRequired,
41
+ selectAllRows: PropTypes.func.isRequired,
42
+ unselectAllRows: PropTypes.func.isRequired,
43
+ };
@@ -1,4 +1,4 @@
1
- import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
 
3
3
  import { ActionSelectButton } from '../ActionSelectButton';
4
4
 
@@ -6,6 +6,7 @@ const fixtures = {
6
6
  'renders with minimal props': {
7
7
  onCancel: jest.fn(),
8
8
  onResume: jest.fn(),
9
+ onForceCancel: jest.fn(),
9
10
  },
10
11
  };
11
12
 
@@ -0,0 +1,29 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+
3
+ import { SelectAllAlert } from '../SelectAllAlert';
4
+
5
+ const baseProps = {
6
+ itemCount: 7,
7
+ perPage: 5,
8
+ selectAllRows: jest.fn(),
9
+ unselectAllRows: jest.fn(),
10
+ };
11
+ const fixtures = {
12
+ 'renders SelectAllAlert with perPage > itemCout': {
13
+ allRowsSelected: false,
14
+ itemCount: 7,
15
+ perPage: 10,
16
+ ...baseProps,
17
+ },
18
+ 'renders SelectAllAlert without all rows selected': {
19
+ allRowsSelected: false,
20
+ ...baseProps,
21
+ },
22
+ 'renders SelectAllAlert with all rows selected': {
23
+ allRowsSelected: true,
24
+ ...baseProps,
25
+ },
26
+ };
27
+
28
+ describe('SelectAllAlert', () =>
29
+ testComponentSnapshotsWithFixtures(SelectAllAlert, fixtures));
@@ -1,4 +1,4 @@
1
- import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
 
3
3
  import TableSelectionCell from '../TableSelectionCell';
4
4
 
@@ -1,4 +1,4 @@
1
- import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
 
3
3
  import TableSelectionHeaderCell from '../TableSelectionHeaderCell';
4
4
 
@@ -28,5 +28,16 @@ exports[`ActionSelectButton renders with minimal props 1`] = `
28
28
  >
29
29
  Resume Selected
30
30
  </MenuItem>
31
+ <MenuItem
32
+ bsClass="dropdown"
33
+ disabled={false}
34
+ divider={false}
35
+ eventKey="3"
36
+ header={false}
37
+ onClick={[MockFunction]}
38
+ title="Force Cancel selected tasks"
39
+ >
40
+ Force Cancel Selected
41
+ </MenuItem>
31
42
  </DropdownButton>
32
43
  `;
@@ -0,0 +1,75 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`SelectAllAlert renders SelectAllAlert with all rows selected 1`] = `
4
+ <Alert
5
+ className=""
6
+ onDismiss={null}
7
+ type="info"
8
+ >
9
+ All 7 tasks are selected.
10
+ <Button
11
+ active={false}
12
+ block={false}
13
+ bsClass="btn"
14
+ bsStyle="link"
15
+ disabled={false}
16
+ onClick={[MockFunction]}
17
+ >
18
+ Undo selection
19
+ </Button>
20
+ </Alert>
21
+ `;
22
+
23
+ exports[`SelectAllAlert renders SelectAllAlert with perPage > itemCout 1`] = `
24
+ <Alert
25
+ className=""
26
+ onDismiss={null}
27
+ type="info"
28
+ >
29
+ All 5 tasks on this page are selected
30
+ <Button
31
+ active={false}
32
+ block={false}
33
+ bsClass="btn"
34
+ bsStyle="link"
35
+ disabled={false}
36
+ onClick={[MockFunction]}
37
+ >
38
+ Select All
39
+ <b>
40
+
41
+ 7
42
+
43
+ </b>
44
+
45
+ tasks.
46
+ </Button>
47
+ </Alert>
48
+ `;
49
+
50
+ exports[`SelectAllAlert renders SelectAllAlert without all rows selected 1`] = `
51
+ <Alert
52
+ className=""
53
+ onDismiss={null}
54
+ type="info"
55
+ >
56
+ All 5 tasks on this page are selected
57
+ <Button
58
+ active={false}
59
+ block={false}
60
+ bsClass="btn"
61
+ bsStyle="link"
62
+ disabled={false}
63
+ onClick={[MockFunction]}
64
+ >
65
+ Select All
66
+ <b>
67
+
68
+ 7
69
+
70
+ </b>
71
+
72
+ tasks.
73
+ </Button>
74
+ </Alert>
75
+ `;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { translate as __ } from 'foremanReact/common/I18n';
3
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
4
4
  import TasksTablePage from './';
5
5
 
6
6
  export const SubTasksPage = props => {
@@ -15,10 +15,13 @@ export const SubTasksPage = props => {
15
15
  { caption: __('Sub tasks') },
16
16
  ],
17
17
  });
18
+ const createHeader = actionName =>
19
+ actionName ? sprintf(__('Sub tasks of %s'), actionName) : __('Sub tasks');
18
20
  return (
19
21
  <TasksTablePage
20
22
  getBreadcrumbs={getBreadcrumbs}
21
23
  parentTaskID={parentTaskID}
24
+ createHeader={createHeader}
22
25
  {...props}
23
26
  />
24
27
  );
@@ -0,0 +1,247 @@
1
+ import API from 'foremanReact/API';
2
+ import { addToast } from 'foremanReact/redux/actions/toasts';
3
+ import { translate as __, sprintf } from 'foremanReact/common/I18n';
4
+ import {
5
+ BULK_CANCEL_PATH,
6
+ BULK_RESUME_PATH,
7
+ BULK_FORCE_CANCEL_PATH,
8
+ } from './TasksTableConstants';
9
+ import {
10
+ TASKS_RESUME_REQUEST,
11
+ TASKS_RESUME_SUCCESS,
12
+ TASKS_RESUME_FAILURE,
13
+ TASKS_CANCEL_REQUEST,
14
+ TASKS_CANCEL_SUCCESS,
15
+ TASKS_CANCEL_FAILURE,
16
+ TASKS_FORCE_CANCEL_REQUEST,
17
+ TASKS_FORCE_CANCEL_SUCCESS,
18
+ TASKS_FORCE_CANCEL_FAILURE,
19
+ } from '../TaskActions/TaskActionsConstants';
20
+ import { reloadPage } from './TasksTableActions';
21
+ import {
22
+ convertDashboardQuery,
23
+ resumeToastInfo,
24
+ cancelToastInfo,
25
+ toastDispatch,
26
+ } from '../TaskActions/TaskActionHelpers';
27
+ import {
28
+ successToastData,
29
+ errorToastData,
30
+ warningToastData,
31
+ infoToastData,
32
+ } from '../common/ToastsHelpers';
33
+
34
+ export const bulkByIdRequest = (resumeTasks, path) => {
35
+ const ids = resumeTasks.map(task => task.id);
36
+ const url = `/foreman_tasks/api/tasks/${path}`;
37
+ const data = { task_ids: ids };
38
+ return API.post(url, data);
39
+ };
40
+
41
+ export const bulkBySearchRequest = ({ query, parentTaskID, path }) => {
42
+ const url = `/foreman_tasks/api/tasks/${path}`;
43
+ if (parentTaskID) {
44
+ query.search = query.search
45
+ ? ` ${query.search} and parent_task_id=${parentTaskID}`
46
+ : `parent_task_id=${parentTaskID}`;
47
+ }
48
+ const searchParam = { search: convertDashboardQuery(query) };
49
+ return API.post(url, searchParam);
50
+ };
51
+
52
+ const handleErrorResume = (error, dispatch) => {
53
+ dispatch({ type: TASKS_RESUME_FAILURE, error });
54
+ dispatch(
55
+ addToast(
56
+ errorToastData(`${__(`Cannot resume tasks at the moment`)} ${error}`)
57
+ )
58
+ );
59
+ };
60
+
61
+ export const bulkResumeById = ({
62
+ selected,
63
+ url,
64
+ parentTaskID,
65
+ }) => async dispatch => {
66
+ const resumeTasks = selected.filter(task => task.isResumable);
67
+ if (resumeTasks.length < selected.length)
68
+ dispatch(
69
+ addToast(
70
+ warningToastData(__('Not all the selected tasks can be resumed'))
71
+ )
72
+ );
73
+ if (resumeTasks.length) {
74
+ dispatch({ type: TASKS_RESUME_REQUEST });
75
+ try {
76
+ const { data } = await bulkByIdRequest(resumeTasks, BULK_RESUME_PATH);
77
+ dispatch({ type: TASKS_RESUME_SUCCESS });
78
+ ['resumed', 'failed', 'skipped'].forEach(type => {
79
+ data[type] &&
80
+ data[type].forEach(task => {
81
+ toastDispatch({
82
+ type,
83
+ name: task.action,
84
+ toastInfo: resumeToastInfo,
85
+ dispatch,
86
+ });
87
+ });
88
+ });
89
+ if (data.resumed) {
90
+ reloadPage(url, parentTaskID, dispatch);
91
+ }
92
+ } catch (error) {
93
+ handleErrorResume(error, dispatch);
94
+ }
95
+ }
96
+ };
97
+
98
+ export const bulkResumeBySearch = ({
99
+ query,
100
+ parentTaskID,
101
+ }) => async dispatch => {
102
+ dispatch({ type: TASKS_RESUME_REQUEST });
103
+ dispatch(
104
+ addToast(
105
+ infoToastData(__('Resuming selected tasks, this might take a while'))
106
+ )
107
+ );
108
+ await bulkBySearchRequest({ query, path: BULK_RESUME_PATH, parentTaskID });
109
+ };
110
+
111
+ const handleErrorCancel = (error, dispatch) => {
112
+ dispatch({ type: TASKS_CANCEL_FAILURE, error });
113
+ dispatch(
114
+ addToast(
115
+ errorToastData(`${__(`Cannot cancel tasks at the moment`)} ${error}`)
116
+ )
117
+ );
118
+ };
119
+
120
+ export const bulkCancelBySearch = ({
121
+ query,
122
+ parentTaskID,
123
+ }) => async dispatch => {
124
+ dispatch({ type: TASKS_CANCEL_REQUEST });
125
+ dispatch(
126
+ addToast(
127
+ infoToastData(__('Canceling selected tasks, this might take a while'))
128
+ )
129
+ );
130
+ await bulkBySearchRequest({ query, path: BULK_CANCEL_PATH, parentTaskID });
131
+ };
132
+
133
+ export const bulkCancelById = ({
134
+ selected,
135
+ url,
136
+ parentTaskID,
137
+ }) => async dispatch => {
138
+ const cancelTasks = selected.filter(task => task.isCancellable);
139
+ if (cancelTasks.length < selected.length)
140
+ dispatch(
141
+ addToast(
142
+ warningToastData(__('Not all the selected tasks can be cancelled'))
143
+ )
144
+ );
145
+ if (cancelTasks.length) {
146
+ dispatch({ type: TASKS_CANCEL_REQUEST });
147
+ try {
148
+ const { data } = await bulkByIdRequest(cancelTasks, BULK_CANCEL_PATH);
149
+ dispatch({ type: TASKS_CANCEL_SUCCESS });
150
+
151
+ ['cancelled', 'skipped'].forEach(type => {
152
+ data[type] &&
153
+ data[type].forEach(task => {
154
+ toastDispatch({
155
+ type,
156
+ name: task.action,
157
+ toastInfo: cancelToastInfo,
158
+ dispatch,
159
+ });
160
+ });
161
+ });
162
+ if (data.cancelled) {
163
+ reloadPage(url, parentTaskID, dispatch);
164
+ }
165
+ } catch (error) {
166
+ handleErrorCancel(error, dispatch);
167
+ }
168
+ }
169
+ };
170
+
171
+ const handleErrorForceCancel = (error, dispatch) => {
172
+ dispatch({ type: TASKS_FORCE_CANCEL_FAILURE, error });
173
+ dispatch(
174
+ addToast(
175
+ errorToastData(
176
+ `${__(`Cannot force cancel tasks at the moment`)} ${error}`
177
+ )
178
+ )
179
+ );
180
+ };
181
+
182
+ export const bulkForceCancelById = ({
183
+ selected,
184
+ url,
185
+ parentTaskID,
186
+ }) => async dispatch => {
187
+ const stopTasks = selected.filter(task => task.state !== 'stopped');
188
+ if (stopTasks.length < selected.length)
189
+ dispatch(
190
+ addToast(
191
+ warningToastData(
192
+ sprintf(
193
+ '%s task(s) are already stopped',
194
+ selected.length - stopTasks.length
195
+ )
196
+ )
197
+ )
198
+ );
199
+ if (stopTasks.length > 0) {
200
+ dispatch({ type: TASKS_FORCE_CANCEL_REQUEST });
201
+ try {
202
+ const { data } = await bulkByIdRequest(stopTasks, BULK_FORCE_CANCEL_PATH);
203
+ dispatch({ type: TASKS_FORCE_CANCEL_SUCCESS });
204
+ if (data.stopped_length) {
205
+ dispatch(
206
+ addToast(
207
+ successToastData(
208
+ sprintf('%s task(s) cancelled with force', data.stopped_length)
209
+ )
210
+ )
211
+ );
212
+ }
213
+ if (data.skipped_length > 0)
214
+ dispatch(
215
+ addToast(
216
+ warningToastData(
217
+ sprintf('%s task(s) are already stopped', data.skipped_length)
218
+ )
219
+ )
220
+ );
221
+ if (data.stopped_length > 0) {
222
+ reloadPage(url, parentTaskID, dispatch);
223
+ }
224
+ } catch (error) {
225
+ handleErrorForceCancel(error, dispatch);
226
+ }
227
+ }
228
+ };
229
+
230
+ export const bulkForceCancelBySearch = ({
231
+ query,
232
+ parentTaskID,
233
+ }) => async dispatch => {
234
+ dispatch({ type: TASKS_FORCE_CANCEL_REQUEST });
235
+ dispatch(
236
+ addToast(
237
+ infoToastData(
238
+ __('Canceling with force selected tasks, this might take a while')
239
+ )
240
+ )
241
+ );
242
+ await bulkBySearchRequest({
243
+ query,
244
+ path: BULK_FORCE_CANCEL_PATH,
245
+ parentTaskID,
246
+ });
247
+ };