github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/stories/charts/line-chart.stories.js (about)

     1  import hbs from 'htmlbars-inline-precompile';
     2  
     3  import EmberObject from '@ember/object';
     4  import { on } from '@ember/object/evented';
     5  import moment from 'moment';
     6  
     7  import DelayedArray from '../utils/delayed-array';
     8  
     9  export default {
    10    title: 'Charts/Line Chart',
    11  };
    12  
    13  let data1 = [
    14    { year: 2010, value: 10 },
    15    { year: 2011, value: 10 },
    16    { year: 2012, value: 20 },
    17    { year: 2013, value: 30 },
    18    { year: 2014, value: 50 },
    19    { year: 2015, value: 80 },
    20    { year: 2016, value: 130 },
    21    { year: 2017, value: 210 },
    22    { year: 2018, value: 340 },
    23  ];
    24  
    25  let data2 = [
    26    { year: 2010, value: 100 },
    27    { year: 2011, value: 90 },
    28    { year: 2012, value: 120 },
    29    { year: 2013, value: 130 },
    30    { year: 2014, value: 115 },
    31    { year: 2015, value: 105 },
    32    { year: 2016, value: 90 },
    33    { year: 2017, value: 85 },
    34    { year: 2018, value: 90 },
    35  ];
    36  
    37  export let Standard = () => {
    38    return {
    39      template: hbs`
    40        <h5 class="title is-5">Line Chart</h5>
    41        <div class="block" style="height:100px; width: 400px;">
    42          {{#if this.lineChartData}}
    43            <LineChart @data={{this.lineChartData}} @xProp="year" @yProp="value">
    44              <:svg as |c|>
    45                <c.Area @data={{this.lineChartData}} />
    46              </:svg>
    47              <:after as |c|>
    48                <c.Tooltip class="is-snappy" as |series datum|>
    49                  <li>
    50                    <span class="label"><span class="color-swatch is-primary" />{{datum.formattedX}}</span>
    51                    <span class="value">{{datum.formattedY}}</span>
    52                  </li>
    53                </c.Tooltip>
    54              </:after>
    55            </LineChart>
    56          {{/if}}
    57        </div>
    58        <div class="block" style="height:100px; width: 400px;">
    59          {{#if this.lineChartMild}}
    60            <LineChart @data={{this.lineChartMild}} @xProp="year" @yProp="value">
    61              <:svg as |c|>
    62                <c.Area @data={{this.lineChartMild}} @colorClass="is-info" />
    63              </:svg>
    64              <:after as |c|>
    65                <c.Tooltip class="is-snappy" as |series datum|>
    66                  <li>
    67                    <span class="label"><span class="color-swatch is-info" />{{datum.formattedX}}</span>
    68                    <span class="value">{{datum.formattedY}}</span>
    69                  </li>
    70                </c.Tooltip>
    71              </:after>
    72            </LineChart>
    73          {{/if}}
    74        </div>
    75        `,
    76      context: {
    77        lineChartData: DelayedArray.create(data1),
    78        lineChartMild: DelayedArray.create(data2),
    79      },
    80    };
    81  };
    82  
    83  export let FluidWidth = () => {
    84    return {
    85      template: hbs`
    86        <h5 class="title is-5">Fluid-width Line Chart</h5>
    87        <div class="block" style="height:250px;">
    88          {{#if this.lineChartData}}
    89            <LineChart @data={{this.lineChartData}} @xProp="year" @yProp="value">
    90              <:svg as |c|>
    91                <c.Area @data={{this.lineChartData}} @colorClass="is-danger" />
    92              </:svg>
    93              <:after as |c|>
    94                <c.Tooltip class="is-snappy" as |series datum|>
    95                  <li>
    96                    <span class="label"><span class="color-swatch is-danger" />{{datum.formattedX}}</span>
    97                    <span class="value">{{datum.formattedY}}</span>
    98                  </li>
    99                </c.Tooltip>
   100              </:after>
   101            </LineChart>
   102          {{/if}}
   103        </div>
   104        <div class="block" style="height:250px;">
   105          {{#if this.lineChartMild}}
   106            <LineChart @data={{this.lineChartMild}} @xProp="year" @yProp="value">
   107              <:svg as |c|>
   108                <c.Area @data={{this.lineChartMild}} @colorClass="is-warning" />
   109              </:svg>
   110              <:after as |c|>
   111                <c.Tooltip class="is-snappy" as |series datum|>
   112                  <li>
   113                    <span class="label"><span class="color-swatch is-warning" />{{datum.formattedX}}</span>
   114                    <span class="value">{{datum.formattedY}}</span>
   115                  </li>
   116                </c.Tooltip>
   117              </:after>
   118            </LineChart>
   119          {{/if}}
   120        </div>
   121        <p class="annotation">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.</p>
   122        `,
   123      context: {
   124        lineChartData: DelayedArray.create(data1),
   125        lineChartMild: DelayedArray.create(data2),
   126      },
   127    };
   128  };
   129  
   130  export let LiveData = () => {
   131    return {
   132      template: hbs`
   133        <h5 class="title is-5">Live data Line Chart</h5>
   134        <div class="block" style="height:250px">
   135          {{#if this.controller.lineChartLive}}
   136            <LineChart
   137              @data={{this.controller.lineChartLive}}
   138              @xProp="ts"
   139              @yProp="val"
   140              @timeseries={{true}}
   141              @xFormat={{this.controller.secondsFormat}}>
   142              <:svg as |c|>
   143                <c.Area @data={{this.controller.lineChartLive}} />
   144              </:svg>
   145            </LineChart>
   146          {{/if}}
   147        </div>
   148        `,
   149      context: {
   150        controller: EmberObject.extend({
   151          startTimer: on('init', function () {
   152            this.lineChartLive = [];
   153  
   154            this.set(
   155              'timer',
   156              setInterval(() => {
   157                this.incrementProperty('timerTicks');
   158  
   159                let ref = this.lineChartLive;
   160                ref.addObject({ ts: Date.now(), val: Math.random() * 30 + 20 });
   161                if (ref.length > 60) {
   162                  ref.splice(0, ref.length - 60);
   163                }
   164              }, 500)
   165            );
   166          }),
   167  
   168          willDestroy() {
   169            clearInterval(this.timer);
   170          },
   171  
   172          get secondsFormat() {
   173            return (date) => moment(date).format('HH:mm:ss');
   174          },
   175        }).create(),
   176      },
   177    };
   178  };
   179  
   180  export let Gaps = () => {
   181    return {
   182      template: hbs`
   183        <h5 class="title is-5">Line Chart data with gaps</h5>
   184        <div class="block" style="height:250px">
   185          {{#if this.lineChartGapData}}
   186            <LineChart @data={{this.lineChartGapData}} @xProp="year" @yProp="value">
   187              <:svg as |c|>
   188                <c.Area @data={{this.lineChartGapData}} />
   189              </:svg>
   190              <:after as |c|>
   191                <c.Tooltip class="is-snappy" as |series datum|>
   192                  <li>
   193                    <span class="label"><span class="color-swatch is-primary" />{{datum.formattedX}}</span>
   194                    <span class="value">{{datum.formattedY}}</span>
   195                  </li>
   196                </c.Tooltip>
   197              </:after>
   198            </LineChart>
   199          {{/if}}
   200        </div>
   201        `,
   202      context: {
   203        lineChartGapData: DelayedArray.create([
   204          { year: 2010, value: 10 },
   205          { year: 2011, value: 10 },
   206          { year: 2012, value: null },
   207          { year: 2013, value: 30 },
   208          { year: 2014, value: 50 },
   209          { year: 2015, value: 80 },
   210          { year: 2016, value: null },
   211          { year: 2017, value: 210 },
   212          { year: 2018, value: 340 },
   213        ]),
   214      },
   215    };
   216  };
   217  
   218  export let VerticalAnnotations = () => {
   219    return {
   220      template: hbs`
   221        <h5 class="title is-5">Line Chart data with annotations</h5>
   222        <div class="block" style="height:250px">
   223          {{#if (and this.data this.annotations)}}
   224            <LineChart
   225              class="with-annotations"
   226              @timeseries={{true}}
   227              @xProp="x"
   228              @yProp="y"
   229              @data={{this.data}}>
   230              <:svg as |c|>
   231                <c.Area @data={{this.data}} @annotationClick={{action (mut this.activeAnnotation)}} />
   232              </:svg>
   233              <:after as |c|>
   234                <c.VAnnotations
   235                  @annotations={{this.annotations}}
   236                  @annotationClick={{action (mut this.activeAnnotation)}}
   237                  @activeAnnotation={{this.activeAnnotation}} />
   238              </:after>
   239            </LineChart>
   240          {{/if}}
   241        </div>
   242        <p style="margin:2em 0; padding: 1em; background:#FFEEAC">{{this.activeAnnotation.info}}</p>
   243        <h5 class="title is-5">Line Chart data with staggered annotations</h5>
   244        <div class="block" style="height:150px; width:450px">
   245          {{#if (and this.data this.annotations)}}
   246            <LineChart
   247              class="with-annotations"
   248              @timeseries={{true}}
   249              @xProp="x"
   250              @yProp="y"
   251              @data={{this.data}}>
   252              <:svg as |c|>
   253                <c.Area @data={{this.data}} @annotationClick={{action (mut this.activeAnnotation)}} />
   254              </:svg>
   255              <:after as |c|>
   256                <c.VAnnotations
   257                  @annotations={{this.annotations}}
   258                  @annotationClick={{action (mut this.activeAnnotation)}}
   259                  @activeAnnotation={{this.activeAnnotation}} />
   260                <c.Tooltip class="is-snappy" as |series datum|>
   261                  <li>
   262                    <span class="label"><span class="color-swatch is-primary" />{{datum.formattedX}}</span>
   263                    <span class="value">{{datum.formattedY}}</span>
   264                  </li>
   265                </c.Tooltip>
   266              </:after>
   267            </LineChart>
   268          {{/if}}
   269        </div>
   270      `,
   271      context: {
   272        data: DelayedArray.create(
   273          new Array(180).fill(null).map((_, idx) => ({
   274            y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200,
   275            x: moment().add(idx, 'd').toDate(),
   276          }))
   277        ),
   278        annotations: [
   279          {
   280            x: moment().toDate(),
   281            type: 'info',
   282            info: 'Far left',
   283          },
   284          {
   285            x: moment()
   286              .add(90 / 4, 'd')
   287              .toDate(),
   288            type: 'error',
   289            info: 'This is the max of the sine curve',
   290          },
   291          {
   292            x: moment().add(89, 'd').toDate(),
   293            type: 'info',
   294            info: 'This is the end of the first period',
   295          },
   296          {
   297            x: moment().add(96, 'd').toDate(),
   298            type: 'info',
   299            info: 'A close annotation for staggering purposes',
   300          },
   301          {
   302            x: moment()
   303              .add((90 / 4) * 3, 'd')
   304              .toDate(),
   305            type: 'error',
   306            info: 'This is the min of the sine curve',
   307          },
   308          {
   309            x: moment().add(179, 'd').toDate(),
   310            type: 'info',
   311            info: 'Far right',
   312          },
   313        ],
   314      },
   315    };
   316  };
   317  
   318  export let HorizontalAnnotations = () => {
   319    return {
   320      template: hbs`
   321        <div class="block" style="height:250px">
   322          {{#if (and this.data this.annotations)}}
   323            <LineChart
   324              class="with-annotations"
   325              @timeseries={{true}}
   326              @xProp="x"
   327              @yProp="y"
   328              @data={{this.data}}>
   329              <:svg as |c|>
   330                <c.Area @data={{this.data}} @annotationClick={{action (mut this.activeAnnotation)}} />
   331              </:svg>
   332              <:after as |c|>
   333                <c.HAnnotations @annotations={{this.annotations}} @labelProp="info" />
   334              </:after>
   335            </LineChart>
   336          {{/if}}
   337        </div>
   338      `,
   339      context: {
   340        data: DelayedArray.create(
   341          new Array(180).fill(null).map((_, idx) => ({
   342            y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200,
   343            x: moment().add(idx, 'd').toDate(),
   344          }))
   345        ),
   346        annotations: [
   347          {
   348            y: 300,
   349            info: 'High',
   350          },
   351          {
   352            y: 100,
   353            info: 'Low',
   354          },
   355        ],
   356      },
   357    };
   358  };
   359  
   360  export let StepLine = () => {
   361    return {
   362      template: hbs`
   363        <h5 class="title is-5">Line Chart with a Step Line</h5>
   364        <div class="block" style="height:250px">
   365          {{#if this.data}}
   366            <LineChart
   367              @xProp="x"
   368              @yProp="y"
   369              @data={{this.data}}>
   370              <:svg as |c|>
   371                <c.Area @data={{this.data}} @curve="stepAfter" />
   372              </:svg>
   373              <:after as |c|>
   374                <c.Tooltip class="is-snappy" as |series datum|>
   375                  <li>
   376                    <span class="label"><span class="color-swatch is-primary" />{{datum.formattedX}}</span>
   377                    <span class="value">{{datum.formattedY}}</span>
   378                  </li>
   379                </c.Tooltip>
   380              </:after>
   381            </LineChart>
   382            <p>{{this.activeAnnotation.info}}</p>
   383          {{/if}}
   384        </div>
   385      `,
   386      context: {
   387        data: DelayedArray.create([
   388          { x: 1, y: 5 },
   389          { x: 2, y: 1 },
   390          { x: 3, y: 2 },
   391          { x: 4, y: 2 },
   392          { x: 5, y: 9 },
   393          { x: 6, y: 3 },
   394          { x: 7, y: 4 },
   395          { x: 8, y: 1 },
   396          { x: 9, y: 5 },
   397        ]),
   398      },
   399    };
   400  };
   401  
   402  export let MultiLine = () => ({
   403    template: hbs`
   404        <h5 class="title is-5">Multiple Lines on One Chart</h5>
   405        <div class="block" style="height:250px">
   406          {{#if this.data}}
   407            <LineChart
   408              @xProp="x"
   409              @yProp="y"
   410              @dataProp="data"
   411              @data={{this.data}}>
   412              <:svg as |c|>
   413                {{#each this.data as |series idx|}}
   414                  <c.Area @data={{series.data}} @colorScale="reds" @index={{idx}} />
   415                {{/each}}
   416              </:svg>
   417              <:after as |c|>
   418                <c.Tooltip class="is-snappy" as |series datum index|>
   419                  <li>
   420                    <span class="label"><span class="color-swatch swatch-reds swatch-reds-{{index}}" />{{series.name}}</span>
   421                    <span class="value">{{datum.formattedY}}</span>
   422                  </li>
   423                </c.Tooltip>
   424              </:after>
   425            </LineChart>
   426            <p>{{this.activeAnnotation.info}}</p>
   427          {{/if}}
   428        </div>
   429    `,
   430    context: {
   431      data: DelayedArray.create([
   432        {
   433          name: 'Series 1',
   434          data: [
   435            { x: 3, y: 7 },
   436            { x: 4, y: 5 },
   437            { x: 5, y: 8 },
   438            { x: 6, y: 9 },
   439            { x: 7, y: 10 },
   440            { x: 8, y: 8 },
   441            { x: 9, y: 6 },
   442          ],
   443        },
   444        {
   445          name: 'Series 2',
   446          data: [
   447            { x: 1, y: 5 },
   448            { x: 2, y: 1 },
   449            { x: 3, y: 2 },
   450            { x: 4, y: 2 },
   451            { x: 5, y: 9 },
   452            { x: 6, y: 3 },
   453            { x: 7, y: 4 },
   454          ],
   455        },
   456      ]),
   457    },
   458  });