Browse Source

SONAR-9833 'A' ratings when a portfolio without project is analyzed

tags/6.6-RC1
Stas Vilchik 6 years ago
parent
commit
c9c9262a4c

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/Activity.tsx View File

@@ -97,7 +97,7 @@ export default class Activity extends React.PureComponent<Props> {

render() {
return (
<div className="huge-spacer-top">
<div className="huge-spacer-bottom">
<header className="page-header">
<h3 className="page-title">{translate('project_activity.page')}</h3>
</header>

+ 60
- 21
server/sonar-web/src/main/js/apps/portfolio/components/App.tsx View File

@@ -31,6 +31,7 @@ import { getChildren } from '../../../api/components';
import { PORTFOLIO_METRICS, SUB_COMPONENTS_METRICS, convertMeasures } from '../utils';
import { SubComponent } from '../types';
import '../styles.css';
import { translate } from '../../../helpers/l10n';

interface Props {
component: { key: string; name: string };
@@ -97,6 +98,11 @@ export default class App extends React.PureComponent<Props, State> {
);
}

isEmpty = () => this.state.measures == undefined || this.state.measures['ncloc'] == undefined;

isNotComputed = () =>
this.state.measures && this.state.measures['reliability_rating'] == undefined;

renderSpinner() {
return (
<div className="page page-limited">
@@ -107,9 +113,59 @@ export default class App extends React.PureComponent<Props, State> {
);
}

renderEmpty() {
return (
<div className="empty-search">
<h3>{translate('portfolio.empty')}</h3>
<p>{translate('portfolio.empty.hint')}</p>
</div>
);
}

renderWhenNotComputed() {
return (
<div className="empty-search">
<h3>{translate('portfolio.not_computed')}</h3>
</div>
);
}

renderMain() {
const { component } = this.props;
const { measures, subComponents, totalSubComponents } = this.state;

if (this.isEmpty()) {
return this.renderEmpty();
}

if (this.isNotComputed()) {
return this.renderWhenNotComputed();
}

return (
<div>
<div className="portfolio-boxes">
<ReleasabilityBox component={component.key} measures={measures!} />
<ReliabilityBox component={component.key} measures={measures!} />
<SecurityBox component={component.key} measures={measures!} />
<MaintainabilityBox component={component.key} measures={measures!} />
</div>

{subComponents != undefined &&
totalSubComponents != undefined && (
<WorstProjects
component={component.key}
subComponents={subComponents}
total={totalSubComponents}
/>
)}
</div>
);
}

render() {
const { component } = this.props;
const { loading, measures, subComponents, totalSubComponents } = this.state;
const { loading, measures } = this.state;

if (loading) {
return this.renderSpinner();
@@ -118,28 +174,11 @@ export default class App extends React.PureComponent<Props, State> {
return (
<div className="page page-limited">
<div className="page-with-sidebar">
<div className="page-main">
{measures != undefined && (
<div className="portfolio-boxes">
<ReleasabilityBox component={component.key} measures={measures} />
<ReliabilityBox component={component.key} measures={measures} />
<SecurityBox component={component.key} measures={measures} />
<MaintainabilityBox component={component.key} measures={measures} />
</div>
)}

{subComponents != undefined &&
totalSubComponents != undefined && (
<WorstProjects
component={component.key}
subComponents={subComponents}
total={totalSubComponents}
/>
)}
</div>
<div className="page-main">{this.renderMain()}</div>

<aside className="page-sidebar-fixed">
{measures != undefined && <Summary component={component} measures={measures} />}
{!this.isEmpty() &&
!this.isNotComputed() && <Summary component={component} measures={measures!} />}
<Activity component={component.key} />
<Report component={component} />
</aside>

+ 2
- 2
server/sonar-web/src/main/js/apps/portfolio/components/Report.tsx View File

@@ -71,7 +71,7 @@ export default class Report extends React.PureComponent<Props, State> {

if (loading) {
return (
<div className="huge-spacer-top">
<div>
{this.renderHeader()}
<i className="spinner" />
</div>
@@ -83,7 +83,7 @@ export default class Report extends React.PureComponent<Props, State> {
}

return (
<div className="huge-spacer-top">
<div>
{this.renderHeader()}

{!status.canDownload && (

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx View File

@@ -35,7 +35,7 @@ export default function Summary({ component, measures }: Props) {
const nclocDistribution = measures['ncloc_language_distribution'];

return (
<section id="portfolio-summary" className="portfolio-section portfolio-section-summary">
<section id="portfolio-summary" className="huge-spacer-bottom">
{component.description && <div className="big-spacer-bottom">{component.description}</div>}

<ul className="portfolio-grid">

+ 18
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/App-test.tsx View File

@@ -49,7 +49,24 @@ const component = { key: 'foo', name: 'Foo' };

it('renders', () => {
const wrapper = shallow(<App component={component} />);
wrapper.setState({ loading: false, measures: {}, subComponents: [], totalSubComponents: 0 });
wrapper.setState({
loading: false,
measures: { ncloc: '173', reliability_rating: '1' },
subComponents: [],
totalSubComponents: 0
});
expect(wrapper).toMatchSnapshot();
});

it('renders when portfolio is empty', () => {
const wrapper = shallow(<App component={component} />);
wrapper.setState({ loading: false, measures: { reliability_rating: '1' } });
expect(wrapper).toMatchSnapshot();
});

it('renders when portfolio is not computed', () => {
const wrapper = shallow(<App component={component} />);
wrapper.setState({ loading: false, measures: { ncloc: '173' } });
expect(wrapper).toMatchSnapshot();
});


+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/Activity-test.tsx.snap View File

@@ -2,7 +2,7 @@

exports[`renders 1`] = `
<div
className="huge-spacer-top"
className="huge-spacer-bottom"
>
<header
className="page-header"

+ 126
- 22
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/App-test.tsx.snap View File

@@ -10,44 +10,148 @@ exports[`renders 1`] = `
<div
className="page-main"
>
<div
className="portfolio-boxes"
>
<ReleasabilityBox
component="foo"
measures={Object {}}
/>
<ReliabilityBox
component="foo"
measures={Object {}}
/>
<SecurityBox
component="foo"
measures={Object {}}
/>
<MaintainabilityBox
<div>
<div
className="portfolio-boxes"
>
<ReleasabilityBox
component="foo"
measures={
Object {
"ncloc": "173",
"reliability_rating": "1",
}
}
/>
<ReliabilityBox
component="foo"
measures={
Object {
"ncloc": "173",
"reliability_rating": "1",
}
}
/>
<SecurityBox
component="foo"
measures={
Object {
"ncloc": "173",
"reliability_rating": "1",
}
}
/>
<MaintainabilityBox
component="foo"
measures={
Object {
"ncloc": "173",
"reliability_rating": "1",
}
}
/>
</div>
<WorstProjects
component="foo"
measures={Object {}}
subComponents={Array []}
total={0}
/>
</div>
<WorstProjects
</div>
<aside
className="page-sidebar-fixed"
>
<Summary
component={
Object {
"key": "foo",
"name": "Foo",
}
}
measures={
Object {
"ncloc": "173",
"reliability_rating": "1",
}
}
/>
<Activity
component="foo"
subComponents={Array []}
total={0}
/>
<Report
component={
Object {
"key": "foo",
"name": "Foo",
}
}
/>
</aside>
</div>
</div>
`;

exports[`renders when portfolio is empty 1`] = `
<div
className="page page-limited"
>
<div
className="page-with-sidebar"
>
<div
className="page-main"
>
<div
className="empty-search"
>
<h3>
portfolio.empty
</h3>
<p>
portfolio.empty.hint
</p>
</div>
</div>
<aside
className="page-sidebar-fixed"
>
<Summary
<Activity
component="foo"
/>
<Report
component={
Object {
"key": "foo",
"name": "Foo",
}
}
measures={Object {}}
/>
</aside>
</div>
</div>
`;

exports[`renders when portfolio is not computed 1`] = `
<div
className="page page-limited"
>
<div
className="page-with-sidebar"
>
<div
className="page-main"
>
<div
className="empty-search"
>
<h3>
portfolio.not_computed
</h3>
</div>
</div>
<aside
className="page-sidebar-fixed"
>
<Activity
component="foo"
/>

+ 2
- 6
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/Report-test.tsx.snap View File

@@ -1,9 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders 1`] = `
<div
className="huge-spacer-top"
>
<div>
<header
className="page-header"
>
@@ -20,9 +18,7 @@ exports[`renders 1`] = `
`;

exports[`renders 2`] = `
<div
className="huge-spacer-top"
>
<div>
<header
className="page-header"
>

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/__snapshots__/Summary-test.tsx.snap View File

@@ -2,7 +2,7 @@

exports[`renders 1`] = `
<section
className="portfolio-section portfolio-section-summary"
className="huge-spacer-bottom"
id="portfolio-summary"
>
<div

+ 3
- 0
server/sonar-web/src/main/less/init/misc.less View File

@@ -83,6 +83,9 @@ th.nowrap {
.huge-spacer-top {
margin-top: 40px;
}
.huge-spacer-bottom {
margin-bottom: 40px;
}
.huge-spacer-left {
margin-left: 40px;
}

+ 3
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -3194,3 +3194,6 @@ branches.settings_hint_tab=Administration > Branches
#------------------------------------------------------------------------------
portfolio.was_x_y=was {rating} {date}
portfolio.x_in_y={projects} in {rating}
portfolio.empty=This portfolio is empty.
portfolio.empty.hint=This portfolio has no projects, or none of associated projects has lines of code.
portfolio.not_computed=This portfolio is not yet computed.

Loading…
Cancel
Save