foreman-tasks 2.0.0 → 3.0.2

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/js_tests.yml +31 -0
  3. data/.github/workflows/ruby_tests.yml +74 -0
  4. data/.rubocop.yml +12 -4
  5. data/.rubocop_todo.yml +32 -25
  6. data/Gemfile +5 -0
  7. data/app/controllers/foreman_tasks/api/tasks_controller.rb +36 -60
  8. data/app/controllers/foreman_tasks/concerns/parameters/triggering.rb +1 -1
  9. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +7 -0
  10. data/app/controllers/foreman_tasks/tasks_controller.rb +6 -3
  11. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +3 -3
  12. data/app/lib/actions/proxy_action.rb +1 -1
  13. data/app/models/foreman_tasks/recurring_logic.rb +1 -1
  14. data/app/models/foreman_tasks/task.rb +11 -0
  15. data/app/models/foreman_tasks/task/dynflow_task.rb +29 -33
  16. data/app/models/foreman_tasks/task/status_explicator.rb +1 -1
  17. data/app/models/foreman_tasks/triggering.rb +1 -1
  18. data/app/models/setting/foreman_tasks.rb +9 -9
  19. data/app/services/foreman_tasks/dashboard_table_filter.rb +5 -1
  20. data/app/views/foreman_tasks/api/tasks/index.json.rabl +2 -0
  21. data/app/views/foreman_tasks/api/tasks/show.json.rabl +2 -0
  22. data/app/views/foreman_tasks/layouts/react.html.erb +1 -2
  23. data/app/views/foreman_tasks/recurring_logics/index.html.erb +3 -1
  24. data/app/views/foreman_tasks/tasks/show.html.erb +1 -6
  25. data/config/routes.rb +2 -1
  26. data/db/migrate/20200517215015_rename_bookmarks_controller.rb +2 -2
  27. data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +9 -0
  28. data/db/seeds.d/30-notification_blueprints.rb +7 -7
  29. data/db/seeds.d/61-foreman_tasks_bookmarks.rb +1 -1
  30. data/foreman-tasks.gemspec +1 -0
  31. data/lib/foreman_tasks/cleaner.rb +4 -6
  32. data/lib/foreman_tasks/dynflow/configuration.rb +1 -1
  33. data/lib/foreman_tasks/dynflow/persistence.rb +4 -6
  34. data/lib/foreman_tasks/engine.rb +2 -7
  35. data/lib/foreman_tasks/tasks/cleanup.rake +2 -2
  36. data/lib/foreman_tasks/tasks/dynflow.rake +6 -0
  37. data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
  38. data/lib/foreman_tasks/version.rb +1 -1
  39. data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
  40. data/locale/en/foreman_tasks.po +50 -20
  41. data/locale/foreman_tasks.pot +173 -126
  42. data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
  43. data/locale/fr/foreman_tasks.po +817 -0
  44. data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
  45. data/locale/ja/foreman_tasks.po +817 -0
  46. data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
  47. data/locale/zh_CN/foreman_tasks.po +816 -0
  48. data/package.json +1 -1
  49. data/script/npm_link_foreman_js.sh +26 -0
  50. data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
  51. data/test/controllers/api/tasks_controller_test.rb +17 -7
  52. data/test/controllers/tasks_controller_test.rb +6 -6
  53. data/test/core/unit/runner_test.rb +20 -20
  54. data/test/core/unit/task_launcher_test.rb +8 -8
  55. data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +7 -7
  56. data/test/helpers/foreman_tasks/tasks_helper_test.rb +3 -3
  57. data/test/lib/actions/middleware/keep_current_request_id_test.rb +3 -3
  58. data/test/support/history_tasks_builder.rb +1 -1
  59. data/test/tasks/generate_task_actions_test.rb +1 -1
  60. data/test/unit/actions/action_with_sub_plans_test.rb +2 -2
  61. data/test/unit/actions/bulk_action_test.rb +6 -6
  62. data/test/unit/actions/proxy_action_test.rb +20 -20
  63. data/test/unit/actions/recurring_action_test.rb +30 -32
  64. data/test/unit/cleaner_test.rb +24 -24
  65. data/test/unit/dashboard_table_filter_test.rb +5 -5
  66. data/test/unit/otp_manager_test.rb +2 -2
  67. data/test/unit/proxy_selector_test.rb +9 -9
  68. data/test/unit/recurring_logic_test.rb +32 -32
  69. data/test/unit/remote_task_test.rb +2 -2
  70. data/test/unit/task_groups_test.rb +4 -4
  71. data/test/unit/task_test.rb +18 -18
  72. data/test/unit/triggering_test.rb +8 -8
  73. data/test/unit/troubleshooting_help_generator_test.rb +6 -6
  74. data/test/unit/ui_notifications_test.rb +11 -11
  75. data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +2 -2
  76. data/webpack/ForemanTasks/Components/TaskActions/index.js +1 -1
  77. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +17 -3
  78. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -153
  79. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +168 -0
  80. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +6 -7
  81. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +48 -0
  82. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +8 -1
  83. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +13 -70
  84. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
  85. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +1 -1
  86. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +78 -208
  87. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +212 -0
  88. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +8 -4
  89. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +100 -53
  90. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +13 -14
  91. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +57 -95
  92. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -12
  93. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +57 -28
  94. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +8 -0
  95. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +8 -1
  96. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +6 -6
  97. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +84 -12
  98. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +25 -21
  99. data/webpack/ForemanTasks/Components/TaskDetails/index.js +8 -3
  100. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +4 -0
  101. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +53 -0
  102. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +14 -0
  103. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +27 -19
  104. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +14 -0
  105. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -34
  106. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/{StoppedTasksCardHelper.js → StoppedTasksCardTable.js} +28 -1
  107. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +54 -0
  108. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +48 -0
  109. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +60 -1367
  110. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +960 -0
  111. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +14 -11
  112. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +1 -1
  113. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +2 -0
  114. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +17 -11
  115. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +2 -2
  116. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +26 -14
  117. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +14 -11
  118. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +38 -22
  119. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +1 -0
  120. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +1 -0
  121. data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +2 -0
  122. data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +25 -8
  123. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +3 -3
  124. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +6 -3
  125. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +0 -10
  126. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +1 -0
  127. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +15 -2
  128. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +1 -0
  129. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +2 -1
  130. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +1 -0
  131. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +48 -0
  132. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +1 -0
  133. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +39 -7
  134. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionCellFormatter.test.js.snap +1 -0
  135. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionCellFormatter.test.js.snap +2 -0
  136. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionCellFormatter.test.js +1 -1
  137. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionCellFormatter.test.js +1 -1
  138. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionCellFormatter.js +10 -7
  139. data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionCellFormatter.js +7 -0
  140. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +39 -31
  141. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +17 -8
  142. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +8 -0
  143. data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
  144. data/webpack/ForemanTasks/ForemanTasksReducers.js +0 -2
  145. data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
  146. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +10 -0
  147. data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
  148. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +5 -0
  149. metadata +35 -17
  150. data/.travis.yml +0 -5
  151. data/app/assets/stylesheets/foreman_tasks/tasks.scss +0 -9
  152. data/script/travis_run_js_tests.sh +0 -7
  153. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -38
  154. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +0 -33
  155. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +0 -26
  156. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +0 -122
  157. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +0 -67
  158. data/webpack/__mocks__/foremanReact/API.js +0 -7
