foreman-tasks 0.17.2 → 0.17.3

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/foreman_tasks/foreman_tasks.js +3 -0
  3. data/app/assets/stylesheets/foreman_tasks/{application.css.scss → foreman_tasks.css} +0 -5
  4. data/app/assets/stylesheets/foreman_tasks/{tasks.css.scss → tasks.scss} +0 -0
  5. data/app/controllers/foreman_tasks/api/tasks_controller.rb +6 -4
  6. data/app/controllers/foreman_tasks/tasks_controller.rb +6 -1
  7. data/app/models/foreman_tasks/concerns/user_extensions.rb +14 -0
  8. data/app/views/common/_trigger_form.html.erb +2 -2
  9. data/app/views/foreman_tasks/tasks/show.html.erb +1 -1
  10. data/config/routes.rb +2 -0
  11. data/lib/foreman_tasks/engine.rb +5 -11
  12. data/lib/foreman_tasks/version.rb +1 -1
  13. data/test/unit/task_test.rb +8 -0
  14. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +11 -4
  15. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +5 -3
  16. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TaskDashboard.fixtures.js +93 -0
  17. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +9 -10
  18. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/{TasksDashboardSelectors.test..js → TasksDashboardSelectors.test.js} +30 -28
  19. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardActions.test.js.snap +91 -1
  20. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +103 -0
  21. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +9 -2
  22. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +5 -2
  23. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +4 -4
  24. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +5 -3
  25. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +1 -0
  26. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +1 -0
  27. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +1 -0
  28. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +4 -2
  29. metadata +9 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 619dcecc5e332cffdf42333007062050274669c3f4e9c312e99ef7ea5c34bf4c
4
- data.tar.gz: 9af4ff95aff9ceaefc7b0cf18cfa63aea31636771b76ad32b87b20e847ef0edf
3
+ metadata.gz: 95c9f8364b129d0fcaccad4e7f8673deb1ff18ab1d5e47b74f2c85fe366af7a3
4
+ data.tar.gz: c36bb9f6aedcab3dc1c590797c09b470dd3097c0295a00f9e61dd1b695a011dd
5
5
  SHA512:
6
- metadata.gz: f9e7f4627493ff41d015766564442406357820b4f29a678eb47d26d41f540926c9ddd0050e569ca6e08a555c18b995a9e4c0daf8d32167619c1ce408689bc38e
7
- data.tar.gz: 9a758f517b217ae729c3442aeb0d8808bad99b29cbe329e2ab833473a99152d24734109780cb195f8ed92f3db5bee3ec3ceac607f8e62ee7274d28a051371280
6
+ metadata.gz: 453f74187dd7bc334ff64dfc0544a317dd60b06e23c83057577a8f346f70281f2a8b71749d200f5edbb09c810f8ec241965a2a5311a7fb849d26166f14a391ae
7
+ data.tar.gz: 3a256485bd5f4c92a39cad572c8b402105c0fb5768c173390ea33e75fbfc590899e8c73f455c157f69d48328308e8c88da0a14038f07d659fd8cd46597943d21
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require foreman_tasks/trigger_form.js
3
+ */
@@ -11,8 +11,3 @@
11
11
  *= require_self
12
12
  *= require_tree .
13
13
  */
14
-
15
- div.form-group div.trigger_fields {
16
- margin-top: 15px;
17
- }
18
-
@@ -37,6 +37,8 @@ module ForemanTasks
37
37
  parent_task = resource_scope.find(params[:id])
38
38
  filtered_scope = parent_task.sub_tasks
39
39
  action_name = { "action_name" => parent_task.action }
40
+
41
+ filtered_scope = DashboardTableFilter.new(filtered_scope, params).scope
40
42
  render :json => action_name.merge(tasks_list(filtered_scope))
41
43
  end
42
44
 
@@ -253,6 +255,10 @@ module ForemanTasks
253
255
  task_hash
254
256
  end
255
257
 
258
+ def resource_class
259
+ @resource_class ||= ForemanTasks::Task
260
+ end
261
+
256
262
  def find_task
257
263
  @task = resource_scope.find(params[:id])
258
264
  end
@@ -261,10 +267,6 @@ module ForemanTasks
261
267
  @resource_scope ||= ForemanTasks::Task.authorized("#{action_permission}_foreman_tasks")
262
268
  end
263
269
 
