import classNames from 'classnames';
export default React.createClass({
- handleClick() {
- if (this.props.linkTo) {
- let tab = React.findDOMNode(this);
- this.props.onRoute(this.props.linkTo, tab);
- }
- },
-
render() {
- let classes = classNames('overview-card', {
- 'overview-card-section': this.props.linkTo,
- 'active': this.props.active
- });
- return <li onClick={this.handleClick} className={classes}>{this.props.children}</li>;
+ return <li className="overview-card">{this.props.children}</li>;
}
});
--- /dev/null
+import React from 'react';
+import classNames from 'classnames';
+
+export default React.createClass({
+ handleClick(e) {
+ e.preventDefault();
+ this.props.onRoute(this.props.linkTo);
+ },
+
+ render() {
+ let classes = classNames('overview-card', 'overview-card-section', {
+ 'active': this.props.active
+ });
+ return <li className={classes}>
+ <a onClick={this.handleClick}>{window.t('overview.domain', this.props.linkTo)}</a>
+ </li>;
+ }
+});
--- /dev/null
+import React from 'react';
+import Cards from './cards';
+import DetailsLink from './details-link';
+
+
+function checkMeasureForDomain (domain, measures) {
+ if (domain === 'coverage' && measures.coverage == null) {
+ return false;
+ }
+ if (domain === 'duplications' && measures.duplications == null) {
+ return false;
+ }
+ return true;
+}
+
+
+export default React.createClass({
+ render() {
+ let domains = ['issues', 'coverage', 'duplications', 'size'].map(domain => {
+ if (!checkMeasureForDomain(domain, this.props.measures)) {
+ return null;
+ }
+ let active = domain === this.props.section;
+ return <DetailsLink key={domain} linkTo={domain} onRoute={this.props.onRoute} active={active}/>;
+ });
+
+ return (
+ <div className="overview-more">
+ <h2 className="overview-title">More Details</h2>
+ <Cards>{domains}</Cards>
+ </div>
+ );
+ }
+});
return (
<div className="overview-gate">
<h2 className="overview-title">{window.t('overview.quality_gate')}</h2>
- <p className="big-spacer-top">You should <a href={qualityGatesUrl}>define</a> a quality gate on this project.</p>
+ <p className="overview-paragraph big-spacer-top">
+ You should <a href={qualityGatesUrl}>define</a> a quality gate on this project.</p>
</div>
);
}
import Gate from './gate';
import Leak from './leak';
import Nutshell from './nutshell';
-import {getPeriodDate} from './../helpers/period-label';
+import MoreDetails from './details';
+import { getPeriodDate } from './../helpers/period-label';
export default React.createClass({
getInitialState() {
return <div>
<Gate component={this.props.component} gate={this.props.gate}/>
<Leak component={this.props.component} leak={this.state.leak} measures={this.state.measures}/>
- <Nutshell component={this.props.component} measures={this.state.measures} section={this.props.section}
- onRoute={this.props.onRoute}/>
+ <Nutshell component={this.props.component} measures={this.state.measures} section={this.props.section}/>
+ <MoreDetails component={this.props.component} measures={this.state.measures}
+ section={this.props.section} onRoute={this.props.onRoute}/>
</div>;
}
});
return null;
}
- let active = this.props.section === 'coverage';
-
return (
- <Card linkTo="coverage" active={active} onRoute={this.props.onRoute}>
+ <Card>
<div className="measures">
<div className="measures-chart">
<Donut data={donutData} size="47"/>
return null;
}
- let active = this.props.section === 'duplications';
-
return (
- <Card linkTo="duplications" active={active} onRoute={this.props.onRoute}>
+ <Card>
<div className="measures">
<div className="measures-chart">
<Donut data={donutData} size="47"/>
criticalIssues = this.props.measures.criticalIssues,
issuesToReview = this.props.measures.openIssues + this.props.measures.reopenedIssues;
- let active = this.props.section === 'issues';
-
return (
- <Card linkTo="issues" active={active} onRoute={this.props.onRoute}>
+ <Card>
<div className="measures">
<div className="measure measure-big" data-metric="sqale_rating">
<DrilldownLink component={this.props.component.key} metric="sqale_rating">
lines = this.props.measures['lines'],
files = this.props.measures['files'];
- let active = this.props.section === 'size';
-
return (
- <Card linkTo="size" active={active} onRoute={this.props.onRoute}>
+ <Card>
<div className="measures">
<div className="measure measure-big" data-metric="lines">
<span className="measure-name">{window.t('overview.metric.lines')}</span>
render() {
let props = {
measures: this.props.measures,
- component: this.props.component,
- section: this.props.section,
- onRoute: this.props.onRoute
+ component: this.props.component
};
return (
<div className="overview-nutshell">
return getMetrics().then(metrics => this.setState({ metrics }));
},
- handleRoute (section, el) {
+ handleRoute (section) {
if (section !== this.state.section) {
+ let el = document.querySelector('.overview-more');
this.setState({ section }, () => this.scrollToEl(el));
window.location.href = '#' + section;
} else {
},
scrollToEl (el) {
- let top = offset(el).top - el.getBoundingClientRect().height;
+ let top = offset(el).top;
window.scrollTo(0, top);
},
@import (reference) "../init/type";
@import (reference) "../init/links";
+@side-padding: 30px;
+
.overview {
display: flex;
width: 100%;
}
.overview-title {
- padding: 0 30px;
+ padding: 0 @side-padding;
font-size: 18px;
font-weight: 400;
}
.overview-nutshell {
- padding: 50px 0 0;
+ padding: 50px 0 25px;
}
.overview-cards {
.overview-card {
flex: 1 0 25%;
- padding: 25px 30px;
+ padding: 25px @side-padding;
box-sizing: border-box;
.overview-gate & {
}
.measure-big + .measure-big {
- margin-left: 30px;
+ margin-left: @side-padding;
}
.measure-big .measure-name {
}
.overview-card-section {
- position: relative;
- z-index: 100;
- cursor: pointer;
-
- &:hover, &.active {
- &:before {
- position: absolute;
- top: 100%;
- left: 50%;
- margin-left: -10px;
- width: 0;
- height: 0;
- border: solid transparent;
- border-width: 10px;
- border-top-color: #fff;
- content: '';
- pointer-events: none;
- }
+ padding: 0;
+ text-align: center;
+
+ a {
+ display: block;
+ padding: 25px @side-padding;
+ .link-no-underline;
+ cursor: pointer;
+ transition: none;
}
}
+.overview-card-section.active a,
+.overview-card-section a:hover {
+ background-color: #2c3946;
+ color: mix(#fff, #2c3946, 75%);
+}
+
.overview-measure {
font-size: 28px;
}
}
}
+.overview-domain {
+ margin-top: -25px;
+}
+
.overview-domain-dark {
background-color: #2c3946;
color: mix(#fff, #2c3946, 75%);
}
.overview-domain-section {
- padding: 50px 30px;
+ padding: 50px @side-padding;
.overview-title {
margin-bottom: 25px;
display: flex;
align-items: baseline;
margin-bottom: 20px;;
- padding: 50px 30px 0;
+ padding: 50px @side-padding 0;
.overview-title {
flex: 1;
align-items: center;
align-content: center;
}
+
+.overview-paragraph {
+ padding: 0 @side-padding;
+}
+
+.overview-more {
+ padding-top: 50px;
+ padding-bottom: 25px;
+ border-top: 1px solid @barBorderColor;
+
+ .overview-title {
+ padding-bottom: 25px;
+ }
+}