@@ -57,17 +57,20 @@ exports[`TasksCardsGrid render with minimal props 1`] = `
57
57
  className=""
58
58
  data={
59
59
  Object {
60
- "error": Object {
61
- "last": 0,
62
- "total": 0,
63
- },
64
- "success": Object {
65
- "last": 0,
66
- "total": 0,
67
- },
68
- "warning": Object {
69
- "last": 0,
70
- "total": 0,
60
+ "other": 0,
61
+ "results": Object {
62
+ "error": Object {
63
+ "last": 0,
64
+ "total": 0,
65
+ },
66
+ "success": Object {
67
+ "last": 0,
68
+ "total": 0,
69
+ },
70
+ "warning": Object {
71
+ "last": 0,
72
+ "total": 0,
73
+ },
71
74
  },
72
75
  }
73
76
  }
@@ -1,4 +1,4 @@
1
- import API from 'foremanReact/API';
1
+ import { API } from 'foremanReact/redux/API';
2
2
  import { timeToHoursNumber, resolveQuery } from './TasksDashboardHelper';
3
3
  import {
4
4
  FOREMAN_TASKS_DASHBOARD_INIT,
@@ -11,6 +11,7 @@ export const TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS = {
11
11
  ERROR: 'error',
12
12
  WARNING: 'warning',
13
13
  SUCCESS: 'success',
14
+ OTHER: 'other',
14
15
  };
15
16
 
16
17
  export const TASKS_DASHBOARD_AVAILABLE_QUERY_MODES = {
@@ -44,6 +45,7 @@ export const TASKS_DASHBOARD_QUERY_VALUES_TEXT = {
44
45
  [TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS.ERROR]: __('error'),
45
46
  [TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS.WARNING]: __('warning'),
46
47
  [TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS.SUCCESS]: __('success'),
48
+ [TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS.OTHER]: __('other'),
47
49
  [TASKS_DASHBOARD_AVAILABLE_QUERY_MODES.LAST]: __('last'),
48
50
  [TASKS_DASHBOARD_AVAILABLE_QUERY_MODES.OLDER]: __('older'),
49
51
  [TASKS_DASHBOARD_AVAILABLE_TIMES.H24]: __('24h'),
@@ -12,6 +12,9 @@ export const selectTime = state =>
12
12
 
13
13
  export const selectQuery = state => selectTasksDashboard(state).query || {};
14
14
 
15
+ export const calcStoppedOther = data =>
16
+ (data?.cancelled?.total || 0) + (data?.pending?.total || 0);
17
+
15
18
  export const selectTasksSummary = state => {
16
19
  const { running, paused, stopped, scheduled } =
17
20
  selectTasksDashboard(state).tasksSummary || TASKS_SUMMARY_ZERO;
@@ -26,18 +29,21 @@ export const selectTasksSummary = state => {
26
29
  older: paused.total - paused.recent,
27
30
  },
28
31
  stopped: {
29
- error: {
30
- total: stopped.by_result.error.total,
31
- last: stopped.by_result.error.recent,
32
- },
33
- warning: {
34
- total: stopped.by_result.warning.total,
35
- last: stopped.by_result.warning.recent,
36
- },
37
- success: {
38
- total: stopped.by_result.success.total,
39
- last: stopped.by_result.success.recent,
32
+ results: {
33
+ error: {
34
+ total: stopped.by_result.error.total,
35
+ last: stopped.by_result.error.recent,
36
+ },
37
+ warning: {
38
+ total: stopped.by_result.warning.total,
39
+ last: stopped.by_result.warning.recent,
40
+ },
41
+ success: {
42
+ total: stopped.by_result.success.total,
43
+ last: stopped.by_result.success.recent,
44
+ },
40
45
  },
46
+ other: calcStoppedOther(stopped.by_result),
41
47
  },
42
48
  scheduled: scheduled.total,
43
49
  };
@@ -1,5 +1,5 @@
1
1
  import { testActionSnapshotWithFixtures } from '@theforeman/test';
2
- import API from 'foremanReact/API';
2
+ import { API } from 'foremanReact/redux/API';
3
3
  import { timeToHoursNumber } from '../TasksDashboardHelper';
4
4
  import {
5
5
  initializeDashboard,
@@ -14,7 +14,7 @@ import {
14
14
  apiGetMock,
15
15
  } from './TaskDashboard.fixtures';
16
16
 
17
- jest.mock('foremanReact/API');
17
+ jest.mock('foremanReact/redux/API');
18
18
  jest.mock('../TasksDashboardHelper');
19
19
 
20
20
  timeToHoursNumber.mockImplementation(arg => arg);
@@ -4,8 +4,32 @@ import {
4
4
  selectTime,
5
5
  selectQuery,
6
6
  selectTasksSummary,
7
+ calcStoppedOther,
7
8
  } from '../TasksDashboardSelectors';
8
9
 
10
+ const stoppedResult = {
11
+ error: {
12
+ total: 9,
13
+ recent: 1,
14
+ },
15
+ warning: {
16
+ total: 8,
17
+ recent: 2,
18
+ },
19
+ success: {
20
+ total: 7,
21
+ recent: 3,
22
+ },
23
+ cancelled: {
24
+ total: 5,
25
+ recent: 3,
26
+ },
27
+ pending: {
28
+ total: 11,
29
+ recent: 4,
30
+ },
31
+ };
32
+
9
33
  const state = {
10
34
  foremanTasks: {
11
35
  tasksDashboard: {
@@ -21,20 +45,7 @@ const state = {
21
45
  total: 9,
22
46
  },
23
47
  stopped: {
24
- by_result: {
25
- error: {
26
- total: 9,
27
- recent: 1,
28
- },
29
- warning: {
30
- total: 8,
31
- recent: 2,
32
- },
33
- success: {
34
- total: 7,
35
- recent: 3,
36
- },
37
- },
48
+ by_result: stoppedResult,
38
49
  },
39
50
  scheduled: {
40
51
  total: 6,
@@ -55,6 +66,7 @@ const fixtures = {
55
66
  'should select tasks-summary': () => selectTasksSummary(state),
56
67
  'should select tasks-summary when state is empty': () =>
57
68
  selectTasksSummary({}),
69
+ 'should calcStoppedOther': () => calcStoppedOther(stoppedResult),
58
70
  };
59
71
 
60
72
  describe('TasksDashboard - Selectors', () =>
@@ -24,17 +24,20 @@ exports[`TasksDashboard rendering render without Props 1`] = `
24
24
  },