264
- def resource_class
265
- @resource_class ||= ForemanTasks::Task
266
- end
267
-
268
270
  def action_permission
269
271
  case params[:action]
270
272
  when 'bulk_search', 'summary', 'details', 'sub_tasks'
@@ -20,6 +20,11 @@ module ForemanTasks
20
20
  render json: Task::Summarizer.new(Task.where(:id => scope), params[:recent_timeframe].to_i).summary
21
21
  end
22
22
 
23
+ def summary_sub_tasks
24
+ filtered_scope = resource_base.find(params[:id]).sub_tasks
25
+ render :json => Task::Summarizer.new(filtered_scope, params[:recent_timeframe].to_i).summary
26
+ end
27
+
23
28
  def sub_tasks
24
29
  # @task is used when rendering breadcrumbs
25
30
  @task = resource_base.find(params[:id])
@@ -108,7 +113,7 @@ module ForemanTasks
108
113
 
109
114
  def action_permission
110
115
  case params[:action]
111
- when 'sub_tasks', 'summary'
116
+ when 'sub_tasks', 'summary', 'summary_sub_tasks'
112
117
  :view
113
118
  when 'resume', 'unlock', 'force_unlock', 'cancel_step', 'cancel', 'abort'
114
119
  :edit
@@ -0,0 +1,14 @@
1
+ module ForemanTasks
2
+ module Concerns
3
+ module UserExtensions
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # rubocop:disable Rails/ReflectionClassName
8
+ has_many :tasks, :dependent => :nullify,
9
+ :class_name => ::ForemanTasks::Task.name
10
+ # rubocop:enable Rails/ReflectionClassName
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,8 +1,8 @@
1
1
  <div class="form-group ">
2
2
  <label class="col-md-2 control-label"><%= _('Schedule') %></label>
3
3
  <div class="col-md-6">
4
- <% javascript 'foreman_tasks/trigger_form' %>
5
- <% stylesheet 'foreman_tasks/trigger_form' %>
4
+ <% javascript 'foreman_tasks/foreman_tasks' %>
5
+ <% stylesheet 'foreman_tasks/foreman_tasks' %>
6
6
 
7
7
  <%= javascript_tag do %>
8
8
  $(function() { trigger_form_selector_binds('<%= f.options[:html][:id] %>','<%= f.object_name %>') });
@@ -1,4 +1,4 @@
1
- <% stylesheet 'foreman_tasks/tasks' %>
1
+ <% stylesheet 'foreman_tasks/foreman_tasks' %>
2
2
  <% content_for(:javascripts) do %>
3
3
  <%= webpacked_plugins_js_for :'foreman-tasks' %>
4
4
  <% end %>
@@ -12,6 +12,7 @@ Foreman::Application.routes.draw do
12
12
  collection do
13
13
  get 'auto_complete_search'
14
14
  get '/summary/:recent_timeframe', action: 'summary'
15
+ get '/summary/:id/sub_tasks/:recent_timeframe', action: 'summary_sub_tasks'
15
16
  end
16
17
  member do
17
18
  post :abort
@@ -49,6 +50,7 @@ Foreman::Application.routes.draw do
49
50
  post :bulk_search
50
51
  post :bulk_resume
51
52
  get :summary
53
+ get '/summary/:id/sub_tasks/', action: 'summary_sub_tasks'
52
54
  post :callback
53
55
  end
54
56
  end
@@ -14,15 +14,8 @@ module ForemanTasks
14
14
  end
15
15
  end
16
16
 
17
- # Precompile any JS or CSS files under app/assets/
18
- # If requiring files from each other, list them explicitly here to avoid precompiling the same
19
- # content twice.
20
- assets_to_precompile =
21
- Dir.chdir(root) do
22
- Dir['app/assets/javascripts/**/*', 'app/assets/stylesheets/**/*'].map do |f|
23
- f.split(File::SEPARATOR, 4).last
24
- end
25
- end
17
+ assets_to_precompile = %w[foreman_tasks/foreman_tasks.css
18
+ foreman_tasks/foreman_tasks.js]
26
19
 
27
20
  initializer 'foreman_tasks.assets.precompile' do |app|
28
21
  app.config.assets.precompile += assets_to_precompile
@@ -56,9 +49,9 @@ module ForemanTasks
56
49
  :last => true
57
50
 
58
51
  security_block :foreman_tasks do |_map|
