diff --git a/.eslintrc b/.eslintrc
index 5ebc30109..bf7886e16 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -14,8 +14,10 @@
"advisor",
"ansible",
"camelcase",
+ "cdn",
"checkbox",
"csrf",
+ "cve",
"cves",
"dropdown",
"donut",
@@ -23,6 +25,7 @@
"href",
"ips",
"ipv4",
+ "dropdown",
"jed",
"katello",
"knowledgebase",
@@ -31,15 +34,15 @@
"nowrap",
"pid",
"redhat",
+ "redux",
"remediate",
"remediations",
"repo",
"rhc",
+ "scalprum",
"theforeman",
"tooltip",
- "unmount",
- "redux",
- "dropdown"
+ "unmount"
],
"minLength": 3
}
diff --git a/package.json b/package.json
index 43479e9e8..f2be22cd4 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,10 @@
"peerDependencies": {
"@theforeman/vendor": ">= 15.0.1"
},
+ "dependencies": {
+ "@scalprum/react-core": "^0.9.3",
+ "@scalprum/core": "^0.8.1"
+ },
"devDependencies": {
"@babel/core": "^7.7.0",
"@theforeman/builder": ">= 15.0.1",
diff --git a/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js b/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js
index 3241c5c9f..e719d5f7d 100644
--- a/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js
+++ b/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js
@@ -1,17 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { translate as __ } from 'foremanReact/common/I18n';
+import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core';
+import { providerOptions } from '../common/ScalprumModule/ScalprumContext';
-const CVEsHostDetailsTab = ({ hostName }) => (
-
-
- {__('CVEs tab for host:')} {hostName}
-
-
-);
+const CVEsHostDetailsTab = ({ systemId }) => {
+ const scope = 'vulnerability';
+ const module = './SystemDetailTable';
+ return (
+
+
+
+ );
+};
CVEsHostDetailsTab.propTypes = {
- hostName: PropTypes.string.isRequired,
+ systemId: PropTypes.string.isRequired,
+};
+
+const CVEsHostDetailsTabWrapper = ({ response }) => (
+
+
+
+);
+
+CVEsHostDetailsTabWrapper.propTypes = {
+ response: PropTypes.shape({
+ subscription_facet_attributes: PropTypes.shape({
+ uuid: PropTypes.string.isRequired,
+ }),
+ }).isRequired,
};
-export default CVEsHostDetailsTab;
+export default CVEsHostDetailsTabWrapper;
diff --git a/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js b/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js
index 42ebf8ee4..be22e2b08 100644
--- a/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js
+++ b/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js
@@ -1,18 +1,25 @@
import React from 'react';
-import { render, screen } from '@testing-library/react';
-import CVEsHostDetailsTab from '../CVEsHostDetailsTab';
+import { render } from '@testing-library/react';
+import CVEsHostDetailsTabWrapper from '../CVEsHostDetailsTab';
-describe('CVEsHostDetailsTab', () => {
+jest.mock('@scalprum/react-core', () => ({
+ ScalprumComponent: jest.fn(props => (
+ {JSON.stringify(props)}
+ )),
+ ScalprumProvider: jest.fn(({ children }) => {children}
),
+}));
+
+describe('CVEsHostDetailsTabWrapper', () => {
it('renders without crashing', () => {
- render();
+ const { container } = render(
+
+ );
expect(
- screen.getByText('CVEs tab for host: test-host.example.com')
+ container.querySelector(
+ '.rh-cloud-insights-vulnerability-host-details-component'
+ )
).toBeTruthy();
});
-
- it('renders the host name', () => {
- const hostName = 'test-host.example.com';
- render();
- expect(screen.getByText(`CVEs tab for host: ${hostName}`)).toBeTruthy();
- });
});
diff --git a/webpack/CVEsHostDetailsTab/index.js b/webpack/CVEsHostDetailsTab/index.js
index e67c6a77e..401a6f39b 100644
--- a/webpack/CVEsHostDetailsTab/index.js
+++ b/webpack/CVEsHostDetailsTab/index.js
@@ -1,3 +1,3 @@
-import CVEsHostDetailsTab from './CVEsHostDetailsTab';
+import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab';
-export default CVEsHostDetailsTab;
+export default CVEsHostDetailsTabWrapper;
diff --git a/webpack/ForemanRhCloudFills.js b/webpack/ForemanRhCloudFills.js
index a64ff9217..088908504 100644
--- a/webpack/ForemanRhCloudFills.js
+++ b/webpack/ForemanRhCloudFills.js
@@ -5,7 +5,7 @@ import InventoryAutoUploadSwitcher from './ForemanInventoryUpload/SubscriptionsP
import NewHostDetailsTab from './InsightsHostDetailsTab/NewHostDetailsTab';
import { InsightsTotalRiskChartWrapper } from './InsightsHostDetailsTab/InsightsTotalRiskChartWrapper';
import { isNotRhelHost, vulnerabilityDisabled } from './ForemanRhCloudHelpers';
-import CVEsHostDetailsTab from './CVEsHostDetailsTab/CVEsHostDetailsTab';
+import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab/CVEsHostDetailsTab';
const fills = [
{
@@ -32,11 +32,12 @@ const fills = [
},
{
slot: 'host-details-page-tabs',
- name: 'CVEs',
- component: props => ,
+ name: 'Vulnerabilities',
+ component: props => ,
weight: 300,
metadata: {
hideTab: vulnerabilityDisabled,
+ title: __('Vulnerabilities'),
},
},
];
diff --git a/webpack/ForemanRhCloudPages.js b/webpack/ForemanRhCloudPages.js
index 988442afb..2cb3512cc 100644
--- a/webpack/ForemanRhCloudPages.js
+++ b/webpack/ForemanRhCloudPages.js
@@ -2,7 +2,7 @@ import React from 'react';
import componentRegistry from 'foremanReact/components/componentRegistry';
import { registerRoutes as foremanRegisterRoutes } from 'foremanReact/routes/RoutingService';
import ForemanInventoryUpload from './ForemanInventoryUpload';
-import InsightsVulnerability from './InsightsVulnerability/InsightsVulnerability';
+import InsightsVulnerabilityListPage from './InsightsVulnerability/InsightsVulnerabilityListPage';
import InsightsCloudSync from './InsightsCloudSync';
import InsightsHostDetailsTab from './InsightsHostDetailsTab';
@@ -10,7 +10,10 @@ const pages = [
{ name: 'ForemanInventoryUpload', type: ForemanInventoryUpload },
{ name: 'InsightsCloudSync', type: InsightsCloudSync },
{ name: 'InsightsHostDetailsTab', type: InsightsHostDetailsTab },
- { name: 'InsightsVulnerability', type: InsightsVulnerability },
+ {
+ name: 'InsightsVulnerabilityListPage',
+ type: InsightsVulnerabilityListPage,
+ },
];
export const registerPages = () => {
@@ -31,7 +34,7 @@ export const routes = [
{
path: '/foreman_rh_cloud/insights_vulnerability',
exact: true,
- render: props => ,
+ render: props => ,
},
];
diff --git a/webpack/InsightsVulnerability/InsightsVulnerability.js b/webpack/InsightsVulnerability/InsightsVulnerability.js
deleted file mode 100644
index a77325dd4..000000000
--- a/webpack/InsightsVulnerability/InsightsVulnerability.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
-import { translate as __ } from 'foremanReact/common/I18n';
-
-const InsightsVulnerability = () => (
-
-
-
This page is under development. Please check back soon for updates.
-
-
-);
-
-export default InsightsVulnerability;
diff --git a/webpack/InsightsVulnerability/InsightsVulnerability.test.js b/webpack/InsightsVulnerability/InsightsVulnerability.test.js
deleted file mode 100644
index 479448c45..000000000
--- a/webpack/InsightsVulnerability/InsightsVulnerability.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import '@testing-library/jest-dom';
-import InsightsVulnerability from './InsightsVulnerability';
-
-describe('InsightsVulnerability component', () => {
- it('renders the "under development" message', () => {
- render();
- expect(
- screen.getByText(/this page is under development/i)
- ).toBeInTheDocument();
- });
-
- it('renders the container with correct class', () => {
- const { container } = render();
- expect(container.querySelector('.insights-vulnerability')).toBeTruthy();
- });
-});
diff --git a/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js
new file mode 100644
index 000000000..fc17c3979
--- /dev/null
+++ b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import { ScalprumComponent, ScalprumProvider } from '@scalprum/react-core';
+import { providerOptions } from '../common/ScalprumModule/ScalprumContext';
+
+const InsightsVulnerabilityListPage = () => {
+ const scope = 'vulnerability';
+ const module = './CveListPage';
+ return (
+
+
+
+ );
+};
+
+const InsightsVulnerabilityListPageWrap = () => (
+
+
+
+);
+
+export default InsightsVulnerabilityListPageWrap;
diff --git a/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js
new file mode 100644
index 000000000..39aecb720
--- /dev/null
+++ b/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import InsightsVulnerabilityListPage from './InsightsVulnerabilityListPage';
+
+jest.mock('@scalprum/react-core', () => ({
+ ScalprumComponent: jest.fn(props => (
+ {JSON.stringify(props)}
+ )),
+ ScalprumProvider: jest.fn(({ children }) => {children}
),
+}));
+
+describe('InsightsVulnerabilityListPage component', () => {
+ it('renders the container with correct class', () => {
+ const { container } = render();
+ expect(
+ container.querySelector('.rh-cloud-insights-vulnerability-page')
+ ).toBeTruthy();
+ });
+});
diff --git a/webpack/common/ScalprumModule/ScalprumContext.js b/webpack/common/ScalprumModule/ScalprumContext.js
new file mode 100644
index 000000000..77829c2d6
--- /dev/null
+++ b/webpack/common/ScalprumModule/ScalprumContext.js
@@ -0,0 +1,63 @@
+export const modulesConfig = {
+ vulnerability: {
+ name: 'vulnerability',
+ manifestLocation: `${window.location.origin}/assets/apps/vulnerability/fed-mods.json`,
+ cdnPath: `${window.location.origin}/assets/apps/vulnerability/`,
+ },
+};
+
+export const mockUser = {
+ entitlements: {},
+ identity: {
+ account_number: 'string',
+ org_id: 'FOREMAN',
+ internal: {
+ org_id: 'string',
+ account_id: 'string',
+ },
+ type: 'string',
+ user: {
+ username: 'string',
+ email: 'string',
+ first_name: 'string',
+ last_name: 'string',
+ is_active: 'boolean',
+ is_internal: 'boolean',
+ is_org_admin: 'boolean',
+ locale: 'string',
+ },
+ },
+};
+
+export const providerOptions = {
+ pluginSDKOptions: {
+ pluginLoaderOptions: {
+ transformPluginManifest: manifest => {
+ if (
+ manifest.baseURL === 'auto' &&
+ modulesConfig[manifest.name]?.cdnPath
+ ) {
+ const _cdnPath = modulesConfig[manifest.name]?.cdnPath;
+ return {
+ ...manifest,
+ baseURL: _cdnPath,
+ loadScripts: manifest.loadScripts.map(
+ script => `${_cdnPath}${script}`
+ ),
+ };
+ }
+ return manifest;
+ },
+ },
+ },
+ api: {
+ chrome: {
+ isBeta: () => false,
+ on: () => {},
+ auth: {
+ getUser: () => Promise.resolve(mockUser),
+ },
+ },
+ },
+ config: modulesConfig,
+};