diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2020-01-09 14:07:10 +0100 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2020-01-13 20:46:38 +0100 |
commit | 8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9 (patch) | |
tree | 5bc38d3ce0d2b2942bb9d728e80731d3e53f8fe8 /server/sonar-web/src | |
parent | 85a0a1ce997c7203a290e200aebef1492a615a8d (diff) | |
download | sonarqube-8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9.tar.gz sonarqube-8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9.zip |
SONAR-12797 Message when no hotspots found (list of keys)
Diffstat (limited to 'server/sonar-web/src')
5 files changed, 202 insertions, 90 deletions
diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx b/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx index d22c07cba21..3e3b800bc96 100644 --- a/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx @@ -19,16 +19,20 @@ */ import * as React from 'react'; import { Helmet } from 'react-helmet-async'; -import { Link } from 'react-router'; import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; import A11ySkipTarget from '../../app/components/a11y/A11ySkipTarget'; import Suggestions from '../../app/components/embed-docs-modal/Suggestions'; import ScreenPositionHelper from '../../components/common/ScreenPositionHelper'; import { isBranch } from '../../helpers/branch-like'; import { BranchLike } from '../../types/branch-like'; -import { HotspotFilters, HotspotUpdate, RawHotspot } from '../../types/security-hotspots'; +import { + HotspotFilters, + HotspotStatusFilter, + HotspotUpdate, + RawHotspot +} from '../../types/security-hotspots'; +import EmptyHotspotsPage from './components/EmptyHotspotsPage'; import FilterBar from './components/FilterBar'; import HotspotList from './components/HotspotList'; import HotspotViewer from './components/HotspotViewer'; @@ -51,37 +55,6 @@ export interface SecurityHotspotsAppRendererProps { securityCategories: T.StandardSecurityCategories; } -function renderNoHotspots(filtered: boolean) { - return ( - <div className="display-flex-column display-flex-center huge-spacer-top"> - <img - alt={translate('hotspots.page')} - className="huge-spacer-top" - height={100} - src={`${getBaseUrl()}/images/${filtered ? 'filter-large' : 'hotspot-large'}.svg`} - /> - <h1 className="huge-spacer-top"> - {filtered - ? translate('hotspots.no_hotspots_for_filters.title') - : translate('hotspots.no_hotspots.title')} - </h1> - <div className="abs-width-400 text-center big-spacer-top"> - {filtered - ? translate('hotspots.no_hotspots_for_filters.description') - : translate('hotspots.no_hotspots.description')} - </div> - {!filtered && ( - <Link - className="big-spacer-top" - target="_blank" - to={{ pathname: '/documentation/user-guide/security-hotspots/' }}> - {translate('hotspots.learn_more')} - </Link> - )} - </div> - ); -} - export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRendererProps) { const { branchLike, @@ -117,9 +90,14 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe ) : ( <> {hotspots.length === 0 ? ( - renderNoHotspots( - filters.assignedToMe || (filters.sinceLeakPeriod && isBranch(branchLike)) - ) + <EmptyHotspotsPage + filtered={ + filters.assignedToMe || + (isBranch(branchLike) && filters.sinceLeakPeriod) || + filters.status !== HotspotStatusFilter.TO_REVIEW + } + isStaticListOfHotspots={isStaticListOfHotspots} + /> ) : ( <div className="layout-page"> <div className="sidebar"> diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap index c24e160260d..a99469f0413 100644 --- a/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap @@ -209,39 +209,10 @@ exports[`should render correctly: no hotspots 1`] = ` <A11ySkipTarget anchor="security_hotspots_main" /> - <div - className="display-flex-column display-flex-center huge-spacer-top" - > - <img - alt="hotspots.page" - className="huge-spacer-top" - height={100} - src="/images/hotspot-large.svg" - /> - <h1 - className="huge-spacer-top" - > - hotspots.no_hotspots.title - </h1> - <div - className="abs-width-400 text-center big-spacer-top" - > - hotspots.no_hotspots.description - </div> - <Link - className="big-spacer-top" - onlyActiveOnIndex={false} - style={Object {}} - target="_blank" - to={ - Object { - "pathname": "/documentation/user-guide/security-hotspots/", - } - } - > - hotspots.learn_more - </Link> - </div> + <EmptyHotspotsPage + filtered={false} + isStaticListOfHotspots={true} + /> </div> </div> `; @@ -267,26 +238,10 @@ exports[`should render correctly: no hotspots with filters 1`] = ` <A11ySkipTarget anchor="security_hotspots_main" /> - <div - className="display-flex-column display-flex-center huge-spacer-top" - > - <img - alt="hotspots.page" - className="huge-spacer-top" - height={100} - src="/images/filter-large.svg" - /> - <h1 - className="huge-spacer-top" - > - hotspots.no_hotspots_for_filters.title - </h1> - <div - className="abs-width-400 text-center big-spacer-top" - > - hotspots.no_hotspots_for_filters.description - </div> - </div> + <EmptyHotspotsPage + filtered={true} + isStaticListOfHotspots={true} + /> </div> </div> `; diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx b/server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx new file mode 100644 index 00000000000..a178c3bbb8b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; + +export interface EmptyHotspotsPageProps { + filtered: boolean; + isStaticListOfHotspots: boolean; +} + +export default function EmptyHotspotsPage(props: EmptyHotspotsPageProps) { + const { filtered, isStaticListOfHotspots } = props; + + let translationRoot; + if (isStaticListOfHotspots) { + translationRoot = 'no_hotspots_for_keys'; + } else if (filtered) { + translationRoot = 'no_hotspots_for_filters'; + } else { + translationRoot = 'no_hotspots'; + } + + return ( + <div className="display-flex-column display-flex-center huge-spacer-top"> + <img + alt={translate('hotspots.page')} + className="huge-spacer-top" + height={100} + src={`${getBaseUrl()}/images/${filtered ? 'filter-large' : 'hotspot-large'}.svg`} + /> + <h1 className="huge-spacer-top">{translate(`hotspots.${translationRoot}.title`)}</h1> + <div className="abs-width-400 text-center big-spacer-top"> + {translate(`hotspots.${translationRoot}.description`)} + </div> + {!(filtered || isStaticListOfHotspots) && ( + <Link + className="big-spacer-top" + target="_blank" + to={{ pathname: '/documentation/user-guide/security-hotspots/' }}> + {translate('hotspots.learn_more')} + </Link> + )} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx b/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx new file mode 100644 index 00000000000..bbeb14429c5 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import EmptyHotspotsPage, { EmptyHotspotsPageProps } from '../EmptyHotspotsPage'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); + expect(shallowRender({ filtered: true })).toMatchSnapshot('filtered'); + expect(shallowRender({ isStaticListOfHotspots: true })).toMatchSnapshot('keys'); +}); + +function shallowRender(props: Partial<EmptyHotspotsPageProps> = {}) { + return shallow(<EmptyHotspotsPage filtered={false} isStaticListOfHotspots={false} {...props} />); +} diff --git a/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap new file mode 100644 index 00000000000..b90efd1eb50 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` +<div + className="display-flex-column display-flex-center huge-spacer-top" +> + <img + alt="hotspots.page" + className="huge-spacer-top" + height={100} + src="/images/hotspot-large.svg" + /> + <h1 + className="huge-spacer-top" + > + hotspots.no_hotspots.title + </h1> + <div + className="abs-width-400 text-center big-spacer-top" + > + hotspots.no_hotspots.description + </div> + <Link + className="big-spacer-top" + onlyActiveOnIndex={false} + style={Object {}} + target="_blank" + to={ + Object { + "pathname": "/documentation/user-guide/security-hotspots/", + } + } + > + hotspots.learn_more + </Link> +</div> +`; + +exports[`should render correctly: filtered 1`] = ` +<div + className="display-flex-column display-flex-center huge-spacer-top" +> + <img + alt="hotspots.page" + className="huge-spacer-top" + height={100} + src="/images/filter-large.svg" + /> + <h1 + className="huge-spacer-top" + > + hotspots.no_hotspots_for_filters.title + </h1> + <div + className="abs-width-400 text-center big-spacer-top" + > + hotspots.no_hotspots_for_filters.description + </div> +</div> +`; + +exports[`should render correctly: keys 1`] = ` +<div + className="display-flex-column display-flex-center huge-spacer-top" +> + <img + alt="hotspots.page" + className="huge-spacer-top" + height={100} + src="/images/hotspot-large.svg" + /> + <h1 + className="huge-spacer-top" + > + hotspots.no_hotspots_for_keys.title + </h1> + <div + className="abs-width-400 text-center big-spacer-top" + > + hotspots.no_hotspots_for_keys.description + </div> +</div> +`; |