59
- permission :view_foreman_tasks, { :'foreman_tasks/tasks' => [:auto_complete_search, :sub_tasks, :index, :summary, :show],
52
+ permission :view_foreman_tasks, { :'foreman_tasks/tasks' => [:auto_complete_search, :sub_tasks, :index, :summary, :summary_sub_tasks, :show],
60
53
  :'foreman_tasks/react' => [:index],
61
- :'foreman_tasks/api/tasks' => [:bulk_search, :show, :index, :summary, :details, :sub_tasks] }, :resource_type => ForemanTasks::Task.name
54
+ :'foreman_tasks/api/tasks' => [:bulk_search, :show, :index, :summary, :summary_sub_tasks, :details, :sub_tasks] }, :resource_type => ForemanTasks::Task.name
62
55
  permission :edit_foreman_tasks, { :'foreman_tasks/tasks' => [:resume, :unlock, :force_unlock, :cancel_step, :cancel, :abort],
63
56
  :'foreman_tasks/api/tasks' => [:bulk_resume] }, :resource_type => ForemanTasks::Task.name
64
57
 
@@ -149,6 +142,7 @@ module ForemanTasks
149
142
  ForemanTasks.dynflow.eager_load_actions! if ForemanTasks.dynflow.initialized?
150
143
 
151
144
  Authorizer.send(:prepend, AuthorizerExt)
145
+ User.send(:include, ForemanTasks::Concerns::UserExtensions)
152
146
  end
153
147
 
154
148
  rake_tasks do
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '0.17.2'.freeze
2
+ VERSION = '0.17.3'.freeze
3
3
  end
@@ -95,6 +95,14 @@ class TasksTest < ActiveSupport::TestCase
95
95
  end
96
96
  end
97
97
 
98
+ describe 'users' do
99
+ test 'users can be deleted even if they have tasks assigned' do
100
+ user = FactoryBot.create(:user)
101
+ FactoryBot.create(:some_task, :user => user)
102
+ user.destroy!
103
+ end
104
+ end
105
+
98
106
  describe 'state_updated_at' do
99
107
  it 'updates the state_updated_at when the state changes' do
100
108
  task = FactoryBot.create(:some_task)
@@ -14,7 +14,12 @@ import './TasksDashboard.scss';
14
14
 