25
25
  "scheduled": 0,
26
26
  "stopped": Object {
27
- "error": Object {
28
- "last": 0,
29
- "total": 0,
30
- },
31
- "success": Object {
32
- "last": 0,
33
- "total": 0,
34
- },
35
- "warning": Object {
36
- "last": 0,
37
- "total": 0,
27
+ "other": 0,
28
+ "results": Object {
29
+ "error": Object {
30
+ "last": 0,
31
+ "total": 0,
32
+ },
33
+ "success": Object {
34
+ "last": 0,
35
+ "total": 0,
36
+ },
37
+ "warning": Object {
38
+ "last": 0,
39
+ "total": 0,
40
+ },
38
41
  },
39
42
  },
40
43
  }
@@ -1,5 +1,7 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`TasksDashboard - Selectors should calcStoppedOther 1`] = `16`;
4
+
3
5
  exports[`TasksDashboard - Selectors should select query 1`] = `"some-query"`;
4
6
 
5
7
  exports[`TasksDashboard - Selectors should select query when state is empty 1`] = `Object {}`;
@@ -21,10 +23,18 @@ Object {
21
23
  },
22
24
  "stopped": Object {
23
25
  "by_result": Object {
26
+ "cancelled": Object {
27
+ "recent": 3,
28
+ "total": 5,
29
+ },
24
30
  "error": Object {
25
31
  "recent": 1,
26
32
  "total": 9,
27
33
  },
34
+ "pending": Object {
35
+ "recent": 4,
36
+ "total": 11,
37
+ },
28
38
  "success": Object {
29
39
  "recent": 3,
30
40
  "total": 7,
@@ -54,17 +64,20 @@ Object {
54
64
  },
55
65
  "scheduled": 6,
56
66
  "stopped": Object {
57
- "error": Object {
58
- "last": 1,
59
- "total": 9,
60
- },
61
- "success": Object {
62
- "last": 3,
63
- "total": 7,
64
- },
65
- "warning": Object {
66
- "last": 2,
67
- "total": 8,
67
+ "other": 16,
68
+ "results": Object {
69
+ "error": Object {
70
+ "last": 1,
71
+ "total": 9,
72
+ },
73
+ "success": Object {
74
+ "last": 3,
75
+ "total": 7,
76
+ },
77
+ "warning": Object {
78
+ "last": 2,
79
+ "total": 8,
80
+ },
68
81
  },
69
82
  },
70
83
  }
@@ -82,17 +95,20 @@ Object {
82
95
  },
83
96
  "scheduled": 0,
84
97
  "stopped": Object {
85
- "error": Object {
86
- "last": 0,
87
- "total": 0,
88
- },
89
- "success": Object {
90
- "last": 0,
91
- "total": 0,
92
- },
93
- "warning": Object {
94
- "last": 0,
95
- "total": 0,
98
+ "other": 0,
99
+ "results": Object {
100
+ "error": Object {
101
+ "last": 0,
102
+ "total": 0,
103
+ },
104
+ "success": Object {
105
+ "last": 0,
106
+ "total": 0,
107
+ },
108
+ "warning": Object {
109
+ "last": 0,
110
+ "total": 0,
111
+ },
96
112
  },
97
113
  },
98
114
  }
@@ -27,6 +27,7 @@ export const selectSelectedTasks = state => {
27
27
  id: item.id,
28
28
  isCancellable: item.availableActions.cancellable,
29
29
  isResumable: item.availableActions.resumable,
30
+ canEdit: item.canEdit,
30
31
  }));
31
32
  };
