foreman_rh_cloud 4.0.23 → 4.0.25.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/foreman_inventory_upload/cloud_status_controller.rb +26 -0
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +15 -7
- data/app/controllers/insights_cloud/hits_controller.rb +0 -1
- data/app/models/insights_client_report_status.rb +11 -22
- data/app/services/foreman_rh_cloud/cloud_auth.rb +4 -0
- data/app/services/foreman_rh_cloud/cloud_ping_service.rb +83 -0
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +1 -9
- data/app/services/foreman_rh_cloud/insights_status_cleaner.rb +17 -0
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +5 -0
- data/config/Gemfile.lock.gh_test +0 -8
- data/config/rh_cert-api_chain.pem +74 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20210720000001_remove_old_insights_statuses.foreman_rh_cloud.rb +6 -0
- data/lib/foreman_inventory_upload.rb +9 -1
- data/lib/foreman_inventory_upload/generators/queries.rb +1 -16
- data/lib/foreman_inventory_upload/generators/slice.rb +1 -0
- data/lib/foreman_inventory_upload/generators/tags.rb +3 -1
- data/lib/foreman_rh_cloud.rb +4 -0
- data/lib/foreman_rh_cloud/engine.rb +14 -12
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud.rb +4 -0
- data/lib/insights_cloud/async/insights_client_status_aging.rb +23 -0
- 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/host_result.rb +4 -0
- data/lib/inventory_sync/async/inventory_full_sync.rb +5 -0
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +15 -0
- data/lib/inventory_sync/async/inventory_self_host_sync.rb +39 -0
- data/lib/inventory_sync/async/query_inventory_job.rb +5 -1
- data/lib/tasks/insights.rake +15 -0
- data/lib/tasks/rh_cloud_inventory.rake +2 -9
- data/package.json +2 -2
- data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +45 -0
- data/test/controllers/inventory_upload/cloud_status_controller_test.rb +44 -0
- data/test/jobs/insights_client_status_aging_test.rb +33 -0
- 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 +3 -0
- data/test/jobs/inventory_self_host_sync_test.rb +104 -0
- data/test/models/insights_client_report_status_test.rb +70 -72
- data/test/test_plugin_helper.rb +53 -0
- data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +6 -37
- data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +66 -0
- data/test/unit/services/foreman_rh_cloud/insights_status_cleaner_test.rb +31 -0
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -0
- data/test/unit/slice_generator_test.rb +15 -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/InventorySettings/InventorySettings.scss +0 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +12 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +10 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +144 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +5 -0
- 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/ForemanInventoryConstants.js +2 -0
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
- data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +5 -1
- data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +6 -4
- data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +9 -5
- data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +6 -6
- data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +0 -14
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +4 -22
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +25 -4
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +51 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +3 -68
- data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +10 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +11 -10
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +14 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +0 -2
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +32 -0
- data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +5 -4
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +17 -13
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +82 -2
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +15 -6
- data/webpack/InsightsHostDetailsTab/InsightsTab.js +3 -2
- data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -4
- data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +9 -7
- data/webpack/common/Switcher/SwitcherPF4.js +1 -1
- data/webpack/common/Switcher/SwitcherPF4.scss +6 -7
- data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -1
- metadata +23 -24
- data/app/subscribers/foreman_rh_cloud/insights_subscriber.rb +0 -9
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.fixtures.js +0 -1
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +0 -45
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/InsightsSyncSwitcher.test.js +0 -17
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/__snapshots__/InsightsSyncSwitcher.test.js.snap +0 -38
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/index.js +0 -1
- data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/insightsSyncSwitcher.scss +0 -3
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +0 -59
@@ -2,7 +2,8 @@
|
|
2
2
|
import React, { useEffect } from 'react';
|
3
3
|
import PropTypes from 'prop-types';
|
4
4
|
import { Table, TableHeader, TableBody } from '@patternfly/react-table';
|
5
|
-
import { Modal, ModalVariant } from '@patternfly/react-core';
|
5
|
+
import { Modal, ModalVariant, Button } from '@patternfly/react-core';
|
6
|
+
import { isEmpty } from 'lodash';
|
6
7
|
import { STATUS } from 'foremanReact/constants';
|
7
8
|
import { translate as __ } from 'foremanReact/common/I18n';
|
8
9
|
import { columns } from './RemediationTableConstants';
|
@@ -10,7 +11,6 @@ import { modifyRows } from './RemediationHelpers';
|
|
10
11
|
import ModalFooter from './RemediationModalFooter';
|
11
12
|
import TableEmptyState from '../../../common/table/EmptyState';
|
12
13
|
import './RemediationModal.scss';
|
13
|
-
import RemediateButton from './RemediateButton';
|
14
14
|
|
15
15
|
const RemediationModal = ({
|
16
16
|
selectedIds,
|
@@ -20,7 +20,6 @@ const RemediationModal = ({
|
|
20
20
|
error,
|
21
21
|
isAllSelected,
|
22
22
|
query,
|
23
|
-
isExperimentalMode,
|
24
23
|
}) => {
|
25
24
|
const [rows, setRows] = React.useState([]);
|
26
25
|
const [open, setOpen] = React.useState(false);
|
@@ -42,11 +41,15 @@ const RemediationModal = ({
|
|
42
41
|
|
43
42
|
return (
|
44
43
|
<React.Fragment>
|
45
|
-
<
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
<Button
|
45
|
+
variant="primary"
|
46
|
+
isDisabled={isEmpty(selectedIds)}
|
47
|
+
onClick={() => {
|
48
|
+
toggleModal();
|
49
|
+
}}
|
50
|
+
>
|
51
|
+
{__('Remediate')}
|
52
|
+
</Button>{' '}
|
50
53
|
<Modal
|
51
54
|
id="remediation-modal"
|
52
55
|
appendTo={document.body}
|
@@ -85,7 +88,6 @@ RemediationModal.propTypes = {
|
|
85
88
|
error: PropTypes.string,
|
86
89
|
isAllSelected: PropTypes.bool,
|
87
90
|
query: PropTypes.string,
|
88
|
-
isExperimentalMode: PropTypes.bool,
|
89
91
|
};
|
90
92
|
|
91
93
|
RemediationModal.defaultProps = {
|
@@ -95,7 +97,6 @@ RemediationModal.defaultProps = {
|
|
95
97
|
error: null,
|
96
98
|
isAllSelected: false,
|
97
99
|
query: null,
|
98
|
-
isExperimentalMode: false,
|
99
100
|
};
|
100
101
|
|
101
102
|
export default RemediationModal;
|
@@ -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
|
}
|
@@ -9,7 +9,6 @@ import * as actions from './RemediationActions';
|
|
9
9
|
import RemediationModal from './RemediationModal';
|
10
10
|
import { REMEDIATIONS_API_KEY } from './RemediationTableConstants';
|
11
11
|
import {
|
12
|
-
selectExperimental,
|
13
12
|
selectIsAllSelected,
|
14
13
|
selectSearch,
|
15
14
|
selectSelectedIds,
|
@@ -24,7 +23,6 @@ const mapStateToProps = state => ({
|
|
24
23
|
itemCount: selectAPIResponse(state, REMEDIATIONS_API_KEY).itemCount || 0,
|
25
24
|
isAllSelected: selectIsAllSelected(state),
|
26
25
|
query: selectSearch(state),
|
27
|
-
isExperimentalMode: selectExperimental(state),
|
28
26
|
});
|
29
27
|
|
30
28
|
// map action dispatchers to props
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
import { Dropdown, DropdownItem, KebabToggle } from '@patternfly/react-core';
|
5
|
+
|
6
|
+
const ToolbarDropdown = ({ onRecommendationSync }) => {
|
7
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
8
|
+
const dropdownItems = [
|
9
|
+
<DropdownItem
|
10
|
+
key="recommendation-manual-sync"
|
11
|
+
onClick={onRecommendationSync}
|
12
|
+
>
|
13
|
+
{__('Sync recommendations')}
|
14
|
+
</DropdownItem>,
|
15
|
+
];
|
16
|
+
return (
|
17
|
+
<Dropdown
|
18
|
+
className="title-dropdown"
|
19
|
+
onSelect={() => setIsDropdownOpen(false)}
|
20
|
+
toggle={<KebabToggle onToggle={isOpen => setIsDropdownOpen(isOpen)} />}
|
21
|
+
isOpen={isDropdownOpen}
|
22
|
+
isPlain
|
23
|
+
dropdownItems={dropdownItems}
|
24
|
+
/>
|
25
|
+
);
|
26
|
+
};
|
27
|
+
|
28
|
+
ToolbarDropdown.propTypes = {
|
29
|
+
onRecommendationSync: PropTypes.func.isRequired,
|
30
|
+
};
|
31
|
+
|
32
|
+
export default ToolbarDropdown;
|
data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap
CHANGED
@@ -5,9 +5,10 @@ exports[`InsightsHeader render 1`] = `
|
|
5
5
|
className="insights-header"
|
6
6
|
>
|
7
7
|
<Connect(InsightsSettings) />
|
8
|
-
<
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
<Text
|
9
|
+
component="p"
|
10
|
+
>
|
11
|
+
Insights synchronization process is used to provide Insights recommendations output for hosts managed here.
|
12
|
+
</Text>
|
12
13
|
</div>
|
13
14
|
`;
|
@@ -1,7 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { Button } from '@patternfly/react-core';
|
3
2
|
import PropTypes from 'prop-types';
|
4
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
5
3
|
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
6
4
|
import InsightsHeader from './Components/InsightsHeader';
|
7
5
|
import { NoTokenEmptyState } from './Components/NoTokenEmptyState';
|
@@ -12,6 +10,8 @@ import {
|
|
12
10
|
INSIGHTS_SEARCH_PROPS,
|
13
11
|
} from './InsightsCloudSyncConstants';
|
14
12
|
import './InsightsCloudSync.scss';
|
13
|
+
import Pagination from './Components/InsightsTable/Pagination';
|
14
|
+
import ToolbarDropdown from './Components/ToolbarDropdown';
|
15
15
|
|
16
16
|
const InsightsCloudSync = ({
|
17
17
|
syncInsights,
|
@@ -26,6 +26,20 @@ const InsightsCloudSync = ({
|
|
26
26
|
</PageLayout>
|
27
27
|
);
|
28
28
|
}
|
29
|
+
|
30
|
+
const onRecommendationSync = () => syncInsights(fetchInsights, query);
|
31
|
+
const toolbarButtons = (
|
32
|
+
<>
|
33
|
+
<span className="insights-toolbar-buttons">
|
34
|
+
<RemediationModal />
|
35
|
+
<ToolbarDropdown onRecommendationSync={onRecommendationSync} />
|
36
|
+
</span>
|
37
|
+
<span className="pull-right">
|
38
|
+
<Pagination variant="top" isCompact />
|
39
|
+
</span>
|
40
|
+
</>
|
41
|
+
);
|
42
|
+
|
29
43
|
return (
|
30
44
|
<div className="rh-cloud-insights">
|
31
45
|
<PageLayout
|
@@ -33,17 +47,7 @@ const InsightsCloudSync = ({
|
|
33
47
|
searchProps={INSIGHTS_SEARCH_PROPS}
|
34
48
|
onSearch={nextQuery => fetchInsights({ query: nextQuery, page: 1 })}
|
35
49
|
header={INSIGHTS_SYNC_PAGE_TITLE}
|
36
|
-
toolbarButtons={
|
37
|
-
<>
|
38
|
-
<RemediationModal />
|
39
|
-
<Button
|
40
|
-
variant="secondary"
|
41
|
-
onClick={() => syncInsights(fetchInsights, query)}
|
42
|
-
>
|
43
|
-
{__('Start recommendations sync')}
|
44
|
-
</Button>
|
45
|
-
</>
|
46
|
-
}
|
50
|
+
toolbarButtons={toolbarButtons}
|
47
51
|
searchQuery={query}
|
48
52
|
beforeToolbarComponent={<InsightsHeader />}
|
49
53
|
>
|
@@ -1,5 +1,85 @@
|
|
1
1
|
.rh-cloud-insights {
|
2
|
-
|
3
|
-
|
2
|
+
#main {
|
3
|
+
padding: 4px;
|
4
|
+
|
5
|
+
#breadcrumb .form-group {
|
6
|
+
margin-bottom: 0;
|
7
|
+
|
8
|
+
h1 {
|
9
|
+
font-family: 'RedHatDisplay';
|
10
|
+
font-weight: 400;
|
11
|
+
margin-bottom: 8px;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
.title_filter {
|
16
|
+
width: 520px;
|
17
|
+
}
|
18
|
+
|
19
|
+
#title_action {
|
20
|
+
width: calc(100% - 520px);
|
21
|
+
}
|
22
|
+
|
23
|
+
@media (max-width: 1138px) {
|
24
|
+
#title_action {
|
25
|
+
width: 70%;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
.search-bar {
|
30
|
+
// Giving pf3 search bar a pf4 look
|
31
|
+
width: 500px;
|
32
|
+
.search-bar {
|
33
|
+
display: block;
|
34
|
+
}
|
35
|
+
.input-group {
|
36
|
+
display: table;
|
37
|
+
}
|
38
|
+
.input-group-btn {
|
39
|
+
.btn-group {
|
40
|
+
z-index: unset; // so the bookmarks drop down will be above other search boxes
|
41
|
+
}
|
42
|
+
.autocomplete-search-btn {
|
43
|
+
display: none;
|
44
|
+
}
|
45
|
+
.dropdown-toggle {
|
46
|
+
font-size: 16px;
|
47
|
+
background-color: white;
|
48
|
+
background-image: none;
|
49
|
+
padding-bottom: 4px;
|
50
|
+
padding-top: 4px;
|
51
|
+
}
|
52
|
+
.scrollable-dropdown {
|
53
|
+
max-width: 250px;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
li {
|
57
|
+
font-size: 16px;
|
58
|
+
}
|
59
|
+
input {
|
60
|
+
font-size: 16px;
|
61
|
+
height: 36px;
|
62
|
+
}
|
63
|
+
.foreman-autocomplete .autocomplete-focus-shortcut {
|
64
|
+
top: 8px;
|
65
|
+
font-size: 16px;
|
66
|
+
}
|
67
|
+
.foreman-autocomplete .autocomplete-aux {
|
68
|
+
top: 8px;
|
69
|
+
font-size: 16px;
|
70
|
+
.autocomplete-clear-button {
|
71
|
+
font-size: 16px;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
.btn-toolbar {
|
77
|
+
display: inherit;
|
78
|
+
width: 100%;
|
79
|
+
}
|
80
|
+
|
81
|
+
.pf-c-pagination {
|
82
|
+
padding-right: 0;
|
83
|
+
}
|
4
84
|
}
|
5
85
|
}
|
@@ -28,13 +28,22 @@ exports[`InsightsCloudSync render 1`] = `
|
|
28
28
|
searchable={true}
|
29
29
|
toolbarButtons={
|
30
30
|
<React.Fragment>
|
31
|
-
<
|
32
|
-
|
33
|
-
onClick={[Function]}
|
34
|
-
variant="secondary"
|
31
|
+
<span
|
32
|
+
className="insights-toolbar-buttons"
|
35
33
|
>
|
36
|
-
|
37
|
-
|
34
|
+
<UNDEFINED />
|
35
|
+
<ToolbarDropdown
|
36
|
+
onRecommendationSync={[Function]}
|
37
|
+
/>
|
38
|
+
</span>
|
39
|
+
<span
|
40
|
+
className="pull-right"
|
41
|
+
>
|
42
|
+
<Pagination
|
43
|
+
isCompact={true}
|
44
|
+
variant="top"
|
45
|
+
/>
|
46
|
+
</span>
|
38
47
|
</React.Fragment>
|
39
48
|
}
|
40
49
|
>
|
@@ -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
|
);
|
@@ -6,7 +6,7 @@ import './SwitcherPF4.scss';
|
|
6
6
|
|
7
7
|
const SwitcherPF4 = ({ id, label, tooltip, isChecked, onChange }) => (
|
8
8
|
<Switch
|
9
|
-
className="foreman-switcher"
|
9
|
+
className="foreman-rh-cloud-switcher"
|
10
10
|
id={`rh-cloud-switcher-${id}`}
|
11
11
|
isChecked={isChecked}
|
12
12
|
onChange={onChange}
|
@@ -1,10 +1,9 @@
|
|
1
|
-
.rh-cloud-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
label.foreman-rh-cloud-switcher {
|
2
|
+
display: block;
|
3
|
+
font-weight: 400;
|
4
|
+
margin-bottom: 5px;
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
}
|
6
|
+
.switcher-help-label {
|
7
|
+
padding-left: 5px;
|
9
8
|
}
|
10
9
|
}
|