From f49dfd9b1940e8d2a36afd3fc6e547183436c4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandr=20=C4=8Celakovsk=C3=BD?= <20592948+AsToNlele@users.noreply.github.com> Date: Mon, 11 Apr 2022 12:20:01 +0200 Subject: [PATCH] feat: Dashbar add fetch data (#1617) --- locales/en.json | 1 + package-lock.json | 14 +- package.json | 2 +- .../SmartComponents/Dashbar/Dashbar.js | 135 ++++++++++++------ .../SmartComponents/Dashbar/Dashbar.test.js | 63 ++++---- .../__snapshots__/Dashbar.test.js.snap | 22 +-- src/Helpers/APIHelper.js | 16 +++ src/Messages.js | 5 + 8 files changed, 170 insertions(+), 88 deletions(-) diff --git a/locales/en.json b/locales/en.json index 29275c787..565befb01 100644 --- a/locales/en.json +++ b/locales/en.json @@ -90,6 +90,7 @@ "cvssVector.popoverTitle": "vector breakdown", "cvssVector.value": "Value", "cvssVector.vector": "base score", + "dashbarAnnouncementTitle": "Announcement", "dashbarCriticalSeverityTitle": "CVEs with critical severity", "dashbarImportantSeverityTitle": "CVEs with important severity", "dashbarKnownExploitsTitle": "CVEs with known exploits", diff --git a/package-lock.json b/package-lock.json index 9778125b7..a0b26d94e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@redhat-cloud-services/frontend-components-pdf-generator": "2.6.7", "@redhat-cloud-services/frontend-components-translations": "3.2.3", "@redhat-cloud-services/frontend-components-utilities": "3.2.8", - "@redhat-cloud-services/vulnerabilities-client": "^1.0.104", + "@redhat-cloud-services/vulnerabilities-client": "1.0.106", "axios": "^0.26.1", "classnames": "^2.2.5", "dot": "^1.1.3", @@ -4115,9 +4115,9 @@ } }, "node_modules/@redhat-cloud-services/vulnerabilities-client": { - "version": "1.0.104", - "resolved": "https://registry.npmjs.org/@redhat-cloud-services/vulnerabilities-client/-/vulnerabilities-client-1.0.104.tgz", - "integrity": "sha512-pKfOq4UOufG3HeX6UyDCdIDTWUcJU4wBSMX7AHPpogmFNaYDJHyQO8LXtI0cGi2X1KF3HneuX5jpdOlwg+Ja+A==", + "version": "1.0.106", + "resolved": "https://registry.npmjs.org/@redhat-cloud-services/vulnerabilities-client/-/vulnerabilities-client-1.0.106.tgz", + "integrity": "sha512-oGnd1w8nJZJcXRnvKzU0K1yswl5zWxGWiTQ1QAzJVsDi8EldGJdAntwVLYB3zJRJKhKZfu8ap51m43qjIFZO1Q==", "dependencies": { "axios": "^0.21.1", "yaml": "^1.8.3" @@ -27077,9 +27077,9 @@ } }, "@redhat-cloud-services/vulnerabilities-client": { - "version": "1.0.104", - "resolved": "https://registry.npmjs.org/@redhat-cloud-services/vulnerabilities-client/-/vulnerabilities-client-1.0.104.tgz", - "integrity": "sha512-pKfOq4UOufG3HeX6UyDCdIDTWUcJU4wBSMX7AHPpogmFNaYDJHyQO8LXtI0cGi2X1KF3HneuX5jpdOlwg+Ja+A==", + "version": "1.0.106", + "resolved": "https://registry.npmjs.org/@redhat-cloud-services/vulnerabilities-client/-/vulnerabilities-client-1.0.106.tgz", + "integrity": "sha512-oGnd1w8nJZJcXRnvKzU0K1yswl5zWxGWiTQ1QAzJVsDi8EldGJdAntwVLYB3zJRJKhKZfu8ap51m43qjIFZO1Q==", "requires": { "axios": "^0.21.1", "yaml": "^1.8.3" diff --git a/package.json b/package.json index 866872a02..7d2518968 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@redhat-cloud-services/frontend-components-pdf-generator": "2.6.7", "@redhat-cloud-services/frontend-components-translations": "3.2.3", "@redhat-cloud-services/frontend-components-utilities": "3.2.8", - "@redhat-cloud-services/vulnerabilities-client": "^1.0.104", + "@redhat-cloud-services/vulnerabilities-client": "1.0.106", "axios": "^0.26.1", "classnames": "^2.2.5", "dot": "^1.1.3", diff --git a/src/Components/SmartComponents/Dashbar/Dashbar.js b/src/Components/SmartComponents/Dashbar/Dashbar.js index e126e41d1..799b8fe01 100644 --- a/src/Components/SmartComponents/Dashbar/Dashbar.js +++ b/src/Components/SmartComponents/Dashbar/Dashbar.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Card, Grid, GridItem, StackItem, Stack, Alert, CardBody, Text } from '@patternfly/react-core'; import { Main } from '@redhat-cloud-services/frontend-components/Main'; import { SecurityIcon } from '@patternfly/react-icons'; @@ -10,6 +10,9 @@ import { FormattedMessage } from 'react-intl'; import messages from '../../../Messages'; import propTypes from 'prop-types'; import { buildActiveFilters, removeFilters } from '../../../Helpers/TableToolbarHelper'; +import { getAnnouncement, getDashbar } from '../../../Helpers/APIHelper'; +import WithLoader, { LoaderType } from '../../PresentationalComponents/WithLoader/WithLoader'; +import { useIntl } from 'react-intl'; const DashbarItem = ({ title, count, impact, onLinkClick, hasIcon }) => { return ( @@ -33,6 +36,8 @@ const DashbarItem = ({ title, count, impact, onLinkClick, hasIcon }) => { ); }; +export { DashbarItem }; + DashbarItem.propTypes = { title: propTypes.node, count: propTypes.number.isRequired, @@ -42,8 +47,12 @@ DashbarItem.propTypes = { }; const Dashbar = () => { + const intl = useIntl(); const dispatch = useDispatch(); const [urlParameters] = useUrlParams([CVES_ALLOWED_PARAMS]); + const [dashbar, setDashbar] = useState({}); + const [announcement, setAnnouncement] = useState({}); + const [isDashbarLoading, setDashbarLoading] = useState(true); const parameters = useSelector( ({ CVEsStore }) => CVEsStore.parameters @@ -60,54 +69,92 @@ const Dashbar = () => { removeFilters(chips, apply, true, filterParams); }; + useEffect(() => { + const fetchAnnouncements = async () => { + let data = await getAnnouncement(); + setAnnouncement(data); + }; + + const fetchDashbar = async () => { + let data = await getDashbar(); + setDashbar(data); + setDashbarLoading(false); + }; + + fetchAnnouncements(); + fetchDashbar(); + }, []); + return (urlParameters?.dashbar === 'true' &&
- - - } - count={12} - onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, known_exploit: 'true' })} - /> - - - } - count={5} - onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, rule_presence: 'true' })} - /> - - - } - count={5} - onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, impact: '7' })} - impact="Critical" - hasIcon - /> - - - } - count={5} - onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, impact: '5' })} - impact="Important" - hasIcon - /> - - - - - - Lorem ipsum - + {!isDashbarLoading ? ( + + + } + count={dashbar?.exploitable_cves} + onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, known_exploit: 'true' })} + /> + + + } + count={dashbar?.cves_with_rule} + onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, rule_presence: 'true' })} + /> + + + } + count={dashbar?.critical_cves} + onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, impact: '7' })} + impact="Critical" + hasIcon + /> + + + } + count={dashbar?.important_cves} + onLinkClick={() => applyOnly({ ...CVES_DEFAULT_FILTERS, impact: '5' })} + impact="Important" + hasIcon + /> + + + ) : ( + + + + + + + + + + + + + + + )} + {announcement?.message && ( + + {announcement.message} + + + )}
); diff --git a/src/Components/SmartComponents/Dashbar/Dashbar.test.js b/src/Components/SmartComponents/Dashbar/Dashbar.test.js index 60af073df..03597a792 100644 --- a/src/Components/SmartComponents/Dashbar/Dashbar.test.js +++ b/src/Components/SmartComponents/Dashbar/Dashbar.test.js @@ -1,53 +1,66 @@ -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'; +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"; +import { DashbarItem } from './Dashbar' jest.mock("react-redux", () => ({ ...jest.requireActual("react-redux"), - useSelector: jest.fn() + useSelector: jest.fn(), })); -const mockStore = configureStore([store => next => action => { }]); +const mockStore = configureStore([(store) => (next) => (action) => { }]); let store = mockStore({}); -jest.mock('../../../Helpers/MiscHelper', () => ({ - ...jest.requireActual('../../../Helpers/MiscHelper'), - useUrlParams: () => [{ dashbar: "true" }, jest.fn()] +jest.mock("../../../Helpers/MiscHelper", () => ({ + ...jest.requireActual("../../../Helpers/MiscHelper"), + useUrlParams: () => [{ dashbar: "true" }, jest.fn()], +})); + + +jest.mock("../../../Helpers/APIHelper", () => ({ + ...jest.requireActual("../../../Helpers/APIHelper"), + getAnnouncement: () => new Promise((resolve) => resolve({ message: "Message test!" })), + getDashbar: () => new Promise((resolve) => resolve({ exploitable_cves: 1, cves_with_rule: 2, critical_cves: 3, important_cves: 4 })) })) -describe('Dashbar', () => { - it('Should match the snapshot', () => { - const wrapper = mountWithIntl( +describe("Dashbar", () => { + it("Should match the snapshot", async () => { + + const wrapper = await mountWithIntl( - ); + + ); + wrapper.update() expect(toJson(wrapper)).toMatchSnapshot(); - }) - it('Should render Grid with props hasGutter = true', () => { - const wrapper = mountWithIntl( + }); + it("Should render Grid with props hasGutter = true", async () => { + const wrapper = await mountWithIntl( ); + wrapper.update() expect(wrapper.find(Grid)).toHaveLength(1); - expect(wrapper.find(Grid).prop('hasGutter')).toBeTruthy(); + expect(wrapper.find(Grid).prop("hasGutter")).toBeTruthy(); }); - it('Should have 4 card items', () => { - const wrapper = mountWithIntl( + it("Should have 4 DashbarItems", async () => { + const wrapper = await mountWithIntl( ); - expect(wrapper.find(Card)).toHaveLength(4); - }) -}) + wrapper.update() + expect(wrapper.find(DashbarItem)).toHaveLength(4); + }); +}); diff --git a/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap b/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap index 6f47ca729..e71bceeb3 100644 --- a/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap +++ b/src/Components/SmartComponents/Dashbar/__snapshots__/Dashbar.test.js.snap @@ -84,7 +84,7 @@ exports[`Dashbar Should match the snapshot 1`] = ` className="pf-l-grid__item pf-m-12-col pf-m-3-col-on-md" > - 12 + 1

