aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js11
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js (renamed from server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js)38
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js106
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js136
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.js82
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.js93
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap122
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.js.snap63
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.js.snap60
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties1
10 files changed, 428 insertions, 284 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js
index d3908234509..9e71d2559ba 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js
@@ -17,10 +17,19 @@
* 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 { connect } from 'react-redux';
-import ProjectCard from './ProjectCard';
+import ProjectCardLeak from './ProjectCardLeak';
+import ProjectCardOverall from './ProjectCardOverall';
import { getComponent, getComponentMeasures } from '../../../store/rootReducer';
+function ProjectCard(props: { type?: string }) {
+ if (props.type === 'leak') {
+ return <ProjectCardLeak {...props} />;
+ }
+ return <ProjectCardOverall {...props} />;
+}
+
export default connect((state, ownProps) => ({
project: getComponent(state, ownProps.projectKey),
measures: getComponentMeasures(state, ownProps.projectKey)
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js
index 94c65bd4a6f..9e38e2bcb2d 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js
@@ -24,7 +24,6 @@ import moment from 'moment';
import { Link } from 'react-router';
import ProjectCardQualityGate from './ProjectCardQualityGate';
import ProjectCardLeakMeasures from './ProjectCardLeakMeasures';
-import ProjectCardOverallMeasures from './ProjectCardOverallMeasures';
import FavoriteContainer from '../../../components/controls/FavoriteContainer';
import Organization from '../../../components/shared/Organization';
import TagsList from '../../../components/tags/TagsList';
@@ -43,11 +42,10 @@ type Props = {
isFavorite?: boolean,
organization?: string,
visibility?: boolean
- },
- type?: string
+ }
};
-export default function ProjectCard({ measures, organization, project, type }: Props) {
+export default function ProjectCardLeak({ measures, organization, project }: Props) {
if (project == null) {
return null;
}
@@ -56,23 +54,15 @@ export default function ProjectCard({ measures, organization, project, type }: P
const isPrivate = project.visibility === 'private';
const hasLeakPeriodStart = project.leakPeriodDate != null;
const hasTags = project.tags.length > 0;
- const isLeakView = type === 'leak';
+ const showOrganization = organization == null && project.organization != null;
- let areProjectMeasuresLoaded;
// check for particular measures because only some measures can be loaded
// if coming from visualizations tab
- if (isLeakView) {
- areProjectMeasuresLoaded = measures != null && measures['new_bugs'];
- } else {
- areProjectMeasuresLoaded =
- measures != null &&
- measures['reliability_rating'] != null &&
- measures['sqale_rating'] != null;
- }
+ const areProjectMeasuresLoaded = measures != null && measures['new_bugs'];
const displayQualityGate = areProjectMeasuresLoaded && isProjectAnalyzed;
const className = classNames('boxed-group', 'project-card', {
- 'boxed-group-loading': isProjectAnalyzed && !areProjectMeasuresLoaded
+ 'boxed-group-loading': isProjectAnalyzed && hasLeakPeriodStart && !areProjectMeasuresLoaded
});
return (
@@ -81,8 +71,7 @@ export default function ProjectCard({ measures, organization, project, type }: P
{project.isFavorite != null &&
<FavoriteContainer className="spacer-right" componentKey={project.key} />}
<h2 className="project-card-name">
- {organization == null &&
- project.organization != null &&
+ {showOrganization &&
<span className="text-normal">
<Organization organizationKey={project.organization} />
</span>}
@@ -94,9 +83,9 @@ export default function ProjectCard({ measures, organization, project, type }: P
{hasTags && <TagsList tags={project.tags} customClass="spacer-left" />}
</div>
{isProjectAnalyzed &&
+ hasLeakPeriodStart &&
<div className="project-card-dates note text-right pull-right">
- {isLeakView &&
- hasLeakPeriodStart &&
+ {hasLeakPeriodStart &&
<span>
{translateWithParameters(
'projects.leak_period_x',
@@ -113,16 +102,15 @@ export default function ProjectCard({ measures, organization, project, type }: P
</div>}
</div>
- {isProjectAnalyzed
+ {isProjectAnalyzed && hasLeakPeriodStart
? <div className="boxed-group-inner">
- {areProjectMeasuresLoaded &&
- (isLeakView
- ? <ProjectCardLeakMeasures measures={measures} />
- : <ProjectCardOverallMeasures measures={measures} />)}
+ {areProjectMeasuresLoaded && <ProjectCardLeakMeasures measures={measures} />}
</div>
: <div className="boxed-group-inner">
<div className="note project-card-not-analyzed">
- {translate('projects.not_analyzed')}
+ {isProjectAnalyzed
+ ? translate('projects.no_leak_period')
+ : translate('projects.not_analyzed')}
</div>
</div>}
</div>
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js
new file mode 100644
index 00000000000..8ef49b49179
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+// @flow
+import React from 'react';
+import classNames from 'classnames';
+import moment from 'moment';
+import { Link } from 'react-router';
+import ProjectCardQualityGate from './ProjectCardQualityGate';
+import ProjectCardOverallMeasures from './ProjectCardOverallMeasures';
+import FavoriteContainer from '../../../components/controls/FavoriteContainer';
+import Organization from '../../../components/shared/Organization';
+import TagsList from '../../../components/tags/TagsList';
+import PrivateBadge from '../../../components/common/PrivateBadge';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+type Props = {
+ measures: { [string]: string },
+ organization?: { key: string },
+ project?: {
+ analysisDate?: string,
+ key: string,
+ name: string,
+ tags: Array<string>,
+ isFavorite?: boolean,
+ organization?: string,
+ visibility?: boolean
+ }
+};
+
+export default function ProjectCardOverall({ measures, organization, project }: Props) {
+ if (project == null) {
+ return null;
+ }
+
+ const isProjectAnalyzed = project.analysisDate != null;
+ const isPrivate = project.visibility === 'private';
+ const hasTags = project.tags.length > 0;
+ const showOrganization = organization == null && project.organization != null;
+
+ // check for particular measures because only some measures can be loaded
+ // if coming from visualizations tab
+ const areProjectMeasuresLoaded =
+ measures != null && measures['reliability_rating'] != null && measures['sqale_rating'] != null;
+
+ const displayQualityGate = areProjectMeasuresLoaded && isProjectAnalyzed;
+ const className = classNames('boxed-group', 'project-card', {
+ 'boxed-group-loading': isProjectAnalyzed && !areProjectMeasuresLoaded
+ });
+
+ return (
+ <div data-key={project.key} className={className}>
+ <div className="boxed-group-header clearfix">
+ {project.isFavorite != null &&
+ <FavoriteContainer className="spacer-right" componentKey={project.key} />}
+ <h2 className="project-card-name">
+ {showOrganization &&
+ <span className="text-normal">
+ <Organization organizationKey={project.organization} />
+ </span>}
+ <Link to={{ pathname: '/dashboard', query: { id: project.key } }}>{project.name}</Link>
+ </h2>
+ {displayQualityGate && <ProjectCardQualityGate status={measures['alert_status']} />}
+ <div className="pull-right text-right">
+ {isPrivate && <PrivateBadge className="spacer-left" tooltipPlacement="left" />}
+ {hasTags && <TagsList tags={project.tags} customClass="spacer-left" />}
+ </div>
+ {isProjectAnalyzed &&
+ <div className="project-card-dates note text-right pull-right">
+ <span className="big-spacer-left">
+ {translateWithParameters(
+ 'projects.last_analysis_on_x',
+ moment(project.analysisDate).format('LLL')
+ )}
+ </span>
+ </div>}
+ </div>
+
+ {isProjectAnalyzed
+ ? <div className="boxed-group-inner">
+ {areProjectMeasuresLoaded && <ProjectCardOverallMeasures measures={measures} />}
+ </div>
+ : <div className="boxed-group-inner">
+ <div className="note project-card-not-analyzed">
+ {translate('projects.not_analyzed')}
+ </div>
+ </div>}
+ </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
deleted file mode 100644
index a5e143fb5f0..00000000000
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCard-test.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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 ProjectCard from '../ProjectCard';
-
-const PROJECT = {
- analysisDate: '2017-01-01',
- leakPeriodDate: '2016-12-01',
- key: 'foo',
- name: 'Foo',
- tags: []
-};
-const MEASURES = {
- alert_status: 'OK',
- reliability_rating: '1.0',
- sqale_rating: '1.0',
- new_bugs: 12
-};
-
-jest.mock('moment', () => () => ({
- format: () => 'March 1, 2017 9:36 AM',
- fromNow: () => 'a month ago'
-}));
-
-describe('overall status project card', () => {
- it('should display analysis date (and not leak period) when defined', () => {
- expect(
- shallow(<ProjectCard measures={{}} project={PROJECT} />).find('.project-card-dates').exists()
- ).toBeTruthy();
- expect(
- shallow(<ProjectCard measures={{}} project={{ ...PROJECT, analysisDate: undefined }} />)
- .find('.project-card-dates')
- .exists()
- ).toBeFalsy();
- });
-
- it('should display loading', () => {
- const measures = { ...MEASURES, sqale_rating: undefined };
- expect(
- shallow(<ProjectCard project={PROJECT} />)
- .find('.boxed-group')
- .hasClass('boxed-group-loading')
- ).toBeTruthy();
- expect(
- shallow(<ProjectCard measures={measures} project={PROJECT} />)
- .find('.boxed-group')
- .hasClass('boxed-group-loading')
- ).toBeTruthy();
- });
-
- it('should not display the quality gate', () => {
- const project = { ...PROJECT, analysisDate: undefined };
- expect(
- shallow(<ProjectCard measures={MEASURES} project={project} />)
- .find('ProjectCardQualityGate')
- .exists()
- ).toBeFalsy();
- });
-
- it('should display tags', () => {
- const project = { ...PROJECT, tags: ['foo', 'bar'] };
- expect(shallow(<ProjectCard project={project} />).find('TagsList').exists()).toBeTruthy();
- });
-
- it('should private badge', () => {
- const project = { ...PROJECT, visibility: 'private' };
- expect(
- shallow(<ProjectCard type="overall" project={project} />).find('PrivateBadge').exists()
- ).toBeTruthy();
- });
-
- it('should display the overall measures and quality gate', () => {
- expect(shallow(<ProjectCard measures={MEASURES} project={PROJECT} />)).toMatchSnapshot();
- });
-});
-
-describe('leak project card', () => {
- it('should display analysis date and leak start date', () => {
- const card = shallow(<ProjectCard type="leak" measures={MEASURES} project={PROJECT} />);
- expect(card.find('.project-card-dates').exists()).toBeTruthy();
- expect(card.find('.project-card-dates').find('span').getNodes()).toHaveLength(2);
- });
-
- it('should not display analysis date or leak start date', () => {
- const project = { ...PROJECT, analysisDate: undefined };
- const card = shallow(<ProjectCard type="leak" measures={MEASURES} project={project} />);
- expect(card.find('.project-card-dates').exists()).toBeFalsy();
- });
-
- it('should display loading', () => {
- const measures = { ...MEASURES, new_bugs: undefined };
- expect(
- shallow(<ProjectCard type="leak" measures={measures} project={PROJECT} />)
- .find('.boxed-group')
- .hasClass('boxed-group-loading')
- ).toBeTruthy();
- });
-
- it('should display tags', () => {
- const project = { ...PROJECT, tags: ['foo', 'bar'] };
- expect(
- shallow(<ProjectCard type="leak" project={project} />).find('TagsList').exists()
- ).toBeTruthy();
- });
-
- it('should private badge', () => {
- const project = { ...PROJECT, visibility: 'private' };
- expect(
- shallow(<ProjectCard type="leak" project={project} />).find('PrivateBadge').exists()
- ).toBeTruthy();
- });
-
- it('should display the leak measures and quality gate', () => {
- expect(
- shallow(<ProjectCard type="leak" measures={MEASURES} project={PROJECT} />)
- ).toMatchSnapshot();
- });
-});
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.js
new file mode 100644
index 00000000000..46819f2bd13
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.js
@@ -0,0 +1,82 @@
+/*
+ * 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 ProjectCardLeak from '../ProjectCardLeak';
+
+const PROJECT = {
+ analysisDate: '2017-01-01',
+ leakPeriodDate: '2016-12-01',
+ key: 'foo',
+ name: 'Foo',
+ tags: []
+};
+const MEASURES = {
+ alert_status: 'OK',
+ reliability_rating: '1.0',
+ sqale_rating: '1.0',
+ new_bugs: 12
+};
+
+jest.mock('moment', () => () => ({
+ format: () => 'March 1, 2017 9:36 AM',
+ fromNow: () => 'a month ago'
+}));
+
+it('should display analysis date and leak start date', () => {
+ const card = shallow(<ProjectCardLeak type="leak" measures={MEASURES} project={PROJECT} />);
+ expect(card.find('.project-card-dates').exists()).toBeTruthy();
+ expect(card.find('.project-card-dates').find('span').getNodes()).toHaveLength(2);
+});
+
+it('should not display analysis date or leak start date', () => {
+ const project = { ...PROJECT, analysisDate: undefined };
+ const card = shallow(<ProjectCardLeak type="leak" measures={MEASURES} project={project} />);
+ expect(card.find('.project-card-dates').exists()).toBeFalsy();
+});
+
+it('should display loading', () => {
+ const measures = { ...MEASURES, new_bugs: undefined };
+ expect(
+ shallow(<ProjectCardLeak type="leak" measures={measures} project={PROJECT} />)
+ .find('.boxed-group')
+ .hasClass('boxed-group-loading')
+ ).toBeTruthy();
+});
+
+it('should display tags', () => {
+ const project = { ...PROJECT, tags: ['foo', 'bar'] };
+ expect(
+ shallow(<ProjectCardLeak type="leak" project={project} />).find('TagsList').exists()
+ ).toBeTruthy();
+});
+
+it('should private badge', () => {
+ const project = { ...PROJECT, visibility: 'private' };
+ expect(
+ shallow(<ProjectCardLeak type="leak" project={project} />).find('PrivateBadge').exists()
+ ).toBeTruthy();
+});
+
+it('should display the leak measures and quality gate', () => {
+ expect(
+ shallow(<ProjectCardLeak type="leak" measures={MEASURES} project={PROJECT} />)
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.js b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.js
new file mode 100644
index 00000000000..b6f5698f231
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.js
@@ -0,0 +1,93 @@
+/*
+ * 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 ProjectCardOverall from '../ProjectCardOverall';
+
+const PROJECT = {
+ analysisDate: '2017-01-01',
+ leakPeriodDate: '2016-12-01',
+ key: 'foo',
+ name: 'Foo',
+ tags: []
+};
+const MEASURES = {
+ alert_status: 'OK',
+ reliability_rating: '1.0',
+ sqale_rating: '1.0',
+ new_bugs: 12
+};
+
+jest.mock('moment', () => () => ({
+ format: () => 'March 1, 2017 9:36 AM',
+ fromNow: () => 'a month ago'
+}));
+
+it('should display analysis date (and not leak period) when defined', () => {
+ expect(
+ shallow(<ProjectCardOverall measures={{}} project={PROJECT} />)
+ .find('.project-card-dates')
+ .exists()
+ ).toBeTruthy();
+ expect(
+ shallow(<ProjectCardOverall measures={{}} project={{ ...PROJECT, analysisDate: undefined }} />)
+ .find('.project-card-dates')
+ .exists()
+ ).toBeFalsy();
+});
+
+it('should display loading', () => {
+ const measures = { ...MEASURES, sqale_rating: undefined };
+ expect(
+ shallow(<ProjectCardOverall project={PROJECT} />)
+ .find('.boxed-group')
+ .hasClass('boxed-group-loading')
+ ).toBeTruthy();
+ expect(
+ shallow(<ProjectCardOverall measures={measures} project={PROJECT} />)
+ .find('.boxed-group')
+ .hasClass('boxed-group-loading')
+ ).toBeTruthy();
+});
+
+it('should not display the quality gate', () => {
+ const project = { ...PROJECT, analysisDate: undefined };
+ expect(
+ shallow(<ProjectCardOverall measures={MEASURES} project={project} />)
+ .find('ProjectCardOverallQualityGate')
+ .exists()
+ ).toBeFalsy();
+});
+
+it('should display tags', () => {
+ const project = { ...PROJECT, tags: ['foo', 'bar'] };
+ expect(shallow(<ProjectCardOverall project={project} />).find('TagsList').exists()).toBeTruthy();
+});
+
+it('should private badge', () => {
+ const project = { ...PROJECT, visibility: 'private' };
+ expect(
+ shallow(<ProjectCardOverall type="overall" project={project} />).find('PrivateBadge').exists()
+ ).toBeTruthy();
+});
+
+it('should display the overall measures and quality gate', () => {
+ expect(shallow(<ProjectCardOverall measures={MEASURES} project={PROJECT} />)).toMatchSnapshot();
+});
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
deleted file mode 100644
index 322b86b25af..00000000000
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCard-test.js.snap
+++ /dev/null
@@ -1,122 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`leak project card should display the leak measures and quality gate 1`] = `
-<div
- className="boxed-group project-card"
- data-key="foo"
->
- <div
- className="boxed-group-header clearfix"
- >
- <h2
- className="project-card-name"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/dashboard",
- "query": Object {
- "id": "foo",
- },
- }
- }
- >
- Foo
- </Link>
- </h2>
- <ProjectCardQualityGate
- status="OK"
- />
- <div
- className="pull-right text-right"
- />
- <div
- className="project-card-dates note text-right pull-right"
- >
- <span>
- projects.leak_period_x.a month ago
- </span>
- <span
- className="big-spacer-left"
- >
- projects.last_analysis_on_x.March 1, 2017 9:36 AM
- </span>
- </div>
- </div>
- <div
- className="boxed-group-inner"
- >
- <ProjectCardLeakMeasures
- measures={
- Object {
- "alert_status": "OK",
- "new_bugs": 12,
- "reliability_rating": "1.0",
- "sqale_rating": "1.0",
- }
- }
- />
- </div>
-</div>
-`;
-
-exports[`overall status project card should display the overall measures and quality gate 1`] = `
-<div
- className="boxed-group project-card"
- data-key="foo"
->
- <div
- className="boxed-group-header clearfix"
- >
- <h2
- className="project-card-name"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/dashboard",
- "query": Object {
- "id": "foo",
- },
- }
- }
- >
- Foo
- </Link>
- </h2>
- <ProjectCardQualityGate
- status="OK"
- />
- <div
- className="pull-right text-right"
- />
- <div
- className="project-card-dates note text-right pull-right"
- >
- <span
- className="big-spacer-left"
- >
- projects.last_analysis_on_x.March 1, 2017 9:36 AM
- </span>
- </div>
- </div>
- <div
- className="boxed-group-inner"
- >
- <ProjectCardOverallMeasures
- measures={
- Object {
- "alert_status": "OK",
- "new_bugs": 12,
- "reliability_rating": "1.0",
- "sqale_rating": "1.0",
- }
- }
- />
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.js.snap
new file mode 100644
index 00000000000..101ba723485
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.js.snap
@@ -0,0 +1,63 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display the leak measures and quality gate 1`] = `
+<div
+ className="boxed-group project-card"
+ data-key="foo"
+>
+ <div
+ className="boxed-group-header clearfix"
+ >
+ <h2
+ className="project-card-name"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/dashboard",
+ "query": Object {
+ "id": "foo",
+ },
+ }
+ }
+ >
+ Foo
+ </Link>
+ </h2>
+ <ProjectCardQualityGate
+ status="OK"
+ />
+ <div
+ className="pull-right text-right"
+ />
+ <div
+ className="project-card-dates note text-right pull-right"
+ >
+ <span>
+ projects.leak_period_x.a month ago
+ </span>
+ <span
+ className="big-spacer-left"
+ >
+ projects.last_analysis_on_x.March 1, 2017 9:36 AM
+ </span>
+ </div>
+ </div>
+ <div
+ className="boxed-group-inner"
+ >
+ <ProjectCardLeakMeasures
+ measures={
+ Object {
+ "alert_status": "OK",
+ "new_bugs": 12,
+ "reliability_rating": "1.0",
+ "sqale_rating": "1.0",
+ }
+ }
+ />
+ </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.js.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.js.snap
new file mode 100644
index 00000000000..1e666cc1854
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.js.snap
@@ -0,0 +1,60 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display the overall measures and quality gate 1`] = `
+<div
+ className="boxed-group project-card"
+ data-key="foo"
+>
+ <div
+ className="boxed-group-header clearfix"
+ >
+ <h2
+ className="project-card-name"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/dashboard",
+ "query": Object {
+ "id": "foo",
+ },
+ }
+ }
+ >
+ Foo
+ </Link>
+ </h2>
+ <ProjectCardQualityGate
+ status="OK"
+ />
+ <div
+ className="pull-right text-right"
+ />
+ <div
+ className="project-card-dates note text-right pull-right"
+ >
+ <span
+ className="big-spacer-left"
+ >
+ projects.last_analysis_on_x.March 1, 2017 9:36 AM
+ </span>
+ </div>
+ </div>
+ <div
+ className="boxed-group-inner"
+ >
+ <ProjectCardOverallMeasures
+ measures={
+ Object {
+ "alert_status": "OK",
+ "new_bugs": 12,
+ "reliability_rating": "1.0",
+ "sqale_rating": "1.0",
+ }
+ }
+ />
+ </div>
+</div>
+`;
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 7d1f3bb714c..5a4ca39c975 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -860,6 +860,7 @@ projects.no_favorite_projects=You don't have any favorite projects yet.
projects.no_favorite_projects.engagement=Discover and mark as favorites projects you are interested in to have a quick access to them.
projects.explore_projects=Explore Projects
projects.not_analyzed=Project is not analyzed yet.
+projects.no_leak_period=Project has no leak data yet.
projects.leak_period_x=Leak Period started {0}
projects.last_analysis_on_x=Last analysis on {0}
projects.search=Search by project name or key