aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2020-05-28 17:56:02 +0200
committersonartech <sonartech@sonarsource.com>2020-06-02 20:05:09 +0000
commit947685909fbdee4146a59c67cc706b5e7f530876 (patch)
treeb2432f20571c6358e7fc7944246ce9ae00c27b0b /server/sonar-web
parent1e44d80e9c900ac61274c7c3ada3c4c2df3e10ee (diff)
downloadsonarqube-947685909fbdee4146a59c67cc706b5e7f530876.tar.gz
sonarqube-947685909fbdee4146a59c67cc706b5e7f530876.zip
SONAR-12920 Add product footer to the Hotspots page
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/app/styles/components/page.css4
-rw-r--r--server/sonar-web/src/main/js/app/styles/init/misc.css4
-rw-r--r--server/sonar-web/src/main/js/apps/projectBaseline/styles.css4
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx67
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx21
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap448
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx144
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css5
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap834
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap10
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap10
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/styles.css64
19 files changed, 848 insertions, 798 deletions
diff --git a/server/sonar-web/src/main/js/app/styles/components/page.css b/server/sonar-web/src/main/js/app/styles/components/page.css
index c00695e5bea..01555387dd5 100644
--- a/server/sonar-web/src/main/js/app/styles/components/page.css
+++ b/server/sonar-web/src/main/js/app/styles/components/page.css
@@ -161,10 +161,6 @@
max-width: 980px;
}
-.no-footer-page #footer {
- display: none;
-}
-
.page-footer-menu-item {
display: inline-block;
}
diff --git a/server/sonar-web/src/main/js/app/styles/init/misc.css b/server/sonar-web/src/main/js/app/styles/init/misc.css
index 921d893c8f8..b05d35cd039 100644
--- a/server/sonar-web/src/main/js/app/styles/init/misc.css
+++ b/server/sonar-web/src/main/js/app/styles/init/misc.css
@@ -39,6 +39,10 @@ th.hide-overflow {
visibility: hidden !important;
}
+.invisible {
+ visibility: hidden;
+}
+
.note {
color: var(--secondFontColor);
font-size: var(--smallFontSize);
diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/styles.css b/server/sonar-web/src/main/js/apps/projectBaseline/styles.css
index 04e71f3813a..0d7889c79a6 100644
--- a/server/sonar-web/src/main/js/apps/projectBaseline/styles.css
+++ b/server/sonar-web/src/main/js/apps/projectBaseline/styles.css
@@ -144,7 +144,3 @@
.project-activity-event-icon.OTHER {
color: #442d1b;
}
-
-.invisible {
- visibility: hidden;
-}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
index 94b6b17b860..f4dc3e08c16 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
@@ -20,7 +20,7 @@
import { Location } from 'history';
import { flatMap, range } from 'lodash';
import * as React from 'react';
-import { addNoFooterPageClass, removeNoFooterPageClass } from 'sonar-ui-common/helpers/pages';
+import { addSideBarClass, removeSideBarClass } from 'sonar-ui-common/helpers/pages';
import { getMeasures } from '../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../api/security-hotspots';
import { withCurrentUser } from '../../components/hoc/withCurrentUser';
@@ -89,7 +89,7 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
componentDidMount() {
this.mounted = true;
- addNoFooterPageClass();
+ addSideBarClass();
this.fetchInitialData();
}
@@ -114,7 +114,7 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
}
componentWillUnmount() {
- removeNoFooterPageClass();
+ removeSideBarClass();
this.mounted = false;
}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx
index ca548d38de6..06862abf159 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsAppRenderer.tsx
@@ -83,6 +83,10 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe
return (
<div id="security_hotspots">
+ <Suggestions suggestions="security_hotspots" />
+ <Helmet title={translate('hotspots.page')} />
+ <A11ySkipTarget anchor="security_hotspots_main" />
+
<FilterBar
component={component}
filters={filters}
@@ -93,29 +97,25 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe
onChangeFilters={props.onChangeFilters}
onShowAllHotspots={props.onShowAllHotspots}
/>
- <ScreenPositionHelper>
- {({ top }) => (
- <div className="wrapper" style={{ top }}>
- <Suggestions suggestions="security_hotspots" />
- <Helmet title={translate('hotspots.page')} />
-
- <A11ySkipTarget anchor="security_hotspots_main" />
- {loading && <DeferredSpinner className="huge-spacer-left big-spacer-top" />}
+ {loading && <DeferredSpinner className="huge-spacer-left big-spacer-top" />}
- {!loading &&
- (hotspots.length === 0 || !selectedHotspot ? (
- <EmptyHotspotsPage
- filtered={
- filters.assignedToMe ||
- (isBranch(branchLike) && filters.sinceLeakPeriod) ||
- filters.status !== HotspotStatusFilter.TO_REVIEW
- }
- isStaticListOfHotspots={isStaticListOfHotspots}
- />
- ) : (
- <div className="layout-page">
- <div className="sidebar" ref={scrollableRef}>
+ {!loading &&
+ (hotspots.length === 0 || !selectedHotspot ? (
+ <EmptyHotspotsPage
+ filtered={
+ filters.assignedToMe ||
+ (isBranch(branchLike) && filters.sinceLeakPeriod) ||
+ filters.status !== HotspotStatusFilter.TO_REVIEW
+ }
+ isStaticListOfHotspots={isStaticListOfHotspots}
+ />
+ ) : (
+ <div className="layout-page">
+ <ScreenPositionHelper className="layout-page-side-outer">
+ {({ top }) => (
+ <div className="layout-page-side" ref={scrollableRef} style={{ top }}>
+ <div className="layout-page-side-inner">
<HotspotList
hotspots={hotspots}
hotspotsTotal={hotspotsTotal}
@@ -128,20 +128,21 @@ export default function SecurityHotspotsAppRenderer(props: SecurityHotspotsAppRe
statusFilter={filters.status}
/>
</div>
- <div className="main">
- <HotspotViewer
- branchLike={branchLike}
- component={component}
- hotspotKey={selectedHotspot.key}
- onUpdateHotspot={props.onUpdateHotspot}
- securityCategories={securityCategories}
- />
- </div>
</div>
- ))}
+ )}
+ </ScreenPositionHelper>
+
+ <div className="layout-page-main">
+ <HotspotViewer
+ branchLike={branchLike}
+ component={component}
+ hotspotKey={selectedHotspot.key}
+ onUpdateHotspot={props.onUpdateHotspot}
+ securityCategories={securityCategories}
+ />
+ </div>
</div>
- )}
- </ScreenPositionHelper>
+ ))}
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
index 4921949f20b..caf2e3ba6f1 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { addNoFooterPageClass } from 'sonar-ui-common/helpers/pages';
+import { addSideBarClass } from 'sonar-ui-common/helpers/pages';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { getMeasures } from '../../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../../api/security-hotspots';
@@ -44,8 +44,8 @@ import SecurityHotspotsAppRenderer from '../SecurityHotspotsAppRenderer';
beforeEach(() => jest.clearAllMocks());
jest.mock('sonar-ui-common/helpers/pages', () => ({
- addNoFooterPageClass: jest.fn(),
- removeNoFooterPageClass: jest.fn()
+ addSideBarClass: jest.fn(),
+ removeSideBarClass: jest.fn()
}));
jest.mock('../../../api/measures', () => ({
@@ -82,7 +82,7 @@ it('should load data correctly', async () => {
expect(wrapper.state().loading).toBe(true);
expect(wrapper.state().loadingMeasure).toBe(true);
- expect(addNoFooterPageClass).toBeCalled();
+ expect(addSideBarClass).toBeCalled();
expect(getStandards).toBeCalled();
expect(getSecurityHotspots).toBeCalledWith(
expect.objectContaining({
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
index 7491ad6bd48..de4d561db97 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsAppRenderer-test.tsx
@@ -33,6 +33,8 @@ jest.mock('sonar-ui-common/helpers/scrolling', () => ({
scrollToElement: jest.fn()
}));
+jest.mock('../../../components/common/ScreenPositionHelper');
+
beforeEach(() => {
jest.clearAllMocks();
});
@@ -43,28 +45,13 @@ it('should render correctly', () => {
shallowRender({
filters: { assignedToMe: true, sinceLeakPeriod: false, status: HotspotStatusFilter.TO_REVIEW }
})
- .find(ScreenPositionHelper)
- .dive()
).toMatchSnapshot('no hotspots with filters');
- expect(
- shallowRender()
- .find(ScreenPositionHelper)
- .dive()
- ).toMatchSnapshot('no hotspots');
- expect(
- shallowRender({ loading: true })
- .find(ScreenPositionHelper)
- .dive()
- ).toMatchSnapshot('loading');
+ expect(shallowRender({ loading: true })).toMatchSnapshot('loading');
});
it('should render correctly with hotspots', () => {
const hotspots = [mockRawHotspot({ key: 'h1' }), mockRawHotspot({ key: 'h2' })];
- expect(
- shallowRender({ hotspots, hotspotsTotal: 2 })
- .find(ScreenPositionHelper)
- .dive()
- ).toMatchSnapshot();
+ expect(shallowRender({ hotspots, hotspotsTotal: 2 })).toMatchSnapshot();
expect(
shallowRender({ hotspots, hotspotsTotal: 3, selectedHotspot: mockRawHotspot({ key: 'h2' }) })
.find(ScreenPositionHelper)
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
index cfbe10346e0..315e1a63280 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
@@ -4,6 +4,17 @@ exports[`should render correctly 1`] = `
<div
id="security_hotspots"
>
+ <Suggestions
+ suggestions="security_hotspots"
+ />
+ <Helmet
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="hotspots.page"
+ />
+ <A11ySkipTarget
+ anchor="security_hotspots_main"
+ />
<Connect(withCurrentUser(FilterBar))
component={
Object {
@@ -41,249 +52,262 @@ exports[`should render correctly 1`] = `
onChangeFilters={[MockFunction]}
onShowAllHotspots={[MockFunction]}
/>
- <ScreenPositionHelper>
- <Component />
- </ScreenPositionHelper>
+ <EmptyHotspotsPage
+ filtered={false}
+ isStaticListOfHotspots={true}
+ />
</div>
`;
exports[`should render correctly with hotspots 1`] = `
-<div>
- <div
- className="wrapper"
- style={
+<div
+ id="security_hotspots"
+>
+ <Suggestions
+ suggestions="security_hotspots"
+ />
+ <Helmet
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="hotspots.page"
+ />
+ <A11ySkipTarget
+ anchor="security_hotspots_main"
+ />
+ <Connect(withCurrentUser(FilterBar))
+ component={
Object {
- "top": 0,
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
}
}
- >
- <Suggestions
- suggestions="security_hotspots"
- />
- <Helmet
- defer={true}
- encodeSpecialCharacters={true}
- title="hotspots.page"
- />
- <A11ySkipTarget
- anchor="security_hotspots_main"
- />
- <EmptyHotspotsPage
- filtered={false}
- isStaticListOfHotspots={true}
- />
- </div>
+ filters={
+ Object {
+ "assignedToMe": false,
+ "sinceLeakPeriod": false,
+ "status": "TO_REVIEW",
+ }
+ }
+ isStaticListOfHotspots={true}
+ loadingMeasure={false}
+ onBranch={false}
+ onChangeFilters={[MockFunction]}
+ onShowAllHotspots={[MockFunction]}
+ />
+ <EmptyHotspotsPage
+ filtered={false}
+ isStaticListOfHotspots={true}
+ />
</div>
`;
exports[`should render correctly with hotspots 2`] = `
-<div>
- <div
- className="wrapper"
- style={
- Object {
- "top": 0,
- }
+<div
+ className="layout-page-side"
+ style={
+ Object {
+ "top": 0,
}
+ }
+>
+ <div
+ className="layout-page-side-inner"
>
- <Suggestions
- suggestions="security_hotspots"
- />
- <Helmet
- defer={true}
- encodeSpecialCharacters={true}
- title="hotspots.page"
- />
- <A11ySkipTarget
- anchor="security_hotspots_main"
+ <HotspotList
+ hotspots={
+ Array [
+ Object {
+ "author": "Developer 1",
+ "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
+ "creationDate": "2013-05-13T17:55:39+0200",
+ "key": "h1",
+ "line": 81,
+ "message": "'3' is a magic number.",
+ "project": "com.github.kevinsawicki:http-request",
+ "resolution": undefined,
+ "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
+ "securityCategory": "command-injection",
+ "status": "TO_REVIEW",
+ "updateDate": "2013-05-13T17:55:39+0200",
+ "vulnerabilityProbability": "HIGH",
+ },
+ Object {
+ "author": "Developer 1",
+ "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
+ "creationDate": "2013-05-13T17:55:39+0200",
+ "key": "h2",
+ "line": 81,
+ "message": "'3' is a magic number.",
+ "project": "com.github.kevinsawicki:http-request",
+ "resolution": undefined,
+ "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
+ "securityCategory": "command-injection",
+ "status": "TO_REVIEW",
+ "updateDate": "2013-05-13T17:55:39+0200",
+ "vulnerabilityProbability": "HIGH",
+ },
+ ]
+ }
+ hotspotsTotal={3}
+ isStaticListOfHotspots={true}
+ loadingMore={false}
+ onHotspotClick={[MockFunction]}
+ onLoadMore={[MockFunction]}
+ securityCategories={Object {}}
+ selectedHotspot={
+ Object {
+ "author": "Developer 1",
+ "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
+ "creationDate": "2013-05-13T17:55:39+0200",
+ "key": "h2",
+ "line": 81,
+ "message": "'3' is a magic number.",
+ "project": "com.github.kevinsawicki:http-request",
+ "resolution": undefined,
+ "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
+ "securityCategory": "command-injection",
+ "status": "TO_REVIEW",
+ "updateDate": "2013-05-13T17:55:39+0200",
+ "vulnerabilityProbability": "HIGH",
+ }
+ }
+ statusFilter="TO_REVIEW"
/>
- <div
- className="layout-page"
- >
- <div
- className="sidebar"
- >
- <HotspotList
- hotspots={
- Array [
- Object {
- "author": "Developer 1",
- "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
- "creationDate": "2013-05-13T17:55:39+0200",
- "key": "h1",
- "line": 81,
- "message": "'3' is a magic number.",
- "project": "com.github.kevinsawicki:http-request",
- "resolution": undefined,
- "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
- "securityCategory": "command-injection",
- "status": "TO_REVIEW",
- "updateDate": "2013-05-13T17:55:39+0200",
- "vulnerabilityProbability": "HIGH",
- },
- Object {
- "author": "Developer 1",
- "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
- "creationDate": "2013-05-13T17:55:39+0200",
- "key": "h2",
- "line": 81,
- "message": "'3' is a magic number.",
- "project": "com.github.kevinsawicki:http-request",
- "resolution": undefined,
- "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
- "securityCategory": "command-injection",
- "status": "TO_REVIEW",
- "updateDate": "2013-05-13T17:55:39+0200",
- "vulnerabilityProbability": "HIGH",
- },
- ]
- }
- hotspotsTotal={3}
- isStaticListOfHotspots={true}
- loadingMore={false}
- onHotspotClick={[MockFunction]}
- onLoadMore={[MockFunction]}
- securityCategories={Object {}}
- selectedHotspot={
- Object {
- "author": "Developer 1",
- "component": "com.github.kevinsawicki:http-request:com.github.kevinsawicki.http.HttpRequest",
- "creationDate": "2013-05-13T17:55:39+0200",
- "key": "h2",
- "line": 81,
- "message": "'3' is a magic number.",
- "project": "com.github.kevinsawicki:http-request",
- "resolution": undefined,
- "rule": "checkstyle:com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheck",
- "securityCategory": "command-injection",
- "status": "TO_REVIEW",
- "updateDate": "2013-05-13T17:55:39+0200",
- "vulnerabilityProbability": "HIGH",
- }
- }
- statusFilter="TO_REVIEW"
- />
- </div>
- <div
- className="main"
- >
- <HotspotViewer
- component={
- Object {
- "breadcrumbs": Array [],
- "key": "my-project",
- "name": "MyProject",
- "organization": "foo",
- "qualifier": "TRK",
- "qualityGate": Object {
- "isDefault": true,
- "key": "30",
- "name": "Sonar way",
- },
- "qualityProfiles": Array [
- Object {
- "deleted": false,
- "key": "my-qp",
- "language": "ts",
- "name": "Sonar way",
- },
- ],
- "tags": Array [],
- }
- }
- hotspotKey="h2"
- onUpdateHotspot={[MockFunction]}
- securityCategories={Object {}}
- />
- </div>
- </div>
</div>
</div>
`;
exports[`should render correctly: loading 1`] = `
-<div>
- <div
- className="wrapper"
- style={
+<div
+ id="security_hotspots"
+>
+ <Suggestions
+ suggestions="security_hotspots"
+ />
+ <Helmet
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="hotspots.page"
+ />
+ <A11ySkipTarget
+ anchor="security_hotspots_main"
+ />
+ <Connect(withCurrentUser(FilterBar))
+ component={
Object {
- "top": 0,
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
}
}
- >
- <Suggestions
- suggestions="security_hotspots"
- />
- <Helmet
- defer={true}
- encodeSpecialCharacters={true}
- title="hotspots.page"
- />
- <A11ySkipTarget
- anchor="security_hotspots_main"
- />
- <DeferredSpinner
- className="huge-spacer-left big-spacer-top"
- timeout={100}
- />
- </div>
-</div>
-`;
-
-exports[`should render correctly: no hotspots 1`] = `
-<div>
- <div
- className="wrapper"
- style={
+ filters={
Object {
- "top": 0,
+ "assignedToMe": false,
+ "sinceLeakPeriod": false,
+ "status": "TO_REVIEW",
}
}
- >
- <Suggestions
- suggestions="security_hotspots"
- />
- <Helmet
- defer={true}
- encodeSpecialCharacters={true}
- title="hotspots.page"
- />
- <A11ySkipTarget
- anchor="security_hotspots_main"
- />
- <EmptyHotspotsPage
- filtered={false}
- isStaticListOfHotspots={true}
- />
- </div>
+ isStaticListOfHotspots={true}
+ loadingMeasure={false}
+ onBranch={false}
+ onChangeFilters={[MockFunction]}
+ onShowAllHotspots={[MockFunction]}
+ />
+ <DeferredSpinner
+ className="huge-spacer-left big-spacer-top"
+ timeout={100}
+ />
</div>
`;
exports[`should render correctly: no hotspots with filters 1`] = `
-<div>
- <div
- className="wrapper"
- style={
+<div
+ id="security_hotspots"
+>
+ <Suggestions
+ suggestions="security_hotspots"
+ />
+ <Helmet
+ defer={true}
+ encodeSpecialCharacters={true}
+ title="hotspots.page"
+ />
+ <A11ySkipTarget
+ anchor="security_hotspots_main"
+ />
+ <Connect(withCurrentUser(FilterBar))
+ component={
Object {
- "top": 0,
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
}
}
- >
- <Suggestions
- suggestions="security_hotspots"
- />
- <Helmet
- defer={true}
- encodeSpecialCharacters={true}
- title="hotspots.page"
- />
- <A11ySkipTarget
- anchor="security_hotspots_main"
- />
- <EmptyHotspotsPage
- filtered={true}
- isStaticListOfHotspots={true}
- />
- </div>
+ filters={
+ Object {
+ "assignedToMe": true,
+ "sinceLeakPeriod": false,
+ "status": "TO_REVIEW",
+ }
+ }
+ isStaticListOfHotspots={true}
+ loadingMeasure={false}
+ onBranch={false}
+ onChangeFilters={[MockFunction]}
+ onShowAllHotspots={[MockFunction]}
+ />
+ <EmptyHotspotsPage
+ filtered={true}
+ isStaticListOfHotspots={true}
+ />
</div>
`;
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
index 283c57fa5e8..8cb4bbed905 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
@@ -76,80 +76,90 @@ export function FilterBar(props: FilterBarProps) {
const isProject = component.qualifier === ComponentQualifier.Project;
return (
- <div className="filter-bar display-flex-center">
- {isStaticListOfHotspots ? (
- <a id="show_all_hotspot" onClick={() => props.onShowAllHotspots()} role="link" tabIndex={0}>
- {translate('hotspot.filters.show_all')}
- </a>
- ) : (
- <div className="display-flex-space-between width-100">
- <div className="display-flex-center">
- <h3 className="huge-spacer-right">{translate('hotspot.filters.title')}</h3>
+ <div className="filter-bar-outer">
+ <div className="filter-bar">
+ <div className="filter-bar-inner display-flex-center">
+ {isStaticListOfHotspots ? (
+ <a
+ id="show_all_hotspot"
+ onClick={() => props.onShowAllHotspots()}
+ role="link"
+ tabIndex={0}>
+ {translate('hotspot.filters.show_all')}
+ </a>
+ ) : (
+ <div className="display-flex-space-between width-100">
+ <div className="display-flex-center">
+ <h3 className="huge-spacer-right">{translate('hotspot.filters.title')}</h3>
- {isLoggedIn(currentUser) && (
- <RadioToggle
- className="huge-spacer-right"
- name="assignee-filter"
- onCheck={(value: AssigneeFilterOption) =>
- props.onChangeFilters({ assignedToMe: value === AssigneeFilterOption.ME })
- }
- options={assigneeFilterOptions}
- value={filters.assignedToMe ? AssigneeFilterOption.ME : AssigneeFilterOption.ALL}
- />
- )}
+ {isLoggedIn(currentUser) && (
+ <RadioToggle
+ className="huge-spacer-right"
+ name="assignee-filter"
+ onCheck={(value: AssigneeFilterOption) =>
+ props.onChangeFilters({ assignedToMe: value === AssigneeFilterOption.ME })
+ }
+ options={assigneeFilterOptions}
+ value={
+ filters.assignedToMe ? AssigneeFilterOption.ME : AssigneeFilterOption.ALL
+ }
+ />
+ )}
- <span className="spacer-right">{translate('status')}</span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={(option: { value: HotspotStatusFilter }) =>
- props.onChangeFilters({ status: option.value })
- }
- options={statusOptions}
- searchable={false}
- value={filters.status}
- />
-
- {onBranch && (
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={(option: { value: boolean }) =>
- props.onChangeFilters({ sinceLeakPeriod: option.value })
- }
- options={periodOptions}
- searchable={false}
- value={filters.sinceLeakPeriod}
- />
- )}
- </div>
-
- {isProject && (
- <div className="display-flex-center">
- <span className="little-spacer-right">
- {translate('metric.security_hotspots_reviewed.name')}
- </span>
- <HelpTooltip
- className="big-spacer-right"
- overlay={translate('hotspots.reviewed.tooltip')}
- />
- <DeferredSpinner loading={loadingMeasure}>
- {hotspotsReviewedMeasure && <CoverageRating value={hotspotsReviewedMeasure} />}
- <Measure
- className="spacer-left huge"
- metricKey={
- onBranch && !filters.sinceLeakPeriod
- ? 'security_hotspots_reviewed'
- : 'new_security_hotspots_reviewed'
+ <span className="spacer-right">{translate('status')}</span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={(option: { value: HotspotStatusFilter }) =>
+ props.onChangeFilters({ status: option.value })
}
- metricType="PERCENT"
- value={hotspotsReviewedMeasure}
+ options={statusOptions}
+ searchable={false}
+ value={filters.status}
/>
- </DeferredSpinner>
+
+ {onBranch && (
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={(option: { value: boolean }) =>
+ props.onChangeFilters({ sinceLeakPeriod: option.value })
+ }
+ options={periodOptions}
+ searchable={false}
+ value={filters.sinceLeakPeriod}
+ />
+ )}
+ </div>
+
+ {isProject && (
+ <div className="display-flex-center">
+ <span className="little-spacer-right">
+ {translate('metric.security_hotspots_reviewed.name')}
+ </span>
+ <HelpTooltip
+ className="big-spacer-right"
+ overlay={translate('hotspots.reviewed.tooltip')}
+ />
+ <DeferredSpinner loading={loadingMeasure}>
+ {hotspotsReviewedMeasure && <CoverageRating value={hotspotsReviewedMeasure} />}
+ <Measure
+ className="spacer-left huge"
+ metricKey={
+ onBranch && !filters.sinceLeakPeriod
+ ? 'security_hotspots_reviewed'
+ : 'new_security_hotspots_reviewed'
+ }
+ metricType="PERCENT"
+ value={hotspotsReviewedMeasure}
+ />
+ </DeferredSpinner>
+ </div>
+ )}
</div>
)}
</div>
- )}
+ </div>
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css
index 566c79cc44e..2e8a86dc8b4 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.css
@@ -17,11 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-.hotspot-list {
- /* sidebar width - 16px padding-right, required so as to ignore the scrollbar */
- width: 284px;
-}
-
.hotspot-list-header {
padding: calc(2 * var(--gridSize)) var(--gridSize);
}
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx
index 60addc3677a..ca0fe5bafec 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotList.tsx
@@ -107,7 +107,7 @@ export default class HotspotList extends React.Component<Props, State> {
const { expandedCategories, groupedHotspots } = this.state;
return (
- <div className="huge-spacer-bottom big-padded-right hotspot-list">
+ <div className="huge-spacer-bottom">
<h1 className="hotspot-list-header bordered-bottom">
<SecurityHotspotIcon className="spacer-right" />
{translateWithParameters(
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx
index 58a2789fdef..7ff33fc0b19 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewer.tsx
@@ -43,12 +43,10 @@ export default class HotspotViewer extends React.PureComponent<Props, State> {
mounted = false;
state: State;
commentTextRef: React.RefObject<HTMLTextAreaElement>;
- parentScrollRef: React.RefObject<HTMLDivElement>;
constructor(props: Props) {
super(props);
this.commentTextRef = React.createRef<HTMLTextAreaElement>();
- this.parentScrollRef = React.createRef<HTMLDivElement>();
this.state = { loading: false, commentVisible: false };
}
@@ -96,9 +94,8 @@ export default class HotspotViewer extends React.PureComponent<Props, State> {
// Edge case when the comment is already open and unfocus.
this.commentTextRef.current.focus({ preventScroll: true });
}
- if (this.commentTextRef.current && this.parentScrollRef.current) {
+ if (this.commentTextRef.current) {
scrollToElement(this.commentTextRef.current, {
- parent: this.parentScrollRef.current,
bottomOffset: 100
});
}
@@ -123,7 +120,6 @@ export default class HotspotViewer extends React.PureComponent<Props, State> {
onCloseComment={this.handleCloseComment}
onOpenComment={this.handleOpenComment}
onUpdateHotspot={this.handleHotspotUpdate}
- parentScrollRef={this.parentScrollRef}
securityCategories={securityCategories}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx
index 7ef7c2e7c17..9bb83fc1f6f 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerRenderer.tsx
@@ -49,7 +49,6 @@ export interface HotspotViewerRendererProps {
onOpenComment: () => void;
onCloseComment: () => void;
onUpdateHotspot: () => Promise<void>;
- parentScrollRef: React.RefObject<HTMLDivElement>;
securityCategories: T.StandardSecurityCategories;
}
@@ -62,8 +61,7 @@ export function HotspotViewerRenderer(props: HotspotViewerRendererProps) {
loading,
securityCategories,
commentTextRef,
- commentVisible,
- parentScrollRef
+ commentVisible
} = props;
const permalink = getPathUrlAsString(
@@ -77,7 +75,7 @@ export function HotspotViewerRenderer(props: HotspotViewerRendererProps) {
return (
<DeferredSpinner loading={loading}>
{hotspot && (
- <div className="big-padded hotspot-content" ref={parentScrollRef}>
+ <div className="big-padded hotspot-content">
<div className="huge-spacer-bottom display-flex-space-between">
<strong className="big big-spacer-right">{hotspot.message}</strong>
<div className="display-flex-row flex-0">
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx
index 5fce1d9f64b..aed74e3b773 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewer-test.tsx
@@ -64,8 +64,6 @@ it('should open comment form when scroll to comment', () => {
const mockTextRef = ({ current: { focus: jest.fn() } } as any) as React.RefObject<
HTMLTextAreaElement
>;
- const mockParentRef = ({ current: {} } as any) as React.RefObject<HTMLDivElement>;
- wrapper.instance().parentScrollRef = mockParentRef;
wrapper.instance().commentTextRef = mockTextRef;
wrapper.find(HotspotViewerRenderer).simulate('openComment');
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx
index f9207838319..71ae598f1cb 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerRenderer-test.tsx
@@ -59,7 +59,6 @@ function shallowRender(props?: Partial<HotspotViewerRendererProps>) {
onCloseComment={jest.fn()}
onOpenComment={jest.fn()}
onUpdateHotspot={jest.fn()}
- parentScrollRef={React.createRef()}
securityCategories={{ 'sql-injection': { title: 'SQL injection' } }}
{...props}
/>
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
index 2e6f744c0a7..2a6b58d6aaf 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
@@ -2,104 +2,120 @@
exports[`should render correctly when the list of hotspot is static 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
- <a
- id="show_all_hotspot"
- onClick={[Function]}
- role="link"
- tabIndex={0}
+ <div
+ className="filter-bar"
>
- hotspot.filters.show_all
- </a>
+ <div
+ className="filter-bar-inner display-flex-center"
+ >
+ <a
+ id="show_all_hotspot"
+ onClick={[Function]}
+ role="link"
+ tabIndex={0}
+ >
+ hotspot.filters.show_all
+ </a>
+ </div>
+ </div>
</div>
`;
exports[`should render correctly: anonymous 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
<div
- className="display-flex-space-between width-100"
+ className="filter-bar"
>
<div
- className="display-flex-center"
- >
- <h3
- className="huge-spacer-right"
- >
- hotspot.filters.title
- </h3>
- <span
- className="spacer-right"
- >
- status
- </span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.status.to_review",
- "value": "TO_REVIEW",
- },
- Object {
- "label": "hotspot.filters.status.fixed",
- "value": "FIXED",
- },
- Object {
- "label": "hotspot.filters.status.safe",
- "value": "SAFE",
- },
- ]
- }
- searchable={false}
- value="TO_REVIEW"
- />
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.period.since_leak_period",
- "value": true,
- },
- Object {
- "label": "hotspot.filters.period.overall",
- "value": false,
- },
- ]
- }
- searchable={false}
- value={false}
- />
- </div>
- <div
- className="display-flex-center"
+ className="filter-bar-inner display-flex-center"
>
- <span
- className="little-spacer-right"
- >
- metric.security_hotspots_reviewed.name
- </span>
- <HelpTooltip
- className="big-spacer-right"
- overlay="hotspots.reviewed.tooltip"
- />
- <DeferredSpinner
- loading={false}
- timeout={100}
+ <div
+ className="display-flex-space-between width-100"
>
- <Measure
- className="spacer-left huge"
- metricKey="security_hotspots_reviewed"
- metricType="PERCENT"
- />
- </DeferredSpinner>
+ <div
+ className="display-flex-center"
+ >
+ <h3
+ className="huge-spacer-right"
+ >
+ hotspot.filters.title
+ </h3>
+ <span
+ className="spacer-right"
+ >
+ status
+ </span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.status.to_review",
+ "value": "TO_REVIEW",
+ },
+ Object {
+ "label": "hotspot.filters.status.fixed",
+ "value": "FIXED",
+ },
+ Object {
+ "label": "hotspot.filters.status.safe",
+ "value": "SAFE",
+ },
+ ]
+ }
+ searchable={false}
+ value="TO_REVIEW"
+ />
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.period.since_leak_period",
+ "value": true,
+ },
+ Object {
+ "label": "hotspot.filters.period.overall",
+ "value": false,
+ },
+ ]
+ }
+ searchable={false}
+ value={false}
+ />
+ </div>
+ <div
+ className="display-flex-center"
+ >
+ <span
+ className="little-spacer-right"
+ >
+ metric.security_hotspots_reviewed.name
+ </span>
+ <HelpTooltip
+ className="big-spacer-right"
+ overlay="hotspots.reviewed.tooltip"
+ />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <Measure
+ className="spacer-left huge"
+ metricKey="security_hotspots_reviewed"
+ metricType="PERCENT"
+ />
+ </DeferredSpinner>
+ </div>
+ </div>
</div>
</div>
</div>
@@ -107,108 +123,116 @@ exports[`should render correctly: anonymous 1`] = `
exports[`should render correctly: logged-in 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
<div
- className="display-flex-space-between width-100"
+ className="filter-bar"
>
<div
- className="display-flex-center"
+ className="filter-bar-inner display-flex-center"
>
- <h3
- className="huge-spacer-right"
+ <div
+ className="display-flex-space-between width-100"
>
- hotspot.filters.title
- </h3>
- <RadioToggle
- className="huge-spacer-right"
- disabled={false}
- name="assignee-filter"
- onCheck={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.assignee.assigned_to_me",
- "value": "me",
- },
- Object {
- "label": "hotspot.filters.assignee.all",
- "value": "all",
- },
- ]
- }
- value="all"
- />
- <span
- className="spacer-right"
- >
- status
- </span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.status.to_review",
- "value": "TO_REVIEW",
- },
- Object {
- "label": "hotspot.filters.status.fixed",
- "value": "FIXED",
- },
- Object {
- "label": "hotspot.filters.status.safe",
- "value": "SAFE",
- },
- ]
- }
- searchable={false}
- value="TO_REVIEW"
- />
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.period.since_leak_period",
- "value": true,
- },
- Object {
- "label": "hotspot.filters.period.overall",
- "value": false,
- },
- ]
- }
- searchable={false}
- value={false}
- />
- </div>
- <div
- className="display-flex-center"
- >
- <span
- className="little-spacer-right"
- >
- metric.security_hotspots_reviewed.name
- </span>
- <HelpTooltip
- className="big-spacer-right"
- overlay="hotspots.reviewed.tooltip"
- />
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <Measure
- className="spacer-left huge"
- metricKey="security_hotspots_reviewed"
- metricType="PERCENT"
- />
- </DeferredSpinner>
+ <div
+ className="display-flex-center"
+ >
+ <h3
+ className="huge-spacer-right"
+ >
+ hotspot.filters.title
+ </h3>
+ <RadioToggle
+ className="huge-spacer-right"
+ disabled={false}
+ name="assignee-filter"
+ onCheck={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.assignee.assigned_to_me",
+ "value": "me",
+ },
+ Object {
+ "label": "hotspot.filters.assignee.all",
+ "value": "all",
+ },
+ ]
+ }
+ value="all"
+ />
+ <span
+ className="spacer-right"
+ >
+ status
+ </span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.status.to_review",
+ "value": "TO_REVIEW",
+ },
+ Object {
+ "label": "hotspot.filters.status.fixed",
+ "value": "FIXED",
+ },
+ Object {
+ "label": "hotspot.filters.status.safe",
+ "value": "SAFE",
+ },
+ ]
+ }
+ searchable={false}
+ value="TO_REVIEW"
+ />
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.period.since_leak_period",
+ "value": true,
+ },
+ Object {
+ "label": "hotspot.filters.period.overall",
+ "value": false,
+ },
+ ]
+ }
+ searchable={false}
+ value={false}
+ />
+ </div>
+ <div
+ className="display-flex-center"
+ >
+ <span
+ className="little-spacer-right"
+ >
+ metric.security_hotspots_reviewed.name
+ </span>
+ <HelpTooltip
+ className="big-spacer-right"
+ overlay="hotspots.reviewed.tooltip"
+ />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <Measure
+ className="spacer-left huge"
+ metricKey="security_hotspots_reviewed"
+ metricType="PERCENT"
+ />
+ </DeferredSpinner>
+ </div>
+ </div>
</div>
</div>
</div>
@@ -216,85 +240,93 @@ exports[`should render correctly: logged-in 1`] = `
exports[`should render correctly: non-project 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
<div
- className="display-flex-space-between width-100"
+ className="filter-bar"
>
<div
- className="display-flex-center"
+ className="filter-bar-inner display-flex-center"
>
- <h3
- className="huge-spacer-right"
+ <div
+ className="display-flex-space-between width-100"
>
- hotspot.filters.title
- </h3>
- <RadioToggle
- className="huge-spacer-right"
- disabled={false}
- name="assignee-filter"
- onCheck={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.assignee.assigned_to_me",
- "value": "me",
- },
- Object {
- "label": "hotspot.filters.assignee.all",
- "value": "all",
- },
- ]
- }
- value="all"
- />
- <span
- className="spacer-right"
- >
- status
- </span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.status.to_review",
- "value": "TO_REVIEW",
- },
- Object {
- "label": "hotspot.filters.status.fixed",
- "value": "FIXED",
- },
- Object {
- "label": "hotspot.filters.status.safe",
- "value": "SAFE",
- },
- ]
- }
- searchable={false}
- value="TO_REVIEW"
- />
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.period.since_leak_period",
- "value": true,
- },
- Object {
- "label": "hotspot.filters.period.overall",
- "value": false,
- },
- ]
- }
- searchable={false}
- value={false}
- />
+ <div
+ className="display-flex-center"
+ >
+ <h3
+ className="huge-spacer-right"
+ >
+ hotspot.filters.title
+ </h3>
+ <RadioToggle
+ className="huge-spacer-right"
+ disabled={false}
+ name="assignee-filter"
+ onCheck={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.assignee.assigned_to_me",
+ "value": "me",
+ },
+ Object {
+ "label": "hotspot.filters.assignee.all",
+ "value": "all",
+ },
+ ]
+ }
+ value="all"
+ />
+ <span
+ className="spacer-right"
+ >
+ status
+ </span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.status.to_review",
+ "value": "TO_REVIEW",
+ },
+ Object {
+ "label": "hotspot.filters.status.fixed",
+ "value": "FIXED",
+ },
+ Object {
+ "label": "hotspot.filters.status.safe",
+ "value": "SAFE",
+ },
+ ]
+ }
+ searchable={false}
+ value="TO_REVIEW"
+ />
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.period.since_leak_period",
+ "value": true,
+ },
+ Object {
+ "label": "hotspot.filters.period.overall",
+ "value": false,
+ },
+ ]
+ }
+ searchable={false}
+ value={false}
+ />
+ </div>
+ </div>
</div>
</div>
</div>
@@ -302,70 +334,78 @@ exports[`should render correctly: non-project 1`] = `
exports[`should render correctly: on Pull request 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
<div
- className="display-flex-space-between width-100"
+ className="filter-bar"
>
<div
- className="display-flex-center"
+ className="filter-bar-inner display-flex-center"
>
- <h3
- className="huge-spacer-right"
- >
- hotspot.filters.title
- </h3>
- <span
- className="spacer-right"
+ <div
+ className="display-flex-space-between width-100"
>
- status
- </span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.status.to_review",
- "value": "TO_REVIEW",
- },
- Object {
- "label": "hotspot.filters.status.fixed",
- "value": "FIXED",
- },
- Object {
- "label": "hotspot.filters.status.safe",
- "value": "SAFE",
- },
- ]
- }
- searchable={false}
- value="TO_REVIEW"
- />
- </div>
- <div
- className="display-flex-center"
- >
- <span
- className="little-spacer-right"
- >
- metric.security_hotspots_reviewed.name
- </span>
- <HelpTooltip
- className="big-spacer-right"
- overlay="hotspots.reviewed.tooltip"
- />
- <DeferredSpinner
- loading={false}
- timeout={100}
- >
- <Measure
- className="spacer-left huge"
- metricKey="new_security_hotspots_reviewed"
- metricType="PERCENT"
- />
- </DeferredSpinner>
+ <div
+ className="display-flex-center"
+ >
+ <h3
+ className="huge-spacer-right"
+ >
+ hotspot.filters.title
+ </h3>
+ <span
+ className="spacer-right"
+ >
+ status
+ </span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.status.to_review",
+ "value": "TO_REVIEW",
+ },
+ Object {
+ "label": "hotspot.filters.status.fixed",
+ "value": "FIXED",
+ },
+ Object {
+ "label": "hotspot.filters.status.safe",
+ "value": "SAFE",
+ },
+ ]
+ }
+ searchable={false}
+ value="TO_REVIEW"
+ />
+ </div>
+ <div
+ className="display-flex-center"
+ >
+ <span
+ className="little-spacer-right"
+ >
+ metric.security_hotspots_reviewed.name
+ </span>
+ <HelpTooltip
+ className="big-spacer-right"
+ overlay="hotspots.reviewed.tooltip"
+ />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <Measure
+ className="spacer-left huge"
+ metricKey="new_security_hotspots_reviewed"
+ metricType="PERCENT"
+ />
+ </DeferredSpinner>
+ </div>
+ </div>
</div>
</div>
</div>
@@ -373,93 +413,101 @@ exports[`should render correctly: on Pull request 1`] = `
exports[`should render correctly: with hotspots reviewed measure 1`] = `
<div
- className="filter-bar display-flex-center"
+ className="filter-bar-outer"
>
<div
- className="display-flex-space-between width-100"
+ className="filter-bar"
>
<div
- className="display-flex-center"
+ className="filter-bar-inner display-flex-center"
>
- <h3
- className="huge-spacer-right"
- >
- hotspot.filters.title
- </h3>
- <span
- className="spacer-right"
- >
- status
- </span>
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.status.to_review",
- "value": "TO_REVIEW",
- },
- Object {
- "label": "hotspot.filters.status.fixed",
- "value": "FIXED",
- },
- Object {
- "label": "hotspot.filters.status.safe",
- "value": "SAFE",
- },
- ]
- }
- searchable={false}
- value="TO_REVIEW"
- />
- <Select
- className="input-medium big-spacer-right"
- clearable={false}
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "hotspot.filters.period.since_leak_period",
- "value": true,
- },
- Object {
- "label": "hotspot.filters.period.overall",
- "value": false,
- },
- ]
- }
- searchable={false}
- value={false}
- />
- </div>
- <div
- className="display-flex-center"
- >
- <span
- className="little-spacer-right"
- >
- metric.security_hotspots_reviewed.name
- </span>
- <HelpTooltip
- className="big-spacer-right"
- overlay="hotspots.reviewed.tooltip"
- />
- <DeferredSpinner
- loading={false}
- timeout={100}
+ <div
+ className="display-flex-space-between width-100"
>
- <CoverageRating
- value="23.30"
- />
- <Measure
- className="spacer-left huge"
- metricKey="security_hotspots_reviewed"
- metricType="PERCENT"
- value="23.30"
- />
- </DeferredSpinner>
+ <div
+ className="display-flex-center"
+ >
+ <h3
+ className="huge-spacer-right"
+ >
+ hotspot.filters.title
+ </h3>
+ <span
+ className="spacer-right"
+ >
+ status
+ </span>
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.status.to_review",
+ "value": "TO_REVIEW",
+ },
+ Object {
+ "label": "hotspot.filters.status.fixed",
+ "value": "FIXED",
+ },
+ Object {
+ "label": "hotspot.filters.status.safe",
+ "value": "SAFE",
+ },
+ ]
+ }
+ searchable={false}
+ value="TO_REVIEW"
+ />
+ <Select
+ className="input-medium big-spacer-right"
+ clearable={false}
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "hotspot.filters.period.since_leak_period",
+ "value": true,
+ },
+ Object {
+ "label": "hotspot.filters.period.overall",
+ "value": false,
+ },
+ ]
+ }
+ searchable={false}
+ value={false}
+ />
+ </div>
+ <div
+ className="display-flex-center"
+ >
+ <span
+ className="little-spacer-right"
+ >
+ metric.security_hotspots_reviewed.name
+ </span>
+ <HelpTooltip
+ className="big-spacer-right"
+ overlay="hotspots.reviewed.tooltip"
+ />
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <CoverageRating
+ value="23.30"
+ />
+ <Measure
+ className="spacer-left huge"
+ metricKey="security_hotspots_reviewed"
+ metricType="PERCENT"
+ value="23.30"
+ />
+ </DeferredSpinner>
+ </div>
+ </div>
</div>
</div>
</div>
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
index cbe8a6ad04e..4aba60b522a 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotList-test.tsx.snap
@@ -2,7 +2,7 @@
exports[`should render correctly 1`] = `
<div
- className="huge-spacer-bottom big-padded-right hotspot-list"
+ className="huge-spacer-bottom"
>
<h1
className="hotspot-list-header bordered-bottom"
@@ -26,7 +26,7 @@ exports[`should render correctly 1`] = `
exports[`should render correctly 2`] = `
<div
- className="huge-spacer-bottom big-padded-right hotspot-list"
+ className="huge-spacer-bottom"
>
<h1
className="hotspot-list-header bordered-bottom"
@@ -49,7 +49,7 @@ exports[`should render correctly 2`] = `
exports[`should render correctly when the list of hotspot is static 1`] = `
<div
- className="huge-spacer-bottom big-padded-right hotspot-list"
+ className="huge-spacer-bottom"
>
<h1
className="hotspot-list-header bordered-bottom"
@@ -73,7 +73,7 @@ exports[`should render correctly when the list of hotspot is static 1`] = `
exports[`should render correctly with hotspots: no pagination 1`] = `
<div
- className="huge-spacer-bottom big-padded-right hotspot-list"
+ className="huge-spacer-bottom"
>
<h1
className="hotspot-list-header bordered-bottom"
@@ -341,7 +341,7 @@ exports[`should render correctly with hotspots: no pagination 1`] = `
exports[`should render correctly with hotspots: pagination 1`] = `
<div
- className="huge-spacer-bottom big-padded-right hotspot-list"
+ className="huge-spacer-bottom"
>
<h1
className="hotspot-list-header bordered-bottom"
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
index 40d870f0e77..d92ff4dff2d 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotViewer-test.tsx.snap
@@ -35,11 +35,6 @@ exports[`should render correctly 1`] = `
onCloseComment={[Function]}
onOpenComment={[Function]}
onUpdateHotspot={[Function]}
- parentScrollRef={
- Object {
- "current": null,
- }
- }
securityCategories={
Object {
"cat1": Object {
@@ -90,11 +85,6 @@ exports[`should render correctly 2`] = `
onCloseComment={[Function]}
onOpenComment={[Function]}
onUpdateHotspot={[Function]}
- parentScrollRef={
- Object {
- "current": null,
- }
- }
securityCategories={
Object {
"cat1": Object {
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/styles.css b/server/sonar-web/src/main/js/apps/security-hotspots/styles.css
index b0a0f304706..e9095d08038 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/styles.css
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/styles.css
@@ -17,49 +17,57 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#security_hotspots .wrapper {
- position: fixed;
- /* top is defined programatically */
- bottom: 0;
- width: 100%;
+#security_hotspots .filter-bar-outer {
+ height: 62px;
}
-#security_hotspots .layout-page {
- margin: 0 auto;
- min-width: var(--minPageWidth);
- max-width: 1280px;
- height: 100%;
+#security_hotspots .filter-bar {
+ position: fixed;
+ background-color: var(--barBackgroundColor);
+ z-index: var(--pageSideZIndex);
+ left: 0;
+ right: 0;
}
-#security_hotspots .filter-bar {
+#security_hotspots .filter-bar-inner {
max-width: 1280px;
- box-sizing: border-box;
margin: 0 auto;
padding: calc(2 * var(--gridSize)) var(--gridSize);
+ box-sizing: border-box;
border-bottom: 1px solid var(--barBorderColor);
}
-#security_hotspots .sidebar {
- flex: 0 0 300px;
- border-right: 1px solid var(--barBorderColor);
- height: 100%;
- overflow-y: auto;
- overflow-x: hidden;
+#security_hotspots .layout-page-side,
+#security_hotspots .layout-page-side-outer {
+ width: calc(50vw - 330px);
+}
+
+#security_hotspots .layout-page-side-inner {
+ margin-left: calc(50vw - 645px);
}
-#security_hotspots .main {
- flex: 1 1 auto;
- background-color: white;
- /* Force flex to take parent width. */
- overflow-x: auto;
+#security_hotspots .layout-page-main {
+ padding: 0;
+}
+
+@media (max-width: 1320px) {
+ #security_hotspots .layout-page-side-outer,
+ #security_hotspots .layout-page-side {
+ width: 316px;
+ }
+
+ #security_hotspots .layout-page-side-inner {
+ margin-left: 0;
+ }
}
-#security_hotspots .main .hotspot-content {
- overflow-y: auto;
- height: 100%;
+#security_hotspots .hotspot-content {
+ max-width: 962px; /* 1280px - 300px - 18px */
+ background: white;
box-sizing: border-box;
}
-.invisible {
- visibility: hidden;
+#security_hotspots .invisible {
+ height: 0;
+ overflow: hidden;
}