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.
- 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
|