diff --git a/locales/en.json b/locales/en.json index c19b209a7..72be20c9f 100644 --- a/locales/en.json +++ b/locales/en.json @@ -90,6 +90,14 @@ "cvssVector.popoverTitle": "vector breakdown", "cvssVector.value": "Value", "cvssVector.vector": "base score", + "dashbarCriticalVulnerabilitiesFilterText": "Filter by CVEs with critical severity", + "dashbarCriticalVulnerabilitiesTitle": "Critical vulnerabilities", + "dashbarImportantVulnerabilitiesFilterText": "Filter by CVEs with important severity", + "dashbarImportantVulnerabilitiesTitle": "Important vulnerabilities", + "dashbarKnownExploitsFilterText": "Filter by CVEs with known exploits", + "dashbarKnownExploitsTitle": "Known exploits", + "dashbarSecurityRulesFilterText": "Filter by CVEs with security rules", + "dashbarSecurityRulesTitle": "Security Rules", "description": "CVE description", "emptyPage.body": "Connect your systems to keep your Red Hat environment running efficiently, with security and compliance with various standards.", "emptyPage.button": "Learn more about connecting your systems", diff --git a/src/Components/SmartComponents/Dashbar/Dashbar.js b/src/Components/SmartComponents/Dashbar/Dashbar.js new file mode 100644 index 000000000..d66a3275e --- /dev/null +++ b/src/Components/SmartComponents/Dashbar/Dashbar.js @@ -0,0 +1,129 @@ +import React from 'react'; +import { Card, Grid, GridItem, Split, SplitItem, StackItem, Stack, Alert, CardBody, Text } from '@patternfly/react-core'; +import { Main } from '@redhat-cloud-services/frontend-components/Main'; +import { SecurityIcon } from '@patternfly/react-icons'; +import { CVES_ALLOWED_PARAMS } from '../../../Helpers/constants'; +import { constructFilterParameters, useUrlParams } from '../../../Helpers/MiscHelper'; +import { useDispatch } from 'react-redux'; +import { changeCveListParameters } from '../../../Store/Actions/Actions'; +import { FormattedMessage } from 'react-intl'; +import messages from '../../../Messages'; + +const Dashbar = () => { + const dispatch = useDispatch(); + const [urlParameters, setUrlParams] = useUrlParams([CVES_ALLOWED_PARAMS]); + + const apply = (filterParams = {}) => { + setUrlParams(filterParams); + const params = constructFilterParameters(filterParams); + dispatch(changeCveListParameters(params)); + }; + + return (urlParameters?.dashbar === 'true' && +
+ + + + + + + + + 5 + + + + + + + apply({ ...urlParameters, known_exploit: 'true' })}> + + + + + + + + + + + + 2 + + + + + + + apply({ ...urlParameters, rule_presence: 'true' })}> + + + + + + + + + + + + + + + 2 + + + + + + + apply({ ...urlParameters, impact: '7' })}> + + + + + + + + + 3 + + + + + + + apply({ ...urlParameters, impact: '5' })}> + + + + + + + + + + + + + Lorem ipsum + + + +
+ ); +}; + +export default Dashbar; diff --git a/src/Components/SmartComponents/Dashbar/Dashbar.test.js b/src/Components/SmartComponents/Dashbar/Dashbar.test.js new file mode 100644 index 000000000..9d71181cf --- /dev/null +++ b/src/Components/SmartComponents/Dashbar/Dashbar.test.js @@ -0,0 +1,55 @@ +import Dashbar from './Dashbar'; +import { Card, Grid } from '@patternfly/react-core'; +import toJson from 'enzyme-to-json'; +import { mountWithIntl } from '../../../Helpers/MiscHelper'; +import { Provider } from 'react-redux'; +import configureStore from 'redux-mock-store'; +import { BrowserRouter as Router } from 'react-router-dom'; +window.insights = {}; + +jest.mock("react-redux", () => ({ + ...jest.requireActual("react-redux"), + useSelector: jest.fn(), + useDispatch: jest.fn() +})); + +const mockStore = configureStore([store => next => action => { }]); +let store = mockStore({}); + +jest.mock('../../../Helpers/MiscHelper', () => ({ + ...jest.requireActual('../../../Helpers/MiscHelper'), + useUrlParams: () => [{ dashbar: "true" }, jest.fn()] +})) + +describe('Dashbar', () => { + it('Should match the snapshot', () => { + const wrapper = mountWithIntl( + + + + + ); + expect(toJson(wrapper)).toMatchSnapshot(); + }) + it('Should render Grid with props hasGutter = true', () => { + const wrapper = mountWithIntl( + + + + + + ); + expect(wrapper.find(Grid)).toHaveLength(1); + expect(wrapper.find(Grid).prop('hasGutter')).toBeTruthy(); + }); + it('Should have 3 card items', () => { + const wrapper = mountWithIntl( + + + + + + ); + expect(wrapper.find(Card)).toHaveLength(3); + }) +}) \ No newline at end of file diff --git a/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap b/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap new file mode 100644 index 000000000..30663af2e --- /dev/null +++ b/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap @@ -0,0 +1,495 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dashbar Should match the snapshot 1`] = ` + + + + + +
+
+ +
+ +
+ +
+ +
+ + + +
+
+ +
+ + + +
+
+ +
+ + + +
+
+
+
+
+
+ +
+ +
+ +
+ + + + + +
+
+

