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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/js_tests.yml +5 -1
  3. data/app/controllers/foreman_tasks/api/tasks_controller.rb +19 -5
  4. data/app/models/foreman_tasks/recurring_logic.rb +3 -3
  5. data/app/models/foreman_tasks/task/search.rb +2 -1
  6. data/app/models/setting/foreman_tasks.rb +8 -8
  7. data/app/services/foreman_tasks/dashboard_table_filter.rb +5 -1
  8. data/app/views/foreman_tasks/layouts/react.html.erb +1 -2
  9. data/app/views/foreman_tasks/tasks/dashboard/_latest_tasks_in_error_warning.html.erb +1 -1
  10. data/app/views/foreman_tasks/tasks/dashboard/_tasks_status.html.erb +1 -1
  11. data/app/views/foreman_tasks/tasks/show.html.erb +1 -6
  12. data/foreman-tasks.gemspec +1 -0
  13. data/lib/foreman_tasks/version.rb +1 -1
  14. data/test/controllers/api/tasks_controller_test.rb +10 -0
  15. data/test/unit/recurring_logic_test.rb +6 -0
  16. data/test/unit/task_test.rb +10 -0
  17. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +10 -0
  18. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +4 -0
  19. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.js +53 -0
  20. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/OtherInfo.test.js +14 -0
  21. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +27 -19
  22. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +14 -0
  23. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +1 -34
  24. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/{StoppedTasksCardHelper.js → StoppedTasksCardTable.js} +28 -1
  25. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardTable.test.js +54 -0
  26. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/OtherInfo.test.js.snap +48 -0
  27. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +60 -1367
  28. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCardTable.test.js.snap +960 -0
  29. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +14 -11
  30. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +2 -0
  31. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +17 -11
  32. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test.js +26 -14
  33. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +14 -11
  34. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardSelectors.test.js.snap +38 -22
  35. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +0 -8
  36. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +13 -4
  37. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +0 -10
  38. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +0 -2
  39. data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +3 -1
  40. data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +6 -1
  41. metadata +14 -9
  42. 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: 24da58e2837688da28a18832b72b154ac74868157f6176f942119b8b856987c8
4
- data.tar.gz: 3031305c5f86f3b03aed95a4501670cbd2dbd595db38f638354ff046f416823a
3
+ metadata.gz: 8e389326a8086026cc0359932b9d3a3c0c13621f9f0cb60e682d785ecbacddcc
4
+ data.tar.gz: '0880da8a4cd833615fe5aa9b79aab13a5dcf1df0f84aea891a2490c6f7a342ba'
5
5
  SHA512:
6
- metadata.gz: a6a21ff8c4b9336f63118c2cdf6a4f11bf25ff882fe1dbd1b17d05f9722705c9cebabb522792416758c3fede1a8507d720cac0317076d8e833bfbb95a83fa8a4
7
- data.tar.gz: bef5dd6cac70ac43d53e83950668e930883649d42966b10ff6303e0d581431d3f11028ae24c7ecc9ed0e2875214f4a512cfbaa46f1da81fd912d6a6f25da2db2
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: ${{ matrix.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
- raise BadRequest, _('Please provide at least one of search or task_ids parameters in the request')
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 all cancellable tasks')
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 all stoppable tasks')
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.select('DISTINCT foreman_tasks_tasks.*')
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
- else
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
- @new_scope = @new_scope.where(field => @params[field]) if @params[field].present?
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
- <div id="foremanTasksReactRoot"></div>
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 ? (_(date_time_relative(task.started_at))) : _('N/A') %></td>
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 ? (_(date_time_relative(result.started_at))) : _('N/A') %></td>
14
+ <td><%= result.started_at ? date_time_relative(result.started_at) : _('N/A') %></td>
15
15
  </tr>
16
16
  <% end %>
17
17
  </table>
@@ -15,9 +15,4 @@
15
15
  switcher_item_url: foreman_tasks_task_path(:id => ':id')
16
16
  ) %>
17
17
 
18
-
19
- <div class="task-details" id="foremanTaskDetails">
20
- </div>
21
-
22
-
23
- <%= mount_react_component('TaskDetails', '#foremanTaskDetails') %>
18
+ <%= react_component('TaskDetails') %>
@@ -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"
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '3.0.0'.freeze
2
+ VERSION = '3.0.5'.freeze
3
3
  end
@@ -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)
@@ -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
@@ -49,4 +49,14 @@
49
49
  .dynflow-button > span {
50
50
  pointer-events: auto;
51
51
  }
52
+
53
+ pre {
54
+ white-space: pre;
55
+ word-break: normal;
56
+ }
57
+
58
+ .param-name {
59
+ display: inline-block;
60
+ width: 10em;
61
+ }
52
62
  }
@@ -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 './StoppedTasksCardHelper';
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
- <table className="table table-bordered table-striped stopped-table">
48
- <thead>
49
- <tr>
50
- <th />
51
- <th>{__('Total')}</th>
52
- <th>{getQueryValueText(time)}</th>
53
- </tr>
54
- </thead>
55
- <tbody>{StoppedTable(data, query, time, updateQuery)}</tbody>
56
- </table>
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
- error: resultPropType.isRequired,
70
- warning: resultPropType.isRequired,
71
- success: resultPropType.isRequired,
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
- error: { total: 0, last: 0 },
82
- warning: { total: 0, last: 0 },
83
- success: { total: 0, last: 0 },
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: {},