github.com/manicqin/nomad@v0.9.5/ui/app/components/stats-time-series.js (about) 1 import { computed } from '@ember/object'; 2 import moment from 'moment'; 3 import d3TimeFormat from 'd3-time-format'; 4 import d3Format from 'd3-format'; 5 import d3Scale from 'd3-scale'; 6 import d3Array from 'd3-array'; 7 import LineChart from 'nomad-ui/components/line-chart'; 8 import formatDuration from 'nomad-ui/utils/format-duration'; 9 10 export default LineChart.extend({ 11 xProp: 'timestamp', 12 yProp: 'percent', 13 timeseries: true, 14 15 xFormat() { 16 return d3TimeFormat.timeFormat('%H:%M:%S'); 17 }, 18 19 yFormat() { 20 return d3Format.format('.1~%'); 21 }, 22 23 // Specific a11y descriptors 24 title: 'Stats Time Series Chart', 25 26 description: computed('data.[]', 'xProp', 'yProp', function() { 27 const { xProp, yProp, data } = this; 28 const yRange = d3Array.extent(data, d => d[yProp]); 29 const xRange = d3Array.extent(data, d => d[xProp]); 30 const yFormatter = this.yFormat(); 31 32 const duration = formatDuration(xRange[1] - xRange[0], 'ms', true); 33 34 return `Time series data for the last ${duration}, with values ranging from ${yFormatter(yRange[0])} to ${yFormatter(yRange[1])}`; 35 }), 36 37 xScale: computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset', function() { 38 const xProp = this.xProp; 39 const scale = this.timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear(); 40 const data = this.data; 41 42 const [low, high] = d3Array.extent(data, d => d[xProp]); 43 const minLow = moment(high) 44 .subtract(5, 'minutes') 45 .toDate(); 46 47 const extent = data.length ? [Math.min(low, minLow), high] : [minLow, new Date()]; 48 scale.rangeRound([10, this.yAxisOffset]).domain(extent); 49 50 return scale; 51 }), 52 53 yScale: computed('data.[]', 'yProp', 'xAxisOffset', function() { 54 const yProp = this.yProp; 55 const yValues = (this.data || []).mapBy(yProp); 56 57 let [low, high] = [0, 1]; 58 if (yValues.compact().length) { 59 [low, high] = d3Array.extent(yValues); 60 } 61 62 return d3Scale 63 .scaleLinear() 64 .rangeRound([this.xAxisOffset, 10]) 65 .domain([Math.min(0, low), Math.max(1, high)]); 66 }), 67 });