diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-11-26 09:21:27 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-11-26 09:21:56 +0100 |
commit | 32473107eb566930e09a02e4f817da9280541ba6 (patch) | |
tree | 088ba7b6ae6d6c53c570de998ecc345cccd4d550 | |
parent | ba1c896797fa25ead9eedc15328e94fcc2a18668 (diff) | |
download | sonarqube-32473107eb566930e09a02e4f817da9280541ba6.tar.gz sonarqube-32473107eb566930e09a02e4f817da9280541ba6.zip |
SONAR-7066 Improve display of leak period on the overview page
10 files changed, 65 insertions, 37 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/components/legend.js b/server/sonar-web/src/main/js/apps/overview/components/legend.js index 1c38b7d17b1..4e4de8f5882 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/legend.js +++ b/server/sonar-web/src/main/js/apps/overview/components/legend.js @@ -1,15 +1,12 @@ import React from 'react'; +import moment from 'moment'; import { DomainLeakTitle } from '../main/components'; export const Legend = React.createClass({ render() { - if (!this.props.leakPeriodDate) { - return null; - } - return <div className="overview-legend"> - <span className="overview-legend-leak"/> + return <div className="overview-legend overview-leak"> <DomainLeakTitle label={this.props.leakPeriodLabel} date={this.props.leakPeriodDate}/> </div>; } diff --git a/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js index 79a45f63408..6b0cbc391bc 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js @@ -9,7 +9,7 @@ import { CoverageSelectionMixin } from '../components/coverage-selection-mixin'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; -import { Legend } from '../components/legend'; +import { DomainLeakTitle } from '../main/components'; import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants'; import { CoverageMeasuresList } from '../components/coverage-measures-list'; @@ -74,7 +74,7 @@ export const CoverageMain = React.createClass({ }, renderLegend () { - return <Legend leakPeriodDate={this.state.leakPeriodDate} leakPeriodLabel={this.state.leakPeriodLabel}/>; + return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/> }, render () { diff --git a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js index bf521c4b69c..f3a28a07ef4 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js @@ -10,7 +10,6 @@ import { DomainBubbleChart } from '../components/domain-bubble-chart'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; -import { Legend } from '../components/legend'; import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants'; import { AddedRemovedMeasure, AddedRemovedDebt, OnNewCodeMeasure, SeverityMeasure } from './../components/issue-measure'; import { IssuesTags } from './../components/issues-tags'; @@ -19,6 +18,7 @@ import { getFacet, extractAssignees } from '../../../api/issues'; import StatusHelper from '../../../components/shared/status-helper'; import { Rating } from '../../../components/shared/rating'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; +import { DomainLeakTitle } from '../main/components'; const KNOWN_METRICS = ['violations', 'sqale_index', 'sqale_rating', 'sqale_debt_ratio', 'blocker_violations', @@ -102,7 +102,7 @@ export const IssuesMain = React.createClass({ }, renderLegend () { - return <Legend leakPeriodDate={this.state.leakPeriodDate} leakPeriodLabel={this.state.leakPeriodLabel}/>; + return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/> }, renderOtherMeasures() { diff --git a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js index 48067d57a17..946b6f1663b 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js @@ -9,7 +9,7 @@ import { DomainBubbleChart } from '../components/domain-bubble-chart'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; -import { Legend } from '../components/legend'; +import { DomainLeakTitle } from '../main/components'; import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants'; @@ -65,7 +65,7 @@ export const DuplicationsMain = React.createClass({ }, renderLegend () { - return <Legend leakPeriodDate={this.state.leakPeriodDate} leakPeriodLabel={this.state.leakPeriodLabel}/>; + return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/> }, renderMeasures() { diff --git a/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js index 45b4728d73e..ed309e8d7f4 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js @@ -9,7 +9,7 @@ import { DomainTreemap } from '../components/domain-treemap'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; -import { Legend } from '../components/legend'; +import { DomainLeakTitle } from '../main/components'; export const SizeMain = React.createClass({ @@ -64,7 +64,7 @@ export const SizeMain = React.createClass({ }, renderLegend () { - return <Legend leakPeriodDate={this.state.leakPeriodDate} leakPeriodLabel={this.state.leakPeriodLabel}/>; + return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/> }, renderOtherMeasures(domain, hiddenMetrics) { diff --git a/server/sonar-web/src/main/js/apps/overview/main/components.js b/server/sonar-web/src/main/js/apps/overview/main/components.js index 87b920f7ea0..33f802d61a4 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/components.js +++ b/server/sonar-web/src/main/js/apps/overview/main/components.js @@ -2,7 +2,6 @@ import moment from 'moment'; import React from 'react'; import { Timeline } from './timeline'; -import { Legend } from '../components/legend'; export const Domain = React.createClass({ @@ -21,7 +20,9 @@ export const DomainTitle = React.createClass({ <div className="overview-title"> {this.props.children} <a className="small big-spacer-left link-no-underline" href={url}> - More <i className="icon-chevron-right" style={{ position: 'relative', top: -1 }}/></a> + {window.t('more')} + <i className="icon-chevron-right" style={{ position: 'relative', top: -1 }}/> + </a> </div> </div>; } else { @@ -32,14 +33,28 @@ export const DomainTitle = React.createClass({ export const DomainLeakTitle = React.createClass({ + renderInline (tooltip, fromNow) { + return <span title={tooltip} data-toggle="tooltip"> + <span>{window.tp('overview.leak_period_x', this.props.label)}</span> + <span className="note spacer-left">{window.tp('overview.started_x', fromNow)}</span> + </span>; + }, + render() { if (!this.props.label || !this.props.date) { return null; } let momentDate = moment(this.props.date); let fromNow = momentDate.fromNow(); - let tooltip = 'Started ' + fromNow + ', ' + momentDate.format('LL'); - return <span title={tooltip} data-toggle="tooltip">Water Leak: {this.props.label}</span>; + let tooltip = 'Started on ' + momentDate.format('LL'); + if (this.props.inline) { + return this.renderInline(tooltip, fromNow); + } + return <span title={tooltip} data-toggle="tooltip"> + <span>{window.tp('overview.leak_period_x', this.props.label)}</span> + <br/> + <span className="note">{window.tp('overview.started_x', fromNow)}</span> + </span>; } }); @@ -48,7 +63,6 @@ export const DomainHeader = React.createClass({ render () { return <div className="overview-card-header"> <DomainTitle {...this.props}>{this.props.title}</DomainTitle> - <Legend leakPeriodLabel={this.props.leakPeriodLabel} leakPeriodDate={this.props.leakPeriodDate}/> </div>; } }); @@ -122,7 +136,13 @@ export const Measure = React.createClass({ export const DomainMixin = { - renderTimeline(range) { + renderTimelineStartDate() { + let momentDate = moment(this.props.historyStartDate), + fromNow = momentDate.fromNow(); + return <span className="overview-domain-timeline-date">{window.tp('overview.started_x', fromNow)}</span>; + }, + + renderTimeline(range, displayDate) { if (!this.props.history) { return null; } @@ -130,6 +150,7 @@ export const DomainMixin = { props[range] = this.props.leakPeriodDate; return <div className="overview-domain-timeline"> <Timeline {...props}/> + {displayDate ? this.renderTimelineStartDate(range) : null} </div>; }, diff --git a/server/sonar-web/src/main/js/apps/overview/main/issues.js b/server/sonar-web/src/main/js/apps/overview/main/issues.js index b291d8243eb..e0772a63100 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/issues.js +++ b/server/sonar-web/src/main/js/apps/overview/main/issues.js @@ -7,6 +7,7 @@ import { IssuesLink } from '../../../components/shared/issues-link'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; import SeverityIcon from '../../../components/shared/severity-icon'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; +import { Legend } from '../components/legend'; import { getMetricName } from '../helpers/metrics'; import { formatMeasure } from '../../../helpers/measures'; @@ -27,6 +28,8 @@ export const GeneralIssues = React.createClass({ let createdAfter = moment(this.props.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ'); return <DomainLeak> + <Legend leakPeriodLabel={this.props.leakPeriodLabel} leakPeriodDate={this.props.leakPeriodDate}/> + <MeasuresList> <Measure label={getMetricName('new_debt')}> <IssuesLink component={this.props.component.key} @@ -47,8 +50,7 @@ export const GeneralIssues = React.createClass({ render () { return <Domain> - <DomainHeader component={this.props.component} title={window.t('overview.domain.debt')} linkTo="/issues" - leakPeriodLabel={this.props.leakPeriodLabel} leakPeriodDate={this.props.leakPeriodDate}/> + <DomainHeader component={this.props.component} title={window.t('overview.domain.debt')} linkTo="/issues"/> <DomainPanel domain="issues"> <DomainNutshell> @@ -69,7 +71,7 @@ export const GeneralIssues = React.createClass({ </IssuesLink> </Measure> </MeasuresList> - {this.renderTimeline('before')} + {this.renderTimeline('before', true)} </DomainNutshell> {this.renderLeak()} </DomainPanel> diff --git a/server/sonar-web/src/main/js/apps/overview/main/main.js b/server/sonar-web/src/main/js/apps/overview/main/main.js index 7d4037a9150..71c45428052 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/main.js +++ b/server/sonar-web/src/main/js/apps/overview/main/main.js @@ -132,7 +132,8 @@ export default React.createClass({ return { date, value }; }); }); - this.setState({ history }); + let historyStartDate = history[HISTORY_METRICS_LIST[0]][0].date; + this.setState({ history, historyStartDate }); }); }, diff --git a/server/sonar-web/src/main/less/pages/overview.less b/server/sonar-web/src/main/less/pages/overview.less index 972b04cbee0..3f616043e1f 100644 --- a/server/sonar-web/src/main/less/pages/overview.less +++ b/server/sonar-web/src/main/less/pages/overview.less @@ -120,7 +120,7 @@ } .overview-card { - margin: 30px 20px; + margin: 15px 20px; } .overview-card-fixed-width { @@ -144,7 +144,6 @@ margin-top: 10px; border: 1px solid @barBorderColor; background-color: #fff; - overflow: hidden; .overview-bar-chart { padding: 0; @@ -155,7 +154,7 @@ .overview-domain-leak { position: relative; display: flex; - padding: 30px 10px; + padding: 15px 10px; } .overview-domain-nutshell { @@ -226,6 +225,14 @@ } } +.overview-domain-timeline-date { + position: absolute; + bottom: 2px; + left: 5px; + color: fade(@secondFontColor, 60%); + font-size: 11px; +} + /* * Detailed Pages */ @@ -347,17 +354,16 @@ padding: 0 10px; } -.overview-legend-leak { - display: inline-block; - vertical-align: middle; - width: 16px; - height: 16px; - margin-top: -2px; - margin-left: 16px; - margin-right: 8px; +.overview-legend { + position: absolute; + bottom: 100%; + left: 0; + right: -1px; + padding: 5px 0 2px; border: 1px solid @barBorderColor; - box-sizing: border-box; - background-color: #fffae7; + border-bottom: none; + font-size: 14px; + text-align: center; } /* 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 aa4069ea989..cd8c9af424a 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3108,7 +3108,8 @@ system.log_level.warning=Current level has performance impacts, please make sure #------------------------------------------------------------------------------ overview.quality_gate=Quality Gate overview.quality_profiles=Quality Profiles -overview.water_leak=Water Leak +overview.leak_period_x=Leak Period {0} +overview.started_x=started {0} overview.project_in_a_nutshell=Project In a Nutshell overview.unmanaged_issues=Unmanaged Issues |