From b32ad26b82a3dd32505dc2faa28bbab30d03c15f Mon Sep 17 00:00:00 2001 From: just-boris Date: Mon, 23 May 2016 23:04:12 +0200 Subject: [PATCH] update pie chart to donut, reuse in widget --- allure-report-face/package.json | 1 - .../src/blocks/splash/styles.css | 11 ++++ .../src/blocks/widget/styles.css | 43 ++++++--------- .../src/components/chart/BaseChartView.js | 1 + .../src/components/chart/styles.css | 4 +- .../widget-overview/OverviewWidget.hbs | 13 ----- .../widget-overview/OverviewWidget.js | 53 ------------------- .../src/components/widget-overview/styles.css | 7 --- .../widgets-grid/WidgetsGridView.js | 2 +- .../src/plugins/default/index.js | 4 -- .../src/plugins/graph/GraphsView.js | 31 +++++++++-- .../src/plugins/graph/charts/StatusChart.js | 52 +++++++++++------- .../src/plugins/graph/charts/index.js | 5 -- .../graph/graph-widget/GraphWidget.hbs | 14 +++++ .../plugins/graph/graph-widget/GraphWidget.js | 18 +++++++ allure-report-face/src/plugins/graph/index.js | 2 + .../src/plugins/graph/styles.css | 7 +++ .../report-stats-widget/ReportStatsWidget.hbs | 30 +++++------ allure-report-face/src/styles.css | 1 + .../test/components/widgets-grid.spec.js | 1 + 20 files changed, 148 insertions(+), 152 deletions(-) create mode 100644 allure-report-face/src/blocks/splash/styles.css delete mode 100644 allure-report-face/src/components/widget-overview/OverviewWidget.hbs delete mode 100644 allure-report-face/src/components/widget-overview/OverviewWidget.js delete mode 100644 allure-report-face/src/components/widget-overview/styles.css delete mode 100644 allure-report-face/src/plugins/graph/charts/index.js create mode 100644 allure-report-face/src/plugins/graph/graph-widget/GraphWidget.hbs create mode 100644 allure-report-face/src/plugins/graph/graph-widget/GraphWidget.js diff --git a/allure-report-face/package.json b/allure-report-face/package.json index dfd9ef4b..9cc79196 100644 --- a/allure-report-face/package.json +++ b/allure-report-face/package.json @@ -55,7 +55,6 @@ "backbone-decorators": "0.0.4", "backbone.marionette": "^2.4.5", "backbone.wreqr": "^1.3.0", - "c3": "^0.4.11-rc4", "d3": "^3.5.12", "denodeify": "^1.2.1", "filesize": "^3.1.5", diff --git a/allure-report-face/src/blocks/splash/styles.css b/allure-report-face/src/blocks/splash/styles.css new file mode 100644 index 00000000..9f1eafc6 --- /dev/null +++ b/allure-report-face/src/blocks/splash/styles.css @@ -0,0 +1,11 @@ +.splash { + margin: auto; + text-align: center; + &__title { + font-size: 3.5em; + line-height: 1; + } + &__subtitle { + color: $text-muted-color; + } +} diff --git a/allure-report-face/src/blocks/widget/styles.css b/allure-report-face/src/blocks/widget/styles.css index f0ecde02..b52029b5 100644 --- a/allure-report-face/src/blocks/widget/styles.css +++ b/allure-report-face/src/blocks/widget/styles.css @@ -1,6 +1,18 @@ @import "../../variables.css"; .widget { + margin-bottom: $gap-size; + position: relative; + + &_ghost { + border: 1px dashed $border-accent-color; + box-shadow: none; + min-height: 50px; + & > * { + display: none; + } + } + &__title { margin-top: 0; font-weight: lighter; @@ -10,23 +22,15 @@ &__subtitle { color: $text-muted-color; font-size: 16px; - text-transform: lowercase; + text-transform: none; } &__flex-line { display: flex; } - margin-bottom: $gap-size; - position: relative; - - &_ghost { - border: 1px dashed $border-accent-color; - box-shadow: none; - min-height: 50px; - & > * { - display: none; - } + &__column { + width: 50%; } &__handle { @@ -50,20 +54,3 @@ } } } - -.widget-content { - width: 50%; - display: flex; - align-items: center; - justify-content: center; - overflow: auto; - flex-direction: column; - - &__title { - font-size: 3.5em; - } - - &__subtitle { - color: $text-muted-color; - } -} diff --git a/allure-report-face/src/components/chart/BaseChartView.js b/allure-report-face/src/components/chart/BaseChartView.js index f2a69ece..352af294 100644 --- a/allure-report-face/src/components/chart/BaseChartView.js +++ b/allure-report-face/src/components/chart/BaseChartView.js @@ -6,6 +6,7 @@ export default class BaseChartView extends View { constructor(options) { super(options); + this.options = options; this.firstRender = true; } diff --git a/allure-report-face/src/components/chart/styles.css b/allure-report-face/src/components/chart/styles.css index 7b8abfda..41ef19fe 100644 --- a/allure-report-face/src/components/chart/styles.css +++ b/allure-report-face/src/components/chart/styles.css @@ -11,6 +11,9 @@ margin-bottom: $gap-size; font-size: 18px; } + &__caption { + text-anchor: middle; + } &__svg { width: 100%; height: 100%; @@ -64,4 +67,3 @@ } } } - diff --git a/allure-report-face/src/components/widget-overview/OverviewWidget.hbs b/allure-report-face/src/components/widget-overview/OverviewWidget.hbs deleted file mode 100644 index c7988ea0..00000000 --- a/allure-report-face/src/components/widget-overview/OverviewWidget.hbs +++ /dev/null @@ -1,13 +0,0 @@ -