32
33
 
@@ -22,6 +22,7 @@ const state = {
22
22
  id: 1,
23
23
  action: 'action1',
24
24
  available_actions: { cancellable: true },
25
+ can_edit: true,
25
26
  },
26
27
  { id: 2, action: 'action2', available_actions: { resumable: true } },
27
28
  ],
@@ -15,12 +15,14 @@ exports[`TasksDashboard - Selectors should select selectedRowsLen some 1`] = `3`
15
15
  exports[`TasksDashboard - Selectors should select selectedTasks 1`] = `
16
16
  Array [
17
17
  Object {
18
+ "canEdit": true,
18
19
  "id": 1,
19
20
  "isCancellable": true,
20
21
  "isResumable": undefined,
21
22
  "name": "action1",
22
23
  },
23
24
  Object {
25
+ "canEdit": undefined,
24
26
  "id": 2,
25
27
  "isCancellable": undefined,
26
28
  "isResumable": true,
@@ -1,4 +1,4 @@
1
- import API from 'foremanReact/API';
1
+ import { API } from 'foremanReact/redux/API';
2
2
  import { addToast } from 'foremanReact/redux/actions/toasts';
3
3
  import { translate as __, sprintf } from 'foremanReact/common/I18n';
4
4
  import {
@@ -63,7 +63,7 @@ export const bulkResumeById = ({
63
63
  url,
64
64
  parentTaskID,
65
65
  }) => async dispatch => {
66
- const resumeTasks = selected.filter(task => task.isResumable);
66
+ const resumeTasks = selected.filter(task => task.isResumable && task.canEdit);
67
67
  if (resumeTasks.length < selected.length)
68
68
  dispatch(
69
69
  addToast(
@@ -87,7 +87,7 @@ export const bulkResumeById = ({
87
87
  });
88
88
  });
89
89
  if (data.resumed) {
90
- reloadPage(url, parentTaskID, dispatch);
90
+ reloadPage(url, parentTaskID)(dispatch);
91
91
  }
92
92
  } catch (error) {
93
93
  handleErrorResume(error, dispatch);
@@ -135,7 +135,9 @@ export const bulkCancelById = ({
135
135
  url,
136
136
  parentTaskID,
137
137
  }) => async dispatch => {
138
- const cancelTasks = selected.filter(task => task.isCancellable);
138
+ const cancelTasks = selected.filter(
139
+ task => task.isCancellable && task.canEdit
140
+ );
139
141
  if (cancelTasks.length < selected.length)
140
142
  dispatch(
141
143
  addToast(
@@ -160,7 +162,7 @@ export const bulkCancelById = ({
160
162
  });
161
163
  });
162
164
  if (data.cancelled) {
163
- reloadPage(url, parentTaskID, dispatch);
165
+ reloadPage(url, parentTaskID)(dispatch);
164
166
  }
165
167
  } catch (error) {
166
168
  handleErrorCancel(error, dispatch);
@@ -185,6 +187,18 @@ export const bulkForceCancelById = ({
185
187
  parentTaskID,
186
188
  }) => async dispatch => {
187
189
  const stopTasks = selected.filter(task => task.state !== 'stopped');
190
+ const authorisedTasks = stopTasks.filter(task => task.canEdit);
191
+ if (authorisedTasks.length < stopTasks.length)
192
+ dispatch(
193
+ addToast(
194
+ warningToastData(
195
+ sprintf(
196
+ 'User has no permission for %s task(s)',
197
+ stopTasks.length - authorisedTasks.length
198
+ )
199
+ )
200
+ )
201
+ );
188
202
  if (stopTasks.length < selected.length)
189
203
  dispatch(
190
204
  addToast(
@@ -196,10 +210,13 @@ export const bulkForceCancelById = ({
196
210
  )
197
211
  )
198
212
  );
199
- if (stopTasks.length > 0) {
213
+ if (authorisedTasks.length > 0) {
200
214
  dispatch({ type: TASKS_FORCE_CANCEL_REQUEST });
201
215
  try {
202
- const { data } = await bulkByIdRequest(stopTasks, BULK_FORCE_CANCEL_PATH);
216
+ const { data } = await bulkByIdRequest(
217
+ authorisedTasks,
218
+ BULK_FORCE_CANCEL_PATH
219
+ );
203
220
  dispatch({ type: TASKS_FORCE_CANCEL_SUCCESS });
204
221
  if (data.stopped_length) {
205
222
  dispatch(
@@ -219,7 +236,7 @@ export const bulkForceCancelById = ({
219
236
  )
220
237
  );
221
238
  if (data.stopped_length > 0) {
222
- reloadPage(url, parentTaskID, dispatch);
239
+ reloadPage(url, parentTaskID)(dispatch);
223
240
  }
224
241
  } catch (error) {
225
242
  handleErrorForceCancel(error, dispatch);
@@ -22,7 +22,7 @@ import {
22
22
  export const getTableItems = url =>
23
23
  getTableItemsAction(TASKS_TABLE_ID, getURIQuery(url), getApiPathname(url));
24
24
 
25
- export const reloadPage = (url, parentTaskID, dispatch) => {
25
+ export const reloadPage = (url, parentTaskID) => dispatch => {
26
26
  dispatch(getTableItems(url));
27
27
  dispatch(fetchTasksSummary(getURIQuery(url).time, parentTaskID));
28
28
  };
@@ -34,7 +34,7 @@ export const cancelTask = ({
34
34
  parentTaskID,
35
35
  }) => async dispatch => {
36
36
  await dispatch(cancelTaskRequest(taskId, taskName));
37
- reloadPage(url, parentTaskID, dispatch);
37
+ reloadPage(url, parentTaskID)(dispatch);
38
38
  };
39
39
 
40
40
  export const resumeTask = ({
@@ -44,7 +44,7 @@ export const resumeTask = ({
44
44
  parentTaskID,
45
45
  }) => async dispatch => {
46
46
  await dispatch(resumeTaskRequest(taskId, taskName));
47
- reloadPage(url, parentTaskID, dispatch);
47
+ reloadPage(url, parentTaskID)(dispatch);
48
48
  };
49
49
 
50
50
  export const forceCancelTask = ({
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { getURIsearch } from 'foremanReact/common/urlHelpers';
4
- import { Spinner } from 'patternfly-react';
4
+ import { Spinner, Button, Icon } from 'patternfly-react';
5
5
  import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
6
6
  import { translate as __ } from 'foremanReact/common/I18n';
7
7
  import { getURIQuery } from 'foremanReact/common/helpers';
@@ -60,10 +60,12 @@ const TasksTablePage = ({
60
60
  onSearch={onSearch}
61
61
  header={createHeader(props.actionName)}
62
62
  breadcrumbOptions={getBreadcrumbs(props.actionName)}
63
- toastNotifications="foreman-tasks-cancel"
64
63
  toolbarButtons={
65
64
  <React.Fragment>
66
- {props.status === STATUS.PENDING && <Spinner size="lg" loading />}
65
+ <Button onClick={() => props.reloadPage(url, props.parentTaskID)}>
66
+ <Icon type="fa" name="refresh" /> {__('Refresh Data')}
67
+ </Button>
68
+ {props.status === STATUS.PENDING && <Spinner size="md" loading />}
67
69
  <ExportButton
68
70
  url={getCSVurl(url, uriQuery)}
69
71
  title={__('Export All')}
@@ -118,6 +120,7 @@ TasksTablePage.propTypes = {
118
120
  openModalAction: PropTypes.func.isRequired,
119
121
  showSelectAll: PropTypes.bool,
120
122
  unselectAllRows: PropTypes.func.isRequired,
123
+ reloadPage: PropTypes.func.isRequired,
121
124
  };
122
125
 
123
126
  TasksTablePage.defaultProps = {