aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2020-01-09 14:07:10 +0100
committerSonarTech <sonartech@sonarsource.com>2020-01-13 20:46:38 +0100
commit8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9 (patch)
tree5bc38d3ce0d2b2942bb9d728e80731d3e53f8fe8 /server/sonar-web/src
parent85a0a1ce997c7203a290e200aebef1492a615a8d (diff)
downloadsonarqube-8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9.tar.gz
sonarqube-8d8f01a13a6e960b34dc2c805faeeccbc89c8ab9.zip
SONAR-12797 Message when no hotspots found (list of keys)
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/apps/securityHotspots/SecurityHotspotsAppRenderer.tsx52
-rw-r--r--server/sonar-web/src/main/js/apps/securityHotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap61
-rw-r--r--server/sonar-web/src/main/js/apps/securityHotspots/components/EmptyHotspotsPage.tsx64
-rw-r--r--server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/EmptyHotspotsPage-test.tsx32
-rw-r--r--server/sonar-web/src/main/js/apps/securityHotspots/components/__tests__/__snapshots__/EmptyHotspotsPage-test.tsx.snap83
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>
+`;