foreman-tasks 3.0.0 → 3.0.5
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/.github/workflows/js_tests.yml +5 -1
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +19 -5
- data/app/models/foreman_tasks/recurring_logic.rb +3 -3
- data/app/models/foreman_tasks/task/search.rb +2 -1
- data/app/models/setting/foreman_tasks.rb +8 -8
- data/app/services/foreman_tasks/dashboard_table_filter.rb +5 -1
- data/app/views/foreman_tasks/layouts/react.html.erb +1 -2
- data/app/views/foreman_tasks/tasks/dashboard/_latest_tasks_in_error_warning.html.erb +1 -1
- data/app/views/foreman_tasks/tasks/dashboard/_tasks_status.html.erb +1 -1
- data/app/views/foreman_tasks/tasks/show.html.erb +1 -6
- data/foreman-tasks.gemspec +1 -0
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +10 -0
- data/test/unit/recurring_logic_test.rb +6 -0
- data/test/unit/task_test.rb +10 -0
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +10 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +4 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +53 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +14 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +27 -19
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +14 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -34
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/{StoppedTasksCardHelper.js → StoppedTasksCardTable.js} +28 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +54 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +48 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +60 -1367
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +960 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +14 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +2 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +17 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +26 -14
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +14 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +38 -22
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +0 -8
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +13 -4
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +0 -10
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +0 -2
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +3 -1
- data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +6 -1
- metadata +14 -9
- data/app/assets/stylesheets/foreman_tasks/tasks.scss +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e389326a8086026cc0359932b9d3a3c0c13621f9f0cb60e682d785ecbacddcc
|
|
4
|
+
data.tar.gz: '0880da8a4cd833615fe5aa9b79aab13a5dcf1df0f84aea891a2490c6f7a342ba'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 15589c91365b2f7f0f14b38d000575048c2c9e316430eb1564357fd7aee02b9af275155e7021cc69bffc55e8eb46d83445554a46f615d703d6e5da52912a4a94
|
|
7
|
+
data.tar.gz: b5083cad3c0268b6c461574f7f9c86887bb395a85ec6cd41dd15d2816c07961bee099fc5e4d926029c1e57802c41852a4768c5c68674d26a8822e900ef879b59
|
|
@@ -18,10 +18,14 @@ jobs:
|
|
|
18
18
|
- name: Setup Node
|
|
19
19
|
uses: actions/setup-node@v1
|
|
20
20
|
with:
|
|
21
|
-
node-version:
|
|
21
|
+
node-version: ${{ matrix.node-version }}
|
|
22
22
|
- name: Npm install
|
|
23
23
|
run: npm install
|
|
24
24
|
- name: Run plugin linter
|
|
25
25
|
run: npm run lint
|
|
26
26
|
- name: Run plugin tests
|
|
27
27
|
run: npm run test
|
|
28
|
+
- name: Publish Coveralls
|
|
29
|
+
uses: coverallsapp/github-action@master
|
|
30
|
+
with:
|
|
31
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -75,11 +75,16 @@ module ForemanTasks
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
api :POST, '/tasks/bulk_resume', N_('Resume all paused error tasks')
|
|
78
|
+
desc <<~DOC
|
|
79
|
+
Resumes all selected resumable tasks. If neither a search query nor an
|
|
80
|
+
explicit list of task IDs is provided, it tries to resume all tasks in
|
|
81
|
+
paused state with result error.
|
|
82
|
+
DOC
|
|
78
83
|
param :search, String, :desc => N_('Resume tasks matching search string')
|
|
79
84
|
param :task_ids, Array, :desc => N_('Resume specific tasks by ID')
|
|
80
85
|
def bulk_resume
|
|
81
86
|
if params[:search].nil? && params[:task_ids].nil?
|
|
82
|
-
|
|
87
|
+
params[:search] = 'state = paused and result = error'
|
|
83
88
|
end
|
|
84
89
|
resumed = []
|
|
85
90
|
failed = []
|
|
@@ -109,9 +114,14 @@ module ForemanTasks
|
|
|
109
114
|
}
|
|
110
115
|
end
|
|
111
116
|
|
|
112
|
-
api :POST, '/tasks/bulk_cancel', N_('Cancel
|
|
117
|
+
api :POST, '/tasks/bulk_cancel', N_('Cancel selected cancellable tasks')
|
|
118
|
+
desc <<~DOC
|
|
119
|
+
Cancels all selected cancellable tasks. Requires a search query or an
|
|
120
|
+
explicit list of task IDs to be provided.
|
|
121
|
+
DOC
|
|
113
122
|
param :search, String, :desc => N_('Cancel tasks matching search string')
|
|
114
123
|
param :task_ids, Array, :desc => N_('Cancel specific tasks by ID')
|
|
124
|
+
error :bad_request, 'Returned if neither search nor task_ids parameter is provided.'
|
|
115
125
|
def bulk_cancel
|
|
116
126
|
if params[:search].nil? && params[:task_ids].nil?
|
|
117
127
|
raise BadRequest, _('Please provide at least one of search or task_ids parameters in the request')
|
|
@@ -130,9 +140,14 @@ module ForemanTasks
|
|
|
130
140
|
}
|
|
131
141
|
end
|
|
132
142
|
|
|
133
|
-
api :POST, '/tasks/bulk_stop', N_('Stop
|
|
143
|
+
api :POST, '/tasks/bulk_stop', N_('Stop selected stoppable tasks')
|
|
144
|
+
desc <<~DOC
|
|
145
|
+
Stops all selected tasks which are not already stopped. Requires a
|
|
146
|
+
search query or an explicit list of task IDs to be provided.
|
|
147
|
+
DOC
|
|
134
148
|
param :search, String, :desc => N_('Stop tasks matching search string')
|
|
135
149
|
param :task_ids, Array, :desc => N_('Stop specific tasks by ID')
|
|
150
|
+
error :bad_request, 'Returned if neither search nor task_ids parameter is provided.'
|
|
136
151
|
def bulk_stop
|
|
137
152
|
if params[:search].nil? && params[:task_ids].nil?
|
|
138
153
|
raise BadRequest, _('Please provide at least one of search or task_ids parameters in the request')
|
|
@@ -221,7 +236,7 @@ module ForemanTasks
|
|
|
221
236
|
end
|
|
222
237
|
|
|
223
238
|
def search_tasks(search_params)
|
|
224
|
-
scope = resource_scope_for_index
|
|
239
|
+
scope = resource_scope_for_index
|
|
225
240
|
scope = ordering_scope(scope, search_params)
|
|
226
241
|
scope = search_scope(scope, search_params)
|
|
227
242
|
scope = active_scope(scope, search_params)
|
|
@@ -287,7 +302,6 @@ module ForemanTasks
|
|
|
287
302
|
sort_by = ordering_params[:sort_by] || 'started_at'
|
|
288
303
|
sort_by = 'foreman_tasks_tasks.' + sort_by if sort_by == 'started_at'
|
|
289
304
|
sort_order = ordering_params[:sort_order] || 'DESC'
|
|
290
|
-
scope = scope.select("foreman_tasks_tasks.*, coalesce(ended_at, current_timestamp) - coalesce(coalesce(started_at, ended_at), current_timestamp) as duration")
|
|
291
305
|
scope.order("#{sort_by} #{sort_order}")
|
|
292
306
|
end
|
|
293
307
|
|
|
@@ -31,12 +31,12 @@ module ForemanTasks
|
|
|
31
31
|
if value
|
|
32
32
|
task.update!(:start_at => next_occurrence_time) if task.start_at < Time.zone.now
|
|
33
33
|
update(:state => 'active')
|
|
34
|
-
else
|
|
35
|
-
update(:state => 'disabled')
|
|
36
34
|
end
|
|
37
|
-
|
|
35
|
+
elsif value
|
|
38
36
|
raise RecurringLogicCancelledException
|
|
39
37
|
end
|
|
38
|
+
|
|
39
|
+
update(:state => 'disabled') unless value
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def enabled?
|
|
@@ -20,7 +20,8 @@ module ForemanTasks
|
|
|
20
20
|
foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_type = '#{resource_type}')
|
|
21
21
|
SQL
|
|
22
22
|
# Select only those tasks which either have the correct taxonomy or are not related to any
|
|
23
|
-
sql = "foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id #{operator} ? OR foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
|
23
|
+
sql = "foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id #{operator} (?) OR foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
|
24
|
+
value = value.split(',') if operator.index(/IN/i)
|
|
24
25
|
{ :conditions => sanitize_sql_for_conditions([sql, value]), :joins => joins }
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
class Setting::ForemanTasks < Setting
|
|
2
2
|
def self.default_settings
|
|
3
3
|
[
|
|
4
|
-
set('foreman_tasks_sync_task_timeout', N_('Number of seconds to wait for synchronous task to finish.'), 120),
|
|
5
|
-
set('dynflow_enable_console', N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'), true),
|
|
6
|
-
set('dynflow_console_require_auth', N_('Require user to be authenticated as user with admin rights when accessing dynflow console'), true),
|
|
7
|
-
set('foreman_tasks_proxy_action_retry_count', N_('Number of attempts to start a task on the smart proxy before failing'), 4),
|
|
8
|
-
set('foreman_tasks_proxy_action_retry_interval', N_('Time in seconds between retries'), 15),
|
|
9
|
-
set('foreman_tasks_proxy_batch_trigger', N_('Allow triggering tasks on the smart proxy in batches'), true),
|
|
10
|
-
set('foreman_tasks_proxy_batch_size', N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'), 100),
|
|
4
|
+
set('foreman_tasks_sync_task_timeout', N_('Number of seconds to wait for synchronous task to finish.'), 120, N_('Sync task timeout')),
|
|
5
|
+
set('dynflow_enable_console', N_('Enable the dynflow console (/foreman_tasks/dynflow) for debugging'), true, N_('Enable dynflow console')),
|
|
6
|
+
set('dynflow_console_require_auth', N_('Require user to be authenticated as user with admin rights when accessing dynflow console'), true, N_('Require auth for dynflow console')),
|
|
7
|
+
set('foreman_tasks_proxy_action_retry_count', N_('Number of attempts to start a task on the smart proxy before failing'), 4, N_('Proxy action retry count')),
|
|
8
|
+
set('foreman_tasks_proxy_action_retry_interval', N_('Time in seconds between retries'), 15, N_('Proxy action retry interval')),
|
|
9
|
+
set('foreman_tasks_proxy_batch_trigger', N_('Allow triggering tasks on the smart proxy in batches'), true, N_('Allow proxy batch tasks')),
|
|
10
|
+
set('foreman_tasks_proxy_batch_size', N_('Number of tasks which should be sent to the smart proxy in one request, if foreman_tasks_proxy_batch_trigger is enabled'), 100, N_('Proxy tasks batch size')),
|
|
11
11
|
set('foreman_tasks_troubleshooting_url',
|
|
12
12
|
N_('Url pointing to the task troubleshooting documentation. '\
|
|
13
13
|
'It should contain %{label} placeholder, that will be replaced with normalized task label '\
|
|
14
14
|
'(restricted to only alphanumeric characters)). %{version} placeholder is also available.'),
|
|
15
|
-
nil),
|
|
15
|
+
nil, N_('Tasks troubleshooting URL')),
|
|
16
16
|
set('foreman_tasks_polling_multiplier',
|
|
17
17
|
N_('Polling multiplier which is used to multiply the default polling intervals. '\
|
|
18
18
|
'This can be used to prevent polling too frequently for long running tasks.'),
|
|
@@ -24,7 +24,11 @@ module ForemanTasks
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def scope_by(field)
|
|
27
|
-
|
|
27
|
+
if (field == :result) && (@params[field] == 'other')
|
|
28
|
+
@new_scope = @new_scope.where(:result => ['cancelled', 'pending'])
|
|
29
|
+
elsif @params[field].present?
|
|
30
|
+
@new_scope = @new_scope.where(field => @params[field])
|
|
31
|
+
end
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def scope_by_time
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
<%= notifications %>
|
|
10
10
|
<div id="organization-id" data-id="<%= Organization.current.id if Organization.current %>" ></div>
|
|
11
11
|
<div id="user-id" data-id="<%= User.current.id if User.current %>" ></div>
|
|
12
|
-
|
|
12
|
+
<%= react_component('ForemanTasks') %>
|
|
13
13
|
<% end %>
|
|
14
14
|
<%= render file: "layouts/base" %>
|
|
15
|
-
<%= mount_react_component('ForemanTasks', '#foremanTasksReactRoot') %>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<td class="ellipsis"><%= link_to task.humanized[:action], defined?(main_app) ? main_app.foreman_tasks_task_path(task.id) : foreman_tasks_task_path(task.id) %></td>
|
|
12
12
|
<td><%= task.state %></td>
|
|
13
13
|
<td><%= task.result %></td>
|
|
14
|
-
<td><%= task.started_at ?
|
|
14
|
+
<td><%= task.started_at ? date_time_relative(task.started_at) : _('N/A') %></td>
|
|
15
15
|
</tr>
|
|
16
16
|
<% end %>
|
|
17
17
|
</table>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<td><%= result.state %></td>
|
|
12
12
|
<td><%= result.result %></td>
|
|
13
13
|
<td><%= link_to result.count, main_app.foreman_tasks_tasks_path(:search => "state=#{result.state}&result=#{result.result}") %></td>
|
|
14
|
-
<td><%= result.started_at ?
|
|
14
|
+
<td><%= result.started_at ? date_time_relative(result.started_at) : _('N/A') %></td>
|
|
15
15
|
</tr>
|
|
16
16
|
<% end %>
|
|
17
17
|
</table>
|
data/foreman-tasks.gemspec
CHANGED
|
@@ -7,6 +7,7 @@ require "foreman_tasks/version"
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "foreman-tasks"
|
|
9
9
|
s.version = ForemanTasks::VERSION
|
|
10
|
+
s.license = 'GPL-3.0'
|
|
10
11
|
s.authors = ["Ivan Nečas"]
|
|
11
12
|
s.email = ["inecas@redhat.com"]
|
|
12
13
|
s.homepage = "https://github.com/theforeman/foreman-tasks"
|
|
@@ -45,6 +45,16 @@ module ForemanTasks
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
describe 'POST /api/tasks/bulk_search' do
|
|
49
|
+
it 'searching for a task' do
|
|
50
|
+
task = FactoryBot.create(:dynflow_task, :user_create_task)
|
|
51
|
+
post :bulk_search, params: { :searches => [{ :type => "task", :task_id => task.id, :search_id => "1" }] }
|
|
52
|
+
assert_response :success
|
|
53
|
+
data = JSON.parse(response.body)
|
|
54
|
+
_(data[0]['results'][0]['id']).must_equal task.id
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
48
58
|
describe 'GET /api/tasks/show' do
|
|
49
59
|
it 'searches for task' do
|
|
50
60
|
task = FactoryBot.create(:dynflow_task, :user_create_task)
|
|
@@ -148,6 +148,12 @@ class RecurringLogicsTest < ActiveSupport::TestCase
|
|
|
148
148
|
assert ForemanTasks.dynflow.world.persistence.load_delayed_plan(task.execution_plan.id).frozen
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
+
it 'handles if the task has been deleted' do
|
|
152
|
+
logic.tasks.find_by(:state => 'scheduled').destroy
|
|
153
|
+
logic.update!(:enabled => false)
|
|
154
|
+
assert_equal 'disabled', logic.state
|
|
155
|
+
end
|
|
156
|
+
|
|
151
157
|
it 'properly re-enables on disable' do
|
|
152
158
|
logic.update!(:enabled => false)
|
|
153
159
|
logic.update!(:enabled => true)
|
data/test/unit/task_test.rb
CHANGED
|
@@ -129,6 +129,16 @@ class TasksTest < ActiveSupport::TestCase
|
|
|
129
129
|
_ { proc { ForemanTasks::Task.search_for('duration = "25 potatoes"') } }.must_raise ScopedSearch::QueryNotSupported
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
|
+
|
|
133
|
+
context 'by taxonomies' do
|
|
134
|
+
test 'can search by taxonomies using IN' do
|
|
135
|
+
assert_nothing_raised(PG::SyntaxError) { ForemanTasks::Task.search_for('location_id ^ (1)').first }
|
|
136
|
+
assert_nothing_raised(PG::SyntaxError) { ForemanTasks::Task.search_for('organization_id ^ (1)').first }
|
|
137
|
+
assert_nothing_raised(PG::SyntaxError) { ForemanTasks::Task.search_for('location_id ^ (1,2)').first }
|
|
138
|
+
assert_nothing_raised(PG::SyntaxError) { ForemanTasks::Task.search_for('organization_id ^ (1,2)').first }
|
|
139
|
+
assert_nothing_raised(PG::SyntaxError) { ForemanTasks::Task.search_for('organization_id = 1').first }
|
|
140
|
+
end
|
|
141
|
+
end
|
|
132
142
|
end
|
|
133
143
|
|
|
134
144
|
describe 'users' do
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
.scheduled-tasks-card {
|
|
2
2
|
text-align: center;
|
|
3
|
+
|
|
3
4
|
.scheduled-data {
|
|
5
|
+
margin-top: 30px;
|
|
4
6
|
padding-right: 15px;
|
|
5
7
|
cursor: pointer;
|
|
6
8
|
font-size: 40px;
|
|
7
9
|
font-weight: 300;
|
|
8
10
|
transition: font-weight 50ms ease-in;
|
|
11
|
+
|
|
9
12
|
p {
|
|
10
13
|
font-size: 20px;
|
|
11
14
|
margin: 0;
|
|
12
15
|
}
|
|
16
|
+
|
|
13
17
|
* {
|
|
14
18
|
margin: 10px;
|
|
15
19
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
|
|
5
|
+
import { Icon, Button, OverlayTrigger, Tooltip } from 'patternfly-react';
|
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
7
|
+
import {
|
|
8
|
+
TASKS_DASHBOARD_AVAILABLE_QUERY_STATES,
|
|
9
|
+
TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS,
|
|
10
|
+
} from '../../../../TasksDashboardConstants';
|
|
11
|
+
import { queryPropType } from '../../../../TasksDashboardPropTypes';
|
|
12
|
+
|
|
13
|
+
const tooltip = (
|
|
14
|
+
<Tooltip id="stopped-tooltip">
|
|
15
|
+
{__('Other includes all stopped tasks that are cancelled or pending')}
|
|
16
|
+
</Tooltip>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const OtherInfo = ({ updateQuery, otherCount, query }) => {
|
|
20
|
+
const { OTHER } = TASKS_DASHBOARD_AVAILABLE_QUERY_RESULTS;
|
|
21
|
+
const { STOPPED } = TASKS_DASHBOARD_AVAILABLE_QUERY_STATES;
|
|
22
|
+
const active = query.state === STOPPED && query.result === OTHER;
|
|
23
|
+
return (
|
|
24
|
+
<span className={classNames(active && 'other-active')}>
|
|
25
|
+
<OverlayTrigger
|
|
26
|
+
overlay={tooltip}
|
|
27
|
+
trigger={['hover', 'focus']}
|
|
28
|
+
placement="bottom"
|
|
29
|
+
>
|
|
30
|
+
<span>
|
|
31
|
+
<Icon type="pf" name="info" />
|
|
32
|
+
<span>{__('Other:')} </span>
|
|
33
|
+
</span>
|
|
34
|
+
</OverlayTrigger>
|
|
35
|
+
<Button
|
|
36
|
+
bsStyle="link"
|
|
37
|
+
onClick={() =>
|
|
38
|
+
updateQuery({
|
|
39
|
+
state: STOPPED,
|
|
40
|
+
result: OTHER,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
>
|
|
44
|
+
{otherCount}
|
|
45
|
+
</Button>
|
|
46
|
+
</span>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
OtherInfo.propTypes = {
|
|
50
|
+
updateQuery: PropTypes.func.isRequired,
|
|
51
|
+
otherCount: PropTypes.number.isRequired,
|
|
52
|
+
query: queryPropType.isRequired,
|
|
53
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
|
|
2
|
+
|
|
3
|
+
import { OtherInfo } from './OtherInfo';
|
|
4
|
+
|
|
5
|
+
const fixtures = {
|
|
6
|
+
render: {
|
|
7
|
+
updateQuery: jest.fn,
|
|
8
|
+
otherCount: 7,
|
|
9
|
+
query: { state: 'STOPPED', result: 'OTHER' },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('OtherInfo', () =>
|
|
14
|
+
testComponentSnapshotsWithFixtures(OtherInfo, fixtures));
|
|
@@ -4,8 +4,8 @@ import { Card } from 'patternfly-react';
|
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import { noop } from 'foremanReact/common/helpers';
|
|
6
6
|
import { translate as __ } from 'foremanReact/common/I18n';
|
|
7
|
-
|
|
8
|
-
import { StoppedTable } from './
|
|
7
|
+
import { OtherInfo } from './OtherInfo';
|
|
8
|
+
import { StoppedTable } from './StoppedTasksCardTable';
|
|
9
9
|
import {
|
|
10
10
|
timePropType,
|
|
11
11
|
queryPropType,
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
TASKS_DASHBOARD_AVAILABLE_TIMES,
|
|
15
15
|
TASKS_DASHBOARD_AVAILABLE_QUERY_STATES,
|
|
16
16
|
} from '../../../../TasksDashboardConstants';
|
|
17
|
-
import { getQueryValueText } from '../../../../TasksDashboardHelper';
|
|
18
17
|
import './StoppedTasksCard.scss';
|
|
19
18
|
|
|
20
19
|
const StoppedTasksCard = ({
|
|
@@ -44,16 +43,19 @@ const StoppedTasksCard = ({
|
|
|
44
43
|
{__('Stopped')}
|
|
45
44
|
</Card.Title>
|
|
46
45
|
<Card.Body>
|
|
47
|
-
<
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
<React.Fragment>
|
|
47
|
+
<StoppedTable
|
|
48
|
+
data={data.results}
|
|
49
|
+
query={query}
|
|
50
|
+
time={time}
|
|
51
|
+
updateQuery={updateQuery}
|
|
52
|
+
/>
|
|
53
|
+
<OtherInfo
|
|
54
|
+
updateQuery={updateQuery}
|
|
55
|
+
otherCount={data.other}
|
|
56
|
+
query={query}
|
|
57
|
+
/>
|
|
58
|
+
</React.Fragment>
|
|
57
59
|
</Card.Body>
|
|
58
60
|
</Card>
|
|
59
61
|
);
|
|
@@ -66,9 +68,12 @@ const resultPropType = PropTypes.shape({
|
|
|
66
68
|
|
|
67
69
|
StoppedTasksCard.propTypes = {
|
|
68
70
|
data: PropTypes.shape({
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
results: PropTypes.shape({
|
|
72
|
+
error: resultPropType.isRequired,
|
|
73
|
+
warning: resultPropType.isRequired,
|
|
74
|
+
success: resultPropType.isRequired,
|
|
75
|
+
}),
|
|
76
|
+
other: PropTypes.number,
|
|
72
77
|
}),
|
|
73
78
|
time: timePropType,
|
|
74
79
|
query: queryPropType,
|
|
@@ -78,9 +83,12 @@ StoppedTasksCard.propTypes = {
|
|
|
78
83
|
|
|
79
84
|
StoppedTasksCard.defaultProps = {
|
|
80
85
|
data: {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
results: {
|
|
87
|
+
error: { total: 0, last: 0 },
|
|
88
|
+
warning: { total: 0, last: 0 },
|
|
89
|
+
success: { total: 0, last: 0 },
|
|
90
|
+
},
|
|
91
|
+
other: 0,
|
|
84
92
|
},
|
|
85
93
|
time: TASKS_DASHBOARD_AVAILABLE_TIMES.H24,
|
|
86
94
|
query: {},
|