foreman_rh_cloud 4.0.24.1 → 4.0.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/services/foreman_rh_cloud/cloud_auth.rb +4 -0
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +5 -0
- data/lib/foreman_inventory_upload/generators/tags.rb +3 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud/async/insights_full_sync.rb +5 -0
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +9 -0
- data/lib/insights_cloud/async/insights_rules_sync.rb +5 -0
- data/lib/inventory_sync/async/inventory_full_sync.rb +5 -0
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +5 -0
- data/lib/inventory_sync/async/inventory_self_host_sync.rb +9 -0
- data/package.json +1 -1
- data/test/jobs/insights_full_sync_test.rb +1 -0
- data/test/jobs/insights_resolutions_sync_test.rb +1 -0
- data/test/jobs/insights_rules_sync_test.rb +1 -0
- data/test/jobs/inventory_full_sync_test.rb +10 -0
- data/test/jobs/inventory_hosts_sync_test.rb +1 -0
- data/test/jobs/inventory_self_host_sync_test.rb +1 -0
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -0
- data/test/unit/tags_generator_test.rb +41 -0
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/EmptyState.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/__tests__/__snapshots__/EmptyState.test.js.snap +1 -2
- data/webpack/ForemanInventoryUpload/Components/FileDownload/FileDownload.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/FileDownload/__tests__/__snapshots__/FileDownload.test.js.snap +2 -1
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -2
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilterConstants.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js +2 -2
- data/webpack/ForemanInventoryUpload/Components/StatusChart/StatusChart.js +4 -3
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +2 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +14 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +2 -2
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +14 -0
- data/webpack/InsightsHostDetailsTab/InsightsTab.js +3 -2
- data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -4
- data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +9 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ac06b57bc84d2c31a7a2e5ad8ec8874053bf4419f018c94b95192ba7281ccf4
|
4
|
+
data.tar.gz: 1e8dd2dce4252a247123e0662f6b33621fadf34e3d03a008335d1902dc7d69db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7f0324f7854d483ce3c8836fcc5a70af02ed5f3f1bb64e3e1fcb68603eb4daa078b7cb7090ba4b9bcda6c4003639d5cd7265432f5d0b60b89cd5bccaf521fe3
|
7
|
+
data.tar.gz: f8e8b5317c59dc110e7315ba8bf665d7bdeda836e899dc81c1c7bcecdcd81a4568b0c8ad9849e69b9f74dd4cf7127ca097f234001b1492992d677d4cd5b44939
|
@@ -12,6 +12,11 @@ module ForemanRhCloud
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def create_playbook
|
15
|
+
unless cloud_auth_available?
|
16
|
+
logger.debug('Cloud authentication is not available, cannot continue')
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
15
20
|
response = query_playbook
|
16
21
|
|
17
22
|
logger.debug("Got playbook response: #{response.body}")
|
@@ -19,7 +19,9 @@ module ForemanInventoryUpload
|
|
19
19
|
def generate_parameters
|
20
20
|
return [] unless Setting[:include_parameter_tags]
|
21
21
|
|
22
|
-
(@host.host_inherited_params_objects || [])
|
22
|
+
(@host.host_inherited_params_objects || [])
|
23
|
+
.map { |item| [item.name, item.value] }
|
24
|
+
.select { |_name, value| value.present? || value.is_a?(FalseClass) }
|
23
25
|
end
|
24
26
|
|
25
27
|
private
|
@@ -6,6 +6,11 @@ module InsightsCloud
|
|
6
6
|
include ::ForemanRhCloud::CloudAuth
|
7
7
|
|
8
8
|
def plan
|
9
|
+
unless cloud_auth_available?
|
10
|
+
logger.debug('Cloud authentication is not available, skipping insights sync')
|
11
|
+
return
|
12
|
+
end
|
13
|
+
|
9
14
|
sequence do
|
10
15
|
# This can be turned off when we enable automatic status syncs
|
11
16
|
# This step will query cloud inventory to retrieve inventory uuids for each host
|
@@ -7,6 +7,15 @@ module InsightsCloud
|
|
7
7
|
|
8
8
|
RULE_ID_REGEX = /[^:]*:(?<id>.*)/
|
9
9
|
|
10
|
+
def plan
|
11
|
+
unless cloud_auth_available?
|
12
|
+
logger.debug('Cloud authentication is not available, skipping resolutions sync')
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
plan_self
|
17
|
+
end
|
18
|
+
|
10
19
|
def run
|
11
20
|
InsightsResolution.transaction do
|
12
21
|
InsightsResolution.delete_all
|
@@ -5,6 +5,11 @@ module InventorySync
|
|
5
5
|
set_callback :step, :around, :update_statuses_batch
|
6
6
|
|
7
7
|
def plan(organization)
|
8
|
+
unless cloud_auth_available?
|
9
|
+
logger.debug('Cloud authentication is not available, skipping inventory hosts sync')
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
8
13
|
plan_self(organization_id: organization.id)
|
9
14
|
end
|
10
15
|
|
@@ -5,6 +5,11 @@ module InventorySync
|
|
5
5
|
set_callback :step, :around, :create_facets
|
6
6
|
|
7
7
|
def plan
|
8
|
+
unless cloud_auth_available?
|
9
|
+
logger.debug('Cloud authentication is not available, skipping inventory hosts sync')
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
8
13
|
# by default the tasks will be executed concurrently
|
9
14
|
plan_self
|
10
15
|
plan_self_host_sync
|
@@ -3,6 +3,15 @@ module InventorySync
|
|
3
3
|
class InventorySelfHostSync < QueryInventoryJob
|
4
4
|
set_callback :step, :around, :create_facets
|
5
5
|
|
6
|
+
def plan
|
7
|
+
unless cloud_auth_available?
|
8
|
+
logger.debug('Cloud authentication is not available, skipping self host sync')
|
9
|
+
return
|
10
|
+
end
|
11
|
+
|
12
|
+
plan_self
|
13
|
+
end
|
14
|
+
|
6
15
|
def create_facets
|
7
16
|
# get the results from the event
|
8
17
|
results = yield
|
data/package.json
CHANGED
@@ -7,6 +7,7 @@ class InsightsFullSyncTest < ActiveSupport::TestCase
|
|
7
7
|
setup do
|
8
8
|
InsightsCloud::Async::InsightsFullSync.any_instance.stubs(:plan_rules_sync)
|
9
9
|
InsightsCloud::Async::InsightsFullSync.any_instance.stubs(:plan_notifications)
|
10
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
10
11
|
|
11
12
|
uuid1 = 'accdf444-5628-451d-bf3e-cf909ad72756'
|
12
13
|
@host1 = FactoryBot.create(:host, :managed, name: 'host1')
|
@@ -63,6 +63,7 @@ class InsightsResolutionsSyncTest < ActiveSupport::TestCase
|
|
63
63
|
}
|
64
64
|
|
65
65
|
@rule = FactoryBot.create(:insights_rule, rule_id: 'network_tcp_connection_hang|NETWORK_TCP_CONNECTION_HANG_WARN')
|
66
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
66
67
|
end
|
67
68
|
|
68
69
|
test 'Resolutions data is replaced with data from cloud' do
|
@@ -112,6 +112,7 @@ class InsightsRulesSyncTest < ActiveSupport::TestCase
|
|
112
112
|
@hit = FactoryBot.create(:insights_hit, host_id: @host.id)
|
113
113
|
|
114
114
|
InsightsCloud::Async::InsightsRulesSync.any_instance.stubs(:plan_resolutions)
|
115
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
115
116
|
end
|
116
117
|
|
117
118
|
test 'Hits data is replaced with data from cloud' do
|
@@ -242,6 +242,7 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
242
242
|
end
|
243
243
|
|
244
244
|
test 'Host status should be SYNC for inventory hosts' do
|
245
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'TEST TOKEN')
|
245
246
|
InventorySync::Async::InventoryFullSync.any_instance.expects(:query_inventory).returns(@inventory)
|
246
247
|
|
247
248
|
ForemanTasks.sync_task(InventorySync::Async::InventoryFullSync, @host2.organization)
|
@@ -253,6 +254,7 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
253
254
|
end
|
254
255
|
|
255
256
|
test 'Host status should be DISCONNECT for hosts that are not returned from cloud' do
|
257
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'TEST TOKEN')
|
256
258
|
InventorySync::Async::InventoryFullSync.any_instance.expects(:query_inventory).returns(@inventory)
|
257
259
|
FactoryBot.create(:fact_value, fact_name: fact_names['virt::uuid'], value: '1234', host: @host2)
|
258
260
|
|
@@ -261,4 +263,12 @@ class InventoryFullSyncTest < ActiveSupport::TestCase
|
|
261
263
|
|
262
264
|
assert_equal InventorySync::InventoryStatus::DISCONNECT, InventorySync::InventoryStatus.where(host_id: @host1.id).first.status
|
263
265
|
end
|
266
|
+
|
267
|
+
test 'Task should be aborted if token is not present' do
|
268
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: '')
|
269
|
+
|
270
|
+
InventorySync::Async::InventoryFullSync.any_instance.expects(:plan_self).never
|
271
|
+
|
272
|
+
ForemanTasks.sync_task(InventorySync::Async::InventoryFullSync, @host1.organization)
|
273
|
+
end
|
264
274
|
end
|
@@ -6,6 +6,7 @@ class InventoryHostsSyncTest < ActiveSupport::TestCase
|
|
6
6
|
|
7
7
|
setup do
|
8
8
|
User.current = User.find_by(login: 'secret_admin')
|
9
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
9
10
|
|
10
11
|
env = FactoryBot.create(:katello_k_t_environment)
|
11
12
|
cv = env.content_views << FactoryBot.create(:katello_content_view, organization: env.organization)
|
@@ -6,6 +6,7 @@ class InventorySelfHostSyncTest < ActiveSupport::TestCase
|
|
6
6
|
|
7
7
|
setup do
|
8
8
|
User.current = User.find_by(login: 'secret_admin')
|
9
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
9
10
|
|
10
11
|
# this host would pass our plugin queries, so it could be uploaded to the cloud.
|
11
12
|
@host1 = FactoryBot.create(:host)
|
@@ -8,6 +8,7 @@ class TemplateRendererHelperTest < ActiveSupport::TestCase
|
|
8
8
|
response.stubs(:body).returns('TEST PLAYBOOK')
|
9
9
|
ForemanRhCloud::RemediationsRetriever.any_instance.stubs(:query_playbook).returns(response)
|
10
10
|
@host1 = FactoryBot.create(:host)
|
11
|
+
FactoryBot.create(:setting, name: 'rh_cloud_token', value: 'MOCK_TOKEN')
|
11
12
|
end
|
12
13
|
|
13
14
|
test 'Generates a playbook for hit and remediation' do
|
@@ -62,6 +62,47 @@ class TagsGeneratorTest < ActiveSupport::TestCase
|
|
62
62
|
assert_equal false, actual.key?('content_view')
|
63
63
|
end
|
64
64
|
|
65
|
+
test 'generates parameter tags' do
|
66
|
+
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => true)
|
67
|
+
|
68
|
+
@host.stubs(:host_inherited_params_objects).returns(
|
69
|
+
[
|
70
|
+
OpenStruct.new(name: 'bool_param', value: true),
|
71
|
+
OpenStruct.new(name: 'false_param', value: false),
|
72
|
+
OpenStruct.new(name: 'int_param', value: 1),
|
73
|
+
OpenStruct.new(name: 'empty_param', value: nil),
|
74
|
+
OpenStruct.new(name: 'empty_str_param', value: ''),
|
75
|
+
]
|
76
|
+
)
|
77
|
+
|
78
|
+
generator = create_generator
|
79
|
+
actual = Hash[generator.generate_parameters]
|
80
|
+
|
81
|
+
assert_equal 3, actual.count
|
82
|
+
assert_equal true, actual['bool_param']
|
83
|
+
assert_equal false, actual['false_param']
|
84
|
+
assert_equal 1, actual['int_param']
|
85
|
+
end
|
86
|
+
|
87
|
+
test 'skips parameter tags if include_parameter_tags setting is off' do
|
88
|
+
FactoryBot.create(:setting, :name => 'include_parameter_tags', :settings_type => "boolean", :category => "Setting::RhCloud", :default => false, :value => false)
|
89
|
+
|
90
|
+
@host.stubs(:host_inherited_params_objects).returns(
|
91
|
+
[
|
92
|
+
OpenStruct.new(name: 'bool_param', value: true),
|
93
|
+
OpenStruct.new(name: 'false_param', value: false),
|
94
|
+
OpenStruct.new(name: 'int_param', value: 1),
|
95
|
+
OpenStruct.new(name: 'empty_param', value: nil),
|
96
|
+
OpenStruct.new(name: 'empty_str_param', value: ''),
|
97
|
+
]
|
98
|
+
)
|
99
|
+
|
100
|
+
generator = create_generator
|
101
|
+
actual = generator.generate_parameters.group_by { |key, value| key }
|
102
|
+
|
103
|
+
assert_equal 0, actual.count
|
104
|
+
end
|
105
|
+
|
65
106
|
private
|
66
107
|
|
67
108
|
def create_generator
|
data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/EmptyState.js
CHANGED
@@ -9,7 +9,7 @@ const inventoryEmptyState = () => (
|
|
9
9
|
<EmptyState.Title>
|
10
10
|
{__('Fetching data about your accounts')}
|
11
11
|
</EmptyState.Title>
|
12
|
-
<EmptyState.Info>{__('Loading')}
|
12
|
+
<EmptyState.Info>{__('Loading...')}</EmptyState.Info>
|
13
13
|
</EmptyState>
|
14
14
|
);
|
15
15
|
|
@@ -2,12 +2,14 @@ import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import { Grid, Button, Icon } from 'patternfly-react';
|
4
4
|
import { noop } from 'foremanReact/common/helpers';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
|
5
7
|
import './fileDownload.scss';
|
6
8
|
|
7
9
|
const FileDownload = ({ onClick }) => (
|
8
10
|
<Grid.Col sm={12}>
|
9
11
|
<Button onClick={onClick} className="download-button">
|
10
|
-
Download Report <Icon name="download" />
|
12
|
+
{__('Download Report')} <Icon name="download" />
|
11
13
|
</Button>
|
12
14
|
</Grid.Col>
|
13
15
|
);
|
@@ -15,8 +15,7 @@ const InventoryFilter = ({
|
|
15
15
|
organization,
|
16
16
|
}) => {
|
17
17
|
useEffect(() => {
|
18
|
-
const initialTerm =
|
19
|
-
organization === __(ANY_ORGANIZATION) ? '' : organization;
|
18
|
+
const initialTerm = organization === ANY_ORGANIZATION ? '' : organization;
|
20
19
|
handleFilterChange(initialTerm);
|
21
20
|
}, []);
|
22
21
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
2
|
+
|
1
3
|
export const INVENTORY_FILTER_UPDATE = 'INVENTORY_FILTER_UPDATE';
|
2
4
|
export const INVENTORY_FILTER_CLEAR = 'INVENTORY_FILTER_CLEAR';
|
3
|
-
export const ANY_ORGANIZATION = 'Any Organization';
|
5
|
+
export const ANY_ORGANIZATION = __('Any Organization');
|
@@ -28,7 +28,7 @@ export const PageDescription = () => (
|
|
28
28
|
target="_blank"
|
29
29
|
rel="noopener noreferrer"
|
30
30
|
>
|
31
|
-
About subscription watch
|
31
|
+
{__('About subscription watch')}
|
32
32
|
</a>
|
33
33
|
</p>
|
34
34
|
<p>
|
@@ -39,7 +39,7 @@ export const PageDescription = () => (
|
|
39
39
|
target="_blank"
|
40
40
|
rel="noopener noreferrer"
|
41
41
|
>
|
42
|
-
Red Hat Insights Data and Application Security
|
42
|
+
{__('Red Hat Insights Data and Application Security')}
|
43
43
|
</a>
|
44
44
|
</p>
|
45
45
|
</div>
|
data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js
CHANGED
@@ -20,13 +20,13 @@ const Toast = ({ syncHosts, disconnectHosts }) => {
|
|
20
20
|
<strong>{disconnectHosts}</strong>
|
21
21
|
</p>
|
22
22
|
<p>
|
23
|
-
For more info, please visit the{' '}
|
23
|
+
{__('For more info, please visit the')}{' '}
|
24
24
|
<a
|
25
25
|
href={foremanUrl('/hosts')}
|
26
26
|
target="_blank"
|
27
27
|
rel="noopener noreferrer"
|
28
28
|
>
|
29
|
-
hosts page
|
29
|
+
{__('hosts page')}
|
30
30
|
</a>
|
31
31
|
</p>
|
32
32
|
</span>
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import { Grid, DonutChart } from 'patternfly-react';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
5
|
import './statusChart.scss';
|
5
6
|
|
6
7
|
const StatusChart = ({ completed }) => {
|
7
8
|
const donutConfigData = {
|
8
9
|
columns: [
|
9
|
-
['Completed', completed],
|
10
|
-
['Remain', 100 - completed],
|
10
|
+
[__('Completed'), completed],
|
11
|
+
[__('Remain'), 100 - completed],
|
11
12
|
],
|
12
13
|
order: null,
|
13
14
|
};
|
@@ -37,7 +38,7 @@ const StatusChart = ({ completed }) => {
|
|
37
38
|
title={{
|
38
39
|
type: 'percent',
|
39
40
|
primary: `${completed}%`,
|
40
|
-
secondary: 'Completed',
|
41
|
+
secondary: __('Completed'),
|
41
42
|
}}
|
42
43
|
/>
|
43
44
|
</div>
|
@@ -41,7 +41,9 @@ const InventoryAutoUploadSwitcher = ({
|
|
41
41
|
|
42
42
|
<Grid.Col sm={5}>
|
43
43
|
<Popover
|
44
|
-
headerContent={
|
44
|
+
headerContent={
|
45
|
+
<strong>{__('Advanced Inventory Settings')}</strong>
|
46
|
+
}
|
45
47
|
bodyContent={
|
46
48
|
<AdvancedSettings
|
47
49
|
autoUploadEnabled={autoUploadEnabled}
|
@@ -17,7 +17,7 @@ class InsightsSyncSwitcher extends Component {
|
|
17
17
|
|
18
18
|
return (
|
19
19
|
<div className="insights_sync_switcher">
|
20
|
-
<span>Synchronize Automatically</span>
|
20
|
+
<span>{__('Synchronize Automatically')}</span>
|
21
21
|
<FieldLevelHelp
|
22
22
|
content={__(
|
23
23
|
'Enable automatic synchronization of Insights recommendations from the Red Hat cloud'
|
@@ -5,7 +5,7 @@ import { Pagination, PaginationVariant } from '@patternfly/react-core';
|
|
5
5
|
import { Table, TableHeader, TableBody } from '@patternfly/react-table';
|
6
6
|
import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
|
7
7
|
import SelectAllAlert from './SelectAllAlert';
|
8
|
-
import { columns } from './InsightsTableConstants';
|
8
|
+
import { columns, paginationTitles } from './InsightsTableConstants';
|
9
9
|
import TableEmptyState from '../../../common/table/EmptyState';
|
10
10
|
import {
|
11
11
|
modifySelectedRows,
|
@@ -82,6 +82,7 @@ const InsightsTable = ({
|
|
82
82
|
onSetPage={onTableSetPage}
|
83
83
|
onPerPageSelect={onTablePerPageSelect}
|
84
84
|
perPageOptions={getPerPageOptions(urlPerPage, appPerPage)}
|
85
|
+
titles={paginationTitles}
|
85
86
|
/>
|
86
87
|
</React.Fragment>
|
87
88
|
);
|
@@ -45,6 +45,20 @@ export const columns = [
|
|
45
45
|
},
|
46
46
|
];
|
47
47
|
|
48
|
+
export const paginationTitles = {
|
49
|
+
items: __('items'),
|
50
|
+
page: __('page'),
|
51
|
+
itemsPerPage: __('Items per page'),
|
52
|
+
perPageSuffix: __('per page'),
|
53
|
+
toFirstPage: __('Go to first page'),
|
54
|
+
toPreviousPage: __('Go to previous page'),
|
55
|
+
toLastPage: __('Go to last page'),
|
56
|
+
toNextPage: __('Go to next page'),
|
57
|
+
optionsToggle: __('Items per page'),
|
58
|
+
currPage: __('Current page'),
|
59
|
+
paginationTitle: __('Pagination'),
|
60
|
+
};
|
61
|
+
|
48
62
|
export const INSIGHTS_HITS_PATH = foremanUrl('/insights_cloud/hits');
|
49
63
|
|
50
64
|
export const INSIGHTS_HITS_API_KEY = 'INSIGHTS_HITS';
|
@@ -18,7 +18,7 @@ const SelectAllAlert = ({
|
|
18
18
|
<Alert
|
19
19
|
isInline
|
20
20
|
variant="info"
|
21
|
-
title={sprintf('Recommendations selected: %s.', selectedCount)}
|
21
|
+
title={sprintf(__('Recommendations selected: %s.'), selectedCount)}
|
22
22
|
actionLinks={
|
23
23
|
<AlertActionLink onClick={selectAll}>
|
24
24
|
{__('Select recommendations from all pages')}
|
@@ -135,10 +135,10 @@ exports[`InsightsTable rendering render with Props 1`] = `
|
|
135
135
|
titles={
|
136
136
|
Object {
|
137
137
|
"currPage": "Current page",
|
138
|
-
"items": "",
|
138
|
+
"items": "items",
|
139
139
|
"itemsPerPage": "Items per page",
|
140
140
|
"optionsToggle": "Items per page",
|
141
|
-
"page": "",
|
141
|
+
"page": "page",
|
142
142
|
"paginationTitle": "Pagination",
|
143
143
|
"perPageSuffix": "per page",
|
144
144
|
"toFirstPage": "Go to first page",
|
@@ -6,4 +6,18 @@
|
|
6
6
|
margin-top: 5px;
|
7
7
|
}
|
8
8
|
}
|
9
|
+
|
10
|
+
// applies to the backdrop parent of the modal
|
11
|
+
@at-root .pf-c-backdrop {
|
12
|
+
width: calc(100% - 200px);
|
13
|
+
left: 200px;
|
14
|
+
}
|
15
|
+
|
16
|
+
// where the vertical nav breaks: https://github.com/theforeman/foreman/blob/3347fa49d500964f0209122d8d36c920d1feafcc/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss#L26
|
17
|
+
@media (max-width: 768px) {
|
18
|
+
@at-root .pf-c-backdrop {
|
19
|
+
width: 100%;
|
20
|
+
left: 0;
|
21
|
+
}
|
22
|
+
}
|
9
23
|
}
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
3
3
|
import { orderBy } from 'lodash';
|
4
4
|
import { Grid, ListView } from 'patternfly-react';
|
5
5
|
import { noop } from 'foremanReact/common/helpers';
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
7
|
import ListItem from './components/ListItem';
|
7
8
|
import './InsightsTab.scss';
|
8
9
|
|
@@ -16,7 +17,7 @@ class InsightsHostDetailsTab extends React.Component {
|
|
16
17
|
const { hits } = this.props;
|
17
18
|
|
18
19
|
if (!hits.length) {
|
19
|
-
return <h2>No recommendations were found for this host
|
20
|
+
return <h2>{__('No recommendations were found for this host!')}</h2>;
|
20
21
|
}
|
21
22
|
const hitsSorted = orderBy(hits, ['total_risk'], ['desc']);
|
22
23
|
const items = hitsSorted.map(
|
@@ -42,7 +43,7 @@ class InsightsHostDetailsTab extends React.Component {
|
|
42
43
|
<div id="host_details_insights_tab">
|
43
44
|
<Grid.Row>
|
44
45
|
<Grid.Col xs={12}>
|
45
|
-
<h2>Recommendations</h2>
|
46
|
+
<h2>{__('Recommendations')}</h2>
|
46
47
|
<ListView id="hits_list">{items}</ListView>
|
47
48
|
</Grid.Col>
|
48
49
|
</Grid.Row>
|
@@ -48,19 +48,19 @@
|
|
48
48
|
padding: 5px 8px;
|
49
49
|
border-radius: 12px;
|
50
50
|
|
51
|
-
&.
|
51
|
+
&.risk-1 {
|
52
52
|
background-color: #e7f1fa;
|
53
53
|
}
|
54
54
|
|
55
|
-
&.
|
55
|
+
&.risk-2 {
|
56
56
|
background-color: #fdf7e7;
|
57
57
|
}
|
58
58
|
|
59
|
-
&.
|
59
|
+
&.risk-3 {
|
60
60
|
background-color: #f9dddd;
|
61
61
|
}
|
62
62
|
|
63
|
-
&.
|
63
|
+
&.risk-4 {
|
64
64
|
background-color: #ffecec;
|
65
65
|
}
|
66
66
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import React, { Fragment } from 'react';
|
2
2
|
import { ListView, Icon } from 'patternfly-react';
|
3
3
|
import PropTypes from 'prop-types';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
5
|
|
5
6
|
const labelMapper = {
|
6
|
-
1: 'Low',
|
7
|
-
2: 'Moderate',
|
8
|
-
3: 'Important',
|
9
|
-
4: 'Critical',
|
7
|
+
1: __('Low'),
|
8
|
+
2: __('Moderate'),
|
9
|
+
3: __('Important'),
|
10
|
+
4: __('Critical'),
|
10
11
|
};
|
11
12
|
|
12
13
|
const ListItem = ({ title, totalRisk, resultsUrl, solutionUrl }) => {
|
@@ -18,7 +19,7 @@ const ListItem = ({ title, totalRisk, resultsUrl, solutionUrl }) => {
|
|
18
19
|
|
19
20
|
const riskLabel = labelMapper[totalRisk];
|
20
21
|
const additionalInfo = [
|
21
|
-
<span key={`risk-info-${title}`} className={`risk-label
|
22
|
+
<span key={`risk-info-${title}`} className={`risk-label risk-${totalRisk}`}>
|
22
23
|
<p>{riskLabel}</p>
|
23
24
|
</span>,
|
24
25
|
];
|
@@ -26,7 +27,7 @@ const ListItem = ({ title, totalRisk, resultsUrl, solutionUrl }) => {
|
|
26
27
|
const knowledgebaseLink = solutionUrl && (
|
27
28
|
<p>
|
28
29
|
<a href={solutionUrl} target="_blank" rel="noopener noreferrer">
|
29
|
-
Knowledgebase article <Icon name="external-link" />
|
30
|
+
{__('Knowledgebase article')} <Icon name="external-link" />
|
30
31
|
</a>
|
31
32
|
</p>
|
32
33
|
);
|
@@ -34,7 +35,8 @@ const ListItem = ({ title, totalRisk, resultsUrl, solutionUrl }) => {
|
|
34
35
|
const insightsCloudLink = resultsUrl && (
|
35
36
|
<p>
|
36
37
|
<a href={resultsUrl} target="_blank" rel="noopener noreferrer">
|
37
|
-
Read more about it in RH cloud insights
|
38
|
+
{__('Read more about it in RH cloud insights')}{' '}
|
39
|
+
<Icon name="external-link" />
|
38
40
|
</a>
|
39
41
|
</p>
|
40
42
|
);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_rh_cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.25
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Foreman Red Hat Cloud team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: katello
|