{{t "TEST_RUN"}} - - {{t "STARTED_AT" date=(date time.start) time=(time time.start)}} -

- -
-
-
{{ statistic.total }}
-
Cases in {{duration time.duration}}
-
- -
-
\ No newline at end of file diff --git a/allure-report-face/src/components/widget-overview/OverviewWidget.js b/allure-report-face/src/components/widget-overview/OverviewWidget.js deleted file mode 100644 index d845161f..00000000 --- a/allure-report-face/src/components/widget-overview/OverviewWidget.js +++ /dev/null @@ -1,53 +0,0 @@ -import './styles.css'; -import {ItemView} from 'backbone.marionette'; -import template from './OverviewWidget.hbs'; -import c3 from 'c3'; -import {colors, states} from '../../util/statuses'; - -export default class OverviewWidget extends ItemView { - template = template; - - onAttach() { - let fill = states.map((state) => [state, this.model.get('statistic')[state]]); - - this.chart = c3.generate({ - bindto: '.overview-widget-graph', - color: { - pattern: colors - }, - size: { - height: 150, - width: 150 - }, - padding: { - left: 30, - right: 15, - top: 0, - bottom: 0 - }, - data: { - type: 'donut', - columns: fill - }, - legend: { - show: false - }, - donut: { - width: 10, - title: `${(this.model.get('statistic')['passed'] / this.model.get('statistic')['total'] * 100).toFixed(1)}%`, - label: { - threshold: 0.00000001, - show: false - } - }, - tooltip: { - grouped: false, - format: { - value: function (value, ratio) { - return `${value} (${(ratio * 100).toFixed(1)}%)`; - } - } - } - }); - } -} diff --git a/allure-report-face/src/components/widget-overview/styles.css b/allure-report-face/src/components/widget-overview/styles.css deleted file mode 100644 index 0b46b319..00000000 --- a/allure-report-face/src/components/widget-overview/styles.css +++ /dev/null @@ -1,7 +0,0 @@ -@import "../../variables.css"; - -.overview-widget { - &__bar { - margin-top: $gap-size; - } -} diff --git a/allure-report-face/src/components/widgets-grid/WidgetsGridView.js b/allure-report-face/src/components/widgets-grid/WidgetsGridView.js index 7e782c8b..b90157cf 100644 --- a/allure-report-face/src/components/widgets-grid/WidgetsGridView.js +++ b/allure-report-face/src/components/widgets-grid/WidgetsGridView.js @@ -20,7 +20,7 @@ class WidgetsGridView extends LayoutView { return ''; } - onRender() { + onShow() { this.getWidgetsArrangement().map(col => { return col.map(widgetName => [widgetName, allurePlugins.widgets[widgetName]]); }).forEach(widgetCol => { diff --git a/allure-report-face/src/plugins/default/index.js b/allure-report-face/src/plugins/default/index.js index ba4b2f7a..c6f8bf61 100644 --- a/allure-report-face/src/plugins/default/index.js +++ b/allure-report-face/src/plugins/default/index.js @@ -1,10 +1,6 @@ import allurePlugins from '../../pluginApi'; - -import OverviewWidget from '../../components/widget-overview/OverviewWidget'; import OverviewLayout from '../../layouts/overview/OverivewLayout'; -allurePlugins.addWidget('total', OverviewWidget); - allurePlugins.addTab('', { title: 'Overview', icon: 'fa fa-home', route: '', diff --git a/allure-report-face/src/plugins/graph/GraphsView.js b/allure-report-face/src/plugins/graph/GraphsView.js index 38b8c94d..9d255690 100644 --- a/allure-report-face/src/plugins/graph/GraphsView.js +++ b/allure-report-face/src/plugins/graph/GraphsView.js @@ -2,17 +2,26 @@ import './styles.css'; import {LayoutView} from 'backbone.marionette'; import $ from 'jquery'; import {className} from '../../decorators'; -import * as charts from './charts'; +import DurationChart from './charts/DurationChart'; +import StatusChart from './charts/StatusChart'; +import SeverityChart from './charts/SeverityChart'; + @className('charts-grid') class GraphsView extends LayoutView { template() { return ''; } onShow() { - Object.keys(charts).forEach(chart => this.addChart(chart, charts[chart])); + const collection = this.collection; + this.addChart('Status', new StatusChart({ + statistic: this.getStatusChartData(), + showLegend: true + })); + this.addChart('Severity', new SeverityChart({collection})); + this.addChart('Duration', new DurationChart({collection})); } - addChart(name, Chart) { + addChart(name, chart) { const container = $(`

${name}

@@ -21,7 +30,21 @@ class GraphsView extends LayoutView {
`); this.$el.append(container); this.addRegion(name, {el: container.find('.chart__body')}); - this.getRegion(name).show(new Chart({collection: this.collection})); + this.getRegion(name).show(chart); + } + + getStatusChartData() { + return this.collection.reduce((stats, testcase) => { + stats[testcase.get('status').toLowerCase()]++; + return stats; + }, { + total: this.collection.length, + failed: 0, + broken: 0, + canceled: 0, + pending: 0, + passed: 0 + }); } } diff --git a/allure-report-face/src/plugins/graph/charts/StatusChart.js b/allure-report-face/src/plugins/graph/charts/StatusChart.js index 9238e4d6..ee4d4256 100644 --- a/allure-report-face/src/plugins/graph/charts/StatusChart.js +++ b/allure-report-face/src/plugins/graph/charts/StatusChart.js @@ -1,6 +1,7 @@ import BaseChartView from '../../../components/chart/BaseChartView'; import TooltipView from '../../../components/tooltip/TooltipView'; import {on} from '../../../decorators'; +import {omit} from 'underscore'; import d3 from 'd3'; import escape from '../../../util/escape'; @@ -13,33 +14,27 @@ const legendTpl = `
export default class StatusChart extends BaseChartView { initialize() { - this.arc = d3.svg.arc().innerRadius(0); + this.arc = d3.svg.arc(); this.pie = d3.layout.pie().sort(null).value(d => d.value); this.tooltip = new TooltipView({position: 'center'}); } getChartData() { - const stats = this.collection.reduce((stats, testcase) => { - stats[testcase.get('status')]++; - return stats; - }, { - FAILED: 0, - BROKEN: 0, - CANCELED: 0, - PENDING: 0, - PASSED: 0 - }); + const {total} = this.options.statistic; + const stats = omit(this.options.statistic, 'total'); return Object.keys(stats).map(key => ({ - name: key, + name: key.toUpperCase(), value: stats[key], - part: stats[key] / this.collection.length + part: stats[key] / total })); } setupViewport() { const svg = super.setupViewport(); - this.$el.append(legendTpl); + if(this.options.showLegend) { + this.$el.append(legendTpl); + } return svg; } @@ -47,13 +42,18 @@ export default class StatusChart extends BaseChartView { const data = this.getChartData(); const width = this.$el.width(); const radius = width / 4; + var leftOffset = width / 2; + + if(this.options.showLegend) { + leftOffset -= 70; + } this.$el.height(radius * 2); - this.arc.outerRadius(radius); + this.arc.innerRadius(0.8 * radius).outerRadius(radius); this.svg = this.setupViewport(); var sectors = this.svg.select('.chart__plot') - .attr({transform: `translate(${width / 2 - 70},${radius})`}) + .attr({transform: `translate(${leftOffset},${radius})`}) .selectAll('.chart__arc').data(this.pie(data)) .enter() .append('path') @@ -61,13 +61,18 @@ export default class StatusChart extends BaseChartView { this.bindTooltip(sectors); + this.svg.select('.chart__plot').append('text') + .classed('chart__caption', true) + .attr({dy: '0.4em'}) + .style({'font-size': radius / 3}) + .text(this.getChartTitle()); + if(this.firstRender) { sectors.transition().duration(750).attrTween('d', d => { - const radiusFn = d3.interpolate(10, radius); const startAngleFn = d3.interpolate(0, d.startAngle); const endAngleFn = d3.interpolate(0, d.endAngle); return t => - this.arc.outerRadius(radiusFn(t))({startAngle: startAngleFn(t), endAngle: endAngleFn(t)}); + this.arc({startAngle: startAngleFn(t), endAngle: endAngleFn(t)}); }); } else { sectors.attr('d', d => this.arc(d)); @@ -75,9 +80,18 @@ export default class StatusChart extends BaseChartView { super.onShow(); } + formatNumber(number) { + return (Math.floor(number * 100) / 100).toString(); + } + + getChartTitle() { + const {passed, total} = this.options.statistic; + return this.formatNumber(passed / total * 100) + '%'; + } + getTooltipContent({data}) { return escape` - ${data.value} tests (${(data.part * 100).toFixed(0)}%)
+ ${data.value} tests (${this.formatNumber(data.part * 100)}%)
${data.name} `; } diff --git a/allure-report-face/src/plugins/graph/charts/index.js b/allure-report-face/src/plugins/graph/charts/index.js deleted file mode 100644 index d82acba0..00000000 --- a/allure-report-face/src/plugins/graph/charts/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import Duration from './DurationChart'; -import Status from './StatusChart'; -import Severity from './SeverityChart'; - -export {Status, Severity, Duration}; diff --git a/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.hbs b/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.hbs new file mode 100644 index 00000000..7a2b499b --- /dev/null +++ b/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.hbs @@ -0,0 +1,14 @@ +

{{t "TEST_RUN"}} + + {{t "STARTED_AT" date=(date time.start) time=(time time.start)}} + +

+ +
+
+
{{ statistic.total }}
+
Cases in {{duration time.duration}}
+
+ +
+
diff --git a/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.js b/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.js new file mode 100644 index 00000000..9e99c810 --- /dev/null +++ b/allure-report-face/src/plugins/graph/graph-widget/GraphWidget.js @@ -0,0 +1,18 @@ +import {LayoutView} from 'backbone.marionette'; +import StatusChart from '../charts/StatusChart'; +import {region} from '../../../decorators'; +import template from './GraphWidget.hbs'; + +export default class GraphWidget extends LayoutView { + template = template; + + @region('.graph-widget__chart') + chart; + + onShow() { + this.chart.show(new StatusChart({ + statistic: this.model.get('statistic'), + showLegend: false + })); + } +} diff --git a/allure-report-face/src/plugins/graph/index.js b/allure-report-face/src/plugins/graph/index.js index 69f95cee..073e0c57 100644 --- a/allure-report-face/src/plugins/graph/index.js +++ b/allure-report-face/src/plugins/graph/index.js @@ -1,8 +1,10 @@ import allurePlugins from '../../pluginApi'; import GraphLayout from './GraphLayout'; +import GraphWidget from './graph-widget/GraphWidget'; allurePlugins.addTab('graph', { title: 'Graph', icon: 'fa fa-bar-chart', route: 'graph', onEnter: () => new GraphLayout() }); +allurePlugins.addWidget('total', GraphWidget); diff --git a/allure-report-face/src/plugins/graph/styles.css b/allure-report-face/src/plugins/graph/styles.css index e1cd3a71..54c8d718 100644 --- a/allure-report-face/src/plugins/graph/styles.css +++ b/allure-report-face/src/plugins/graph/styles.css @@ -10,6 +10,7 @@ } .chart { + padding-bottom: $gap-size; &__legend { position: absolute; top: 20%; @@ -27,3 +28,9 @@ @mixin status-bg; } } + +.graph-widget { + &__chart { + padding: 1em 0; + } +} diff --git a/allure-report-face/src/plugins/report-stats/report-stats-widget/ReportStatsWidget.hbs b/allure-report-face/src/plugins/report-stats/report-stats-widget/ReportStatsWidget.hbs index 064368ac..80562570 100644 --- a/allure-report-face/src/plugins/report-stats/report-stats-widget/ReportStatsWidget.hbs +++ b/allure-report-face/src/plugins/report-stats/report-stats-widget/ReportStatsWidget.hbs @@ -1,20 +1,21 @@ -

Report stats

- -
- {{#if report.url}} - {{report.name}} - {{else}} - {{report.name}} - {{/if}} -
+

+ Report stats + + {{#if report.url}} + {{report.name}} + {{else}} + {{report.name}} + {{/if}} + +

-
-
{{default report.version 'Latest'}}
-
Allure's version
+
+
{{default report.version 'Latest'}}
+
Allure's version
-
+
{{#if report.size}} @@ -29,6 +30,3 @@
- - - diff --git a/allure-report-face/src/styles.css b/allure-report-face/src/styles.css index 2b396b92..4c5d1fd5 100644 --- a/allure-report-face/src/styles.css +++ b/allure-report-face/src/styles.css @@ -10,6 +10,7 @@ @import "./blocks/label/styles.css"; @import "./blocks/link/styles.css"; @import "./blocks/spinner/styles.css"; +@import "./blocks/splash/styles.css"; @import "./blocks/text/styles.css"; @import "./blocks/widget/styles.css"; @import "./variables.css"; diff --git a/allure-report-face/test/components/widgets-grid.spec.js b/allure-report-face/test/components/widgets-grid.spec.js index 3baa568d..1d79cb33 100644 --- a/allure-report-face/test/components/widgets-grid.spec.js +++ b/allure-report-face/test/components/widgets-grid.spec.js @@ -28,6 +28,7 @@ describe('WidgetsGridView', function() { } }); this.view = new WidgetsGridView({model: this.model}).render(); + this.view.onShow(); this.el = new PageObject(this.view.$el); });