From 3d7e3e6b9c4eee7891b0d13bc643181f2f55ad12 Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Fri, 8 May 2020 17:26:18 -0700 Subject: [PATCH] Gauge chart component --- ui/app/components/gauge-chart.js | 86 +++++++++++++++++++++ ui/app/templates/components/gauge-chart.hbs | 19 +++++ 2 files changed, 105 insertions(+) create mode 100644 ui/app/components/gauge-chart.js create mode 100644 ui/app/templates/components/gauge-chart.hbs diff --git a/ui/app/components/gauge-chart.js b/ui/app/components/gauge-chart.js new file mode 100644 index 000000000..2f30a2f3d --- /dev/null +++ b/ui/app/components/gauge-chart.js @@ -0,0 +1,86 @@ +import Component from '@ember/component'; +import { computed } from '@ember/object'; +import { assert } from '@ember/debug'; +import { guidFor } from '@ember/object/internals'; +import { run } from '@ember/runloop'; +import d3Shape from 'd3-shape'; +import WindowResizable from 'nomad-ui/mixins/window-resizable'; + +export default Component.extend(WindowResizable, { + classNames: ['chart', 'gauge-chart'], + + value: null, + complement: null, + total: null, + chartClass: 'is-info', + + width: 0, + height: 0, + + percent: computed('value', 'complement', 'total', function() { + assert( + 'Provide complement OR total to GaugeChart, not both.', + this.complement != null || this.total != null + ); + + if (this.complement != null) { + return this.value / (this.value + this.complement); + } + + return this.value / this.total; + }), + + fillId: computed(function() { + return `gauge-chart-fill-${guidFor(this)}`; + }), + + maskId: computed(function() { + return `gauge-chart-mask-${guidFor(this)}`; + }), + + radius: computed('width', function() { + return this.width / 2; + }), + + weight: 4, + + backgroundArc: computed('radius', 'weight', function() { + const { radius, weight } = this; + const arc = d3Shape + .arc() + .outerRadius(radius) + .innerRadius(radius - weight) + .cornerRadius(weight) + .startAngle(-Math.PI / 2) + .endAngle(Math.PI / 2); + return arc(); + }), + + valueArc: computed('radius', 'weight', 'percent', function() { + const { radius, weight, percent } = this; + + const arc = d3Shape + .arc() + .outerRadius(radius) + .innerRadius(radius - weight) + .cornerRadius(weight) + .startAngle(-Math.PI / 2) + .endAngle(-Math.PI / 2 + Math.PI * percent); + return arc(); + }), + + didInsertElement() { + this.updateDimensions(); + }, + + updateDimensions() { + const $svg = this.$('svg'); + const width = $svg.width(); + + this.setProperties({ width, height: width / 2 }); + }, + + windowResizeHandler() { + run.once(this, this.updateDimensions); + }, +}); diff --git a/ui/app/templates/components/gauge-chart.hbs b/ui/app/templates/components/gauge-chart.hbs new file mode 100644 index 000000000..fcd94f266 --- /dev/null +++ b/ui/app/templates/components/gauge-chart.hbs @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + +
+

{{label}}

+

{{format-percentage value total=total complement=complement}}

+