15
15
  class TasksDashboard extends React.Component {
16
16
  componentDidMount() {
17
- const { time, initializeDashboard, fetchTasksSummary } = this.props;
17
+ const {
18
+ time,
19
+ initializeDashboard,
20
+ fetchTasksSummary,
21
+ parentTaskID,
22
+ } = this.props;
18
23
  const query = getQueryFromUrl();
19
24
 
20
25
  initializeDashboard({
@@ -24,15 +29,15 @@ class TasksDashboard extends React.Component {
24
29
 
25
30
  // dont fetch if time is going to be changed
26
31
  if (!query.time || query.time === time) {
27
- fetchTasksSummary(time);
32
+ fetchTasksSummary(time, parentTaskID);
28
33
  }
29
34
  }
30
35
 
31
36
  componentDidUpdate(prevProps) {
32
- const { time, fetchTasksSummary } = this.props;
37
+ const { time, fetchTasksSummary, parentTaskID } = this.props;
33
38
 
34
39
  if (time !== prevProps.time) {
35
- fetchTasksSummary(time);
40
+ fetchTasksSummary(time, parentTaskID);
36
41
  }
37
42
  }
38
43
 
@@ -65,6 +70,7 @@ TasksDashboard.propTypes = {
65
70
  updateQuery: PropTypes.func,
66
71
  fetchTasksSummary: PropTypes.func,
67
72
  history: PropTypes.object.isRequired,
73
+ parentTaskID: PropTypes.string,
68
74
  };
69
75
 
70
76
  TasksDashboard.defaultProps = {
@@ -75,6 +81,7 @@ TasksDashboard.defaultProps = {
75
81
  updateTime: noop,
76
82
  updateQuery: noop,
77
83
  fetchTasksSummary: noop,
84
+ parentTaskID: '',
78
85
  };
79
86
 
80
87
  export default TasksDashboard;
@@ -32,13 +32,15 @@ export const updateQuery = (query, history) => (dispatch, getState) => {
32
32
  });
33
33
  };
34
34
 
35
- export const fetchTasksSummary = time => async dispatch => {
35
+ export const fetchTasksSummary = (time, parentTaskID) => async dispatch => {
36
36
  try {
37
37
  dispatch(startRequest());
38
38
 
39
39
  const hours = timeToHoursNumber(time);
40
-
41
- const { data } = await API.get(`/foreman_tasks/tasks/summary/${hours}`);
40
+ const url = parentTaskID
41
+ ? `/foreman_tasks/tasks/summary/${parentTaskID}/sub_tasks/${hours}`
42
+ : `/foreman_tasks/tasks/summary/${hours}`;
43
+ const { data } = await API.get(url);
42
44
 
43
45
  return dispatch(requestSuccess(data));
44
46
  } catch (error) {
@@ -0,0 +1,93 @@
1
+ export const correctTime = 'H24';
2
+ export const wrongTime = 'H25';
3
+ export const parentTaskID = 7;
4
+ export const taskSummary = {
5
+ tasksSummary: {
6
+ running: {
7
+ recent: 0,
8
+ total: 3,
9
+ },
10
+ paused: {
11
+ recent: 0,
12
+ total: 54,
13
+ },
14
+ stopped: {
15
+ recent: 0,
16
+ total: 768,
17
+ by_result: {
18
+ success: {
19
+ recent: 0,
20
+ total: 532,
21
+ },
22
+ error: {
23
+ recent: 0,
24
+ total: 121,
25
+ },
26
+ warning: {
27
+ recent: 0,
28
+ total: 10,
29
+ },
30
+ cancelled: {
31
+ recent: 0,
32
+ total: 105,
33
+ },
34
+ },
35
+ },
36
+ scheduled: {
37
+ recent: 0,
38
+ total: 7,
39
+ },
40
+ },
41
+ };
42
+
43
+ export const subtaskSummary = {
44
+ tasksSummary: {
45
+ running: {
46
+ recent: 0,
47
+ total: 3,
48
+ },
49
+ paused: {
50
+ recent: 0,
51
+ total: 7,
52
+ },
53
+ stopped: {
54
+ recent: 0,
55
+ total: 0,
56
+ by_result: {
57
+ success: {
58
+ recent: 0,
59
+ total: 0,
60
+ },
61
+ error: {
62
+ recent: 0,
63
+ total: 0,
64
+ },
65
+ warning: {
66
+ recent: 0,
67
+ total: 0,
68
+ },
69
+ cancelled: {
70
+ recent: 0,
71
+ total: 0,
72
+ },
73
+ },
74
+ },
75
+ scheduled: {
76
+ recent: 0,
77
+ total: 7,
78
+ },
79
+ },
80
+ };
81
+
82
+ export const apiGetMock = async path => {
83
+ if (path === `/foreman_tasks/tasks/summary/${correctTime}`) {
84
+ return { data: taskSummary };
85
+ } else if (
86
+ path ===
87
+ `/foreman_tasks/tasks/summary/${parentTaskID}/sub_tasks/${correctTime}`
88
+ ) {
89
+ return { data: subtaskSummary };
90
+ }
91
+
92
+ throw new Error('wrong time');
93
+ };
@@ -7,21 +7,18 @@ import {
7
7
  updateQuery,
8
8
  fetchTasksSummary,
9
9
  } from '../TasksDashboardActions';
10
+ import {
11
+ correctTime,
12
+ wrongTime,
13
+ parentTaskID,
14
+ apiGetMock,
15
+ } from './TaskDashboard.fixtures';
10
16
 
11
17
  jest.mock('foremanReact/API');
12
18
  jest.mock('../TasksDashboardHelper');
13
19
 
14
- const correctTime = 'H24';
15
- const wrongTime = 'H25';
16
-
17
20
  timeToHoursNumber.mockImplementation(arg => arg);
18
- API.get.mockImplementation(async path => {
19
- if (path === `/foreman_tasks/tasks/summary/${correctTime}`) {
20
- return { data: 'some-data' };
21
- }
22
-
23
- throw new Error('wrong time');
24
- });
21
+ API.get.mockImplementation(apiGetMock);
25
22
 
26
23
  const fixtures = {
27
24
  'should initialize-dashboard': () =>
@@ -30,6 +27,8 @@ const fixtures = {
30
27
  'should update-query': () => updateQuery('some-query'),
31
28
  'should fetch-tasks-summary and success': () =>
32
29
  fetchTasksSummary(correctTime),
30
+ 'should fetch-tasks-summary for subtasks and success': () =>
31
+ fetchTasksSummary(correctTime, parentTaskID),
33
32
  'should fetch-tasks-summary and fail': () => fetchTasksSummary(wrongTime),
34
33
  };
35
34
 
@@ -7,36 +7,38 @@ import {
7
7
  } from '../TasksDashboardSelectors';
8
8
 
9
9
  const state = {
10
- tasksDashboard: {
11
- time: 'some-time',
12
- query: 'some-query',
13
- tasksSummary: {
14
- running: {
15
- recent: 3,
16
- total: 8,
17
- },
18
- paused: {
19
- recent: 2,
20
- total: 9,
21
- },
22
- stopped: {
23
- by_result: {
24
- error: {
25
- total: 9,
26
- recent: 1,
27
- },
28
- warning: {
29
- total: 8,
30
- recent: 2,
31
- },
32
- success: {
33
- total: 7,
34
- recent: 3,
10
+ foremanTasks: {
11
+ tasksDashboard: {
12
+ time: 'some-time',
13
+ query: 'some-query',
14
+ tasksSummary: {
15
+ running: {
16
+ recent: 3,
17
+ total: 8,
18
+ },
19
+ paused: {
20
+ recent: 2,
21
+ total: 9,
22
+ },
23
+ 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
+ },
35
37
  },
36
38
  },
37
- },
38
- scheduled: {
39
- total: 6,
39
+ scheduled: {
40
+ total: 6,
41
+ },
40
42
  },
41
43
  },
42
44
  },
@@ -25,7 +25,97 @@ Array [
25
25
  ],
26
26
  Array [
27
27
  Object {
28
- "payload": "some-data",
28
+ "payload": Object {
29
+ "tasksSummary": Object {
30
+ "paused": Object {
31
+ "recent": 0,
32
+ "total": 54,
33
+ },
34
+ "running": Object {
35
+ "recent": 0,
36
+ "total": 3,
37
+ },
38
+ "scheduled": Object {
39
+ "recent": 0,
40
+ "total": 7,
41
+ },
42
+ "stopped": Object {
43
+ "by_result": Object {
44
+ "cancelled": Object {
45
+ "recent": 0,
46
+ "total": 105,
47
+ },
48
+ "error": Object {
49
+ "recent": 0,
50
+ "total": 121,
51
+ },
52
+ "success": Object {
53
+ "recent": 0,
54
+ "total": 532,
55
+ },
56
+ "warning": Object {
57
+ "recent": 0,
58
+ "total": 10,
59
+ },
60
+ },
61
+ "recent": 0,
62
+ "total": 768,
63
+ },
64
+ },
65
+ },
66
+ "type": "FOREMAN_TASKS_DASHBOARD_FETCH_TASKS_SUMMARY_SUCCESS",
67
+ },
68
+ ],
69
+ ]
70
+ `;
71
+
72
+ exports[`TasksDashboard - Actions should fetch-tasks-summary for subtasks and success 1`] = `
73
+ Array [
74
+ Array [
75
+ Object {
76
+ "type": "FOREMAN_TASKS_DASHBOARD_FETCH_TASKS_SUMMARY_REQUEST",
77
+ },
78
+ ],
79
+ Array [
80
+ Object {
81
+ "payload": Object {
82
+ "tasksSummary": Object {
83
+ "paused": Object {
84
+ "recent": 0,
85
+ "total": 7,
86
+ },
87
+ "running": Object {
88
+ "recent": 0,
89
+ "total": 3,
90
+ },
91
+ "scheduled": Object {
92
+ "recent": 0,
93
+ "total": 7,
94
+ },
95
+ "stopped": Object {
96
+ "by_result": Object {
97
+ "cancelled": Object {
98
+ "recent": 0,
99
+ "total": 0,
100
+ },
101
+ "error": Object {
102
+ "recent": 0,
103
+ "total": 0,
104
+ },
105
+ "success": Object {
106
+ "recent": 0,
107
+ "total": 0,
108
+ },
109
+ "warning": Object {
110
+ "recent": 0,
111
+ "total": 0,
112
+ },
113
+ },
114
+ "recent": 0,
115
+ "total": 0,
116
+ },
117
+ },
118
+ },
29
119
  "type": "FOREMAN_TASKS_DASHBOARD_FETCH_TASKS_SUMMARY_SUCCESS",
30
120
  },
31
121
  ],
@@ -0,0 +1,103 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TasksDashboard - Selectors should select query 1`] = `"some-query"`;
4
+
5
+ exports[`TasksDashboard - Selectors should select query when state is empty 1`] = `Object {}`;
6
+
7
+ exports[`TasksDashboard - Selectors should select tasks-dashboard 1`] = `
8
+ Object {
9
+ "query": "some-query",
10
+ "tasksSummary": Object {
11
+ "paused": Object {
12
+ "recent": 2,
13
+ "total": 9,
14
+ },
15
+ "running": Object {
16
+ "recent": 3,
17
+ "total": 8,
18
+ },
19
+ "scheduled": Object {
20
+ "total": 6,
21
+ },
22
+ "stopped": Object {
23
+ "by_result": Object {
24
+ "error": Object {
25
+ "recent": 1,
26
+ "total": 9,
27
+ },
28
+ "success": Object {
29
+ "recent": 3,
30
+ "total": 7,
31
+ },
32
+ "warning": Object {
33
+ "recent": 2,
34
+ "total": 8,
35
+ },
36
+ },
37
+ },
38
+ },
39
+ "time": "some-time",
40
+ }
41
+ `;
42
+
43
+ exports[`TasksDashboard - Selectors should select tasks-dashboard when state is empty 1`] = `Object {}`;
44
+
45
+ exports[`TasksDashboard - Selectors should select tasks-summary 1`] = `
46
+ Object {
47
+ "paused": Object {
48
+ "last": 2,
49
+ "older": 7,
50
+ },
51
+ "running": Object {
52
+ "last": 3,
53
+ "older": 5,
54
+ },
55
+ "scheduled": 6,
56
+ "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,
68
+ },
69
+ },
70
+ }
71
+ `;
72
+
73
+ exports[`TasksDashboard - Selectors should select tasks-summary when state is empty 1`] = `
74
+ Object {
75
+ "paused": Object {
76
+ "last": 0,
77
+ "older": 0,
78
+ },
79
+ "running": Object {
80
+ "last": 0,
81
+ "older": 0,
82
+ },
83
+ "scheduled": 0,
84
+ "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,
96
+ },
97
+ },
98
+ }
99
+ `;
100
+
101
+ exports[`TasksDashboard - Selectors should select time 1`] = `"some-time"`;
102
+
103
+ exports[`TasksDashboard - Selectors should select time when state is empty 1`] = `"H24"`;
@@ -4,17 +4,24 @@ import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import TasksTablePage from './';
5
5
 
6
6
  export const SubTasksPage = props => {
7
+ const parentTaskID = props.match.params.id;
7
8
  const getBreadcrumbs = actionName => ({
8
9
  breadcrumbItems: [
9
10
  { caption: __('Tasks'), url: `/foreman_tasks/tasks` },
10
11
  {
11
12
  caption: actionName,
12
- url: `/foreman_tasks/tasks/${props.match.params.id}`,
13
+ url: `/foreman_tasks/tasks/${parentTaskID}`,
13
14
  },
14
15
  { caption: __('Sub tasks') },
15
16
  ],
16
17
  });
17
- return <TasksTablePage getBreadcrumbs={getBreadcrumbs} {...props} />;
18
+ return (
19
+ <TasksTablePage
20
+ getBreadcrumbs={getBreadcrumbs}
21
+ parentTaskID={parentTaskID}
22
+ {...props}
23
+ />
24
+ );
18
25
  };
19
26
 
20
27
  SubTasksPage.propTypes = {
@@ -24,6 +24,7 @@ const TasksTable = ({
24
24
  unselectAllRows,
25
25
  selectRow,
26
26
  unselectRow,
27
+ parentTaskID,
27
28
  }) => {
28
29
  const url = history.location.pathname + history.location.search;
29
30
  const uriQuery = getURIQuery(url);
@@ -82,10 +83,10 @@ const TasksTable = ({
82
83
 
83
84
  const taskActions = {
84
85
  cancel: (id, name) => {
85
- cancelTask(id, name, url);
86
+ cancelTask(id, name, url, parentTaskID);
86
87
  },
87
88
  resume: (id, name) => {
88
- resumeTask(id, name, url);
89
+ resumeTask(id, name, url, parentTaskID);
89
90
  },
90
91
  };
91
92
 
@@ -132,6 +133,7 @@ TasksTable.propTypes = {
132
133
  unselectAllRows: PropTypes.func.isRequired,
133
134
  selectRow: PropTypes.func.isRequired,
134
135
  unselectRow: PropTypes.func.isRequired,
136
+ parentTaskID: PropTypes.string,
135
137
  };
136
138
 
137
139
  TasksTable.defaultProps = {
@@ -142,6 +144,7 @@ TasksTable.defaultProps = {
142
144
  perPage: 20,
143
145
  },
144
146
  selectedRows: [],
147
+ parentTaskID: null,
145
148
  };
146
149
 
147
150
  export default TasksTable;
@@ -19,10 +19,10 @@ import { fetchTasksSummary } from '../TasksDashboard/TasksDashboardActions';
19
19
  export const getTableItems = url =>
20
20
  getTableItemsAction(TASKS_TABLE_ID, getURIQuery(url), getApiPathname(url));
21
21
 
22
- export const cancelTask = (id, name, url) => async dispatch => {
22
+ export const cancelTask = (id, name, url, parentTaskID) => async dispatch => {
23
23
  await dispatch(cancelTaskRequest(id, name));
24
24
  dispatch(getTableItems(url));
25
- dispatch(fetchTasksSummary(getURIQuery(url).time));
25
+ dispatch(fetchTasksSummary(getURIQuery(url).time, parentTaskID));
26
26
  };
27
27
 
28
28
  export const cancelTaskRequest = (id, name) => async dispatch => {
@@ -50,10 +50,10 @@ export const cancelTaskRequest = (id, name) => async dispatch => {
50
50
  }
51
51
  };
52
52
 
53
- export const resumeTask = (id, name, url) => async dispatch => {
53
+ export const resumeTask = (id, name, url, parentTaskID) => async dispatch => {
54
54
  await dispatch(resumeTaskRequest(id, name));
55
55
  dispatch(getTableItems(url));
56
- dispatch(fetchTasksSummary(getURIQuery(url).time));
56
+ dispatch(fetchTasksSummary(getURIQuery(url).time), parentTaskID);
57
57
  };
58
58
 
59
59
  export const resumeTaskRequest = (id, name) => async dispatch => {
@@ -74,7 +74,9 @@ const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
74
74
  </React.Fragment>
75
75
  }
76
76
  searchQuery={getURIsearch()}
77
- beforeToolbarComponent={<TasksDashboard history={history} />}
77
+ beforeToolbarComponent={
78
+ <TasksDashboard history={history} parentTaskID={props.parentTaskID} />
79
+ }
78
80
  >
79
81
  <TasksTable history={history} {...props} />
80
82
  </PageLayout>
@@ -87,7 +89,6 @@ TasksTablePage.propTypes = {
87
89
  getTableItems: PropTypes.func.isRequired,
88
90
  getBreadcrumbs: PropTypes.func.isRequired,
89
91
  actionName: PropTypes.string,
90
- isSubTask: PropTypes.bool,
91
92
  status: PropTypes.oneOf(Object.keys(STATUS)),
92
93
  history: PropTypes.object.isRequired,
93
94
  actionSelected: PropTypes.func.isRequired,
@@ -96,14 +97,15 @@ TasksTablePage.propTypes = {
96
97
  showCancelSelcetedModal: PropTypes.func.isRequired,
97
98
  hideSelcetedModal: PropTypes.func.isRequired,
98
99
  modalStatus: PropTypes.oneOf([CANCEL, RESUME, CLOSED]),
100
+ parentTaskID: PropTypes.string,
99
101
  };
100
102
 
101
103
  TasksTablePage.defaultProps = {
102
104
  actionName: '',
103
- isSubTask: false,
104
105
  status: STATUS.PENDING,
105
106
  selectedRows: [],
106
107
  modalStatus: CLOSED,
108
+ parentTaskID: null,
107
109
  };
108
110
 
109
111
  export default TasksTablePage;
@@ -32,6 +32,7 @@ export const selectResults = state => {
32
32
  if (!results) return [];
33
33
  return results.map(result => ({
34
34
  ...result,
35
+ action: result.action || result.label.replace(/::/g, ' '),
35
36
  username: result.username || '',
36
37
  state: result.state + (result.frozen ? ` ${__('Disabled')}` : ''),
37
38
  duration: getDuration(result.started_at, result.ended_at),
@@ -28,6 +28,7 @@ exports[`SubTasksPage rendering render with minimal props 1`] = `
28
28
  "perPage": 10,
29
29
  }
30
30
  }
31
+ parentTaskID="some-id"
31
32
  results={
32
33
  Array [
33
34
  "a",
@@ -21,6 +21,7 @@ exports[`TasksTablePage rendering render with Breadcrubs 1`] = `
21
21
  },
22
22
  }
23
23
  }
24
+ parentTaskID={null}
24
25
  />
25
26
  }
26
27
  breadcrumbOptions={
@@ -88,7 +89,6 @@ exports[`TasksTablePage rendering render with Breadcrubs 1`] = `
88
89
  },
89
90
  }
90
91
  }
91
- isSubTask={false}
92
92
  itemCount={2}
93
93
  modalStatus="CLOSED"
94
94
  pagination={
@@ -97,6 +97,7 @@ exports[`TasksTablePage rendering render with Breadcrubs 1`] = `
97
97
  "perPage": 10,
98
98
  }
99
99
  }
100
+ parentTaskID={null}
100
101
  results={
101
102
  Array [
102
103
  "a",
@@ -144,6 +145,7 @@ exports[`TasksTablePage rendering render with minimal props 1`] = `
144
145
  },
145
146
  }
146
147
  }
148
+ parentTaskID={null}
147
149
  />
148
150
  }
