aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main
diff options
context:
space:
mode:
authorPascal Mugnier <pascal.mugnier@sonarsource.com>2018-04-11 14:32:57 +0200
committerSonarTech <sonartech@sonarsource.com>2018-04-17 20:20:47 +0200
commitb9d7623d0ce7d804f0c5a6dcfc476ae96c9b8518 (patch)
treecbde1c6db4914aca80dd68f4660300b54ad4bb90 /server/sonar-web/src/main
parentfebe5e5d486667bb8c523825285f1c22e4a48bb6 (diff)
downloadsonarqube-b9d7623d0ce7d804f0c5a6dcfc476ae96c9b8518.tar.gz
sonarqube-b9d7623d0ce7d804f0c5a6dcfc476ae96c9b8518.zip
GOV-288 Portfolio containing only provisioned projects is not 'empty'
Diffstat (limited to 'server/sonar-web/src/main')
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/App.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx72
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx55
-rw-r--r--server/sonar-web/src/main/js/apps/overview/styles.css3
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/App.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/RatingFreshness.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx20
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap31
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/RatingFreshness-test.tsx.snap20
9 files changed, 163 insertions, 71 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.tsx b/server/sonar-web/src/main/js/apps/issues/components/App.tsx
index 37e354aca8d..a433057b301 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/App.tsx
@@ -67,6 +67,7 @@ import {
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { RawQuery } from '../../../helpers/query';
import { scrollToElement } from '../../../helpers/scrolling';
+import EmptySearch from '../../../components/common/EmptySearch';
import Checkbox from '../../../components/controls/Checkbox';
import '../styles.css';
@@ -926,6 +927,17 @@ export default class App extends React.PureComponent<Props, State> {
return null;
}
+ let noIssuesMessage = null;
+ if (paging.total === 0) {
+ if (this.isFiltered()) {
+ noIssuesMessage = <EmptySearch />;
+ } else if (this.state.myIssues) {
+ noIssuesMessage = <NoMyIssues />;
+ } else {
+ noIssuesMessage = <NoIssues />;
+ }
+ }
+
return (
<div>
{paging.total > 0 && (
@@ -949,8 +961,7 @@ export default class App extends React.PureComponent<Props, State> {
<ListFooter count={issues.length} loadMore={this.fetchMoreIssues} total={paging.total} />
)}
- {paging.total === 0 &&
- (this.state.myIssues && !this.isFiltered() ? <NoMyIssues /> : <NoIssues />)}
+ {noIssuesMessage}
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx
index 4a0fce06905..f1860ce427e 100644
--- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx
@@ -45,6 +45,7 @@ import { isSameBranchLike, getBranchLikeQuery } from '../../../helpers/branches'
import { fetchMetrics } from '../../../store/rootActions';
import { getMetrics } from '../../../store/rootReducer';
import { BranchLike, Component, Metric } from '../../../app/types';
+import { translate } from '../../../helpers/l10n';
import '../styles.css';
interface OwnProps {
@@ -158,6 +159,10 @@ export class OverviewApp extends React.PureComponent<Props, State> {
? { index: 1 }
: undefined;
+ isEmpty = () =>
+ this.state.measures === undefined ||
+ this.state.measures.find(measure => measure.metric.key === 'ncloc') === undefined;
+
renderLoading() {
return (
<div className="text-center">
@@ -166,14 +171,22 @@ export class OverviewApp extends React.PureComponent<Props, State> {
);
}
- render() {
- const { branchLike, component } = this.props;
- const { loading, measures, periods, history, historyStartDate } = this.state;
-
- if (loading) {
- return this.renderLoading();
- }
+ renderEmpty() {
+ return (
+ <div className="overview-main page-main">
+ <h3>
+ {!this.state.measures ||
+ !this.state.measures.find(measure => measure.metric.key === 'projects')
+ ? translate('portfolio.app.empty')
+ : translate('portfolio.app.no_lines_of_code')}
+ </h3>
+ </div>
+ );
+ }
+ renderMain() {
+ const { branchLike, component } = this.props;
+ const { periods, measures, history, historyStartDate } = this.state;
const leakPeriod =
component.qualifier === 'APP' ? this.getApplicationLeakPeriod() : getLeakPeriod(periods);
const domainProps = {
@@ -185,23 +198,40 @@ export class OverviewApp extends React.PureComponent<Props, State> {
historyStartDate
};
+ if (this.isEmpty()) {
+ return this.renderEmpty();
+ }
+
+ return (
+ <div className="overview-main page-main">
+ {component.qualifier === 'APP' ? (
+ <ApplicationQualityGate component={component} />
+ ) : (
+ <QualityGate branchLike={branchLike} component={component} measures={measures} />
+ )}
+
+ <div className="overview-domains-list">
+ <BugsAndVulnerabilities {...domainProps} />
+ <CodeSmells {...domainProps} />
+ <Coverage {...domainProps} />
+ <Duplications {...domainProps} />
+ </div>
+ </div>
+ );
+ }
+
+ render() {
+ const { branchLike, component } = this.props;
+ const { loading, measures, history } = this.state;
+
+ if (loading) {
+ return this.renderLoading();
+ }
+
return (
<div className="page page-limited">
<div className="overview page-with-sidebar">
- <div className="overview-main page-main">
- {component.qualifier === 'APP' ? (
- <ApplicationQualityGate component={component} />
- ) : (
- <QualityGate branchLike={branchLike} component={component} measures={measures} />
- )}
-
- <div className="overview-domains-list">
- <BugsAndVulnerabilities {...domainProps} />
- <CodeSmells {...domainProps} />
- <Coverage {...domainProps} />
- <Duplications {...domainProps} />
- </div>
- </div>
+ {this.renderMain()}
<div className="overview-sidebar page-sidebar-fixed">
<Meta
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx
index 0fe760979f5..243a5765d77 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx
@@ -34,21 +34,27 @@ interface Props {
}
export default class MetaSize extends React.PureComponent<Props> {
- renderLoC = (ncloc: MeasureEnhanced) => (
+ renderLoC = (ncloc?: MeasureEnhanced) => (
<div
- id="overview-ncloc"
className={classNames('overview-meta-size-ncloc', {
'is-half-width': this.props.component.qualifier === 'APP'
- })}>
- <span className="spacer-right">
- <SizeRating value={Number(ncloc.value)} />
- </span>
- <DrilldownLink
- branchLike={this.props.branchLike}
- component={this.props.component.key}
- metric="ncloc">
- {formatMeasure(ncloc.value, 'SHORT_INT')}
- </DrilldownLink>
+ })}
+ id="overview-ncloc">
+ {ncloc && (
+ <span className="spacer-right">
+ <SizeRating value={Number(ncloc.value)} />
+ </span>
+ )}
+ {ncloc ? (
+ <DrilldownLink
+ branchLike={this.props.branchLike}
+ component={this.props.component.key}
+ metric="ncloc">
+ {formatMeasure(ncloc.value, 'SHORT_INT')}
+ </DrilldownLink>
+ ) : (
+ <span>0</span>
+ )}
<div className="spacer-top text-muted">{getMetricName('ncloc')}</div>
</div>
);
@@ -70,24 +76,27 @@ export default class MetaSize extends React.PureComponent<Props> {
renderProjects = () => {
const projects = this.props.measures.find(measure => measure.metric.key === 'projects');
-
- return projects ? (
- <div id="overview-projects" className="overview-meta-size-ncloc is-half-width">
- <DrilldownLink
- branchLike={this.props.branchLike}
- component={this.props.component.key}
- metric="projects">
- {formatMeasure(projects.value, 'SHORT_INT')}
- </DrilldownLink>
+ return (
+ <div className="overview-meta-size-ncloc is-half-width" id="overview-projects">
+ {projects ? (
+ <DrilldownLink
+ branchLike={this.props.branchLike}
+ component={this.props.component.key}
+ metric="projects">
+ {formatMeasure(projects.value, 'SHORT_INT')}
+ </DrilldownLink>
+ ) : (
+ <span>0</span>
+ )}
<div className="spacer-top text-muted">{translate('metric.projects.name')}</div>
</div>
- ) : null;
+ );
};
render() {
const ncloc = this.props.measures.find(measure => measure.metric.key === 'ncloc');
- if (ncloc == null) {
+ if (ncloc == null && this.props.component.qualifier !== 'APP') {
return null;
}
diff --git a/server/sonar-web/src/main/js/apps/overview/styles.css b/server/sonar-web/src/main/js/apps/overview/styles.css
index 5b556ae3a88..ac492720ff5 100644
--- a/server/sonar-web/src/main/js/apps/overview/styles.css
+++ b/server/sonar-web/src/main/js/apps/overview/styles.css
@@ -363,7 +363,8 @@
box-sizing: border-box;
}
-.overview-meta-size-ncloc a {
+.overview-meta-size-ncloc a,
+.overview-meta-size-ncloc span {
line-height: var(--controlHeight);
font-size: 18px;
font-weight: 300;
diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/App.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/App.tsx
index ab35a37e8ae..188130d59e1 100644
--- a/server/sonar-web/src/main/js/apps/portfolio/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/portfolio/components/App.tsx
@@ -123,8 +123,11 @@ export class App extends React.PureComponent<Props, State> {
renderEmpty() {
return (
<div className="empty-search">
- <h3>{translate('portfolio.empty')}</h3>
- <p>{translate('portfolio.empty.hint')}</p>
+ <h3>
+ {!this.state.measures || !this.state.measures['projects']
+ ? translate('portfolio.empty')
+ : translate('portfolio.no_lines_of_code')}
+ </h3>
</div>
);
}
@@ -188,8 +191,7 @@ export class App extends React.PureComponent<Props, State> {
<h4 className="portfolio-meta-header">
{translate('overview.about_this_portfolio')}
</h4>
- {!this.isEmpty() &&
- !this.isNotComputed() && <Summary component={component} measures={measures!} />}
+ <Summary component={component} measures={measures || {}} />
</div>
<div className="portfolio-meta-card">
diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/RatingFreshness.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/RatingFreshness.tsx
index bb28c4be116..13c37926c03 100644
--- a/server/sonar-web/src/main/js/apps/portfolio/components/RatingFreshness.tsx
+++ b/server/sonar-web/src/main/js/apps/portfolio/components/RatingFreshness.tsx
@@ -33,9 +33,11 @@ export default function RatingFreshness({ lastChange, rating }: Props) {
return (
<div className="portfolio-freshness">
{rating && (
- <>
- {translate('portfolio.has_always_been')} <Rating small={true} value={rating} />
- </>
+ <FormattedMessage
+ defaultMessage={translate('portfolio.has_always_been_x')}
+ id="portfolio.has_always_been_x"
+ values={{ rating: <Rating small={true} value={rating} /> }}
+ />
)}
</div>
);
diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx
index b32e4cda434..7d438b6167f 100644
--- a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx
+++ b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx
@@ -40,17 +40,25 @@ export default function Summary({ component, measures }: Props) {
<ul className="portfolio-grid">
<li>
<div className="portfolio-measure-secondary-value">
- <Link to={getComponentDrilldownUrl(component.key, 'projects')}>
- <Measure metricKey="projects" metricType="SHORT_INT" value={projects} />
- </Link>
+ {projects ? (
+ <Link to={getComponentDrilldownUrl(component.key, 'projects')}>
+ <Measure metricKey="projects" metricType="SHORT_INT" value={projects} />
+ </Link>
+ ) : (
+ '0'
+ )}
</div>
<div className="spacer-top text-muted">{translate('projects')}</div>
</li>
<li>
<div className="portfolio-measure-secondary-value">
- <Link to={getComponentDrilldownUrl(component.key, 'ncloc')}>
- <Measure metricKey="ncloc" metricType="SHORT_INT" value={ncloc} />
- </Link>
+ {ncloc ? (
+ <Link to={getComponentDrilldownUrl(component.key, 'ncloc')}>
+ <Measure metricKey="ncloc" metricType="SHORT_INT" value={ncloc} />
+ </Link>
+ ) : (
+ '0'
+ )}
</div>
<div className="spacer-top text-muted">{translate('metric.ncloc.name')}</div>
</li>
diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap
index 4a89b29c509..bee7a5e17b9 100644
--- a/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap
@@ -127,9 +127,6 @@ exports[`renders when portfolio is empty 1`] = `
<h3>
portfolio.empty
</h3>
- <p>
- portfolio.empty.hint
- </p>
</div>
</div>
<aside
@@ -143,6 +140,20 @@ exports[`renders when portfolio is empty 1`] = `
>
overview.about_this_portfolio
</h4>
+ <Summary
+ component={
+ Object {
+ "key": "foo",
+ "name": "Foo",
+ "qualifier": "TRK",
+ }
+ }
+ measures={
+ Object {
+ "reliability_rating": "1",
+ }
+ }
+ />
</div>
<div
className="portfolio-meta-card"
@@ -199,6 +210,20 @@ exports[`renders when portfolio is not computed 1`] = `
>
overview.about_this_portfolio
</h4>
+ <Summary
+ component={
+ Object {
+ "key": "foo",
+ "name": "Foo",
+ "qualifier": "TRK",
+ }
+ }
+ measures={
+ Object {
+ "ncloc": "173",
+ }
+ }
+ />
</div>
<div
className="portfolio-meta-card"
diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/RatingFreshness-test.tsx.snap b/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/RatingFreshness-test.tsx.snap
index 4cb8a857051..e7bb08f34e3 100644
--- a/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/RatingFreshness-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/RatingFreshness-test.tsx.snap
@@ -32,13 +32,17 @@ exports[`renders has always been 1`] = `
<div
className="portfolio-freshness"
>
- <React.Fragment>
- portfolio.has_always_been
-
- <Rating
- small={true}
- value="A"
- />
- </React.Fragment>
+ <FormattedMessage
+ defaultMessage="portfolio.has_always_been_x"
+ id="portfolio.has_always_been_x"
+ values={
+ Object {
+ "rating": <Rating
+ small={true}
+ value="A"
+ />,
+ }
+ }
+ />
</div>
`;