+ + Warning alert: + + This is an announcement +

+
+ Lorem ipsum +
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/src/Components/SmartComponents/LandingPage/LandingPage.js b/src/Components/SmartComponents/LandingPage/LandingPage.js index b11185c40..cc2d8bcc4 100644 --- a/src/Components/SmartComponents/LandingPage/LandingPage.js +++ b/src/Components/SmartComponents/LandingPage/LandingPage.js @@ -6,6 +6,7 @@ import messages from '../../../Messages'; import { Main } from '@redhat-cloud-services/frontend-components/Main'; import Header from '../../PresentationalComponents/Header/Header'; import CVEs from '../CVEs/CVEs'; +import Dashbar from '../Dashbar/Dashbar'; const LandingPage = () => { // eslint-disable-next-line max-len @@ -35,6 +36,7 @@ const LandingPage = () => { return (
+
diff --git a/src/Components/SmartComponents/LandingPage/__snapshots__/LandingPage.test.js.snap b/src/Components/SmartComponents/LandingPage/__snapshots__/LandingPage.test.js.snap index 2b765514b..0dac09ce2 100644 --- a/src/Components/SmartComponents/LandingPage/__snapshots__/LandingPage.test.js.snap +++ b/src/Components/SmartComponents/LandingPage/__snapshots__/LandingPage.test.js.snap @@ -64,6 +64,7 @@ exports[`CVEs: Should match the snapshot 1`] = ` } /> + diff --git a/src/Helpers/constants.js b/src/Helpers/constants.js index 09c7eb393..fda455ee2 100644 --- a/src/Helpers/constants.js +++ b/src/Helpers/constants.js @@ -855,7 +855,8 @@ export const CVES_ALLOWED_PARAMS = [ 'tags', 'sap_sids', 'sap_system', - 'remediation' + 'remediation', + 'dashbar' ]; export const SYSTEMS_EXPOSED_ALLOWED_PARAMS = [ diff --git a/src/Messages.js b/src/Messages.js index 7cc9d1a10..ebd6b359b 100644 --- a/src/Messages.js +++ b/src/Messages.js @@ -1727,6 +1727,46 @@ export default defineMessages({ description: 'No CVE metadata description', defaultMessage: 'This CVE has been published, however metadata about this CVE is not yet available on Red Hat Insights. Metadata is usually available on Insights within 24 hours of a CVE being published.' }, + dashbarKnownExploitsTitle: { + id: 'dashbarKnownExploitsTitle', + description: 'Title of Known exploit card', + defaultMessage: 'Known exploits' + }, + dashbarKnownExploitsFilterText: { + id: 'dashbarKnownExploitsFilterText', + description: 'Link to Known exploits filter', + defaultMessage: 'Filter by CVEs with known exploits' + }, + dashbarSecurityRulesTitle: { + id: 'dashbarSecurityRulesTitle', + description: 'Title of Security rule card', + defaultMessage: 'Security Rules' + }, + dashbarSecurityRulesFilterText: { + id: 'dashbarSecurityRulesFilterText', + description: 'Link to Security rules filter', + defaultMessage: 'Filter by CVEs with security rules' + }, + dashbarCriticalVulnerabilitiesTitle: { + id: 'dashbarCriticalVulnerabilitiesTitle', + description: 'Title of Critical vulnerabilities card', + defaultMessage: 'Critical vulnerabilities' + }, + dashbarCriticalVulnerabilitiesFilterText: { + id: 'dashbarCriticalVulnerabilitiesFilterText', + description: 'Link to Critical vulnerabilities filter', + defaultMessage: 'Filter by CVEs with critical severity' + }, + dashbarImportantVulnerabilitiesTitle: { + id: 'dashbarImportantVulnerabilitiesTitle', + description: 'Title of Important vulnerabilities card', + defaultMessage: 'Important vulnerabilities' + }, + dashbarImportantVulnerabilitiesFilterText: { + id: 'dashbarImportantVulnerabilitiesFilterText', + description: 'Link to Important vulnerabilities filter', + defaultMessage: 'Filter by CVEs with important severity' + }, unknownCveId: { id: 'unknownCveId', description: 'Breadcrumb item when user tries to access detail of CVE that does not exist',