149
151
  onSearch={[Function]}
@@ -194,7 +196,6 @@ exports[`TasksTablePage rendering render with minimal props 1`] = `
194
196
  },
195
197
  }
196
198
  }
197
- isSubTask={false}
198
199
  itemCount={2}
199
200
  modalStatus="CLOSED"
200
201
  pagination={
@@ -203,6 +204,7 @@ exports[`TasksTablePage rendering render with minimal props 1`] = `
203
204
  "perPage": 10,
204
205
  }
205
206
  }
207
+ parentTaskID={null}
206
208
  results={
207
209
  Array [
208
210
  "a",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.2
4
+ version: 0.17.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-14 00:00:00.000000000 Z
11
+ date: 2019-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: foreman-tasks-core
@@ -123,9 +123,10 @@ files:
123
123
  - Gemfile
124
124
  - LICENSE
125
125
  - README.md
126
+ - app/assets/javascripts/foreman_tasks/foreman_tasks.js
126
127
  - app/assets/javascripts/foreman_tasks/trigger_form.js
127
- - app/assets/stylesheets/foreman_tasks/application.css.scss
128
- - app/assets/stylesheets/foreman_tasks/tasks.css.scss
128
+ - app/assets/stylesheets/foreman_tasks/foreman_tasks.css
129
+ - app/assets/stylesheets/foreman_tasks/tasks.scss
129
130
  - app/assets/stylesheets/foreman_tasks/trigger_form.css
130
131
  - app/controllers/foreman_tasks/api/recurring_logics_controller.rb
131
132
  - app/controllers/foreman_tasks/api/tasks_controller.rb
@@ -166,6 +167,7 @@ files:
166
167
  - app/models/foreman_tasks/concerns/action_subject.rb
167
168
  - app/models/foreman_tasks/concerns/action_triggering.rb
168
169
  - app/models/foreman_tasks/concerns/host_action_subject.rb
170
+ - app/models/foreman_tasks/concerns/user_extensions.rb
169
171
  - app/models/foreman_tasks/lock.rb
170
172
  - app/models/foreman_tasks/recurring_logic.rb
171
173
  - app/models/foreman_tasks/recurring_logic_cancelled_exception.rb
@@ -406,14 +408,16 @@ files:
406
408
  - webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardPropTypes.js
407
409
  - webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardReducer.js
408
410
  - webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js
411
+ - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TaskDashboard.fixtures.js
409
412
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js
410
413
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js
411
414
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardHelper.test.js
412
415
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js
413
- - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test..js
416
+ - webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js
414
417
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap
415
418
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardActions.test.js.snap
416
419
  - webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardReducer.test.js.snap
420
+ - webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap
417
421
  - webpack/ForemanTasks/Components/TasksDashboard/index.js
418
422
  - webpack/ForemanTasks/Components/TasksTable/Components/ActionConfirmation.js
419
423
  - webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js