open-nomad/ui/app/components/stats-time-series.js

78 lines
2.1 KiB
JavaScript

import { computed } from '@ember/object';
import moment from 'moment';
import d3TimeFormat from 'd3-time-format';
import d3Format from 'd3-format';
import d3Scale from 'd3-scale';
import d3Array from 'd3-array';
import LineChart from 'nomad-ui/components/line-chart';
import layout from '../templates/components/line-chart';
import formatDuration from 'nomad-ui/utils/format-duration';
import classic from 'ember-classic-decorator';
@classic
export default class StatsTimeSeries extends LineChart {
layout = layout;
xProp = 'timestamp';
yProp = 'percent';
timeseries = true;
xFormat() {
return d3TimeFormat.timeFormat('%H:%M:%S');
}
yFormat() {
return d3Format.format('.1~%');
}
// Specific a11y descriptors
title = 'Stats Time Series Chart';
@computed('data.[]', 'xProp', 'yProp')
get description() {
const { xProp, yProp, data } = this;
const yRange = d3Array.extent(data, d => d[yProp]);
const xRange = d3Array.extent(data, d => d[xProp]);
const yFormatter = this.yFormat();
const duration = formatDuration(xRange[1] - xRange[0], 'ms', true);
return `Time series data for the last ${duration}, with values ranging from ${yFormatter(
yRange[0]
)} to ${yFormatter(yRange[1])}`;
}
@computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset')
get xScale() {
const xProp = this.xProp;
const scale = this.timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear();
const data = this.data;
const [low, high] = d3Array.extent(data, d => d[xProp]);
const minLow = moment(high)
.subtract(5, 'minutes')
.toDate();
const extent = data.length ? [Math.min(low, minLow), high] : [minLow, new Date()];
scale.rangeRound([10, this.yAxisOffset]).domain(extent);
return scale;
}
@computed('data.[]', 'yProp', 'xAxisOffset')
get yScale() {
const yProp = this.yProp;
const yValues = (this.data || []).mapBy(yProp);
let [low, high] = [0, 1];
if (yValues.compact().length) {
[low, high] = d3Array.extent(yValues);
}
return d3Scale
.scaleLinear()
.rangeRound([this.xAxisOffset, 10])
.domain([Math.min(0, low), Math.max(1, high)]);
}
}