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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/foreman_tasks/foreman_tasks.js +3 -0
- data/app/assets/stylesheets/foreman_tasks/{application.css.scss → foreman_tasks.css} +0 -5
- data/app/assets/stylesheets/foreman_tasks/{tasks.css.scss → tasks.scss} +0 -0
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +6 -4
- data/app/controllers/foreman_tasks/tasks_controller.rb +6 -1
- data/app/models/foreman_tasks/concerns/user_extensions.rb +14 -0
- data/app/views/common/_trigger_form.html.erb +2 -2
- data/app/views/foreman_tasks/tasks/show.html.erb +1 -1
- data/config/routes.rb +2 -0
- data/lib/foreman_tasks/engine.rb +5 -11
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/unit/task_test.rb +8 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +11 -4
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +5 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TaskDashboard.fixtures.js +93 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +9 -10
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/{TasksDashboardSelectors.test..js → TasksDashboardSelectors.test.js} +30 -28
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardActions.test.js.snap +91 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +103 -0
- data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +9 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +5 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +4 -4
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +5 -3
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +4 -2
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95c9f8364b129d0fcaccad4e7f8673deb1ff18ab1d5e47b74f2c85fe366af7a3
|
4
|
+
data.tar.gz: c36bb9f6aedcab3dc1c590797c09b470dd3097c0295a00f9e61dd1b695a011dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 453f74187dd7bc334ff64dfc0544a317dd60b06e23c83057577a8f346f70281f2a8b71749d200f5edbb09c810f8ec241965a2a5311a7fb849d26166f14a391ae
|
7
|
+
data.tar.gz: 3a256485bd5f4c92a39cad572c8b402105c0fb5768c173390ea33e75fbfc590899e8c73f455c157f69d48328308e8c88da0a14038f07d659fd8cd46597943d21
|
File without changes
|
@@ -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/
|
5
|
-
<% stylesheet 'foreman_tasks/
|
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 %>') });
|
data/config/routes.rb
CHANGED
@@ -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
|
data/lib/foreman_tasks/engine.rb
CHANGED
@@ -14,15 +14,8 @@ module ForemanTasks
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
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
|
data/test/unit/task_test.rb
CHANGED
@@ -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 {
|
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
|
-
|
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(
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
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":
|
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/${
|
13
|
+
url: `/foreman_tasks/tasks/${parentTaskID}`,
|
13
14
|
},
|
14
15
|
{ caption: __('Sub tasks') },
|
15
16
|
],
|
16
17
|
});
|
17
|
-
return
|
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={
|
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),
|
data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap
CHANGED
@@ -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.
|
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-
|
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/
|
128
|
-
- app/assets/stylesheets/foreman_tasks/tasks.
|
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
|
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
|