aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-05-23 13:53:41 +0200
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-06-09 08:26:48 +0200
commitea37577db04eba371145873d41ac8ad9cae9bb64 (patch)
tree523cfd63c8585b4ac5f21eea7c36a846ed09ad44 /server/sonar-web
parent1689d1f1ca71dfac66682fd87b4ce56ad58dfce0 (diff)
downloadsonarqube-ea37577db04eba371145873d41ac8ad9cae9bb64.tar.gz
sonarqube-ea37577db04eba371145873d41ac8ad9cae9bb64.zip
SONAR-9256 Update project cards design on the projects page
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js29
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js2
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js9
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js38
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js2
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeakMeasures-test.js61
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverallMeasures-test.js (renamed from server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardMeasures-test.js)42
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.js.snap10
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap47
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeakMeasures-test.js.snap291
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardMeasures-test.js.snap531
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverallMeasures-test.js.snap308
-rw-r--r--server/sonar-web/src/main/js/apps/projects/styles.css18
-rw-r--r--server/sonar-web/src/main/js/components/common/PrivateBadge.js9
14 files changed, 779 insertions, 618 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js
index f08708da24d..18b485bdcc8 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js
@@ -72,10 +72,20 @@ export default function ProjectCard({ measures, organization, project, type }: P
return (
<div data-key={project.key} className={className}>
- {displayQualityGate &&
- <div className="boxed-group-actions">
- <ProjectCardQualityGate status={measures['alert_status']} />
- </div>}
+
+ <div className="boxed-group-actions text-right">
+ {project.visibility === 'private' &&
+ <PrivateBadge className="spacer-left" tooltipPlacement="left" />}
+ {project.tags.length > 0 && <TagsList tags={project.tags} customClass="spacer-left" />}
+ {isLeakView &&
+ isProjectAnalyzed &&
+ <div className="little-spacer-top spacer-left note">
+ {translateWithParameters(
+ 'overview.last_analysis_on_x',
+ moment(project.analysisDate).format('LLL')
+ )}
+ </div>}
+ </div>
<div className="boxed-group-header">
{project.isFavorite != null &&
@@ -88,8 +98,7 @@ export default function ProjectCard({ measures, organization, project, type }: P
</span>}
<Link to={{ pathname: '/dashboard', query: { id: project.key } }}>{project.name}</Link>
</h2>
- {project.visibility === 'private' && <PrivateBadge className="spacer-left" />}
- {project.tags.length > 0 && <TagsList tags={project.tags} customClass="spacer-left" />}
+ {displayQualityGate && <ProjectCardQualityGate status={measures['alert_status']} />}
</div>
{isProjectAnalyzed
@@ -103,14 +112,6 @@ export default function ProjectCard({ measures, organization, project, type }: P
{translate('projects.not_analyzed')}
</div>
</div>}
-
- {isProjectAnalyzed &&
- <div className="project-card-analysis-date note">
- {translateWithParameters(
- 'overview.last_analysis_on_x',
- moment(project.analysisDate).format('LLL')
- )}
- </div>}
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js
index b1490444391..b42ea3bdd13 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js
@@ -117,7 +117,7 @@ export default function ProjectCardLeakMeasures({ measures }: Props) {
</div>
{measures['new_lines'] != null &&
- <div className="project-card-measure smaller-card" data-key="new_lines">
+ <div className="project-card-measure smaller-card pull-right" data-key="new_lines">
<div className="project-card-measure-inner">
<div className="project-card-measure-number">
<Measure
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js
index 883b8039953..87ad40ee285 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js
@@ -26,7 +26,6 @@ import CoverageRating from '../../../components/ui/CoverageRating';
import DuplicationsRating from '../../../components/ui/DuplicationsRating';
import SizeRating from '../../../components/ui/SizeRating';
import { translate } from '../../../helpers/l10n';
-import { formatMeasure } from '../../../helpers/measures';
type Props = {
measures?: { [string]: string }
@@ -95,9 +94,7 @@ export default function ProjectCardMeasures({ measures }: Props) {
<div className="project-card-measure-number">
{measures['duplicated_lines_density'] != null &&
<span className="spacer-right">
- <DuplicationsRating
- value={formatMeasure(measures['duplicated_lines_density'], 'FLOAT')}
- />
+ <DuplicationsRating value={Number(measures['duplicated_lines_density'])} />
</span>}
<Measure
measure={{ value: measures['duplicated_lines_density'] }}
@@ -111,11 +108,11 @@ export default function ProjectCardMeasures({ measures }: Props) {
</div>
{measures['ncloc'] != null &&
- <div className="project-card-measure" data-key="ncloc">
+ <div className="project-card-measure pull-right" data-key="ncloc">
<div className="project-card-measure-inner">
<div className="project-card-measure-number">
<span className="spacer-right">
- <SizeRating value={formatMeasure(measures['ncloc'], 'INT')} />
+ <SizeRating value={Number(measures['ncloc'])} />
</span>
<Measure
measure={{ value: measures['ncloc'] }}
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js
index 1c4995a8bb8..585c2648e1c 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js
@@ -17,32 +17,30 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+//@flow
import React from 'react';
import Level from '../../../components/ui/Level';
-import { translate } from '../../../helpers/l10n';
+import Tooltip from '../../../components/controls/Tooltip';
+import { formatMeasure } from '../../../helpers/measures';
+import { translateWithParameters } from '../../../helpers/l10n';
-export default class ProjectCardQualityGate extends React.PureComponent {
- static propTypes = {
- status: React.PropTypes.string
- };
-
- render() {
- const { status } = this.props;
+export default function ProjectCardQualityGate({ status }: { status?: string }) {
+ if (!status) {
+ return null;
+ }
- if (!status) {
- return null;
- }
+ const tooltip = translateWithParameters(
+ 'overview.quality_gate_x',
+ formatMeasure(status, 'LEVEL')
+ );
- return (
- <div className="project-card-measure project-card-quality-gate">
+ return (
+ <div className="project-card-measure project-card-quality-gate spacer-left">
+ <Tooltip overlay={tooltip}>
<div className="project-card-measure-inner">
- <span className="small spacer-right">
- {translate('overview.quality_gate')}
- {':'}
- </span>
<Level level={status} small={true} />
</div>
- </div>
- );
- }
+ </Tooltip>
+ </div>
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js
index 3961e537d86..bb5b0ecef82 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js
@@ -24,7 +24,7 @@ import ProjectCard from '../ProjectCard';
const PROJECT = { analysisDate: '2017-01-01', key: 'foo', name: 'Foo', tags: [] };
const MEASURES = {};
-it('should display analysis date', () => {
+it('should not display analysis date', () => {
expect(
shallow(<ProjectCard measures={MEASURES} project={PROJECT} />).find(
'.project-card-analysis-date'
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeakMeasures-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeakMeasures-test.js
new file mode 100644
index 00000000000..8ef407e3181
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeakMeasures-test.js
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 React from 'react';
+import { shallow } from 'enzyme';
+import ProjectCardLeakMeasures from '../ProjectCardLeakMeasures';
+
+const measures = {
+ alert_status: 'ERROR',
+ new_reliability_rating: '1.0',
+ new_bugs: '8',
+ new_security_rating: '2.0',
+ new_vulnerabilities: '2',
+ new_maintainability_rating: '1.0',
+ new_code_smells: '0',
+ new_coverage: '26.55',
+ new_duplicated_lines_density: '0.55',
+ new_lines: '87'
+};
+
+it('should render correctly with all data', () => {
+ const wrapper = shallow(<ProjectCardLeakMeasures measures={measures} />);
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should not render new coverage', () => {
+ const wrapper = shallow(
+ <ProjectCardLeakMeasures measures={{ ...measures, new_coverage: undefined }} />
+ );
+ expect(wrapper.find('[data-key="new_coverage"]')).toMatchSnapshot();
+});
+
+it('should not render new duplications', () => {
+ const wrapper = shallow(
+ <ProjectCardLeakMeasures measures={{ ...measures, new_duplicated_lines_density: undefined }} />
+ );
+ expect(wrapper.find('[data-key="new_duplicated_lines_density"]')).toMatchSnapshot();
+});
+
+it('should not render new lines', () => {
+ const wrapper = shallow(
+ <ProjectCardLeakMeasures measures={{ ...measures, new_lines: undefined }} />
+ );
+ expect(wrapper.find('[data-key="new_lines"]')).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardMeasures-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverallMeasures-test.js
index b0d6e3280b3..7ee12ea5dfa 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardMeasures-test.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverallMeasures-test.js
@@ -19,21 +19,35 @@
*/
import React from 'react';
import { shallow } from 'enzyme';
-import ProjectCardMeasures from '../ProjectCardMeasures';
+import ProjectCardOverallMeasures from '../ProjectCardOverallMeasures';
-it('should not render coverage', () => {
+it('should render correctly with all data', () => {
const measures = {
alert_status: 'ERROR',
+ coverage: '88.3',
duplicated_lines_density: '9.8',
ncloc: '2053',
reliability_rating: '1.0',
security_rating: '1.0',
sqale_rating: '1.0'
};
- const wrapper = shallow(<ProjectCardMeasures measures={measures} />);
+ const wrapper = shallow(<ProjectCardOverallMeasures measures={measures} />);
expect(wrapper).toMatchSnapshot();
});
+it('should not render coverage', () => {
+ const measures = {
+ alert_status: 'ERROR',
+ duplicated_lines_density: '9.8',
+ ncloc: '2053',
+ reliability_rating: '1.0',
+ security_rating: '1.0',
+ sqale_rating: '1.0'
+ };
+ const wrapper = shallow(<ProjectCardOverallMeasures measures={measures} />);
+ expect(wrapper.find('[data-key="coverage"]')).toMatchSnapshot();
+});
+
it('should not render duplications', () => {
const measures = {
alert_status: 'ERROR',
@@ -43,8 +57,8 @@ it('should not render duplications', () => {
security_rating: '1.0',
sqale_rating: '1.0'
};
- const wrapper = shallow(<ProjectCardMeasures measures={measures} />);
- expect(wrapper).toMatchSnapshot();
+ const wrapper = shallow(<ProjectCardOverallMeasures measures={measures} />);
+ expect(wrapper.find('[data-key="duplicated_lines_density"]')).toMatchSnapshot();
});
it('should not render ncloc', () => {
@@ -56,6 +70,20 @@ it('should not render ncloc', () => {
security_rating: '1.0',
sqale_rating: '1.0'
};
- const wrapper = shallow(<ProjectCardMeasures measures={measures} />);
- expect(wrapper).toMatchSnapshot();
+ const wrapper = shallow(<ProjectCardOverallMeasures measures={measures} />);
+ expect(wrapper.find('[data-key="ncloc"]').length).toBe(0);
+});
+
+it('should render ncloc correctly', () => {
+ const measures = {
+ alert_status: 'ERROR',
+ coverage: '88.3',
+ ncloc: '16549887',
+ duplicated_lines_density: '9.8',
+ reliability_rating: '1.0',
+ security_rating: '1.0',
+ sqale_rating: '1.0'
+ };
+ const wrapper = shallow(<ProjectCardOverallMeasures measures={measures} />);
+ expect(wrapper.find('[data-key="ncloc"]')).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.js.snap
index 8939575929b..b4ab927ee51 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/PerspectiveSelect-test.js.snap
@@ -66,6 +66,11 @@ exports[`should render correctly 1`] = `
"value": "overall",
},
Object {
+ "label": "projects.view.leak",
+ "type": "view",
+ "value": "leak",
+ },
+ Object {
"label": "projects.visualization.risk",
"type": "visualization",
"value": "risk",
@@ -156,6 +161,11 @@ exports[`should render with coverage selected 1`] = `
"value": "overall",
},
Object {
+ "label": "projects.view.leak",
+ "type": "view",
+ "value": "leak",
+ },
+ Object {
"label": "projects.visualization.risk",
"type": "visualization",
"value": "risk",
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap
index 5221745c187..ff77d4e7b33 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap
@@ -1,19 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should display analysis date 1`] = `
-<div
- className="project-card-analysis-date note"
->
- overview.last_analysis_on_x.January 1, 2017 12:00 AM
-</div>
-`;
-
exports[`should display loading 1`] = `
<div
className="boxed-group project-card boxed-group-loading"
data-key="foo"
>
<div
+ className="boxed-group-actions text-right"
+ />
+ <div
className="boxed-group-header"
>
<h2
@@ -37,11 +32,8 @@ exports[`should display loading 1`] = `
</div>
<div
className="boxed-group-inner"
- />
- <div
- className="project-card-analysis-date note"
>
- overview.last_analysis_on_x.January 1, 2017 12:00 AM
+ <ProjectCardMeasures />
</div>
</div>
`;
@@ -52,6 +44,20 @@ exports[`should display tags 1`] = `
data-key="foo"
>
<div
+ className="boxed-group-actions text-right"
+ >
+ <TagsList
+ allowUpdate={false}
+ customClass="spacer-left"
+ tags={
+ Array [
+ "foo",
+ "bar",
+ ]
+ }
+ />
+ </div>
+ <div
className="boxed-group-header"
>
<h2
@@ -72,24 +78,13 @@ exports[`should display tags 1`] = `
Foo
</Link>
</h2>
- <TagsList
- allowUpdate={false}
- customClass="spacer-left"
- tags={
- Array [
- "foo",
- "bar",
- ]
- }
- />
</div>
<div
className="boxed-group-inner"
- />
- <div
- className="project-card-analysis-date note"
>
- overview.last_analysis_on_x.January 1, 2017 12:00 AM
+ <ProjectCardMeasures />
</div>
</div>
`;
+
+exports[`should not display analysis date 1`] = `undefined`;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeakMeasures-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeakMeasures-test.js.snap
new file mode 100644
index 00000000000..9171745b0da
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeakMeasures-test.js.snap
@@ -0,0 +1,291 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should not render new coverage 1`] = `
+<div
+ className="project-card-measure"
+ data-key="new_coverage"
+>
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "leak": undefined,
+ }
+ }
+ metric={
+ Object {
+ "key": "new_coverage",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.new_coverage.name
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should not render new duplications 1`] = `
+<div
+ className="project-card-measure"
+ data-key="new_duplicated_lines_density"
+>
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "leak": undefined,
+ }
+ }
+ metric={
+ Object {
+ "key": "new_duplicated_lines_density",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.new_duplicated_lines_density.short_name
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should not render new lines 1`] = `undefined`;
+
+exports[`should render correctly with all data 1`] = `
+<div
+ className="project-card-leak-measures"
+>
+ <div
+ className="project-card-measure smaller-card"
+ data-key="new_reliability_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ className="spacer-right"
+ measure={
+ Object {
+ "leak": "8",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_bugs",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ <Rating
+ muted={false}
+ small={false}
+ value="1.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ <BugIcon
+ className="little-spacer-right vertical-bottom"
+ />
+ metric.new_bugs.name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="new_security_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ className="spacer-right"
+ measure={
+ Object {
+ "leak": "2",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_vulnerabilities",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ <Rating
+ muted={false}
+ small={false}
+ value="2.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ <VulnerabilityIcon
+ className="little-spacer-right vertical-bottom"
+ />
+ metric.new_vulnerabilities.name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="new_maintainability_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ className="spacer-right"
+ measure={
+ Object {
+ "leak": "0",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_code_smells",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ <Rating
+ muted={false}
+ small={false}
+ value="1.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ <CodeSmellIcon
+ className="little-spacer-right vertical-bottom"
+ />
+ metric.new_code_smells.name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="new_coverage"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "leak": "26.55",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_coverage",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.new_coverage.name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="new_duplicated_lines_density"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "leak": "0.55",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_duplicated_lines_density",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.new_duplicated_lines_density.short_name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure smaller-card pull-right"
+ data-key="new_lines"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "leak": "87",
+ }
+ }
+ metric={
+ Object {
+ "key": "new_lines",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.new_lines.short_name
+ </div>
+ </div>
+ </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardMeasures-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardMeasures-test.js.snap
deleted file mode 100644
index 787d967682c..00000000000
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardMeasures-test.js.snap
+++ /dev/null
@@ -1,531 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should not render coverage 1`] = `
-<div
- className="project-card-measures"
->
- <div
- className="project-card-measure"
- data-key="reliability_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Reliability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="security_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Security
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="sqale_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Maintainability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="coverage"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Measure
- measure={
- Object {
- "value": undefined,
- }
- }
- metric={
- Object {
- "key": "coverage",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.coverage.name
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="duplicated_lines_density"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <DuplicationsRating
- muted={false}
- small={false}
- value="9.8"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "9.8",
- }
- }
- metric={
- Object {
- "key": "duplicated_lines_density",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.duplicated_lines_density.short_name
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="ncloc"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <SizeRating
- muted={false}
- small={false}
- value="2053"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "2053",
- }
- }
- metric={
- Object {
- "key": "ncloc",
- "type": "SHORT_INT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- <Connect(ProjectCardLanguages) />
- </div>
- </div>
- </div>
-</div>
-`;
-
-exports[`should not render duplications 1`] = `
-<div
- className="project-card-measures"
->
- <div
- className="project-card-measure"
- data-key="reliability_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Reliability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="security_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Security
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="sqale_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Maintainability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="coverage"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <CoverageRating
- muted={false}
- size="normal"
- value="88.3"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "88.3",
- }
- }
- metric={
- Object {
- "key": "coverage",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.coverage.name
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="duplicated_lines_density"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Measure
- measure={
- Object {
- "value": undefined,
- }
- }
- metric={
- Object {
- "key": "duplicated_lines_density",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.duplicated_lines_density.short_name
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="ncloc"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <SizeRating
- muted={false}
- small={false}
- value="2053"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "2053",
- }
- }
- metric={
- Object {
- "key": "ncloc",
- "type": "SHORT_INT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- <Connect(ProjectCardLanguages) />
- </div>
- </div>
- </div>
-</div>
-`;
-
-exports[`should not render ncloc 1`] = `
-<div
- className="project-card-measures"
->
- <div
- className="project-card-measure"
- data-key="reliability_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Reliability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="security_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Security
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="sqale_rating"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <Rating
- muted={false}
- small={false}
- value="1.0"
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric_domain.Maintainability
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="coverage"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <CoverageRating
- muted={false}
- size="normal"
- value="88.3"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "88.3",
- }
- }
- metric={
- Object {
- "key": "coverage",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.coverage.name
- </div>
- </div>
- </div>
- <div
- className="project-card-measure"
- data-key="duplicated_lines_density"
- >
- <div
- className="project-card-measure-inner"
- >
- <div
- className="project-card-measure-number"
- >
- <span
- className="spacer-right"
- >
- <DuplicationsRating
- muted={false}
- small={false}
- value="9.8"
- />
- </span>
- <Measure
- measure={
- Object {
- "value": "9.8",
- }
- }
- metric={
- Object {
- "key": "duplicated_lines_density",
- "type": "PERCENT",
- }
- }
- />
- </div>
- <div
- className="project-card-measure-label"
- >
- metric.duplicated_lines_density.short_name
- </div>
- </div>
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverallMeasures-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverallMeasures-test.js.snap
new file mode 100644
index 00000000000..b5431a1454a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverallMeasures-test.js.snap
@@ -0,0 +1,308 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should not render coverage 1`] = `
+<div
+ className="project-card-measure"
+ data-key="coverage"
+>
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "value": undefined,
+ }
+ }
+ metric={
+ Object {
+ "key": "coverage",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.coverage.name
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should not render duplications 1`] = `
+<div
+ className="project-card-measure"
+ data-key="duplicated_lines_density"
+>
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Measure
+ measure={
+ Object {
+ "value": undefined,
+ }
+ }
+ metric={
+ Object {
+ "key": "duplicated_lines_density",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.duplicated_lines_density.short_name
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should render correctly with all data 1`] = `
+<div
+ className="project-card-measures"
+>
+ <div
+ className="project-card-measure smaller-card"
+ data-key="reliability_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Rating
+ muted={false}
+ small={false}
+ value="1.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric_domain.Reliability
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure smaller-card"
+ data-key="security_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Rating
+ muted={false}
+ small={false}
+ value="1.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric_domain.Security
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="sqale_rating"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <Rating
+ muted={false}
+ small={false}
+ value="1.0"
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric_domain.Maintainability
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="coverage"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <span
+ className="spacer-right"
+ >
+ <CoverageRating
+ muted={false}
+ size="normal"
+ value="88.3"
+ />
+ </span>
+ <Measure
+ measure={
+ Object {
+ "value": "88.3",
+ }
+ }
+ metric={
+ Object {
+ "key": "coverage",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.coverage.name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure"
+ data-key="duplicated_lines_density"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <span
+ className="spacer-right"
+ >
+ <DuplicationsRating
+ muted={false}
+ small={false}
+ value={9.8}
+ />
+ </span>
+ <Measure
+ measure={
+ Object {
+ "value": "9.8",
+ }
+ }
+ metric={
+ Object {
+ "key": "duplicated_lines_density",
+ "type": "PERCENT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ metric.duplicated_lines_density.short_name
+ </div>
+ </div>
+ </div>
+ <div
+ className="project-card-measure pull-right"
+ data-key="ncloc"
+ >
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <span
+ className="spacer-right"
+ >
+ <SizeRating
+ muted={false}
+ small={false}
+ value={2053}
+ />
+ </span>
+ <Measure
+ measure={
+ Object {
+ "value": "2053",
+ }
+ }
+ metric={
+ Object {
+ "key": "ncloc",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ <Connect(ProjectCardLanguages) />
+ </div>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should render ncloc correctly 1`] = `
+<div
+ className="project-card-measure pull-right"
+ data-key="ncloc"
+>
+ <div
+ className="project-card-measure-inner"
+ >
+ <div
+ className="project-card-measure-number"
+ >
+ <span
+ className="spacer-right"
+ >
+ <SizeRating
+ muted={false}
+ small={false}
+ value={16549887}
+ />
+ </span>
+ <Measure
+ measure={
+ Object {
+ "value": "16549887",
+ }
+ }
+ metric={
+ Object {
+ "key": "ncloc",
+ "type": "SHORT_INT",
+ }
+ }
+ />
+ </div>
+ <div
+ className="project-card-measure-label"
+ >
+ <Connect(ProjectCardLanguages) />
+ </div>
+ </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/projects/styles.css b/server/sonar-web/src/main/js/apps/projects/styles.css
index 5a94f6006a7..a5c32750f3c 100644
--- a/server/sonar-web/src/main/js/apps/projects/styles.css
+++ b/server/sonar-web/src/main/js/apps/projects/styles.css
@@ -87,11 +87,12 @@
.project-card-leak-measures {
padding: 4px 0;
- margin: 0 -4px 4px;
+ margin: 4px -4px;
background-color: #fbf3d5;
border: 1px solid #eae3c7;
}
+
.project-card-measures .project-card-measure {
width: 120px;
box-sizing: border-box;
@@ -136,10 +137,18 @@
content: "";
}
+.project-card-measure.pull-right {
+ text-align: right;
+}
+
.project-card-measure.pull-right:before {
display: none;
}
+.project-card-measure.pull-right .project-card-measure-inner {
+ text-align: right;
+}
+
.project-card-measure .level {
margin-top: 0;
margin-bottom: 0;
@@ -173,13 +182,6 @@
line-height: 24px;
}
-.project-card-analysis-date {
- margin-top: -15px;
- padding-bottom: 5px;
- padding-right: 20px;
- text-align: right;
-}
-
.project-card-not-analyzed {
padding: 14px 0;
}
diff --git a/server/sonar-web/src/main/js/components/common/PrivateBadge.js b/server/sonar-web/src/main/js/components/common/PrivateBadge.js
index 775c0727911..a949dc4d1dc 100644
--- a/server/sonar-web/src/main/js/components/common/PrivateBadge.js
+++ b/server/sonar-web/src/main/js/components/common/PrivateBadge.js
@@ -25,13 +25,14 @@ import { translate } from '../../helpers/l10n';
import './PrivateBadge.css';
type Props = {
- className?: string
+ className?: string,
+ tooltipPlacement?: string
};
-export default function PrivateBadge(props: Props) {
+export default function PrivateBadge({ className, tooltipPlacement = 'bottom' }: Props) {
return (
- <Tooltip overlay={translate('visibility.private.description')}>
- <div className={classNames('private-badge', props.className)}>
+ <Tooltip overlay={translate('visibility.private.description')} placement={tooltipPlacement}>
+ <div className={classNames('private-badge', className)}>
{translate('visibility.private')}
</div>
</Tooltip>