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 });