diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-10-26 18:54:59 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-10-27 10:07:00 +0100 |
commit | a99c03d15f741249a8205ec26287496dfbfa7f52 (patch) | |
tree | 1586e5ae3a58b532e4e6944b6436451a4dd136c3 /server | |
parent | 0fd95d868388fa487bfec93eaad7f3560f6e70bf (diff) | |
download | sonarqube-a99c03d15f741249a8205ec26287496dfbfa7f52.tar.gz sonarqube-a99c03d15f741249a8205ec26287496dfbfa7f52.zip |
SONAR-6331 apply feedback
Diffstat (limited to 'server')
16 files changed, 109 insertions, 66 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/app.js b/server/sonar-web/src/main/js/apps/overview/app.js index 6b661b9b592..29fabe96cd3 100644 --- a/server/sonar-web/src/main/js/apps/overview/app.js +++ b/server/sonar-web/src/main/js/apps/overview/app.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import _ from 'underscore'; import React from 'react'; -import Main from './main'; +import { Overview } from './main'; class App { start (options) { @@ -9,7 +9,7 @@ class App { _.extend(opts.component, options.component); $('html').toggleClass('dashboard-page', opts.component.hasSnapshot); let el = document.querySelector(opts.el); - React.render(<Main {...opts}/>, el); + React.render(<Overview {...opts}/>, el); } } diff --git a/server/sonar-web/src/main/js/apps/overview/general/gate-condition.js b/server/sonar-web/src/main/js/apps/overview/general/gate-condition.js index eb947c8eaf7..32727972d03 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/gate-condition.js +++ b/server/sonar-web/src/main/js/apps/overview/general/gate-condition.js @@ -1,26 +1,30 @@ import React from 'react'; + import Measure from './../helpers/measure'; import { periodLabel, getPeriodDate } from './../helpers/period-label'; import DrilldownLink from './../helpers/drilldown-link'; + export default React.createClass({ render() { let metricName = window.t('metric', this.props.condition.metric.name, 'name'), threshold = this.props.condition.level === 'ERROR' ? - this.props.condition.error : this.props.condition.warning, - iconClassName = 'icon-alert-' + this.props.condition.level.toLowerCase(), + this.props.condition.error : this.props.condition.warning, period = this.props.condition.period ? - `(${periodLabel(this.props.component.periods, this.props.condition.period)})` : null, + `(${periodLabel(this.props.component.periods, this.props.condition.period)})` : null, periodDate = getPeriodDate(this.props.component.periods, this.props.condition.period); + let classes = 'alert_' + this.props.condition.level.toUpperCase(); + return ( <div> <h4 className="overview-gate-condition-metric">{metricName}<br/><span className="nowrap">{period}</span></h4> <div className="overview-gate-condition-value"> - <i className={iconClassName}/> <DrilldownLink component={this.props.component.key} metric={this.props.condition.metric.name} period={this.props.condition.period} periodDate={periodDate}> - <Measure value={this.props.condition.actual} type={this.props.condition.metric.type}/> + <span className={classes}> + <Measure value={this.props.condition.actual} type={this.props.condition.metric.type}/> + </span> </DrilldownLink> <span className="overview-gate-condition-itself"> {window.t('quality_gates.operator', this.props.condition.op, 'short')} diff --git a/server/sonar-web/src/main/js/apps/overview/general/leak-coverage.js b/server/sonar-web/src/main/js/apps/overview/general/leak-coverage.js index 5af186b9933..23e3fabd7e1 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/leak-coverage.js +++ b/server/sonar-web/src/main/js/apps/overview/general/leak-coverage.js @@ -26,12 +26,12 @@ export default React.createClass({ <Donut data={donutData} size="47"/> </div> <div className="measure measure-big" data-metric="new_coverage"> + <span className="measure-name">{window.t('overview.metric.new_coverage')}</span> <span className="measure-value"> - <DrilldownLink component={this.props.component.key} metric="new_coverage" period="3"> + <DrilldownLink component={this.props.component.key} metric="new_coverage" period="1"> <Measure value={newCoverage} type="PERCENT"/> </DrilldownLink> </span> - <span className="measure-name">{window.t('overview.metric.new_coverage')}</span> </div> </div> <ul className="list-inline big-spacer-top measures-chart-indent"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/leak-dups.js b/server/sonar-web/src/main/js/apps/overview/general/leak-dups.js index bdd2188c4df..f59e996c967 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/leak-dups.js +++ b/server/sonar-web/src/main/js/apps/overview/general/leak-dups.js @@ -24,10 +24,10 @@ export default React.createClass({ <Donut data={donutData} size="47"/> </div> <div className="measure measure-big" data-metric="duplicated_lines_density"> + <span className="measure-name">{window.t('overview.metric.duplications')}</span> <span className="measure-value"> <MeasureVariation value={density} type="PERCENT"/> </span> - <span className="measure-name">{window.t('overview.metric.duplications')}</span> </div> </div> <ul className="list-inline big-spacer-top measures-chart-indent"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/leak-issues.js b/server/sonar-web/src/main/js/apps/overview/general/leak-issues.js index fc33b7c3065..29574509109 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/leak-issues.js +++ b/server/sonar-web/src/main/js/apps/overview/general/leak-issues.js @@ -16,28 +16,28 @@ export default React.createClass({ blockerIssues = this.props.leak.newBlockerIssues, criticalIssues = this.props.leak.newCriticalIssues, issuesToReview = this.props.leak.newOpenIssues + this.props.leak.newReopenedIssues, - periodDate = moment(getPeriodDate(this.props.component.periods, '3')).format('YYYY-MM-DDTHH:mm:ssZZ'); + periodDate = moment(getPeriodDate(this.props.component.periods, '1')).format('YYYY-MM-DDTHH:mm:ssZZ'); return ( <Card> <div className="measures"> <div className="measure measure-big" data-metric="sqale_index"> + <span className="measure-name">{window.t('overview.metric.new_debt')}</span> <span className="measure-value"> <IssuesLink component={this.props.component.key} params={{ resolved: 'false', createdAfter: periodDate, facetMode: 'debt' }}> <Measure value={newDebt} type="SHORT_WORK_DUR"/> </IssuesLink> </span> - <span className="measure-name">{window.t('overview.metric.new_debt')}</span> </div> <div className="measure measure-big" data-metric="violations"> + <span className="measure-name">{window.t('overview.metric.new_issues')}</span> <span className="measure-value"> <IssuesLink component={this.props.component.key} params={{ resolved: 'false', createdAfter: periodDate }}> <Measure value={issues} type="SHORT_INT"/> </IssuesLink> </span> - <span className="measure-name">{window.t('overview.metric.new_issues')}</span> </div> </div> <ul className="list-inline big-spacer-top"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/leak-size.js b/server/sonar-web/src/main/js/apps/overview/general/leak-size.js index 77162374312..5b09ddf0eed 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/leak-size.js +++ b/server/sonar-web/src/main/js/apps/overview/general/leak-size.js @@ -12,16 +12,16 @@ export default React.createClass({ <Card> <div className="measures"> <div className="measure measure-big" data-metric="lines"> + <span className="measure-name">{window.t('overview.metric.lines')}</span> <span className="measure-value"> <MeasureVariation value={lines} type="SHORT_INT"/> </span> - <span className="measure-name">{window.t('overview.metric.lines')}</span> </div> <div className="measure measure-big" data-metric="files"> + <span className="measure-name">{window.t('overview.metric.files')}</span> <span className="measure-value"> <MeasureVariation value={files} type="SHORT_INT"/> </span> - <span className="measure-name">{window.t('overview.metric.files')}</span> </div> </div> </Card> diff --git a/server/sonar-web/src/main/js/apps/overview/general/leak.js b/server/sonar-web/src/main/js/apps/overview/general/leak.js index 20db93ff6c3..1cef6139954 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/leak.js +++ b/server/sonar-web/src/main/js/apps/overview/general/leak.js @@ -1,25 +1,29 @@ import _ from 'underscore'; +import moment from 'moment'; import React from 'react'; + import Cards from './cards'; import LeakIssues from './leak-issues'; import LeakCoverage from './leak-coverage'; import LeakSize from './leak-size'; import LeakDups from './leak-dups'; -import {periodLabel} from './../helpers/period-label'; +import { periodLabel, getPeriodDate } from './../helpers/period-label'; + export default React.createClass({ render() { - if (_.size(this.props.component.periods) < 3) { + if (_.size(this.props.component.periods) < 1) { return null; } - let period = periodLabel(this.props.component.periods, '3'); + let period = periodLabel(this.props.component.periods, '1'); + let periodDate = getPeriodDate(this.props.component.periods, '1'); return ( <div className="overview-leak"> <h2 className="overview-title"> {window.t('overview.water_leak')} - <span className="overview-leak-period">{period}</span> + <span className="overview-leak-period">{period} / {moment(periodDate).format('LL')}</span> </h2> <Cards> <LeakIssues component={this.props.component} leak={this.props.leak} measures={this.props.measures}/> diff --git a/server/sonar-web/src/main/js/apps/overview/general/main.js b/server/sonar-web/src/main/js/apps/overview/general/main.js index a55eacf2d1d..fc0cc1a1199 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/main.js +++ b/server/sonar-web/src/main/js/apps/overview/general/main.js @@ -22,7 +22,7 @@ export default React.createClass({ }, _hasWaterLeak() { - return !!_.findWhere(this.props.component.periods, { index: '3' }); + return !!_.findWhere(this.props.component.periods, { index: '1' }); }, _requestIssues(data) { @@ -33,7 +33,7 @@ export default React.createClass({ }, requestLeakIssues() { - let createdAfter = moment(getPeriodDate(this.props.component.periods, '3')).format('YYYY-MM-DDTHH:mm:ssZZ'); + let createdAfter = moment(getPeriodDate(this.props.component.periods, '1')).format('YYYY-MM-DDTHH:mm:ssZZ'); this._requestIssues({ resolved: 'false', createdAfter, facets: 'severities,statuses' }).done(r => { let severitiesFacet = _.findWhere(r.facets, { property: 'severities' }).values, @@ -70,7 +70,7 @@ export default React.createClass({ }, requestLeakDebt() { - let createdAfter = moment(getPeriodDate(this.props.component.periods, '3')).format('YYYY-MM-DDTHH:mm:ssZZ'); + let createdAfter = moment(getPeriodDate(this.props.component.periods, '1')).format('YYYY-MM-DDTHH:mm:ssZZ'); this._requestIssues({ resolved: 'false', createdAfter, facets: 'severities', facetMode: 'debt' }).done(r => { this.setState({ leak: _.extend({}, this.state.leak, { newDebt: r.debtTotal }) diff --git a/server/sonar-web/src/main/js/apps/overview/general/nutshell-coverage.js b/server/sonar-web/src/main/js/apps/overview/general/nutshell-coverage.js index d7cbec60553..20d8444d798 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/nutshell-coverage.js +++ b/server/sonar-web/src/main/js/apps/overview/general/nutshell-coverage.js @@ -27,12 +27,12 @@ export default React.createClass({ <Donut data={donutData} size="47"/> </div> <div className="measure measure-big"> + <span className="measure-name">{window.t('overview.metric.coverage')}</span> <span className="measure-value"> <DrilldownLink component={this.props.component.key} metric="overall_coverage"> <Measure value={coverage} type="PERCENT"/> </DrilldownLink> </span> - <span className="measure-name">{window.t('overview.metric.coverage')}</span> </div> </div> <ul className="list-inline big-spacer-top measures-chart-indent"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/nutshell-dups.js b/server/sonar-web/src/main/js/apps/overview/general/nutshell-dups.js index 92594c6c6ab..277d1662dac 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/nutshell-dups.js +++ b/server/sonar-web/src/main/js/apps/overview/general/nutshell-dups.js @@ -27,12 +27,12 @@ export default React.createClass({ <Donut data={donutData} size="47"/> </div> <div className="measure measure-big"> + <span className="measure-name">{window.t('overview.metric.duplications')}</span> <span className="measure-value"> <DrilldownLink component={this.props.component.key} metric="duplicated_lines_density"> <Measure value={density} type="PERCENT"/> </DrilldownLink> </span> - <span className="measure-name">{window.t('overview.metric.duplications')}</span> </div> </div> <ul className="list-inline big-spacer-top measures-chart-indent"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/nutshell-issues.js b/server/sonar-web/src/main/js/apps/overview/general/nutshell-issues.js index 8856bac3a3b..2d72a7d0243 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/nutshell-issues.js +++ b/server/sonar-web/src/main/js/apps/overview/general/nutshell-issues.js @@ -28,20 +28,20 @@ export default React.createClass({ </DrilldownLink> </div> <div className="measure measure-big" data-metric="sqale_index"> + <span className="measure-name">{window.t('overview.metric.debt')}</span> <span className="measure-value"> <IssuesLink component={this.props.component.key} params={{ resolved: 'false', facetMode: 'debt' }}> <Measure value={debt} type="SHORT_WORK_DUR"/> </IssuesLink> </span> - <span className="measure-name">{window.t('overview.metric.debt')}</span> </div> <div className="measure measure-big" data-metric="violations"> + <span className="measure-name">{window.t('overview.metric.issues')}</span> <span className="measure-value"> <IssuesLink component={this.props.component.key} params={{ resolved: 'false' }}> <Measure value={issues} type="SHORT_INT"/> </IssuesLink> </span> - <span className="measure-name">{window.t('overview.metric.issues')}</span> </div> </div> <ul className="list-inline big-spacer-top"> diff --git a/server/sonar-web/src/main/js/apps/overview/general/nutshell-size.js b/server/sonar-web/src/main/js/apps/overview/general/nutshell-size.js index 967f752fb88..e1136d228bb 100644 --- a/server/sonar-web/src/main/js/apps/overview/general/nutshell-size.js +++ b/server/sonar-web/src/main/js/apps/overview/general/nutshell-size.js @@ -15,20 +15,20 @@ export default React.createClass({ <Card linkTo="size" active={active} onRoute={this.props.onRoute}> <div className="measures"> <div className="measure measure-big" data-metric="lines"> + <span className="measure-name">{window.t('overview.metric.lines')}</span> <span className="measure-value"> <DrilldownLink component={this.props.component.key} metric="lines"> <Measure value={lines} type="SHORT_INT"/> </DrilldownLink> </span> - <span className="measure-name">{window.t('overview.metric.lines')}</span> </div> <div className="measure measure-big" data-metric="files"> + <span className="measure-name">{window.t('overview.metric.files')}</span> <span className="measure-value"> <DrilldownLink component={this.props.component.key} metric="files"> <Measure value={files} type="SHORT_INT"/> </DrilldownLink> </span> - <span className="measure-name">{window.t('overview.metric.files')}</span> </div> </div> </Card> diff --git a/server/sonar-web/src/main/js/apps/overview/main.js b/server/sonar-web/src/main/js/apps/overview/main.js index f2111487d3f..aa7ba34cb60 100644 --- a/server/sonar-web/src/main/js/apps/overview/main.js +++ b/server/sonar-web/src/main/js/apps/overview/main.js @@ -10,30 +10,48 @@ import Meta from './meta'; import { getMetrics } from '../../api/metrics'; -export default class Overview extends React.Component { - constructor () { - super(); + +export const Overview = React.createClass({ + getInitialState () { let hash = window.location.hash; - this.state = { section: hash.length ? hash.substr(1) : null }; - } + return { section: hash.length ? hash.substr(1) : null }; + }, + + componentWillMount () { + window.addEventListener('hashchange', this.handleHashChange); + }, componentDidMount () { this.requestMetrics(); - } + }, + + componentWillUnmount () { + window.removeEventListener('hashchange', this.handleHashChange); + }, requestMetrics () { return getMetrics().then(metrics => this.setState({ metrics })); - } + }, handleRoute (section, el) { - this.setState({ section }, () => this.scrollToEl(el)); - window.location.href = '#' + section; - } + if (section !== this.state.section) { + this.setState({ section }, () => this.scrollToEl(el)); + window.location.href = '#' + section; + } else { + this.setState({ section: null }); + window.location.href = '#'; + } + }, + + handleHashChange () { + let hash = window.location.hash; + this.setState({ section: hash.substr(1) }); + }, scrollToEl (el) { let top = offset(el).top - el.getBoundingClientRect().height; window.scrollTo(0, top); - } + }, render () { if (!this.state.metrics) { @@ -60,10 +78,10 @@ export default class Overview extends React.Component { return <div className="overview"> <div className="overview-main"> - <GeneralMain {...this.props} section={this.state.section} onRoute={this.handleRoute.bind(this)}/> + <GeneralMain {...this.props} section={this.state.section} onRoute={this.handleRoute}/> {child} </div> <Meta component={this.props.component}/> </div>; } -} +}); diff --git a/server/sonar-web/src/main/js/components/charts/treemap.js b/server/sonar-web/src/main/js/components/charts/treemap.js index 51b140e003d..9e311a838e3 100644 --- a/server/sonar-web/src/main/js/components/charts/treemap.js +++ b/server/sonar-web/src/main/js/components/charts/treemap.js @@ -55,9 +55,10 @@ export const TreemapRect = React.createClass({ fontSize: SIZE_SCALE(this.props.width / this.props.label.length), lineHeight: `${this.props.height}px` }; + let isTextVisible = this.props.width >= 40 && this.props.height >= 40; return <div className="treemap-cell" {...tooltipAttrs} style={cellStyles}> <div className="treemap-inner" dangerouslySetInnerHTML={{ __html: this.props.label }} - style={{ maxWidth: this.props.width }}/> + style={{ maxWidth: this.props.width, visibility: isTextVisible ? 'visible': 'hidden' }}/> </div>; } }); @@ -89,7 +90,8 @@ export const Treemap = React.createClass({ .size([this.state.width, 360]); let nodes = treemap .nodes({ children: this.props.items }) - .filter(d => !d.children); + .filter(d => !d.children) + .filter(d => !!d.dx && !!d.dy); let prefix = mostCommitPrefix(this.props.items.map(item => item.label)), prefixLength = prefix.length; diff --git a/server/sonar-web/src/main/less/pages/overview.less b/server/sonar-web/src/main/less/pages/overview.less index 9b43ba81fdf..4798e0df32b 100644 --- a/server/sonar-web/src/main/less/pages/overview.less +++ b/server/sonar-web/src/main/less/pages/overview.less @@ -17,7 +17,7 @@ .overview-gate { .clearfix; - padding: 50px 30px; + padding: 50px 0 25px; } .overview-gate-box { @@ -70,11 +70,6 @@ margin-top: 8px; font-weight: 300; font-size: 22px; - - i { - position: relative; - top: -1px; - } } .overview-gate-condition-itself { @@ -89,13 +84,13 @@ } .overview-leak { - padding: 50px 30px; + padding: 50px 0 25px; border-top: 1px solid @barBorderColor; border-bottom: 1px solid @barBorderColor; } .overview-title { - margin-bottom: 20px; + padding: 0 30px; font-size: 18px; font-weight: 400; @@ -115,11 +110,7 @@ } .overview-nutshell { - padding: 50px 30px 0; - - .overview-card { - padding-bottom: 25px; - } + padding: 50px 0 0; } .overview-cards { @@ -128,6 +119,7 @@ .overview-card { flex: 1 0 25%; + padding: 25px 30px; box-sizing: border-box; .overview-gate & { @@ -151,6 +143,11 @@ margin-left: 30px; } + .measure-big .measure-name { + margin-top: 0; + margin-bottom: 2px; + } + .list-inline { margin-left: -10px; margin-right: -10px; @@ -163,10 +160,24 @@ } .overview-card-section { + position: relative; + z-index: 100; cursor: pointer; &:hover, &.active { - border-bottom: 4px solid #2c3946; + &: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; + } } } @@ -180,7 +191,6 @@ .overview-meta { width: 240px; - padding: 50px 30px; border-left: 1px solid @barBorderColor; box-sizing: border-box; background-color: @barBackgroundColor; @@ -192,7 +202,6 @@ .overview-meta .overview-card { width: auto; - margin-bottom: 30px; } .overview-meta-description { @@ -234,6 +243,12 @@ .overview-domain-section { padding: 50px 30px; + + .overview-title { + margin-bottom: 25px; + padding-left: 0; + padding-right: 0; + } } .overview-domain-header { diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/overview/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/overview/index.html.erb index 41fe8714401..c86e998a518 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/overview/index.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/overview/index.html.erb @@ -152,20 +152,20 @@ <% if @snapshot %> // coverage <% if @snapshot.measure('new_overall_coverage') %> - newCoverage: '<%= @snapshot.measure('new_overall_coverage').variation(3) -%>', + newCoverage: '<%= @snapshot.measure('new_overall_coverage').variation(1) -%>', <% end %> <% if @snapshot.measure('tests') %> - tests: '<%= @snapshot.measure('tests').variation(3) -%>', + tests: '<%= @snapshot.measure('tests').variation(1) -%>', <% end %> // duplications - duplications: '<%= @snapshot.measure('duplicated_lines_density').variation(3) -%>', - duplicatedLines: '<%= @snapshot.measure('duplicated_lines').variation(3) -%>', - duplicatedBlocks: '<%= @snapshot.measure('duplicated_blocks').variation(3) -%>', + duplications: '<%= @snapshot.measure('duplicated_lines_density').variation(1) -%>', + duplicatedLines: '<%= @snapshot.measure('duplicated_lines').variation(1) -%>', + duplicatedBlocks: '<%= @snapshot.measure('duplicated_blocks').variation(1) -%>', // size - lines: '<%= @snapshot.measure('lines').variation(3) -%>', - files: '<%= @snapshot.measure('files').variation(3) -%>' + lines: '<%= @snapshot.measure('lines').variation(1) -%>', + files: '<%= @snapshot.measure('files').variation(1) -%>' <% end %> }; |