@inb/oeb_visualizations 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -285,9 +285,11 @@ var script$1 = {
|
|
|
285
285
|
// sneak in (it would draw green and skew the average); treat it
|
|
286
286
|
// as a break, just like a null access_time.
|
|
287
287
|
if (data[i].access_time !== null && !this.isErrorCode(data[i].code)) {
|
|
288
|
-
// keep adding to subarray
|
|
288
|
+
// keep adding to subarray. Snap the x to the day centre so
|
|
289
|
+
// the online marker sits in the middle of its day, on the
|
|
290
|
+
// same grid as the offline/NA bars.
|
|
289
291
|
subarrayTime.push(data[i].access_time);
|
|
290
|
-
subarrayDate.push(data[i].date);
|
|
292
|
+
subarrayDate.push(this.dayCenter(data[i].date));
|
|
291
293
|
sum += data[i].access_time;
|
|
292
294
|
nonNullValues += 1;
|
|
293
295
|
} else {
|
|
@@ -420,29 +422,62 @@ var script$1 = {
|
|
|
420
422
|
const errorCodes = [400, 403, 404, 408, 500, 502, 503, 504];
|
|
421
423
|
return errorCodes.includes(code);
|
|
422
424
|
},
|
|
425
|
+
dayCenter(date) {
|
|
426
|
+
/*
|
|
427
|
+
Snaps a date to the centre (12:00) of its UTC calendar day, returned
|
|
428
|
+
as ms since epoch. The whole chart is a daily grid: null placeholders
|
|
429
|
+
arrive at 00:00Z and real probes mid-afternoon, so aligning every
|
|
430
|
+
point and every bar to the day centre keeps them on one grid. That is
|
|
431
|
+
what makes blocks sit centred on their day and prevents bars from
|
|
432
|
+
bleeding into a neighbouring day's measurement.
|
|
433
|
+
*/
|
|
434
|
+
const d = new Date(date);
|
|
435
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
436
|
+
return d.getTime() + 1000 * 3600 * 24 / 2;
|
|
437
|
+
},
|
|
438
|
+
computeDaySlots(data) {
|
|
439
|
+
/*
|
|
440
|
+
Returns, for every data point, the bar slot it should occupy: a full
|
|
441
|
+
calendar day centred on that day (see dayCenter). Consecutive
|
|
442
|
+
offline/NA days therefore tile into a single block, and because every
|
|
443
|
+
online point is snapped to the same daily grid a bar never overlaps a
|
|
444
|
+
measurement.
|
|
445
|
+
Arguments:
|
|
446
|
+
- data: array of objects with a "date" key
|
|
447
|
+
Returns an array (parallel to data) of objects with keys:
|
|
448
|
+
- center: slot centre (day centre), in ms since epoch
|
|
449
|
+
- width: slot width, in ms (one full day)
|
|
450
|
+
*/
|
|
451
|
+
const DAY = 1000 * 3600 * 24;
|
|
452
|
+
return data.map(item => ({
|
|
453
|
+
center: this.dayCenter(item.date),
|
|
454
|
+
width: DAY
|
|
455
|
+
}));
|
|
456
|
+
},
|
|
423
457
|
extractOfflineNADates(data) {
|
|
424
458
|
/*
|
|
425
|
-
This function extracts
|
|
426
|
-
Depending on the code, the server is offline or NA on
|
|
459
|
+
This function extracts the bar slots of points with no successful
|
|
460
|
+
measurement. Depending on the code, the server is offline or NA on
|
|
461
|
+
those dates.
|
|
427
462
|
Arguments:
|
|
428
463
|
- data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
-
|
|
432
|
-
- down: array of dates with code in errorCodes (server offline)
|
|
464
|
+
Returns an object with keys:
|
|
465
|
+
- NA: array of slots (see computeDaySlots) for code null (no information available)
|
|
466
|
+
- down: array of slots for code in errorCodes (server offline)
|
|
433
467
|
Classification is driven by the HTTP code, not by access_time
|
|
434
468
|
null-ness: an error response that happened to record an access_time
|
|
435
469
|
is still "offline", and a missing code is "no information available".
|
|
436
470
|
*/
|
|
471
|
+
const slots = this.computeDaySlots(data);
|
|
437
472
|
const resultNA = [];
|
|
438
473
|
const resultOffline = [];
|
|
439
474
|
for (let i = 0; i < data.length; i++) {
|
|
440
475
|
// no code at all -> grey "No information available"
|
|
441
476
|
if (data[i].code === null) {
|
|
442
|
-
resultNA.push(
|
|
477
|
+
resultNA.push(slots[i]);
|
|
443
478
|
// an error code -> red "Offline"
|
|
444
479
|
} else if (this.isErrorCode(data[i].code)) {
|
|
445
|
-
resultOffline.push(
|
|
480
|
+
resultOffline.push(slots[i]);
|
|
446
481
|
}
|
|
447
482
|
}
|
|
448
483
|
return {
|
|
@@ -454,10 +489,12 @@ var script$1 = {
|
|
|
454
489
|
/*
|
|
455
490
|
This function builds a bar trace.
|
|
456
491
|
Arguments:
|
|
457
|
-
- data: object with keys "dates" and "
|
|
458
|
-
- dates: array of dates
|
|
492
|
+
- data: object with keys "dates", "access_times", "colors" and "widths"
|
|
493
|
+
- dates: array of dates (slot centres, in ms)
|
|
459
494
|
- access_times: array of access_times
|
|
460
495
|
- colors: array of colors in rgba format (eg:"rgba(255, 153, 145,0.8)")
|
|
496
|
+
- widths: array of per-bar widths in ms, so each bar fills its
|
|
497
|
+
own time slot (see computeDaySlots) instead of a fixed day
|
|
461
498
|
- name: name of the trace
|
|
462
499
|
*/
|
|
463
500
|
const trace = {
|
|
@@ -472,35 +509,43 @@ var script$1 = {
|
|
|
472
509
|
showlegend: showlegend,
|
|
473
510
|
hoverinfo: hoverinfo,
|
|
474
511
|
hovertemplate: hovertemplate,
|
|
475
|
-
width:
|
|
512
|
+
width: data.widths
|
|
476
513
|
};
|
|
477
|
-
|
|
478
|
-
console.log(trace);
|
|
479
514
|
return trace;
|
|
480
515
|
},
|
|
481
|
-
buildBarTraces(
|
|
516
|
+
buildBarTraces(slots, color, label, group) {
|
|
482
517
|
/*
|
|
483
518
|
This function builds the series used to display the offline/NA bars.
|
|
484
|
-
For each
|
|
485
|
-
|
|
486
|
-
|
|
519
|
+
For each slot two stacked columns are created that together span the
|
|
520
|
+
whole plot height: a thin strong-coloured band sitting on the axis,
|
|
521
|
+
and a light-coloured column filling the rest of the height above it.
|
|
487
522
|
Arguments:
|
|
488
|
-
-
|
|
523
|
+
- slots: array of slots ({ center, width }), see computeDaySlots
|
|
489
524
|
- color: color of the bars
|
|
490
525
|
Returns array with offline and NA traces
|
|
491
526
|
*/
|
|
492
527
|
|
|
493
528
|
const colorStrong = `rgba(${color},.8)`;
|
|
494
529
|
const colorLight = `rgba(${color},.2)`;
|
|
530
|
+
const centers = slots.map(s => s.center);
|
|
531
|
+
const widths = slots.map(s => s.width);
|
|
532
|
+
|
|
533
|
+
// Total background height (keeps the previous y-axis extent). The
|
|
534
|
+
// strong colour is a thin band on the axis; the light colour fills
|
|
535
|
+
// the remaining height stacked on top of it.
|
|
536
|
+
const totalHeight = 2 + this.max_access_time * 1.1;
|
|
537
|
+
const baseHeight = totalHeight * 0.03;
|
|
495
538
|
const dataShort = {
|
|
496
|
-
dates:
|
|
497
|
-
access_times: Array(
|
|
498
|
-
colors: Array(
|
|
539
|
+
dates: centers,
|
|
540
|
+
access_times: Array(slots.length).fill(baseHeight),
|
|
541
|
+
colors: Array(slots.length).fill(colorStrong),
|
|
542
|
+
widths: widths
|
|
499
543
|
};
|
|
500
544
|
const dataTall = {
|
|
501
|
-
dates:
|
|
502
|
-
access_times: Array(
|
|
503
|
-
colors: Array(
|
|
545
|
+
dates: centers,
|
|
546
|
+
access_times: Array(slots.length).fill(totalHeight - baseHeight),
|
|
547
|
+
colors: Array(slots.length).fill(colorLight),
|
|
548
|
+
widths: widths
|
|
504
549
|
};
|
|
505
550
|
const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
|
|
506
551
|
const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
|
|
@@ -522,12 +567,10 @@ var script$1 = {
|
|
|
522
567
|
// Down arrays
|
|
523
568
|
if (arrays.down.length > 0) {
|
|
524
569
|
traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
|
|
525
|
-
console.log(arrays.down);
|
|
526
570
|
}
|
|
527
571
|
// NA arrays
|
|
528
572
|
if (arrays.NA.length > 0) {
|
|
529
573
|
traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
|
|
530
|
-
console.log(arrays.NA);
|
|
531
574
|
}
|
|
532
575
|
return traces;
|
|
533
576
|
},
|
|
@@ -578,7 +621,10 @@ var script$1 = {
|
|
|
578
621
|
console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
|
|
579
622
|
return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
|
|
580
623
|
} else {
|
|
581
|
-
|
|
624
|
+
// Anchor day ticks at the day centre (noon) so each label sits
|
|
625
|
+
// under the middle of its day block, aligned with the online dot
|
|
626
|
+
// (which is snapped to the same day centre).
|
|
627
|
+
return this.dayCenter(this.dataItems[0].date);
|
|
582
628
|
}
|
|
583
629
|
},
|
|
584
630
|
xaxisMode() {
|
|
@@ -589,11 +635,17 @@ var script$1 = {
|
|
|
589
635
|
}
|
|
590
636
|
},
|
|
591
637
|
xaxisRange() {
|
|
592
|
-
if (
|
|
593
|
-
return [this.dataItems[0], this.dataItems[this.dataItems.length - 1]];
|
|
594
|
-
} else {
|
|
638
|
+
if (this.xrange) {
|
|
595
639
|
return this.xrange;
|
|
596
640
|
}
|
|
641
|
+
// Span whole calendar days so the first and last day blocks (which
|
|
642
|
+
// are centred on their day, one full day wide) are fully visible.
|
|
643
|
+
const DAY = 1000 * 3600 * 24;
|
|
644
|
+
const firstDay = new Date(this.dataItems[0].date);
|
|
645
|
+
firstDay.setUTCHours(0, 0, 0, 0);
|
|
646
|
+
const lastDay = new Date(this.dataItems[this.dataItems.length - 1].date);
|
|
647
|
+
lastDay.setUTCHours(0, 0, 0, 0);
|
|
648
|
+
return [firstDay.getTime(), lastDay.getTime() + DAY];
|
|
597
649
|
},
|
|
598
650
|
monthTickVales() {
|
|
599
651
|
// First day of month of last date and previous five months
|
|
@@ -711,7 +763,7 @@ const __vue_inject_styles__$1 = undefined;
|
|
|
711
763
|
/* scoped */
|
|
712
764
|
const __vue_scope_id__$1 = undefined;
|
|
713
765
|
/* module identifier */
|
|
714
|
-
const __vue_module_identifier__$1 = "data-v-
|
|
766
|
+
const __vue_module_identifier__$1 = "data-v-bab9d544";
|
|
715
767
|
/* functional template */
|
|
716
768
|
const __vue_is_functional_template__$1 = false;
|
|
717
769
|
/* style inject */
|
|
@@ -289,9 +289,11 @@ var script$1 = {
|
|
|
289
289
|
// sneak in (it would draw green and skew the average); treat it
|
|
290
290
|
// as a break, just like a null access_time.
|
|
291
291
|
if (data[i].access_time !== null && !this.isErrorCode(data[i].code)) {
|
|
292
|
-
// keep adding to subarray
|
|
292
|
+
// keep adding to subarray. Snap the x to the day centre so
|
|
293
|
+
// the online marker sits in the middle of its day, on the
|
|
294
|
+
// same grid as the offline/NA bars.
|
|
293
295
|
subarrayTime.push(data[i].access_time);
|
|
294
|
-
subarrayDate.push(data[i].date);
|
|
296
|
+
subarrayDate.push(this.dayCenter(data[i].date));
|
|
295
297
|
sum += data[i].access_time;
|
|
296
298
|
nonNullValues += 1;
|
|
297
299
|
} else {
|
|
@@ -424,29 +426,62 @@ var script$1 = {
|
|
|
424
426
|
const errorCodes = [400, 403, 404, 408, 500, 502, 503, 504];
|
|
425
427
|
return errorCodes.includes(code);
|
|
426
428
|
},
|
|
429
|
+
dayCenter(date) {
|
|
430
|
+
/*
|
|
431
|
+
Snaps a date to the centre (12:00) of its UTC calendar day, returned
|
|
432
|
+
as ms since epoch. The whole chart is a daily grid: null placeholders
|
|
433
|
+
arrive at 00:00Z and real probes mid-afternoon, so aligning every
|
|
434
|
+
point and every bar to the day centre keeps them on one grid. That is
|
|
435
|
+
what makes blocks sit centred on their day and prevents bars from
|
|
436
|
+
bleeding into a neighbouring day's measurement.
|
|
437
|
+
*/
|
|
438
|
+
const d = new Date(date);
|
|
439
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
440
|
+
return d.getTime() + 1000 * 3600 * 24 / 2;
|
|
441
|
+
},
|
|
442
|
+
computeDaySlots(data) {
|
|
443
|
+
/*
|
|
444
|
+
Returns, for every data point, the bar slot it should occupy: a full
|
|
445
|
+
calendar day centred on that day (see dayCenter). Consecutive
|
|
446
|
+
offline/NA days therefore tile into a single block, and because every
|
|
447
|
+
online point is snapped to the same daily grid a bar never overlaps a
|
|
448
|
+
measurement.
|
|
449
|
+
Arguments:
|
|
450
|
+
- data: array of objects with a "date" key
|
|
451
|
+
Returns an array (parallel to data) of objects with keys:
|
|
452
|
+
- center: slot centre (day centre), in ms since epoch
|
|
453
|
+
- width: slot width, in ms (one full day)
|
|
454
|
+
*/
|
|
455
|
+
const DAY = 1000 * 3600 * 24;
|
|
456
|
+
return data.map(item => ({
|
|
457
|
+
center: this.dayCenter(item.date),
|
|
458
|
+
width: DAY
|
|
459
|
+
}));
|
|
460
|
+
},
|
|
427
461
|
extractOfflineNADates(data) {
|
|
428
462
|
/*
|
|
429
|
-
This function extracts
|
|
430
|
-
Depending on the code, the server is offline or NA on
|
|
463
|
+
This function extracts the bar slots of points with no successful
|
|
464
|
+
measurement. Depending on the code, the server is offline or NA on
|
|
465
|
+
those dates.
|
|
431
466
|
Arguments:
|
|
432
467
|
- data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
-
|
|
436
|
-
- down: array of dates with code in errorCodes (server offline)
|
|
468
|
+
Returns an object with keys:
|
|
469
|
+
- NA: array of slots (see computeDaySlots) for code null (no information available)
|
|
470
|
+
- down: array of slots for code in errorCodes (server offline)
|
|
437
471
|
Classification is driven by the HTTP code, not by access_time
|
|
438
472
|
null-ness: an error response that happened to record an access_time
|
|
439
473
|
is still "offline", and a missing code is "no information available".
|
|
440
474
|
*/
|
|
475
|
+
const slots = this.computeDaySlots(data);
|
|
441
476
|
const resultNA = [];
|
|
442
477
|
const resultOffline = [];
|
|
443
478
|
for (let i = 0; i < data.length; i++) {
|
|
444
479
|
// no code at all -> grey "No information available"
|
|
445
480
|
if (data[i].code === null) {
|
|
446
|
-
resultNA.push(
|
|
481
|
+
resultNA.push(slots[i]);
|
|
447
482
|
// an error code -> red "Offline"
|
|
448
483
|
} else if (this.isErrorCode(data[i].code)) {
|
|
449
|
-
resultOffline.push(
|
|
484
|
+
resultOffline.push(slots[i]);
|
|
450
485
|
}
|
|
451
486
|
}
|
|
452
487
|
return {
|
|
@@ -458,10 +493,12 @@ var script$1 = {
|
|
|
458
493
|
/*
|
|
459
494
|
This function builds a bar trace.
|
|
460
495
|
Arguments:
|
|
461
|
-
- data: object with keys "dates" and "
|
|
462
|
-
- dates: array of dates
|
|
496
|
+
- data: object with keys "dates", "access_times", "colors" and "widths"
|
|
497
|
+
- dates: array of dates (slot centres, in ms)
|
|
463
498
|
- access_times: array of access_times
|
|
464
499
|
- colors: array of colors in rgba format (eg:"rgba(255, 153, 145,0.8)")
|
|
500
|
+
- widths: array of per-bar widths in ms, so each bar fills its
|
|
501
|
+
own time slot (see computeDaySlots) instead of a fixed day
|
|
465
502
|
- name: name of the trace
|
|
466
503
|
*/
|
|
467
504
|
const trace = {
|
|
@@ -476,35 +513,43 @@ var script$1 = {
|
|
|
476
513
|
showlegend: showlegend,
|
|
477
514
|
hoverinfo: hoverinfo,
|
|
478
515
|
hovertemplate: hovertemplate,
|
|
479
|
-
width:
|
|
516
|
+
width: data.widths
|
|
480
517
|
};
|
|
481
|
-
|
|
482
|
-
console.log(trace);
|
|
483
518
|
return trace;
|
|
484
519
|
},
|
|
485
|
-
buildBarTraces(
|
|
520
|
+
buildBarTraces(slots, color, label, group) {
|
|
486
521
|
/*
|
|
487
522
|
This function builds the series used to display the offline/NA bars.
|
|
488
|
-
For each
|
|
489
|
-
|
|
490
|
-
|
|
523
|
+
For each slot two stacked columns are created that together span the
|
|
524
|
+
whole plot height: a thin strong-coloured band sitting on the axis,
|
|
525
|
+
and a light-coloured column filling the rest of the height above it.
|
|
491
526
|
Arguments:
|
|
492
|
-
-
|
|
527
|
+
- slots: array of slots ({ center, width }), see computeDaySlots
|
|
493
528
|
- color: color of the bars
|
|
494
529
|
Returns array with offline and NA traces
|
|
495
530
|
*/
|
|
496
531
|
|
|
497
532
|
const colorStrong = `rgba(${color},.8)`;
|
|
498
533
|
const colorLight = `rgba(${color},.2)`;
|
|
534
|
+
const centers = slots.map(s => s.center);
|
|
535
|
+
const widths = slots.map(s => s.width);
|
|
536
|
+
|
|
537
|
+
// Total background height (keeps the previous y-axis extent). The
|
|
538
|
+
// strong colour is a thin band on the axis; the light colour fills
|
|
539
|
+
// the remaining height stacked on top of it.
|
|
540
|
+
const totalHeight = 2 + this.max_access_time * 1.1;
|
|
541
|
+
const baseHeight = totalHeight * 0.03;
|
|
499
542
|
const dataShort = {
|
|
500
|
-
dates:
|
|
501
|
-
access_times: Array(
|
|
502
|
-
colors: Array(
|
|
543
|
+
dates: centers,
|
|
544
|
+
access_times: Array(slots.length).fill(baseHeight),
|
|
545
|
+
colors: Array(slots.length).fill(colorStrong),
|
|
546
|
+
widths: widths
|
|
503
547
|
};
|
|
504
548
|
const dataTall = {
|
|
505
|
-
dates:
|
|
506
|
-
access_times: Array(
|
|
507
|
-
colors: Array(
|
|
549
|
+
dates: centers,
|
|
550
|
+
access_times: Array(slots.length).fill(totalHeight - baseHeight),
|
|
551
|
+
colors: Array(slots.length).fill(colorLight),
|
|
552
|
+
widths: widths
|
|
508
553
|
};
|
|
509
554
|
const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
|
|
510
555
|
const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
|
|
@@ -526,12 +571,10 @@ var script$1 = {
|
|
|
526
571
|
// Down arrays
|
|
527
572
|
if (arrays.down.length > 0) {
|
|
528
573
|
traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
|
|
529
|
-
console.log(arrays.down);
|
|
530
574
|
}
|
|
531
575
|
// NA arrays
|
|
532
576
|
if (arrays.NA.length > 0) {
|
|
533
577
|
traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
|
|
534
|
-
console.log(arrays.NA);
|
|
535
578
|
}
|
|
536
579
|
return traces;
|
|
537
580
|
},
|
|
@@ -582,7 +625,10 @@ var script$1 = {
|
|
|
582
625
|
console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
|
|
583
626
|
return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
|
|
584
627
|
} else {
|
|
585
|
-
|
|
628
|
+
// Anchor day ticks at the day centre (noon) so each label sits
|
|
629
|
+
// under the middle of its day block, aligned with the online dot
|
|
630
|
+
// (which is snapped to the same day centre).
|
|
631
|
+
return this.dayCenter(this.dataItems[0].date);
|
|
586
632
|
}
|
|
587
633
|
},
|
|
588
634
|
xaxisMode() {
|
|
@@ -593,11 +639,17 @@ var script$1 = {
|
|
|
593
639
|
}
|
|
594
640
|
},
|
|
595
641
|
xaxisRange() {
|
|
596
|
-
if (
|
|
597
|
-
return [this.dataItems[0], this.dataItems[this.dataItems.length - 1]];
|
|
598
|
-
} else {
|
|
642
|
+
if (this.xrange) {
|
|
599
643
|
return this.xrange;
|
|
600
644
|
}
|
|
645
|
+
// Span whole calendar days so the first and last day blocks (which
|
|
646
|
+
// are centred on their day, one full day wide) are fully visible.
|
|
647
|
+
const DAY = 1000 * 3600 * 24;
|
|
648
|
+
const firstDay = new Date(this.dataItems[0].date);
|
|
649
|
+
firstDay.setUTCHours(0, 0, 0, 0);
|
|
650
|
+
const lastDay = new Date(this.dataItems[this.dataItems.length - 1].date);
|
|
651
|
+
lastDay.setUTCHours(0, 0, 0, 0);
|
|
652
|
+
return [firstDay.getTime(), lastDay.getTime() + DAY];
|
|
601
653
|
},
|
|
602
654
|
monthTickVales() {
|
|
603
655
|
// First day of month of last date and previous five months
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var oeb_visualizations=function(e,t){"use strict";function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);function a(e){return Math.random().toString(36).replace("0.",e||"")}var r=function(e,t,i,s,a,r,o,n,l,d){"boolean"!=typeof o&&(l=n,n=o,o=!1);var c,h="function"==typeof i?i.options:i;if(e&&e.render&&(h.render=e.render,h.staticRenderFns=e.staticRenderFns,h._compiled=!0,a&&(h.functional=!0)),s&&(h._scopeId=s),r?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),t&&t.call(this,l(e)),e&&e._registeredComponents&&e._registeredComponents.add(r)},h._ssrRegister=c):t&&(c=o?function(){t.call(this,d(this.$root.$options.shadowRoot))}:function(e){t.call(this,n(e))}),c)if(h.functional){var u=h.render;h.render=function(e,t){return c.call(t),u(e,t)}}else{var m=h.beforeCreate;h.beforeCreate=m?[].concat(m,c):[c]}return i};var o=r({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"accessibilityPlot",data:()=>({divId:a("acc_plot_"),max_access_time:0,config:{displaylogo:!1,responsive:!0,modeBarButtonsToRemove:["lasso"]}}),props:{xrange:{type:Array,required:!1},dtick:{type:Number,required:!1,default:864e5},xaxisTitle:{type:String,required:!1,default:"Date"},yaxisTitle:{type:String,required:!1,default:"Access time (ms)"},colorOnline:{type:String,required:!1,default:"111, 176, 129"},colorOffline:{type:String,required:!1,default:"255, 153, 145"},colorNA:{type:String,required:!1,default:"204,204,204"},height:{type:Number,required:!1,default:350},width:{type:Number,required:!1,default:700},week:{type:Boolean,required:!1,default:!1},sixMonths:{type:Boolean,required:!1,default:!1},dataItems:{type:Array,required:!0,validator:function(e){for(let t=0;t<e.length;t++){e[t].hasOwnProperty("access_time")?e[t].hasOwnProperty("date")?e[t].hasOwnProperty("code")||console.error(`[oeb-visualizations warn] code key is missing in dataItems prop item (at position ${t})`):console.error(`[oeb-visualizations warn] date key is missing in dataItems prop item (at position ${t})`):console.error(`[oeb-visualizations warn] access_time key is missing in dataItems prop item (at position ${t})`),null!==e[t].access_time&&"number"!=typeof e[t].access_time&&console.error(`[oeb-visualizations warn] access_time must be null or a number in dataItems prop item (at position ${t})`),null!==e[t].code&&"number"!=typeof e[t].code&&console.error(`[oeb-visualizations warn] code must be null or a number in dataItems prop item (at position ${t})`);const i="string"==typeof e[t].date&&!isNaN(Date.parse(e[t].date)),s="number"==typeof e[t].date;i||s||(console.error(`[oeb-visualizations warn] date must be a string containing a date or a number in dataItems prop item (at position ${t})`),console.error(`[oeb-visualizations warn] date type is ${typeof e[t].date} and the value is ${e[t].date}`)),null===e[t].date&&console.error(`[oeb-visualizations warn] date cannot be null in dataItems prop item (at position ${t})`)}return!0}}},mounted(){const e=this.dataItems.map((e=>e.access_time)).filter((e=>"number"==typeof e&&!isNaN(e)));this.max_access_time=e.length?Math.max(...e):100;var t=this.buildOnlineTraces(this.dataItems);t=t.concat(this.buildOfflineNATraces(this.dataItems));const i={bargap:0,barmode:"stack",showlegend:!0,autosize:!0,height:this.height,width:this.width,margin:{l:50,r:50,b:50,t:20,pad:4},xaxis:{type:"date",ticklabelmode:this.xaxisMode(),title:this.xaxisTitle,font:{size:10},tickfont:{size:10},showgrid:!!this.sixMonths,griddash:"dot",gridwidth:1,gridcolor:"#d9d7d7",showspikes:!0,spikedash:"4px",spikethickness:1,tick0:this.xaxisTickZero(),dtick:this.xaxisTickD(),tickangle:this.xaxisTickAngle(),tickformat:this.xaxisTickFormat(),tickvals:this.sixMonths?this.monthTickVales():null,range:this.xaxisRange()},yaxis:{title:this.yaxisTitle,titlefont:{size:10},tickfont:{size:10}},template:"plotly_white",legend:{orientation:"h",yanchor:"bottom",y:-.5,xanchor:"left",x:.05,font:{size:8}},hoverlabel:{bgcolor:"#FFF"},hovermode:"closest"};console.log(this.divId),s.default.newPlot(this.divId,t,i,this.config)},methods:{generateColor(e,t){let i=[];for(let s=0;s<30;s++)switch(e[s]){case"up":i.push(`rgba(${this.colorOnline},0)`);break;case"down":i.push(`rgba(${this.colorOffline},${t})`);break;case"NA":i.push(`rgba(${this.colorNA},${t})`)}return i},extractSubarraysBetweenNullValues(e){var t={access_time:[],date:[],average_access_time:0},i=[],s=[],a=0,r=0;for(let o=0;o<e.length;o++)null===e[o].access_time||this.isErrorCode(e[o].code)?i.length>0&&(t.access_time.push(i),t.date.push(s),i=[],s=[]):(i.push(e[o].access_time),s.push(e[o].date),a+=e[o].access_time,r+=1);return t.access_time.push(i),t.date.push(s),t.average_access_time=a/r,t},buildAccessTimeTraces(e){var t=[];for(let i=0;i<e.access_time.length;i++){const s=e.access_time[i],a={x:e.date[i],y:s,name:"Online",legendgroup:"up",showlegend:0===i,mode:"markers+lines",type:"scatter",fill:"tozeroy",fillcolor:`rgba(${this.colorOnline},.2)`,connectgaps:!1,line:{color:`rgba(${this.colorOnline},.8)`,width:1.5},marker:{size:5},hovertemplate:"<b>Online</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>",hoveron:"points+fills"};t.push(a)}return t},buildAvgAccessTimeTrace(e){const t=new Date(this.dataItems[0].date);this.week?t.setDate(t.getDate()-.3):t.setDate(t.getDate()-1);const i=new Date(this.dataItems[this.dataItems.length-1].date);this.week?i.setDate(i.getDate()+.3):i.setDate(i.getDate()+1);return{x:[t,i],y:[e,e],name:"Average access time",showlegend:!0,mode:"lines",type:"scatter",line:{color:`rgba(${this.colorOnline},.6)`,width:1.5,dash:"4px"},marker:{size:5},hovertemplate:"<b>Average access time</b><br>%{y:.2f} ms <extra></extra>"}},buildOnlineTraces(e){const t=this.extractSubarraysBetweenNullValues(e);var i=this.buildAccessTimeTraces(t);return i.push(this.buildAvgAccessTimeTrace(t.average_access_time)),i},isErrorCode:e=>[400,403,404,408,500,502,503,504].includes(e),extractOfflineNADates(e){const t=[],i=[];for(let s=0;s<e.length;s++)null===e[s].code?t.push(e[s].date):this.isErrorCode(e[s].code)&&i.push(e[s].date);return{NA:t,down:i}},barTrace(e,t,i,s,a,r){const o={x:e.dates,y:e.access_times,marker:{color:e.colors},name:t,type:"bar",legendgroup:r,showlegend:i,hoverinfo:s,hovertemplate:a,width:864e5};return console.log(o),o},buildBarTraces(e,t,i,s){const a=`rgba(${t},.8)`,r=`rgba(${t},.2)`,o={dates:e,access_times:Array(e.length).fill(2),colors:Array(e.length).fill(a)},n={dates:e,access_times:Array(e.length).fill(1.1*this.max_access_time),colors:Array(e.length).fill(r)},l=`<b>${i}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;return[this.barTrace(o,i,!1,"skip","",s),this.barTrace(n,i,!0,"all",l,s)]},buildOfflineNATraces(e){var t=[];const i=this.extractOfflineNADates(e);return i.down.length>0&&(t=t.concat(this.buildBarTraces(i.down,this.colorOffline,"Offline","down")),console.log(i.down)),i.NA.length>0&&(t=t.concat(this.buildBarTraces(i.NA,this.colorNA,"No information available","na")),console.log(i.NA)),t},xaxisTickFormat(){return this.week?"%A<br>%d %b":(this.sixMonths,"%d %b")},xaxisTickAngle(){return this.week?0:(this.sixMonths,45)},xaxisTickD(){return!0===this.sixMonths?"M1":this.dtick},xaxisTickZero(){if(!0===this.sixMonths){console.log("zero six months ago");const e=new Date(this.dataItems[this.dataItems.length-1].date);return console.log(e),console.log("six months ago: "+new Date(e.setMonth(e.getMonth()-6))),new Date(e.setMonth(e.getMonth()-6))}return this.dataItems[0]},xaxisMode(){return!0===this.sixMonths?"period":"instant"},xaxisRange(){return this.xrange?this.xrange:[this.dataItems[0],this.dataItems[this.dataItems.length-1]]},monthTickVales(){const e=new Date(this.dataItems[this.dataItems.length-1].date),t=e.getMonth(),i=e.getFullYear(),s=[];for(let e=0;e<6;e++)s.push(new Date(i,t-e,1));return s}}},undefined,!1,undefined,void 0,void 0);var n=r({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"citationsPlot",data:()=>({divId:a("cit_plot_")}),props:{dataTraces:{type:Array,required:!0},stack:{type:Boolean,required:!1,default:!1},colors:{type:Array,required:!1,default:()=>["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd"]},height:{type:Number,required:!1,default:400},showlegend:{type:Boolean,required:!1,default:!0},title:{type:String,required:!1,default:""},xaxisTitle:{type:String,required:!1,default:"Year"},yaxisTitle:{type:String,required:!1,default:"Number of citations"},darkMode:{type:Boolean,required:!1,default:!1}},mounted(){const e=this.buildTraces(),t={showlegend:this.showlegend,autosize:!0,height:this.height,margin:{l:50,r:50,b:70,t:50,pad:4},xaxis:{title:this.xaxisTitle,font:{size:10},tickfont:{size:10},tickmode:"linear",color:this.darkMode?"white":"black"},yaxis:{title:this.yaxisTitle,titlefont:{size:10},tickfont:{size:10},font:{size:10},color:this.darkMode?"white":"black"},legend:{orientation:"h",yanchor:"bottom",y:1.02,xanchor:"right",x:1,font:{size:8,color:this.darkMode?"white":"black"}},hoverlabel:{color:this.darkMode?"white":"black"},hovermode:this.stack?"x unified":"closest",hoverdistance:70,plot_bgcolor:this.darkMode?"rgb(38, 50, 56)":"white",paper_bgcolor:this.darkMode?"rgb(38, 50, 56)":"white"};s.default.newPlot(this.divId,e,t)},methods:{buildTraces(){const e=[];for(let t=0;t<this.dataTraces.length;t++){const i={x:this.dataTraces[t].data.map((e=>e.year)),y:this.dataTraces[t].data.map((e=>e.citations)),mode:"lines+markers",name:this.dataTraces[t].label,hovertemplate:this.hoverTemplate(),marker:{size:5},line:{color:this.colors[t],width:1.8},stackgroup:this.stack?"one":null};e.push(i)}return e},hoverTemplate(){return this.stack?"%{y} citations <extra></extra>":"%{y} citations in %{x} <extra></extra>"}}},undefined,!1,undefined,void 0,void 0),l=Object.freeze({__proto__:null,accessibilityPlot:o,citationsPlot:n});const d=function(e){d.installed||(d.installed=!0,Object.entries(l).forEach((([t,i])=>{e.component(t,i)})))},c={install:d};{let e=null;"undefined"!=typeof window?e=window.Vue:"undefined"!=typeof global&&(e=global.Vue),e&&e.use(c)}return e.accessibilityPlot=o,e.citationsPlot=n,e.default=c,Object.defineProperty(e,"__esModule",{value:!0}),e}({},Plotly);
|
|
1
|
+
var oeb_visualizations=function(e,t){"use strict";function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);function a(e){return Math.random().toString(36).replace("0.",e||"")}var r=function(e,t,i,s,a,r,o,n,l,d){"boolean"!=typeof o&&(l=n,n=o,o=!1);var c,h="function"==typeof i?i.options:i;if(e&&e.render&&(h.render=e.render,h.staticRenderFns=e.staticRenderFns,h._compiled=!0,a&&(h.functional=!0)),s&&(h._scopeId=s),r?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),t&&t.call(this,l(e)),e&&e._registeredComponents&&e._registeredComponents.add(r)},h._ssrRegister=c):t&&(c=o?function(){t.call(this,d(this.$root.$options.shadowRoot))}:function(e){t.call(this,n(e))}),c)if(h.functional){var u=h.render;h.render=function(e,t){return c.call(t),u(e,t)}}else{var m=h.beforeCreate;h.beforeCreate=m?[].concat(m,c):[c]}return i};var o=r({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"accessibilityPlot",data:()=>({divId:a("acc_plot_"),max_access_time:0,config:{displaylogo:!1,responsive:!0,modeBarButtonsToRemove:["lasso"]}}),props:{xrange:{type:Array,required:!1},dtick:{type:Number,required:!1,default:864e5},xaxisTitle:{type:String,required:!1,default:"Date"},yaxisTitle:{type:String,required:!1,default:"Access time (ms)"},colorOnline:{type:String,required:!1,default:"111, 176, 129"},colorOffline:{type:String,required:!1,default:"255, 153, 145"},colorNA:{type:String,required:!1,default:"204,204,204"},height:{type:Number,required:!1,default:350},width:{type:Number,required:!1,default:700},week:{type:Boolean,required:!1,default:!1},sixMonths:{type:Boolean,required:!1,default:!1},dataItems:{type:Array,required:!0,validator:function(e){for(let t=0;t<e.length;t++){e[t].hasOwnProperty("access_time")?e[t].hasOwnProperty("date")?e[t].hasOwnProperty("code")||console.error(`[oeb-visualizations warn] code key is missing in dataItems prop item (at position ${t})`):console.error(`[oeb-visualizations warn] date key is missing in dataItems prop item (at position ${t})`):console.error(`[oeb-visualizations warn] access_time key is missing in dataItems prop item (at position ${t})`),null!==e[t].access_time&&"number"!=typeof e[t].access_time&&console.error(`[oeb-visualizations warn] access_time must be null or a number in dataItems prop item (at position ${t})`),null!==e[t].code&&"number"!=typeof e[t].code&&console.error(`[oeb-visualizations warn] code must be null or a number in dataItems prop item (at position ${t})`);const i="string"==typeof e[t].date&&!isNaN(Date.parse(e[t].date)),s="number"==typeof e[t].date;i||s||(console.error(`[oeb-visualizations warn] date must be a string containing a date or a number in dataItems prop item (at position ${t})`),console.error(`[oeb-visualizations warn] date type is ${typeof e[t].date} and the value is ${e[t].date}`)),null===e[t].date&&console.error(`[oeb-visualizations warn] date cannot be null in dataItems prop item (at position ${t})`)}return!0}}},mounted(){const e=this.dataItems.map((e=>e.access_time)).filter((e=>"number"==typeof e&&!isNaN(e)));this.max_access_time=e.length?Math.max(...e):100;var t=this.buildOnlineTraces(this.dataItems);t=t.concat(this.buildOfflineNATraces(this.dataItems));const i={bargap:0,barmode:"stack",showlegend:!0,autosize:!0,height:this.height,width:this.width,margin:{l:50,r:50,b:50,t:20,pad:4},xaxis:{type:"date",ticklabelmode:this.xaxisMode(),title:this.xaxisTitle,font:{size:10},tickfont:{size:10},showgrid:!!this.sixMonths,griddash:"dot",gridwidth:1,gridcolor:"#d9d7d7",showspikes:!0,spikedash:"4px",spikethickness:1,tick0:this.xaxisTickZero(),dtick:this.xaxisTickD(),tickangle:this.xaxisTickAngle(),tickformat:this.xaxisTickFormat(),tickvals:this.sixMonths?this.monthTickVales():null,range:this.xaxisRange()},yaxis:{title:this.yaxisTitle,titlefont:{size:10},tickfont:{size:10}},template:"plotly_white",legend:{orientation:"h",yanchor:"bottom",y:-.5,xanchor:"left",x:.05,font:{size:8}},hoverlabel:{bgcolor:"#FFF"},hovermode:"closest"};console.log(this.divId),s.default.newPlot(this.divId,t,i,this.config)},methods:{generateColor(e,t){let i=[];for(let s=0;s<30;s++)switch(e[s]){case"up":i.push(`rgba(${this.colorOnline},0)`);break;case"down":i.push(`rgba(${this.colorOffline},${t})`);break;case"NA":i.push(`rgba(${this.colorNA},${t})`)}return i},extractSubarraysBetweenNullValues(e){var t={access_time:[],date:[],average_access_time:0},i=[],s=[],a=0,r=0;for(let o=0;o<e.length;o++)null===e[o].access_time||this.isErrorCode(e[o].code)?i.length>0&&(t.access_time.push(i),t.date.push(s),i=[],s=[]):(i.push(e[o].access_time),s.push(this.dayCenter(e[o].date)),a+=e[o].access_time,r+=1);return t.access_time.push(i),t.date.push(s),t.average_access_time=a/r,t},buildAccessTimeTraces(e){var t=[];for(let i=0;i<e.access_time.length;i++){const s=e.access_time[i],a={x:e.date[i],y:s,name:"Online",legendgroup:"up",showlegend:0===i,mode:"markers+lines",type:"scatter",fill:"tozeroy",fillcolor:`rgba(${this.colorOnline},.2)`,connectgaps:!1,line:{color:`rgba(${this.colorOnline},.8)`,width:1.5},marker:{size:5},hovertemplate:"<b>Online</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>",hoveron:"points+fills"};t.push(a)}return t},buildAvgAccessTimeTrace(e){const t=new Date(this.dataItems[0].date);this.week?t.setDate(t.getDate()-.3):t.setDate(t.getDate()-1);const i=new Date(this.dataItems[this.dataItems.length-1].date);this.week?i.setDate(i.getDate()+.3):i.setDate(i.getDate()+1);return{x:[t,i],y:[e,e],name:"Average access time",showlegend:!0,mode:"lines",type:"scatter",line:{color:`rgba(${this.colorOnline},.6)`,width:1.5,dash:"4px"},marker:{size:5},hovertemplate:"<b>Average access time</b><br>%{y:.2f} ms <extra></extra>"}},buildOnlineTraces(e){const t=this.extractSubarraysBetweenNullValues(e);var i=this.buildAccessTimeTraces(t);return i.push(this.buildAvgAccessTimeTrace(t.average_access_time)),i},isErrorCode:e=>[400,403,404,408,500,502,503,504].includes(e),dayCenter(e){const t=new Date(e);return t.setUTCHours(0,0,0,0),t.getTime()+432e5},computeDaySlots(e){return e.map((e=>({center:this.dayCenter(e.date),width:864e5})))},extractOfflineNADates(e){const t=this.computeDaySlots(e),i=[],s=[];for(let a=0;a<e.length;a++)null===e[a].code?i.push(t[a]):this.isErrorCode(e[a].code)&&s.push(t[a]);return{NA:i,down:s}},barTrace:(e,t,i,s,a,r)=>({x:e.dates,y:e.access_times,marker:{color:e.colors},name:t,type:"bar",legendgroup:r,showlegend:i,hoverinfo:s,hovertemplate:a,width:e.widths}),buildBarTraces(e,t,i,s){const a=`rgba(${t},.8)`,r=`rgba(${t},.2)`,o=e.map((e=>e.center)),n=e.map((e=>e.width)),l=2+1.1*this.max_access_time,d=.03*l,c={dates:o,access_times:Array(e.length).fill(d),colors:Array(e.length).fill(a),widths:n},h={dates:o,access_times:Array(e.length).fill(l-d),colors:Array(e.length).fill(r),widths:n},u=`<b>${i}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;return[this.barTrace(c,i,!1,"skip","",s),this.barTrace(h,i,!0,"all",u,s)]},buildOfflineNATraces(e){var t=[];const i=this.extractOfflineNADates(e);return i.down.length>0&&(t=t.concat(this.buildBarTraces(i.down,this.colorOffline,"Offline","down"))),i.NA.length>0&&(t=t.concat(this.buildBarTraces(i.NA,this.colorNA,"No information available","na"))),t},xaxisTickFormat(){return this.week?"%A<br>%d %b":(this.sixMonths,"%d %b")},xaxisTickAngle(){return this.week?0:(this.sixMonths,45)},xaxisTickD(){return!0===this.sixMonths?"M1":this.dtick},xaxisTickZero(){if(!0===this.sixMonths){console.log("zero six months ago");const e=new Date(this.dataItems[this.dataItems.length-1].date);return console.log(e),console.log("six months ago: "+new Date(e.setMonth(e.getMonth()-6))),new Date(e.setMonth(e.getMonth()-6))}return this.dayCenter(this.dataItems[0].date)},xaxisMode(){return!0===this.sixMonths?"period":"instant"},xaxisRange(){if(this.xrange)return this.xrange;const e=new Date(this.dataItems[0].date);e.setUTCHours(0,0,0,0);const t=new Date(this.dataItems[this.dataItems.length-1].date);return t.setUTCHours(0,0,0,0),[e.getTime(),t.getTime()+864e5]},monthTickVales(){const e=new Date(this.dataItems[this.dataItems.length-1].date),t=e.getMonth(),i=e.getFullYear(),s=[];for(let e=0;e<6;e++)s.push(new Date(i,t-e,1));return s}}},undefined,!1,undefined,void 0,void 0);var n=r({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"citationsPlot",data:()=>({divId:a("cit_plot_")}),props:{dataTraces:{type:Array,required:!0},stack:{type:Boolean,required:!1,default:!1},colors:{type:Array,required:!1,default:()=>["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd"]},height:{type:Number,required:!1,default:400},showlegend:{type:Boolean,required:!1,default:!0},title:{type:String,required:!1,default:""},xaxisTitle:{type:String,required:!1,default:"Year"},yaxisTitle:{type:String,required:!1,default:"Number of citations"},darkMode:{type:Boolean,required:!1,default:!1}},mounted(){const e=this.buildTraces(),t={showlegend:this.showlegend,autosize:!0,height:this.height,margin:{l:50,r:50,b:70,t:50,pad:4},xaxis:{title:this.xaxisTitle,font:{size:10},tickfont:{size:10},tickmode:"linear",color:this.darkMode?"white":"black"},yaxis:{title:this.yaxisTitle,titlefont:{size:10},tickfont:{size:10},font:{size:10},color:this.darkMode?"white":"black"},legend:{orientation:"h",yanchor:"bottom",y:1.02,xanchor:"right",x:1,font:{size:8,color:this.darkMode?"white":"black"}},hoverlabel:{color:this.darkMode?"white":"black"},hovermode:this.stack?"x unified":"closest",hoverdistance:70,plot_bgcolor:this.darkMode?"rgb(38, 50, 56)":"white",paper_bgcolor:this.darkMode?"rgb(38, 50, 56)":"white"};s.default.newPlot(this.divId,e,t)},methods:{buildTraces(){const e=[];for(let t=0;t<this.dataTraces.length;t++){const i={x:this.dataTraces[t].data.map((e=>e.year)),y:this.dataTraces[t].data.map((e=>e.citations)),mode:"lines+markers",name:this.dataTraces[t].label,hovertemplate:this.hoverTemplate(),marker:{size:5},line:{color:this.colors[t],width:1.8},stackgroup:this.stack?"one":null};e.push(i)}return e},hoverTemplate(){return this.stack?"%{y} citations <extra></extra>":"%{y} citations in %{x} <extra></extra>"}}},undefined,!1,undefined,void 0,void 0),l=Object.freeze({__proto__:null,accessibilityPlot:o,citationsPlot:n});const d=function(e){d.installed||(d.installed=!0,Object.entries(l).forEach((([t,i])=>{e.component(t,i)})))},c={install:d};{let e=null;"undefined"!=typeof window?e=window.Vue:"undefined"!=typeof global&&(e=global.Vue),e&&e.use(c)}return e.accessibilityPlot=o,e.citationsPlot=n,e.default=c,Object.defineProperty(e,"__esModule",{value:!0}),e}({},Plotly);
|
|
@@ -285,9 +285,11 @@ var script$1 = {
|
|
|
285
285
|
// sneak in (it would draw green and skew the average); treat it
|
|
286
286
|
// as a break, just like a null access_time.
|
|
287
287
|
if (data[i].access_time !== null && !this.isErrorCode(data[i].code)) {
|
|
288
|
-
// keep adding to subarray
|
|
288
|
+
// keep adding to subarray. Snap the x to the day centre so
|
|
289
|
+
// the online marker sits in the middle of its day, on the
|
|
290
|
+
// same grid as the offline/NA bars.
|
|
289
291
|
subarrayTime.push(data[i].access_time);
|
|
290
|
-
subarrayDate.push(data[i].date);
|
|
292
|
+
subarrayDate.push(this.dayCenter(data[i].date));
|
|
291
293
|
sum += data[i].access_time;
|
|
292
294
|
nonNullValues += 1;
|
|
293
295
|
} else {
|
|
@@ -420,29 +422,62 @@ var script$1 = {
|
|
|
420
422
|
const errorCodes = [400, 403, 404, 408, 500, 502, 503, 504];
|
|
421
423
|
return errorCodes.includes(code);
|
|
422
424
|
},
|
|
425
|
+
dayCenter(date) {
|
|
426
|
+
/*
|
|
427
|
+
Snaps a date to the centre (12:00) of its UTC calendar day, returned
|
|
428
|
+
as ms since epoch. The whole chart is a daily grid: null placeholders
|
|
429
|
+
arrive at 00:00Z and real probes mid-afternoon, so aligning every
|
|
430
|
+
point and every bar to the day centre keeps them on one grid. That is
|
|
431
|
+
what makes blocks sit centred on their day and prevents bars from
|
|
432
|
+
bleeding into a neighbouring day's measurement.
|
|
433
|
+
*/
|
|
434
|
+
const d = new Date(date);
|
|
435
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
436
|
+
return d.getTime() + 1000 * 3600 * 24 / 2;
|
|
437
|
+
},
|
|
438
|
+
computeDaySlots(data) {
|
|
439
|
+
/*
|
|
440
|
+
Returns, for every data point, the bar slot it should occupy: a full
|
|
441
|
+
calendar day centred on that day (see dayCenter). Consecutive
|
|
442
|
+
offline/NA days therefore tile into a single block, and because every
|
|
443
|
+
online point is snapped to the same daily grid a bar never overlaps a
|
|
444
|
+
measurement.
|
|
445
|
+
Arguments:
|
|
446
|
+
- data: array of objects with a "date" key
|
|
447
|
+
Returns an array (parallel to data) of objects with keys:
|
|
448
|
+
- center: slot centre (day centre), in ms since epoch
|
|
449
|
+
- width: slot width, in ms (one full day)
|
|
450
|
+
*/
|
|
451
|
+
const DAY = 1000 * 3600 * 24;
|
|
452
|
+
return data.map(item => ({
|
|
453
|
+
center: this.dayCenter(item.date),
|
|
454
|
+
width: DAY
|
|
455
|
+
}));
|
|
456
|
+
},
|
|
423
457
|
extractOfflineNADates(data) {
|
|
424
458
|
/*
|
|
425
|
-
This function extracts
|
|
426
|
-
Depending on the code, the server is offline or NA on
|
|
459
|
+
This function extracts the bar slots of points with no successful
|
|
460
|
+
measurement. Depending on the code, the server is offline or NA on
|
|
461
|
+
those dates.
|
|
427
462
|
Arguments:
|
|
428
463
|
- data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
-
|
|
432
|
-
- down: array of dates with code in errorCodes (server offline)
|
|
464
|
+
Returns an object with keys:
|
|
465
|
+
- NA: array of slots (see computeDaySlots) for code null (no information available)
|
|
466
|
+
- down: array of slots for code in errorCodes (server offline)
|
|
433
467
|
Classification is driven by the HTTP code, not by access_time
|
|
434
468
|
null-ness: an error response that happened to record an access_time
|
|
435
469
|
is still "offline", and a missing code is "no information available".
|
|
436
470
|
*/
|
|
471
|
+
const slots = this.computeDaySlots(data);
|
|
437
472
|
const resultNA = [];
|
|
438
473
|
const resultOffline = [];
|
|
439
474
|
for (let i = 0; i < data.length; i++) {
|
|
440
475
|
// no code at all -> grey "No information available"
|
|
441
476
|
if (data[i].code === null) {
|
|
442
|
-
resultNA.push(
|
|
477
|
+
resultNA.push(slots[i]);
|
|
443
478
|
// an error code -> red "Offline"
|
|
444
479
|
} else if (this.isErrorCode(data[i].code)) {
|
|
445
|
-
resultOffline.push(
|
|
480
|
+
resultOffline.push(slots[i]);
|
|
446
481
|
}
|
|
447
482
|
}
|
|
448
483
|
return {
|
|
@@ -454,10 +489,12 @@ var script$1 = {
|
|
|
454
489
|
/*
|
|
455
490
|
This function builds a bar trace.
|
|
456
491
|
Arguments:
|
|
457
|
-
- data: object with keys "dates" and "
|
|
458
|
-
- dates: array of dates
|
|
492
|
+
- data: object with keys "dates", "access_times", "colors" and "widths"
|
|
493
|
+
- dates: array of dates (slot centres, in ms)
|
|
459
494
|
- access_times: array of access_times
|
|
460
495
|
- colors: array of colors in rgba format (eg:"rgba(255, 153, 145,0.8)")
|
|
496
|
+
- widths: array of per-bar widths in ms, so each bar fills its
|
|
497
|
+
own time slot (see computeDaySlots) instead of a fixed day
|
|
461
498
|
- name: name of the trace
|
|
462
499
|
*/
|
|
463
500
|
const trace = {
|
|
@@ -472,35 +509,43 @@ var script$1 = {
|
|
|
472
509
|
showlegend: showlegend,
|
|
473
510
|
hoverinfo: hoverinfo,
|
|
474
511
|
hovertemplate: hovertemplate,
|
|
475
|
-
width:
|
|
512
|
+
width: data.widths
|
|
476
513
|
};
|
|
477
|
-
|
|
478
|
-
console.log(trace);
|
|
479
514
|
return trace;
|
|
480
515
|
},
|
|
481
|
-
buildBarTraces(
|
|
516
|
+
buildBarTraces(slots, color, label, group) {
|
|
482
517
|
/*
|
|
483
518
|
This function builds the series used to display the offline/NA bars.
|
|
484
|
-
For each
|
|
485
|
-
|
|
486
|
-
|
|
519
|
+
For each slot two stacked columns are created that together span the
|
|
520
|
+
whole plot height: a thin strong-coloured band sitting on the axis,
|
|
521
|
+
and a light-coloured column filling the rest of the height above it.
|
|
487
522
|
Arguments:
|
|
488
|
-
-
|
|
523
|
+
- slots: array of slots ({ center, width }), see computeDaySlots
|
|
489
524
|
- color: color of the bars
|
|
490
525
|
Returns array with offline and NA traces
|
|
491
526
|
*/
|
|
492
527
|
|
|
493
528
|
const colorStrong = `rgba(${color},.8)`;
|
|
494
529
|
const colorLight = `rgba(${color},.2)`;
|
|
530
|
+
const centers = slots.map(s => s.center);
|
|
531
|
+
const widths = slots.map(s => s.width);
|
|
532
|
+
|
|
533
|
+
// Total background height (keeps the previous y-axis extent). The
|
|
534
|
+
// strong colour is a thin band on the axis; the light colour fills
|
|
535
|
+
// the remaining height stacked on top of it.
|
|
536
|
+
const totalHeight = 2 + this.max_access_time * 1.1;
|
|
537
|
+
const baseHeight = totalHeight * 0.03;
|
|
495
538
|
const dataShort = {
|
|
496
|
-
dates:
|
|
497
|
-
access_times: Array(
|
|
498
|
-
colors: Array(
|
|
539
|
+
dates: centers,
|
|
540
|
+
access_times: Array(slots.length).fill(baseHeight),
|
|
541
|
+
colors: Array(slots.length).fill(colorStrong),
|
|
542
|
+
widths: widths
|
|
499
543
|
};
|
|
500
544
|
const dataTall = {
|
|
501
|
-
dates:
|
|
502
|
-
access_times: Array(
|
|
503
|
-
colors: Array(
|
|
545
|
+
dates: centers,
|
|
546
|
+
access_times: Array(slots.length).fill(totalHeight - baseHeight),
|
|
547
|
+
colors: Array(slots.length).fill(colorLight),
|
|
548
|
+
widths: widths
|
|
504
549
|
};
|
|
505
550
|
const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
|
|
506
551
|
const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
|
|
@@ -522,12 +567,10 @@ var script$1 = {
|
|
|
522
567
|
// Down arrays
|
|
523
568
|
if (arrays.down.length > 0) {
|
|
524
569
|
traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
|
|
525
|
-
console.log(arrays.down);
|
|
526
570
|
}
|
|
527
571
|
// NA arrays
|
|
528
572
|
if (arrays.NA.length > 0) {
|
|
529
573
|
traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
|
|
530
|
-
console.log(arrays.NA);
|
|
531
574
|
}
|
|
532
575
|
return traces;
|
|
533
576
|
},
|
|
@@ -578,7 +621,10 @@ var script$1 = {
|
|
|
578
621
|
console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
|
|
579
622
|
return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
|
|
580
623
|
} else {
|
|
581
|
-
|
|
624
|
+
// Anchor day ticks at the day centre (noon) so each label sits
|
|
625
|
+
// under the middle of its day block, aligned with the online dot
|
|
626
|
+
// (which is snapped to the same day centre).
|
|
627
|
+
return this.dayCenter(this.dataItems[0].date);
|
|
582
628
|
}
|
|
583
629
|
},
|
|
584
630
|
xaxisMode() {
|
|
@@ -589,11 +635,17 @@ var script$1 = {
|
|
|
589
635
|
}
|
|
590
636
|
},
|
|
591
637
|
xaxisRange() {
|
|
592
|
-
if (
|
|
593
|
-
return [this.dataItems[0], this.dataItems[this.dataItems.length - 1]];
|
|
594
|
-
} else {
|
|
638
|
+
if (this.xrange) {
|
|
595
639
|
return this.xrange;
|
|
596
640
|
}
|
|
641
|
+
// Span whole calendar days so the first and last day blocks (which
|
|
642
|
+
// are centred on their day, one full day wide) are fully visible.
|
|
643
|
+
const DAY = 1000 * 3600 * 24;
|
|
644
|
+
const firstDay = new Date(this.dataItems[0].date);
|
|
645
|
+
firstDay.setUTCHours(0, 0, 0, 0);
|
|
646
|
+
const lastDay = new Date(this.dataItems[this.dataItems.length - 1].date);
|
|
647
|
+
lastDay.setUTCHours(0, 0, 0, 0);
|
|
648
|
+
return [firstDay.getTime(), lastDay.getTime() + DAY];
|
|
597
649
|
},
|
|
598
650
|
monthTickVales() {
|
|
599
651
|
// First day of month of last date and previous five months
|
|
@@ -711,7 +763,7 @@ const __vue_inject_styles__$1 = undefined;
|
|
|
711
763
|
/* scoped */
|
|
712
764
|
const __vue_scope_id__$1 = undefined;
|
|
713
765
|
/* module identifier */
|
|
714
|
-
const __vue_module_identifier__$1 = "data-v-
|
|
766
|
+
const __vue_module_identifier__$1 = "data-v-bab9d544";
|
|
715
767
|
/* functional template */
|
|
716
768
|
const __vue_is_functional_template__$1 = false;
|
|
717
769
|
/* style inject */
|