@@ -160,7 +160,7 @@ exports[`Dashbar Should match the snapshot 1`] = ` className="pf-l-grid__item pf-m-12-col pf-m-3-col-on-md" > - 5 + 2

@@ -236,7 +236,7 @@ exports[`Dashbar Should match the snapshot 1`] = ` className="pf-l-grid__item pf-m-12-col pf-m-3-col-on-md" > - 5 + 3

@@ -340,7 +340,7 @@ exports[`Dashbar Should match the snapshot 1`] = ` className="pf-l-grid__item pf-m-12-col pf-m-3-col-on-md" > - 5 + 4

@@ -446,7 +446,7 @@ exports[`Dashbar Should match the snapshot 1`] = ` >
Warning alert: - This is an announcement + Announcement
- Lorem ipsum + Message test!
diff --git a/src/Helpers/APIHelper.js b/src/Helpers/APIHelper.js index 2f7b10570..4e66998c7 100644 --- a/src/Helpers/APIHelper.js +++ b/src/Helpers/APIHelper.js @@ -235,3 +235,19 @@ export function getSystemsIds(apiProps) { let result = api.getSystemsIds(...parameterArray); return result; } + +export function getAnnouncement() { + let result = api.getAnnouncement(); + return result; +} + +export function getDashbar(apiProps) { + let parameterNames = [ + 'tags', + 'sap_sids', + 'sap_system' + ]; + let parameterArray = constructParameters(apiProps, parameterNames); + let result = api.getDashbar(...parameterArray); + return result; +} diff --git a/src/Messages.js b/src/Messages.js index dc511e695..8af8c5082 100644 --- a/src/Messages.js +++ b/src/Messages.js @@ -1747,6 +1747,11 @@ export default defineMessages({ description: 'Title of Important Severity card', defaultMessage: 'CVEs with important severity' }, + dashbarAnnouncementTitle: { + id: 'dashbarAnnouncementTitle', + description: 'Title of Dashbar Announcement', + defaultMessage: 'Announcement' + }, unknownCveId: { id: 'unknownCveId', description: 'Breadcrumb item when user tries to access detail of CVE that does not exist',