foreman-tasks 0.17.6 → 1.2.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/.travis.yml +2 -2
  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 +0 -2
  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/ui_notifications/tasks/task_bulk_cancel.rb +36 -0
  23. data/app/services/ui_notifications/tasks/task_bulk_resume.rb +38 -0
  24. data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
  25. data/app/views/foreman_tasks/api/recurring_logics/base.json.rabl +2 -1
  26. data/app/views/foreman_tasks/api/tasks/details.json.rabl +1 -1
  27. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
  28. data/app/views/foreman_tasks/recurring_logics/index.html.erb +30 -0
  29. data/app/views/foreman_tasks/tasks/show.html.erb +3 -0
  30. data/babel.config.js +3 -0
  31. data/config/routes.rb +8 -0
  32. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
  33. data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
  34. data/db/seeds.d/30-notification_blueprints.rb +21 -0
  35. data/foreman-tasks.gemspec +5 -6
  36. data/gemfile.d/foreman-tasks.rb +1 -0
  37. data/lib/foreman_tasks/dynflow/console_authorizer.rb +2 -2
  38. data/lib/foreman_tasks/engine.rb +17 -14
  39. data/lib/foreman_tasks/tasks/cleanup.rake +1 -1
  40. data/lib/foreman_tasks/tasks/export_tasks.rake +2 -2
  41. data/lib/foreman_tasks/test_extensions.rb +1 -1
  42. data/lib/foreman_tasks/version.rb +1 -1
  43. data/locale/action_names.rb +2 -2
  44. data/locale/en/foreman_tasks.po +227 -41
  45. data/locale/foreman_tasks.pot +579 -288
  46. data/package.json +19 -79
  47. data/script/rails +2 -2
  48. data/script/travis_run_js_tests.sh +2 -2
  49. data/test/controllers/api/tasks_controller_test.rb +9 -0
  50. data/test/factories/task_factory.rb +34 -2
  51. data/test/foreman_tasks_test_helper.rb +4 -0
  52. data/test/lib/concerns/polling_action_extensions_test.rb +34 -0
  53. data/test/unit/actions/action_with_sub_plans_test.rb +1 -1
  54. data/test/unit/task_test.rb +160 -74
  55. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
  56. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.js +67 -0
  57. data/webpack/ForemanTasks/Components/TaskActions/TaskActionHelpers.test.js +46 -0
  58. data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
  59. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
  60. data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
  61. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
  62. data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
  63. data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
  64. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +132 -150
  65. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +1 -4
  66. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +1 -1
  67. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +1 -1
  68. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +1 -1
  69. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +1 -1
  70. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +68 -3
  71. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +1 -2
  72. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +104 -71
  73. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +9 -15
  74. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.stories.js +6 -2
  75. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +2 -17
  76. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +0 -5
  77. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -6
  78. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +3 -9
  79. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
  80. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +6 -1
  81. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +1 -1
  82. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +1 -1
  83. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +3 -7
  84. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +5 -1
  85. data/webpack/ForemanTasks/Components/TaskDetails/index.js +6 -8
  86. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.stories.js +44 -40
  87. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +1 -1
  88. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.stories.js +45 -40
  89. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +1 -1
  90. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.stories.js +27 -22
  91. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +1 -1
  92. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.stories.js +61 -56
  93. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -1
  94. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.stories.js +40 -35
  95. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +1 -1
  96. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.stories.js +21 -20
  97. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +1 -1
  98. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.stories.js +40 -39
  99. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +1 -1
  100. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.stories.js +16 -17
  101. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +1 -2
  102. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.mdx +57 -0
  103. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +1 -1
  104. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.stories.js +36 -18
  105. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.test.js +1 -1
  106. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +5 -0
  107. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +3 -2
  108. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +1 -1
  109. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +1 -1
  110. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js +1 -1
  111. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +1 -1
  112. data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
  113. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
  114. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
  115. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
  116. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +45 -0
  117. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
  118. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
  119. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
  120. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +54 -0
  121. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
  122. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
  123. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +30 -0
  124. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
  125. data/webpack/ForemanTasks/Components/TasksTable/Components/SelectAllAlert.js +43 -0
  126. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +2 -1
  127. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/SelectAllAlert.test.js +29 -0
  128. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionCell.test.js +1 -1
  129. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionHeaderCell.test.js +1 -1
  130. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
  131. data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/SelectAllAlert.test.js.snap +75 -0
  132. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +4 -1
  133. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +247 -0
  134. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +50 -22
  135. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +62 -101
  136. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +18 -5
  137. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +4 -3
  138. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +65 -38
  139. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +26 -9
  140. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
  141. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +27 -16
  142. data/webpack/ForemanTasks/Components/TasksTable/__tests__/SubTasksPage.test.js +1 -1
  143. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +147 -0
  144. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksIndexPage.test.js +1 -1
  145. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +4 -7
  146. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.test.js +1 -1
  147. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +46 -74
  148. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +17 -1
  149. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +10 -2
  150. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +28 -8
  151. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +5 -7
  152. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +336 -0
  153. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +4 -7
  154. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +22 -158
  155. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +66 -44
  156. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +43 -16
  157. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +1 -1
  158. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +2 -2
  159. data/webpack/ForemanTasks/Components/TasksTable/index.js +11 -4
  160. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +49 -21
  161. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +61 -14
  162. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +80 -21
  163. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
  164. data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
  165. data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
  166. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
  167. data/webpack/ForemanTasks/Components/common/ToastsHelpers/ToastTypesConstants.js +11 -0
  168. data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
  169. data/webpack/ForemanTasks/ForemanTasks.test.js +1 -1
  170. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  171. data/webpack/ForemanTasks/Routes/ForemanTasksRouter.test.js +1 -1
  172. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +4 -4
  173. data/webpack/ForemanTasks/Routes/ShowTask/__tests__/ShowTask.test.js +1 -1
  174. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
  175. data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +10 -0
  176. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +18 -0
  177. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  178. metadata +71 -30
  179. data/.babelrc +0 -35
  180. data/.storybook/addons.js +0 -2
  181. data/.storybook/config.js +0 -7
  182. data/.storybook/webpack.config.js +0 -63
  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 -6
