foreman-tasks 0.17.2 → 0.17.3

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