/** * Copyright (c) HashiCorp, Inc. * SPDX-License-Identifier: MPL-2.0 */ import hbs from 'htmlbars-inline-precompile'; import EmberObject from '@ember/object'; import { on } from '@ember/object/evented'; import moment from 'moment'; import DelayedArray from '../utils/delayed-array'; export default { title: 'Charts/Line Chart', }; let data1 = [ { year: 2010, value: 10 }, { year: 2011, value: 10 }, { year: 2012, value: 20 }, { year: 2013, value: 30 }, { year: 2014, value: 50 }, { year: 2015, value: 80 }, { year: 2016, value: 130 }, { year: 2017, value: 210 }, { year: 2018, value: 340 }, ]; let data2 = [ { year: 2010, value: 100 }, { year: 2011, value: 90 }, { year: 2012, value: 120 }, { year: 2013, value: 130 }, { year: 2014, value: 115 }, { year: 2015, value: 105 }, { year: 2016, value: 90 }, { year: 2017, value: 85 }, { year: 2018, value: 90 }, ]; export let Standard = () => { return { template: hbs`
Line Chart
{{#if this.lineChartData}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}
    {{#if this.lineChartMild}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}
    `, context: { lineChartData: DelayedArray.create(data1), lineChartMild: DelayedArray.create(data2), }, }; }; export let FluidWidth = () => { return { template: hbs`
    Fluid-width Line Chart
    {{#if this.lineChartData}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}
    {{#if this.lineChartMild}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}

    A line chart will assume the width of its container. This includes the dimensions of the axes, which are calculated based on real DOM measurements. This requires a two-pass render: first the axes are placed with their real domains (in order to capture width and height of tick labels), second the axes are adjusted to make sure both the x and y axes are within the height and width bounds of the container.

    `, context: { lineChartData: DelayedArray.create(data1), lineChartMild: DelayedArray.create(data2), }, }; }; export let LiveData = () => { return { template: hbs`
    Live data Line Chart
    {{#if this.controller.lineChartLive}} <:svg as |c|> {{/if}}
    `, context: { controller: EmberObject.extend({ startTimer: on('init', function () { this.lineChartLive = []; this.set( 'timer', setInterval(() => { this.incrementProperty('timerTicks'); let ref = this.lineChartLive; ref.addObject({ ts: Date.now(), val: Math.random() * 30 + 20 }); if (ref.length > 60) { ref.splice(0, ref.length - 60); } }, 500) ); }), willDestroy() { clearInterval(this.timer); }, get secondsFormat() { return (date) => moment(date).format('HH:mm:ss'); }, }).create(), }, }; }; export let Gaps = () => { return { template: hbs`
    Line Chart data with gaps
    {{#if this.lineChartGapData}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}
    `, context: { lineChartGapData: DelayedArray.create([ { year: 2010, value: 10 }, { year: 2011, value: 10 }, { year: 2012, value: null }, { year: 2013, value: 30 }, { year: 2014, value: 50 }, { year: 2015, value: 80 }, { year: 2016, value: null }, { year: 2017, value: 210 }, { year: 2018, value: 340 }, ]), }, }; }; export let VerticalAnnotations = () => { return { template: hbs`
    Line Chart data with annotations
    {{#if (and this.data this.annotations)}} <:svg as |c|> <:after as |c|> {{/if}}

    {{this.activeAnnotation.info}}

    Line Chart data with staggered annotations
    {{#if (and this.data this.annotations)}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{/if}}
    `, context: { data: DelayedArray.create( new Array(180).fill(null).map((_, idx) => ({ y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200, x: moment().add(idx, 'd').toDate(), })) ), annotations: [ { x: moment().toDate(), type: 'info', info: 'Far left', }, { x: moment() .add(90 / 4, 'd') .toDate(), type: 'error', info: 'This is the max of the sine curve', }, { x: moment().add(89, 'd').toDate(), type: 'info', info: 'This is the end of the first period', }, { x: moment().add(96, 'd').toDate(), type: 'info', info: 'A close annotation for staggering purposes', }, { x: moment() .add((90 / 4) * 3, 'd') .toDate(), type: 'error', info: 'This is the min of the sine curve', }, { x: moment().add(179, 'd').toDate(), type: 'info', info: 'Far right', }, ], }, }; }; export let HorizontalAnnotations = () => { return { template: hbs`
    {{#if (and this.data this.annotations)}} <:svg as |c|> <:after as |c|> {{/if}}
    `, context: { data: DelayedArray.create( new Array(180).fill(null).map((_, idx) => ({ y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200, x: moment().add(idx, 'd').toDate(), })) ), annotations: [ { y: 300, info: 'High', }, { y: 100, info: 'Low', }, ], }, }; }; export let StepLine = () => { return { template: hbs`
    Line Chart with a Step Line
    {{#if this.data}} <:svg as |c|> <:after as |c|>
  • {{datum.formattedX}} {{datum.formattedY}}
  • {{this.activeAnnotation.info}}

    {{/if}}
    `, context: { data: DelayedArray.create([ { x: 1, y: 5 }, { x: 2, y: 1 }, { x: 3, y: 2 }, { x: 4, y: 2 }, { x: 5, y: 9 }, { x: 6, y: 3 }, { x: 7, y: 4 }, { x: 8, y: 1 }, { x: 9, y: 5 }, ]), }, }; }; export let MultiLine = () => ({ template: hbs`
    Multiple Lines on One Chart
    {{#if this.data}} <:svg as |c|> {{#each this.data as |series idx|}} {{/each}} <:after as |c|>
  • {{series.name}} {{datum.formattedY}}
  • {{this.activeAnnotation.info}}

    {{/if}}
    `, context: { data: DelayedArray.create([ { name: 'Series 1', data: [ { x: 3, y: 7 }, { x: 4, y: 5 }, { x: 5, y: 8 }, { x: 6, y: 9 }, { x: 7, y: 10 }, { x: 8, y: 8 }, { x: 9, y: 6 }, ], }, { name: 'Series 2', data: [ { x: 1, y: 5 }, { x: 2, y: 1 }, { x: 3, y: 2 }, { x: 4, y: 2 }, { x: 5, y: 9 }, { x: 6, y: 3 }, { x: 7, y: 4 }, ], }, ]), }, });