@@ -8,6 +8,8 @@ import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
8
8
  import { getURIQuery } from 'foremanReact/common/helpers';
9
9
  import createTasksTableSchema from './TasksTableSchema';
10
10
  import { updateURlQuery } from './TasksTableHelpers';
11
+ import { RESUME_MODAL, CANCEL_MODAL } from './TasksTableConstants';
12
+ import { FORCE_UNLOCK_MODAL } from '../TaskActions/TaskActionsConstants';
11
13
 
12
14
  const TasksTable = ({
13
15
  getTableItems,
@@ -17,35 +19,46 @@ const TasksTable = ({
17
19
  history,
18
20
  itemCount,
19
21
  pagination,
20
- cancelTask,
21
- resumeTask,
22
22
  selectedRows,
23
- selectAllRows,
23
+ selectPage,
24
24
  unselectAllRows,
25
25
  selectRow,
26
26
  unselectRow,
27
- parentTaskID,
27
+ openClickedModal,
28
+ openModal,
29
+ allRowsSelected,
28
30
  }) => {
29
- const url = history.location.pathname + history.location.search;
31
+ const { search, pathname } = history.location;
32
+ const url = pathname + search;
30
33
  const uriQuery = getURIQuery(url);
31
34
 
32
35
  useEffect(() => {
33
36
  getTableItems(url);
34
- }, [history.location.search]);
37
+ }, [getTableItems, url]);
38
+
39
+ useEffect(() => {
40
+ unselectAllRows();
41
+ }, [unselectAllRows, search]);
35
42
 
36
43
  const getSelectionController = () => {
37
- const checkAllRowsSelected = () => results.length === selectedRows.length;
44
+ const checkAllPageSelected = () =>
45
+ allRowsSelected || results.length === selectedRows.length;
38
46
  return {
39
- allRowsSelected: () => checkAllRowsSelected(),
40
- selectAllRows: () => {
41
- if (checkAllRowsSelected()) unselectAllRows();
42
- else selectAllRows(results);
47
+ allRowsSelected,
48
+ allPageSelected: () => checkAllPageSelected(),
49
+ selectPage: () => {
50
+ if (checkAllPageSelected()) unselectAllRows();
51
+ else {
52
+ selectPage(results);
53
+ }
43
54
  },
44
55
  selectRow: ({ rowData: { id } }) => {
45
- if (selectedRows.includes(id)) unselectRow(id);
56
+ if (selectedRows.includes(id) || allRowsSelected)
57
+ unselectRow(id, allRowsSelected && results);
46
58
  else selectRow(id);
47
59
  },
48
- isSelected: ({ rowData }) => selectedRows.includes(rowData.id),
60
+ isSelected: ({ rowData }) =>
61
+ allRowsSelected || selectedRows.includes(rowData.id),
49
62
  };
50
63
  };
51
64
 
@@ -82,11 +95,26 @@ const TasksTable = ({
82
95
  };
83
96
 
84
97
  const taskActions = {
85
- cancel: (id, name) => {
86
- cancelTask(id, name, url, parentTaskID);
98
+ cancelTask: (taskId, taskName) => {
99
+ openClickedModal({
100
+ taskId,
101
+ taskName,
102
+ setModalOpen: () => openModal(CANCEL_MODAL),
103
+ });
104
+ },
105
+ resumeTask: (taskId, taskName) => {
106
+ openClickedModal({
107
+ taskId,
108
+ taskName,
109
+ setModalOpen: () => openModal(RESUME_MODAL),
110
+ });
87
111
  },
88
- resume: (id, name) => {
89
- resumeTask(id, name, url, parentTaskID);
112
+ forceCancelTask: (taskId, taskName) => {
113
+ openClickedModal({
114
+ taskId,
115
+ taskName,
116
+ setModalOpen: () => openModal(FORCE_UNLOCK_MODAL),
117
+ });
90
118
  },
91
119
  };
92
120
 
@@ -126,14 +154,14 @@ TasksTable.propTypes = {
126
154
  perPage: PropTypes.number,
127
155
  }),
128
156
  history: PropTypes.object.isRequired,
129
- cancelTask: PropTypes.func.isRequired,
130
- resumeTask: PropTypes.func.isRequired,
157
+ openClickedModal: PropTypes.func.isRequired,
131
158
  selectedRows: PropTypes.array,
132
- selectAllRows: PropTypes.func.isRequired,
159
+ selectPage: PropTypes.func.isRequired,
133
160
  unselectAllRows: PropTypes.func.isRequired,
134
161
  selectRow: PropTypes.func.isRequired,
135
162
  unselectRow: PropTypes.func.isRequired,
136
- parentTaskID: PropTypes.string,
163
+ openModal: PropTypes.func.isRequired,
164
+ allRowsSelected: PropTypes.bool,
137
165
  };
138
166
 
139
167
  TasksTable.defaultProps = {
@@ -144,7 +172,7 @@ TasksTable.defaultProps = {
144
172
  perPage: 20,
145
173
  },
146
174
  selectedRows: [],
147
- parentTaskID: null,
175
+ allRowsSelected: false,
148
176
  };
149
177
 
150
178
  export default TasksTable;
@@ -1,83 +1,75 @@
1
1
  import { getURIQuery } from 'foremanReact/common/helpers';
2
2
  import { getTableItemsAction } from 'foremanReact/components/common/table';
3
- import API from 'foremanReact/API';
4
- import { addToast } from 'foremanReact/redux/actions/toasts';
5
- import { translate as __ } from 'foremanReact/common/I18n';
3
+
6
4
  import {
7
5
  TASKS_TABLE_ID,
8
6
  SELECT_ROWS,
9
7
  UNSELECT_ALL_ROWS,
8
+ SELECT_ALL_ROWS,
10
9
  UNSELECT_ROWS,
11
- TASKS_TABLE_SELECTED_MODAL,
12
- CLOSED,
13
- RESUME,
14
- CANCEL,
10
+ UPDATE_CLICKED,
11
+ OPEN_SELECT_ALL,
12
+ UPDATE_MODAL,
15
13
  } from './TasksTableConstants';
16
14
  import { getApiPathname } from './TasksTableHelpers';
17
15
  import { fetchTasksSummary } from '../TasksDashboard/TasksDashboardActions';
16
+ import {
17
+ cancelTaskRequest,
18
+ resumeTaskRequest,
19
+ forceCancelTaskRequest,
20
+ } from '../TaskActions';
18
21
 
19
22
  export const getTableItems = url =>
20
23
  getTableItemsAction(TASKS_TABLE_ID, getURIQuery(url), getApiPathname(url));
21
24
 
22
- export const cancelTask = (id, name, url, parentTaskID) => async dispatch => {
23
- await dispatch(cancelTaskRequest(id, name));
25
+ export const reloadPage = (url, parentTaskID, dispatch) => {
24
26
  dispatch(getTableItems(url));
25
27
  dispatch(fetchTasksSummary(getURIQuery(url).time, parentTaskID));
26
28
  };
27
29
 
28
- export const cancelTaskRequest = (id, name) => async dispatch => {
29
- dispatch(
30
- addToast({
31
- type: 'info',
32
- message: `${__('Trying to cancel')} "${name}" ${__('task')}`,
33
- })
34
- );
35
- try {
36
- await API.post(`/foreman_tasks/tasks/${id}/cancel`);
37
- dispatch(
38
- addToast({
39
- type: 'success',
40
- message: `"${name}" ${__('Task cancelled')}`,
41
- })
42
- );
43
- } catch ({ response }) {
44
- dispatch(
45
- addToast({
46
- type: 'error',
47
- message: `"${name}" ${__('Task cannot be cancelled at the moment.')}`,
48
- })
49
- );
50
- }
30
+ export const cancelTask = ({
31
+ taskId,
32
+ taskName,
33
+ url,
34
+ parentTaskID,
35
+ }) => async dispatch => {
36
+ await dispatch(cancelTaskRequest(taskId, taskName));
37
+ reloadPage(url, parentTaskID, dispatch);
38
+ };
39
+
40
+ export const resumeTask = ({
41
+ taskId,
42
+ taskName,
43
+ url,
44
+ parentTaskID,
45
+ }) => async dispatch => {
46
+ await dispatch(resumeTaskRequest(taskId, taskName));
47
+ reloadPage(url, parentTaskID, dispatch);
51
48
  };
52
49
 
53
- export const resumeTask = (id, name, url, parentTaskID) => async dispatch => {
54
- await dispatch(resumeTaskRequest(id, name));
50
+ export const forceCancelTask = ({
51
+ taskId,
52
+ taskName,
53
+ url,
54
+ parentTaskID,
55
+ }) => async dispatch => {
56
+ await dispatch(forceCancelTaskRequest(taskId, taskName));
55
57
  dispatch(getTableItems(url));
56
- dispatch(fetchTasksSummary(getURIQuery(url).time), parentTaskID);
58
+ dispatch(fetchTasksSummary(getURIQuery(url).time, parentTaskID));
57
59
  };
58
60
 
59
- export const resumeTaskRequest = (id, name) => async dispatch => {
60
- try {
61
- await API.post(`/foreman_tasks/tasks/${id}/resume`);
62
- dispatch(
63
- addToast({
64
- type: 'success',
65
- message: __(`"${name}" ${__('Task execution was resumed')}`),
66
- })
67
- );
68
- } catch ({ response }) {
69
- dispatch(
70
- addToast({
71
- type: 'error',
72
- message: __(`Task "${name}" has to be resumable.`),
73
- })
74
- );
75
- }
61
+ export const selectPage = results => dispatch => {
62
+ dispatch({
63
+ type: SELECT_ROWS,
64
+ payload: results.map(row => row.id),
65
+ });
66
+ dispatch({
67
+ type: OPEN_SELECT_ALL,
68
+ });
76
69
  };
77
70
 
78
- export const selectAllRows = results => ({
79
- type: SELECT_ROWS,
80
- payload: results.map(row => row.id),
71
+ export const selectAllRows = () => ({
72
+ type: SELECT_ALL_ROWS,
81
73
  });
82
74
 
83
75
  export const unselectAllRows = () => ({
@@ -89,54 +81,23 @@ export const selectRow = id => ({
89
81
  payload: [id],
90
82
  });
91
83
 
92
- export const unselectRow = id => ({
84
+ export const unselectRow = (id, results) => ({
93
85
  type: UNSELECT_ROWS,
94
- payload: id,
86
+ payload: { id, results },
95
87
  });
96
88
 
97
- export const actionSelected = (actionType, selected, url) => async dispatch => {
98
- let notAllActionable = false;
99
- let someActionable = false;
100
- const promises = selected.map(task => {
101
- if (actionType === RESUME && task.isResumeble) {
102
- someActionable = true;
103
- return dispatch(resumeTaskRequest(task.id, task.name, url));
104
- } else if (actionType === CANCEL && task.isCancelleble) {
105
- someActionable = true;
106
- return dispatch(cancelTaskRequest(task.id, task.name, url));
107
- }
108
- notAllActionable = true;
109
- return null;
110
- });
111
- if (notAllActionable)
112
- dispatch(
113
- addToast({
114
- type: 'warning',
115
- message: __(
116
- `Not all the selected tasks can be ${
117
- actionType === RESUME ? 'resumed' : 'canceled'
118
- }`
119
- ),
120
- })
121
- );
122
- if (someActionable) {
123
- await Promise.all(promises);
124
- dispatch(getTableItems(url));
125
- dispatch(fetchTasksSummary(getURIQuery(url).time));
126
- }
89
+ export const openClickedModal = ({ taskId, taskName, setModalOpen }) => {
90
+ setModalOpen();
91
+ return {
92
+ type: UPDATE_CLICKED,
93
+ payload: { clicked: { taskId, taskName } },
94
+ };
127
95
  };
128
96
 
129
- export const showCancelSelcetedModal = () => ({
130
- type: TASKS_TABLE_SELECTED_MODAL,
131
- payload: CANCEL,
132
- });
133
-
134
- export const showResumeSelcetedModal = () => ({
135
- type: TASKS_TABLE_SELECTED_MODAL,
136
- payload: RESUME,
137
- });
138
-
139
- export const hideSelcetedModal = () => ({
140
- type: TASKS_TABLE_SELECTED_MODAL,
141
- payload: CLOSED,
142
- });
97
+ export const openModalAction = (modalID, setModalOpen) => {
98
+ setModalOpen();
99
+ return {
100
+ type: UPDATE_MODAL,
101
+ payload: { modalID },
102
+ };
103
+ };
@@ -1,15 +1,28 @@
1
1
  import { getControllerSearchProps } from 'foremanReact/constants';
2
2
 
3
3
  export const TASKS_TABLE_ID = 'TASKS_TABLE';
4
+
4
5
  export const SELECT_ROWS = 'SELECT_ROWS';
5
6
  export const UNSELECT_ROWS = 'UNSELECT_ROWS';
6
7
  export const UNSELECT_ALL_ROWS = 'UNSELECT_ALL_ROWS';
7
- export const CANCEL = 'CANCEL';
8
- export const RESUME = 'RESUME';
9
- export const CLOSED = 'CLOSED';
8
+ export const SELECT_ALL_ROWS = 'SELECT_ALL_ROWS';
9
+ export const OPEN_SELECT_ALL = 'OPEN_SELECT_ALL';
10
+
11
+ export const BULK_CANCEL_PATH = 'bulk_cancel';
12
+ export const BULK_RESUME_PATH = 'bulk_resume';
13
+ export const BULK_FORCE_CANCEL_PATH = 'bulk_stop';
14
+
15
+ export const CANCEL_MODAL = 'cancelConfirmModal';
16
+ export const RESUME_MODAL = 'resumeConfirmModal';
17
+ export const CANCEL_SELECTED_MODAL = 'cancelSelectedConfirmModal';
18
+ export const RESUME_SELECTED_MODAL = 'resumeSelectedConfirmModal';
19
+ export const CONFIRM_MODAL = 'ConfirmModal';
20
+ export const FORCE_UNLOCK_SELECTED_MODAL = 'forceUnlockSelectedConfirmModal';
21
+
22
+ export const UPDATE_CLICKED = 'UPDATE_CLICKED';
23
+ export const UPDATE_MODAL = 'UPDATE_MODAL';
10
24
 
11
- export const TASKS_TABLE_SELECTED_MODAL = 'TASKS_TABLE_SELECTED_MODAL';
12
25
  export const TASKS_SEARCH_PROPS = {
13
26
  ...getControllerSearchProps('tasks'),
14
- controller: 'foreman_tasks/tasks'
27
+ controller: 'foreman_tasks_tasks',
15
28
  };
@@ -22,9 +22,10 @@ export const resolveSearchQuery = (search, history) => {
22
22
  updateURlQuery(uriQuery, history);
23
23
  };
24
24
 
25
- export const addSearchToURL = (path, query) => {
26
- const url = new URI(path);
27
- url.addSearch({ ...query, include_permissions: true });
25
+ export const getCSVurl = (path, query) => {
26
+ let url = new URI(path);
27
+ url = url.pathname(`${url.pathname()}.csv`);
28
+ url.addSearch(query);
28
29
  return url.toString();
29
30
  };
30
31
 
@@ -7,69 +7,72 @@ import { translate as __ } from 'foremanReact/common/I18n';
7
7
  import { getURIQuery } from 'foremanReact/common/helpers';
8
8
  import ExportButton from 'foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton';
9
9
  import { STATUS } from 'foremanReact/constants';
10
+ import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
10
11
  import TasksDashboard from '../TasksDashboard';
11
12
  import TasksTable from './TasksTable';
12
- import { resolveSearchQuery, addSearchToURL } from './TasksTableHelpers';
13
- import { CancelResumeConfirm } from './Components/CancelResumeConfirm';
13
+ import { resolveSearchQuery, getCSVurl } from './TasksTableHelpers';
14
+ import ConfirmModal from './Components/ConfirmModal/';
14
15
  import {
15
16
  TASKS_SEARCH_PROPS,
16
- RESUME,
17
- CANCEL,
18
- CLOSED,
17
+ CANCEL_SELECTED_MODAL,
18
+ RESUME_SELECTED_MODAL,
19
+ FORCE_UNLOCK_SELECTED_MODAL,
20
+ CONFIRM_MODAL,
19
21
  } from './TasksTableConstants';
20
22
  import { ActionSelectButton } from './Components/ActionSelectButton';
21
23
  import './TasksTablePage.scss';
24
+ import { SelectAllAlert } from './Components/SelectAllAlert';
22
25
 
23
- const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
26
+ const TasksTablePage = ({
27
+ getBreadcrumbs,
28
+ history,
29
+ createHeader,
30
+ selectAllRows,
31
+ showSelectAll,
32
+ modalID,
33
+ openModalAction,
34
+ ...props
35
+ }) => {
24
36
  const url = history.location.pathname + history.location.search;
25
37
  const uriQuery = getURIQuery(url);
26
38
  const onSearch = searchQuery => {
27
39
  resolveSearchQuery(searchQuery, history);
28
- props.getTableItems(url);
29
40
  };
30
41
 
31
- const getSelected = () => {
32
- const selected = props.results.filter(item =>
33
- props.selectedRows.includes(item.id)
34
- );
35
- return selected.map(item => ({
36
- name: item.action,
37
- id: item.id,
38
- isCancelleble: item.availableActions.cancellable,
39
- isResumeble: item.availableActions.resumable,
40
- }));
41
- };
42
+ const { setModalOpen, setModalClosed } = useForemanModal({
43
+ id: CONFIRM_MODAL,
44
+ });
42
45
 
43
- const TaskSelectedAction = (id, name) => {
44
- props.actionSelected(id, name, url);
45
- };
46
+ const openModal = id => openModalAction(id, setModalOpen);
46
47
 
47
48
  return (
48
49
  <div className="tasks-table-wrapper">
49
- <CancelResumeConfirm
50
- closeModal={props.hideSelcetedModal}
51
- action={TaskSelectedAction}
52
- selected={getSelected()}
53
- modalStatus={props.modalStatus}
54
- selectedRowsLen={props.selectedRows.length}
50
+ <ConfirmModal
51
+ id={CONFIRM_MODAL}
52
+ url={url}
53
+ parentTaskID={props.parentTaskID}
54
+ uriQuery={uriQuery}
55
+ setModalClosed={setModalClosed}
55
56
  />
56
57
  <PageLayout
57
58
  searchable
58
59
  searchProps={TASKS_SEARCH_PROPS}
59
60
  onSearch={onSearch}
61
+ header={createHeader(props.actionName)}
60
62
  breadcrumbOptions={getBreadcrumbs(props.actionName)}
61
63
  toastNotifications="foreman-tasks-cancel"
62
64
  toolbarButtons={
63
65
  <React.Fragment>
64
66
  {props.status === STATUS.PENDING && <Spinner size="lg" loading />}
65
67
  <ExportButton
66
- url={addSearchToURL('/foreman_tasks/tasks.csv', uriQuery)}
68
+ url={getCSVurl(url, uriQuery)}
67
69
  title={__('Export All')}
68
70
  />
69
71
  <ActionSelectButton
70
- disabled={props.selectedRows.length < 1}
71
- onCancel={props.showCancelSelcetedModal}
72
- onResume={props.showResumeSelcetedModal}
72
+ disabled={!(props.selectedRows.length || props.allRowsSelected)}
73
+ onCancel={() => openModal(CANCEL_SELECTED_MODAL)}
74
+ onResume={() => openModal(RESUME_SELECTED_MODAL)}
75
+ onForceCancel={() => openModal(FORCE_UNLOCK_SELECTED_MODAL)}
73
76
  />
74
77
  </React.Fragment>
75
78
  }
@@ -78,34 +81,58 @@ const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
78
81
  <TasksDashboard history={history} parentTaskID={props.parentTaskID} />
79
82
  }
80
83
  >
81
- <TasksTable history={history} {...props} />
84
+ <React.Fragment>
85
+ {showSelectAll && props.itemCount >= props.pagination.perPage && (
86
+ <SelectAllAlert
87
+ itemCount={props.itemCount}
88
+ perPage={props.pagination.perPage}
89
+ selectAllRows={selectAllRows}
90
+ unselectAllRows={props.unselectAllRows}
91
+ allRowsSelected={props.allRowsSelected}
92
+ />
93
+ )}
94
+ <TasksTable history={history} {...props} openModal={openModal} />
95
+ </React.Fragment>
82
96
  </PageLayout>
83
97
  </div>
84
98
  );
85
99
  };
86
100
 
87
101
  TasksTablePage.propTypes = {
102
+ allRowsSelected: PropTypes.bool,
103
+ itemCount: PropTypes.number.isRequired,
104
+ pagination: PropTypes.shape({
105
+ perPage: PropTypes.number,
106
+ }),
107
+ selectAllRows: PropTypes.func.isRequired,
88
108
  results: PropTypes.array.isRequired,
89
109
  getTableItems: PropTypes.func.isRequired,
90
110
  getBreadcrumbs: PropTypes.func.isRequired,
91
111
  actionName: PropTypes.string,
92
112
  status: PropTypes.oneOf(Object.keys(STATUS)),
93
113
  history: PropTypes.object.isRequired,
94
- actionSelected: PropTypes.func.isRequired,
95
114
  selectedRows: PropTypes.arrayOf(PropTypes.string),
96
- showResumeSelcetedModal: PropTypes.func.isRequired,
97
- showCancelSelcetedModal: PropTypes.func.isRequired,
98
- hideSelcetedModal: PropTypes.func.isRequired,
99
- modalStatus: PropTypes.oneOf([CANCEL, RESUME, CLOSED]),
100
115
  parentTaskID: PropTypes.string,
116
+ createHeader: PropTypes.func,
117
+ modalID: PropTypes.string,
118
+ openModalAction: PropTypes.func.isRequired,
119
+ showSelectAll: PropTypes.bool,
120
+ unselectAllRows: PropTypes.func.isRequired,
101
121
  };
102
122
 
103
123
  TasksTablePage.defaultProps = {
124
+ pagination: {
125
+ page: 1,
126
+ perPage: 20,
127
+ },
128
+ allRowsSelected: false,
104
129
  actionName: '',
105
130
  status: STATUS.PENDING,
106
131
  selectedRows: [],
107
- modalStatus: CLOSED,
108
132
  parentTaskID: null,
133
+ createHeader: () => __('Tasks'),
134
+ showSelectAll: false,
135
+ modalID: '',
109
136
  };
110
137
 
111
138
  export default TasksTablePage;