@inb/oeb_visualizations 0.0.6 → 0.0.8-beta

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.
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # OpenEBench Visualizations
2
2
 
3
- Collection of Vue components for data visualization in OpenEBench.
3
+ Collection of Vue components for data visualization in [OpenEBench](https://openebench.bsc.es/).
4
4
 
5
- - Go to the [demo](https://inab.github.io/oeb-visualizations-demo/) to see the components in action.
6
- - This package is available through [npmjs](https://www.npmjs.com/package/@inb/oeb-visualizations).
5
+ - :magic_wand: Go to the [live demo](https://inab.github.io/oeb-visualizations-demo/) to see the components in action.
6
+ - :open_book: Check the [documentation](https://inab.github.io/oeb-visualizations/) for details on how to use the components.
7
+ - :package: This package is available through [npmjs](https://www.npmjs.com/package/@inb/oeb_visualizations).
7
8
 
8
9
 
9
10
  ## Installation
@@ -11,209 +12,9 @@ Collection of Vue components for data visualization in OpenEBench.
11
12
  To install the package run:
12
13
 
13
14
  ```bash
14
- npm install @inb/oeb-visualizations
15
+ npm install @inb/oeb_visualizations
15
16
  ```
16
17
 
17
- ## Components
18
+ ## Development
18
19
 
19
- ### accessibilityPlot
20
-
21
-
22
- #### Data
23
-
24
- Data is provided to the component as an array of objects through the `dataItems` prop. Each object represents an access to the server. The object must have the following keys: `access_time`, `date` and `code`.
25
- - `access_time`: time it took to access the server in ms.
26
- - `date`: date of the access. Should not be null.
27
- - `code`: HTTP code returned by the server. If `null` the bar will be colored with the color specified in the `colorNA` prop. If the code is an error code the bar will be colored with the color specified in the `colorOffline` prop. If the code is 200 the bar will be colored with the color specified in the `colorOnline` prop.
28
-
29
- Example:
30
-
31
- ```json
32
- [
33
- {
34
- "date": "2022-10-23T07:54:06.716122Z",
35
- "code": 200,
36
- "access_time": 51
37
- },
38
- {
39
- "date": "2022-10-24T07:58:50.609475Z",
40
- "code": 200,
41
- "access_time": 67
42
- },
43
- {
44
- "date": "2022-10-25T07:51:53.841140Z",
45
- "code": 200,
46
- "access_time": 55
47
- }
48
- ]
49
- ```
50
-
51
- #### Props
52
-
53
- | Name | Type | Description | Default | Required |
54
- | --- | --- | --- | --- | --- |
55
- |dataItems | Array | Array of objects with keys `access_time`, `date` and `code`. <br> More details in "Data" section | | true |
56
- | height | Number | Height of the plot in pixels. | 400 | false |
57
- | colorNA | String | Color of bars for which there is no monitoring information (`code`=`null`). RGB format: `"<R>, <G>, <B>"` | 204, 204, 204 | false |
58
- | colorOffline | String | Color of bars for which the server was offline (`code` is an error code). RGB format: `"<R>, <G>, <B>"` | 255, 153, 145 | false |
59
- | colorOnline | String | Color of bars for which the server was online (`code` is 200). RGB format: `"<R>, <G>, <B>"` | 111, 176, 129 | false |
60
- | yaxisTitle | String | Title of the y axis. | Access time (ms) | false |
61
- | xaxisTitle | String | Title of the x axis. | Date | false |
62
- | dtick | String | Tick interval for the x axis in unix epoch. | 86400000 | false |
63
-
64
- #### Usage
65
-
66
- Import the `accessibilityPlot` in your Vue component and add it to the `components` section. Then use the component in the template.
67
-
68
- ```html
69
- <template>
70
- <div>
71
- <accessibilityPlot :dataItems="data" />
72
- </div>
73
- </template>
74
-
75
- <script>
76
- import { accessibilityPlot } from '@inb/oeb_visualizations'
77
-
78
- export default {
79
- components: {
80
- accessibilityPlot
81
- },
82
- data(){
83
- return {
84
- data: [
85
- {
86
- "date": "2022-10-23T07:54:06.716122Z",
87
- "code": 200,
88
- "access_time": 51
89
- },
90
- {
91
- "date": "2022-10-24T07:58:50.609475Z",
92
- "code": 200,
93
- "access_time": 67
94
- },
95
- {
96
- "date": "2022-10-25T07:51:53.841140Z",
97
- "code": 200,
98
- "access_time": 55
99
- }
100
- ]
101
- }
102
- }
103
- }
104
- </script>
105
- ```
106
-
107
- ### citationsPlot
108
-
109
- #### Data
110
-
111
- Data is provided to the component as an array of objects through the `dataTraces` prop. Each object corresponds to a publication and will be represented as a trace in the resulting plot. They have the following keys: `data`, `id`, `label`, `title`, `year` and `url`.
112
- - `data`: array of objects. Each object has the following keys: `count` and `year`. `count` is the number of citations of the publication in the year `year`. Exmple
113
- ```
114
- [
115
- {
116
- "count": 1,
117
- "year": 2019
118
- },
119
- {
120
- "count": 1,
121
- "year": 2020
122
- },
123
- {
124
- "count": 1,
125
- "year": 2021
126
- }
127
- ]
128
-
129
- ```
130
-
131
- - `id`: string. Identifier of the publication.
132
- - `label`: string. Label of the publication.
133
- - `title`: string. Title of the publication.
134
- - `year`: number. Year of the publication.
135
- - `url`: string. URL of the publication.
136
-
137
- #### Props
138
-
139
- | Name | Type | Description | Default | Required |
140
- | --- | --- | --- | --- | --- |
141
- |dataTraces | Array | Array of objects with keys `data`, `id`, `label`, `title`, `year` and `url`. <br> More details in "Data" section | | true |
142
- | stack | Boolean | If true, the traces will be stacked. | false | false |
143
- | colors | Array | Array of colors for the traces. HEX format | | false |
144
- | height | Number | Height of the plot in pixels. | 400 | false |
145
- | showlegend | Boolean | If true, the legend will be shown. | true | false |
146
- | title | String | Title of the plot. | | false |
147
- | xaxisTitle | String | Title of the x axis. | Year | false |
148
- | yaxisTitle | String | Title of the y axis. | Number of citations | false |
149
- | dark | Boolean | If true, the plot will be displayed in dark mode. | false | false |
150
-
151
- #### Usage
152
-
153
- Import the `citationsPlot` in your Vue component and add it to the `components` section. Then use the component in the template.
154
-
155
- ```html
156
- <template>
157
- <div>
158
- <citationsPlot :dataTraces="data" />
159
- </div>
160
- </template>
161
- <script>
162
- import citationsPlotPage from '../components/citationsPlotPage.vue'
163
-
164
- export default {
165
- name: 'IndexPage',
166
- components: {
167
- citationsPlotPage
168
- },
169
- data(){
170
- return {
171
- data: [
172
- {
173
- "data": [
174
- {
175
- "count": 1,
176
- "year": 2019
177
- },
178
- {
179
- "count": 1,
180
- "year": 2020
181
- },
182
- {
183
- "count": 1,
184
- "year": 2021
185
- }
186
- ],
187
- "id": "paper1",
188
- "label": "OEB paper",
189
- "title": "OpenEBench: a web platform for transparent and reproducible biomedical benchmarking",
190
- "year": 2020,
191
- "url": ""
192
- },
193
- {
194
- "data": [
195
- {
196
- "count": 1,
197
- "year": 2019
198
- },
199
- {
200
- "count": 1,
201
- "year": 2020
202
- },
203
- {
204
- "count": 1,
205
- "year": 2021
206
- }
207
- ],
208
- "id": "paper2",
209
- "label": "OEB paper 2",
210
- "title": "OpenEBench 2: an update of the web platform for transparent and reproducible biomedical benchmarking",
211
- "year": 2020,
212
- "url": ""
213
- }
214
- ]
215
- }
216
- }
217
- }
218
- </script>
219
- ```
20
+ 🚧 Work in progress 🚧
@@ -4,7 +4,13 @@
4
4
  var script$1 = {
5
5
  name: 'accessibilityPlot',
6
6
  data: () => ({
7
- divId: randstr('acc_plot')
7
+ divId: randstr('acc_plot_'),
8
+ max_access_time: 0,
9
+ config: {
10
+ displaylogo: false,
11
+ responsive: true,
12
+ modeBarButtonsToRemove: ['lasso']
13
+ }
8
14
  }),
9
15
  props: {
10
16
  dtick: {
@@ -66,6 +72,24 @@ var script$1 = {
66
72
  required: false,
67
73
  default: 350
68
74
  },
75
+ week: {
76
+ /*
77
+ whether the plot is used to show data of one week
78
+ If true, days of the week are shown on the x axis
79
+ */
80
+ type: Boolean,
81
+ required: false,
82
+ default: false
83
+ },
84
+ sixMonths: {
85
+ /*
86
+ whether the plot is used to show data of six months
87
+ If true, months are shown on the x axis
88
+ */
89
+ type: Boolean,
90
+ required: false,
91
+ default: false
92
+ },
69
93
  dataItems: {
70
94
  /*
71
95
  dataItems is an array of objects with keys "access_time", "date" and "code".
@@ -114,6 +138,7 @@ var script$1 = {
114
138
  }
115
139
  },
116
140
  mounted() {
141
+ this.max_access_time = Math.max(...this.dataItems.map(item => item.access_time));
117
142
  var traces = this.buildOnlineTraces(this.dataItems); // generate line traces
118
143
 
119
144
  traces = traces.concat(this.buildOfflineNATraces(this.dataItems)); // generate bar traces
@@ -127,12 +152,13 @@ var script$1 = {
127
152
  margin: {
128
153
  l: 50,
129
154
  r: 50,
130
- b: 70,
131
- t: 70,
155
+ b: 50,
156
+ t: 20,
132
157
  pad: 4
133
158
  },
134
159
  xaxis: {
135
160
  type: 'date',
161
+ ticklabelmode: this.xaxisMode(),
136
162
  title: this.xaxisTitle,
137
163
  font: {
138
164
  size: 10
@@ -140,11 +166,17 @@ var script$1 = {
140
166
  tickfont: {
141
167
  size: 10
142
168
  },
143
- tickmode: 'linear',
144
- tick0: this.dataItems[0].date,
145
- dtick: this.dtick,
146
- tickangle: 45,
147
- tickformat: "%d %b"
169
+ showgrid: this.sixMonths ? true : false,
170
+ griddash: "dot",
171
+ gridwidth: 1,
172
+ gridcolor: "#d9d7d7",
173
+ showspikes: true,
174
+ spikedash: "4px",
175
+ spikethickness: 1,
176
+ tick0: this.xaxisTickZero(),
177
+ dtick: this.xaxisTickD(),
178
+ tickangle: this.xaxisTickAngle(),
179
+ tickformat: this.xaxisTickFormat()
148
180
  },
149
181
  yaxis: {
150
182
  title: this.yaxisTitle,
@@ -159,9 +191,9 @@ var script$1 = {
159
191
  legend: {
160
192
  orientation: 'h',
161
193
  yanchor: 'bottom',
162
- y: 1.02,
163
- xanchor: 'right',
164
- x: 1,
194
+ y: -0.5,
195
+ xanchor: 'left',
196
+ x: 0.05,
165
197
  font: {
166
198
  size: 8
167
199
  }
@@ -171,7 +203,8 @@ var script$1 = {
171
203
  },
172
204
  hovermode: 'closest'
173
205
  };
174
- Plotly__default["default"].newPlot(this.divId, traces, layout);
206
+ console.log(this.divId);
207
+ Plotly__default["default"].newPlot(this.divId, traces, layout, this.config);
175
208
  },
176
209
  methods: {
177
210
  generateColor(values, transparency) {
@@ -298,10 +331,18 @@ var script$1 = {
298
331
 
299
332
  // set start and end dates so that the line spands the whole plot
300
333
  const firstDate = new Date(this.dataItems[0].date);
301
- firstDate.setDate(firstDate.getDate() - 1); // one day before the first date in data
334
+ if (this.week) {
335
+ firstDate.setDate(firstDate.getDate() - 0.3); // one day before the first date in data
336
+ } else {
337
+ firstDate.setDate(firstDate.getDate() - 1); // one month before the first date in data
338
+ }
302
339
 
303
340
  const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
304
- lastDate.setDate(lastDate.getDate() + 1); // one day after the last date in data
341
+ if (this.week) {
342
+ lastDate.setDate(lastDate.getDate() + 0.3);
343
+ } else {
344
+ lastDate.setDate(lastDate.getDate() + 1); // one month after the last date in data
345
+ }
305
346
 
306
347
  const trace = {
307
348
  x: [firstDate, lastDate],
@@ -340,17 +381,6 @@ var script$1 = {
340
381
  return traces;
341
382
  },
342
383
  extractOfflineNADates(data) {
343
- /*
344
- This function extracts dates with access_time null.
345
- Depending on the code, the server is offline or NA on those dates.
346
- Arguments:
347
- - data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
348
-
349
- Returns an object with keys:
350
- - NA: array of dates with access_time null and code null
351
- - down: array of dates with access_time null and code in errorCodes
352
- */
353
- const errorCodes = [404, 500, 502, 503, 504];
354
384
  const resultNA = [];
355
385
  const resultOffline = [];
356
386
  for (let i = 0; i < data.length; i++) {
@@ -358,7 +388,7 @@ var script$1 = {
358
388
  if (data[i].access_time === null && data[i].code === null) {
359
389
  resultNA.push(data[i].date);
360
390
  // if the access_time is null and the code is in errorCodes, it means that the server is offline
361
- } else if (data[i].access_time === null && errorCodes.includes(data[i].code)) {
391
+ } else if (data[i].access_time === null) {
362
392
  resultOffline.push(data[i].date);
363
393
  }
364
394
  }
@@ -367,7 +397,7 @@ var script$1 = {
367
397
  down: resultOffline
368
398
  };
369
399
  },
370
- barTrace(data, name, showlegend, hoverinfo, hovertemplate) {
400
+ barTrace(data, name, showlegend, hoverinfo, hovertemplate, group) {
371
401
  /*
372
402
  This function builds a bar trace.
373
403
  Arguments:
@@ -385,14 +415,17 @@ var script$1 = {
385
415
  },
386
416
  name: name,
387
417
  type: "bar",
388
- legendgroup: name,
418
+ legendgroup: group,
389
419
  showlegend: showlegend,
390
420
  hoverinfo: hoverinfo,
391
- hovertemplate: hovertemplate
421
+ hovertemplate: hovertemplate,
422
+ width: 1000 * 3600 * 24 * 1 // 100% of the space between two dates
392
423
  };
424
+
425
+ console.log(trace);
393
426
  return trace;
394
427
  },
395
- buildBarTraces(dates, color, label) {
428
+ buildBarTraces(dates, color, label, group) {
396
429
  /*
397
430
  This function builds the series used to display the offline/NA bars.
398
431
  For each date, two columns are created: one very short and one tall.
@@ -413,12 +446,12 @@ var script$1 = {
413
446
  };
414
447
  const dataTall = {
415
448
  dates: dates,
416
- access_times: Array(dates.length).fill(120),
449
+ access_times: Array(dates.length).fill(this.max_access_time * 1.1),
417
450
  colors: Array(dates.length).fill(colorLight)
418
451
  };
419
452
  const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
420
- const traceShort = this.barTrace(dataShort, label, false, 'skip', '');
421
- const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate);
453
+ const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
454
+ const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate, group);
422
455
  return [traceShort, traceTall];
423
456
  },
424
457
  buildOfflineNATraces(data) {
@@ -434,11 +467,73 @@ var script$1 = {
434
467
  const arrays = this.extractOfflineNADates(data);
435
468
 
436
469
  // Down arrays
437
- traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline'));
438
-
470
+ if (arrays.down.length > 0) {
471
+ traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
472
+ console.log(arrays.down);
473
+ }
439
474
  // NA arrays
440
- traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available'));
475
+ if (arrays.NA.length > 0) {
476
+ traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
477
+ console.log(arrays.NA);
478
+ }
441
479
  return traces;
480
+ },
481
+ xaxisTickFormat() {
482
+ /*
483
+ This function returns the tickformat of the x axis.
484
+ If the plot is used to show data of one week, it returns the day of the week and the day.
485
+ Otherwise, it returns the day and the month.
486
+ */
487
+
488
+ if (this.week) {
489
+ return "%A<br>%d %b";
490
+ }
491
+ if (this.sixMonths) {
492
+ return "%b";
493
+ } else {
494
+ return "%d %b";
495
+ }
496
+ },
497
+ xaxisTickAngle() {
498
+ /*
499
+ This function returns the tickangle of the x axis.
500
+ If the plot is used to show data of one week, it returns 0.
501
+ Otherwise, it returns 45.
502
+ */
503
+ if (this.week) {
504
+ return 0;
505
+ }
506
+ if (this.sixMonths) {
507
+ return 0;
508
+ } else {
509
+ return 45;
510
+ }
511
+ },
512
+ xaxisTickD() {
513
+ if (this.sixMonths === true) {
514
+ return "M1";
515
+ } else {
516
+ return this.dtick;
517
+ }
518
+ },
519
+ xaxisTickZero() {
520
+ if (this.sixMonths === true) {
521
+ console.log('zero six months ago');
522
+ const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
523
+ //return lastDate minus six months
524
+ console.log(lastDate);
525
+ console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
526
+ return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
527
+ } else {
528
+ return this.dataItems[0];
529
+ }
530
+ },
531
+ xaxisMode() {
532
+ if (this.sixMonths === true) {
533
+ return "period";
534
+ } else {
535
+ return "instant";
536
+ }
442
537
  }
443
538
  }
444
539
  };function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier
@@ -545,7 +640,7 @@ const __vue_inject_styles__$1 = undefined;
545
640
  /* scoped */
546
641
  const __vue_scope_id__$1 = undefined;
547
642
  /* module identifier */
548
- const __vue_module_identifier__$1 = "data-v-3124a55a";
643
+ const __vue_module_identifier__$1 = "data-v-77c84891";
549
644
  /* functional template */
550
645
  const __vue_is_functional_template__$1 = false;
551
646
  /* style inject */
@@ -559,7 +654,7 @@ var accessibilityPlot = normalizeComponent_1({
559
654
  var script = {
560
655
  name: 'citationsPlot',
561
656
  data: () => ({
562
- divId: randstr('cit_plot')
657
+ divId: randstr('cit_plot_')
563
658
  }),
564
659
  props: {
565
660
  dataTraces: {
@@ -731,7 +826,7 @@ const __vue_inject_styles__ = undefined;
731
826
  /* scoped */
732
827
  const __vue_scope_id__ = undefined;
733
828
  /* module identifier */
734
- const __vue_module_identifier__ = "data-v-64c53c55";
829
+ const __vue_module_identifier__ = "data-v-4ac5e814";
735
830
  /* functional template */
736
831
  const __vue_is_functional_template__ = false;
737
832
  /* style inject */
@@ -8,7 +8,13 @@ function randstr(prefix) {
8
8
  var script$1 = {
9
9
  name: 'accessibilityPlot',
10
10
  data: () => ({
11
- divId: randstr('acc_plot')
11
+ divId: randstr('acc_plot_'),
12
+ max_access_time: 0,
13
+ config: {
14
+ displaylogo: false,
15
+ responsive: true,
16
+ modeBarButtonsToRemove: ['lasso']
17
+ }
12
18
  }),
13
19
  props: {
14
20
  dtick: {
@@ -70,6 +76,24 @@ var script$1 = {
70
76
  required: false,
71
77
  default: 350
72
78
  },
79
+ week: {
80
+ /*
81
+ whether the plot is used to show data of one week
82
+ If true, days of the week are shown on the x axis
83
+ */
84
+ type: Boolean,
85
+ required: false,
86
+ default: false
87
+ },
88
+ sixMonths: {
89
+ /*
90
+ whether the plot is used to show data of six months
91
+ If true, months are shown on the x axis
92
+ */
93
+ type: Boolean,
94
+ required: false,
95
+ default: false
96
+ },
73
97
  dataItems: {
74
98
  /*
75
99
  dataItems is an array of objects with keys "access_time", "date" and "code".
@@ -118,6 +142,7 @@ var script$1 = {
118
142
  }
119
143
  },
120
144
  mounted() {
145
+ this.max_access_time = Math.max(...this.dataItems.map(item => item.access_time));
121
146
  var traces = this.buildOnlineTraces(this.dataItems); // generate line traces
122
147
 
123
148
  traces = traces.concat(this.buildOfflineNATraces(this.dataItems)); // generate bar traces
@@ -131,12 +156,13 @@ var script$1 = {
131
156
  margin: {
132
157
  l: 50,
133
158
  r: 50,
134
- b: 70,
135
- t: 70,
159
+ b: 50,
160
+ t: 20,
136
161
  pad: 4
137
162
  },
138
163
  xaxis: {
139
164
  type: 'date',
165
+ ticklabelmode: this.xaxisMode(),
140
166
  title: this.xaxisTitle,
141
167
  font: {
142
168
  size: 10
@@ -144,11 +170,17 @@ var script$1 = {
144
170
  tickfont: {
145
171
  size: 10
146
172
  },
147
- tickmode: 'linear',
148
- tick0: this.dataItems[0].date,
149
- dtick: this.dtick,
150
- tickangle: 45,
151
- tickformat: "%d %b"
173
+ showgrid: this.sixMonths ? true : false,
174
+ griddash: "dot",
175
+ gridwidth: 1,
176
+ gridcolor: "#d9d7d7",
177
+ showspikes: true,
178
+ spikedash: "4px",
179
+ spikethickness: 1,
180
+ tick0: this.xaxisTickZero(),
181
+ dtick: this.xaxisTickD(),
182
+ tickangle: this.xaxisTickAngle(),
183
+ tickformat: this.xaxisTickFormat()
152
184
  },
153
185
  yaxis: {
154
186
  title: this.yaxisTitle,
@@ -163,9 +195,9 @@ var script$1 = {
163
195
  legend: {
164
196
  orientation: 'h',
165
197
  yanchor: 'bottom',
166
- y: 1.02,
167
- xanchor: 'right',
168
- x: 1,
198
+ y: -0.5,
199
+ xanchor: 'left',
200
+ x: 0.05,
169
201
  font: {
170
202
  size: 8
171
203
  }
@@ -175,7 +207,8 @@ var script$1 = {
175
207
  },
176
208
  hovermode: 'closest'
177
209
  };
178
- Plotly.newPlot(this.divId, traces, layout);
210
+ console.log(this.divId);
211
+ Plotly.newPlot(this.divId, traces, layout, this.config);
179
212
  },
180
213
  methods: {
181
214
  generateColor(values, transparency) {
@@ -302,10 +335,18 @@ var script$1 = {
302
335
 
303
336
  // set start and end dates so that the line spands the whole plot
304
337
  const firstDate = new Date(this.dataItems[0].date);
305
- firstDate.setDate(firstDate.getDate() - 1); // one day before the first date in data
338
+ if (this.week) {
339
+ firstDate.setDate(firstDate.getDate() - 0.3); // one day before the first date in data
340
+ } else {
341
+ firstDate.setDate(firstDate.getDate() - 1); // one month before the first date in data
342
+ }
306
343
 
307
344
  const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
308
- lastDate.setDate(lastDate.getDate() + 1); // one day after the last date in data
345
+ if (this.week) {
346
+ lastDate.setDate(lastDate.getDate() + 0.3);
347
+ } else {
348
+ lastDate.setDate(lastDate.getDate() + 1); // one month after the last date in data
349
+ }
309
350
 
310
351
  const trace = {
311
352
  x: [firstDate, lastDate],
@@ -344,17 +385,6 @@ var script$1 = {
344
385
  return traces;
345
386
  },
346
387
  extractOfflineNADates(data) {
347
- /*
348
- This function extracts dates with access_time null.
349
- Depending on the code, the server is offline or NA on those dates.
350
- Arguments:
351
- - data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
352
-
353
- Returns an object with keys:
354
- - NA: array of dates with access_time null and code null
355
- - down: array of dates with access_time null and code in errorCodes
356
- */
357
- const errorCodes = [404, 500, 502, 503, 504];
358
388
  const resultNA = [];
359
389
  const resultOffline = [];
360
390
  for (let i = 0; i < data.length; i++) {
@@ -362,7 +392,7 @@ var script$1 = {
362
392
  if (data[i].access_time === null && data[i].code === null) {
363
393
  resultNA.push(data[i].date);
364
394
  // if the access_time is null and the code is in errorCodes, it means that the server is offline
365
- } else if (data[i].access_time === null && errorCodes.includes(data[i].code)) {
395
+ } else if (data[i].access_time === null) {
366
396
  resultOffline.push(data[i].date);
367
397
  }
368
398
  }
@@ -371,7 +401,7 @@ var script$1 = {
371
401
  down: resultOffline
372
402
  };
373
403
  },
374
- barTrace(data, name, showlegend, hoverinfo, hovertemplate) {
404
+ barTrace(data, name, showlegend, hoverinfo, hovertemplate, group) {
375
405
  /*
376
406
  This function builds a bar trace.
377
407
  Arguments:
@@ -389,14 +419,17 @@ var script$1 = {
389
419
  },
390
420
  name: name,
391
421
  type: "bar",
392
- legendgroup: name,
422
+ legendgroup: group,
393
423
  showlegend: showlegend,
394
424
  hoverinfo: hoverinfo,
395
- hovertemplate: hovertemplate
425
+ hovertemplate: hovertemplate,
426
+ width: 1000 * 3600 * 24 * 1 // 100% of the space between two dates
396
427
  };
428
+
429
+ console.log(trace);
397
430
  return trace;
398
431
  },
399
- buildBarTraces(dates, color, label) {
432
+ buildBarTraces(dates, color, label, group) {
400
433
  /*
401
434
  This function builds the series used to display the offline/NA bars.
402
435
  For each date, two columns are created: one very short and one tall.
@@ -417,12 +450,12 @@ var script$1 = {
417
450
  };
418
451
  const dataTall = {
419
452
  dates: dates,
420
- access_times: Array(dates.length).fill(120),
453
+ access_times: Array(dates.length).fill(this.max_access_time * 1.1),
421
454
  colors: Array(dates.length).fill(colorLight)
422
455
  };
423
456
  const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
424
- const traceShort = this.barTrace(dataShort, label, false, 'skip', '');
425
- const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate);
457
+ const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
458
+ const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate, group);
426
459
  return [traceShort, traceTall];
427
460
  },
428
461
  buildOfflineNATraces(data) {
@@ -438,11 +471,73 @@ var script$1 = {
438
471
  const arrays = this.extractOfflineNADates(data);
439
472
 
440
473
  // Down arrays
441
- traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline'));
442
-
474
+ if (arrays.down.length > 0) {
475
+ traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
476
+ console.log(arrays.down);
477
+ }
443
478
  // NA arrays
444
- traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available'));
479
+ if (arrays.NA.length > 0) {
480
+ traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
481
+ console.log(arrays.NA);
482
+ }
445
483
  return traces;
484
+ },
485
+ xaxisTickFormat() {
486
+ /*
487
+ This function returns the tickformat of the x axis.
488
+ If the plot is used to show data of one week, it returns the day of the week and the day.
489
+ Otherwise, it returns the day and the month.
490
+ */
491
+
492
+ if (this.week) {
493
+ return "%A<br>%d %b";
494
+ }
495
+ if (this.sixMonths) {
496
+ return "%b";
497
+ } else {
498
+ return "%d %b";
499
+ }
500
+ },
501
+ xaxisTickAngle() {
502
+ /*
503
+ This function returns the tickangle of the x axis.
504
+ If the plot is used to show data of one week, it returns 0.
505
+ Otherwise, it returns 45.
506
+ */
507
+ if (this.week) {
508
+ return 0;
509
+ }
510
+ if (this.sixMonths) {
511
+ return 0;
512
+ } else {
513
+ return 45;
514
+ }
515
+ },
516
+ xaxisTickD() {
517
+ if (this.sixMonths === true) {
518
+ return "M1";
519
+ } else {
520
+ return this.dtick;
521
+ }
522
+ },
523
+ xaxisTickZero() {
524
+ if (this.sixMonths === true) {
525
+ console.log('zero six months ago');
526
+ const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
527
+ //return lastDate minus six months
528
+ console.log(lastDate);
529
+ console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
530
+ return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
531
+ } else {
532
+ return this.dataItems[0];
533
+ }
534
+ },
535
+ xaxisMode() {
536
+ if (this.sixMonths === true) {
537
+ return "period";
538
+ } else {
539
+ return "instant";
540
+ }
446
541
  }
447
542
  }
448
543
  };
@@ -569,7 +664,7 @@ var accessibilityPlot = normalizeComponent_1({
569
664
  var script = {
570
665
  name: 'citationsPlot',
571
666
  data: () => ({
572
- divId: randstr('cit_plot')
667
+ divId: randstr('cit_plot_')
573
668
  }),
574
669
  props: {
575
670
  dataTraces: {
@@ -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 a=i(t);function r(e){return Math.random().toString(36).replace("0.",e||"")}var s=function(e,t,i,a,r,s,o,n,l,c){"boolean"!=typeof o&&(l=n,n=o,o=!1);var d,u="function"==typeof i?i.options:i;if(e&&e.render&&(u.render=e.render,u.staticRenderFns=e.staticRenderFns,u._compiled=!0,r&&(u.functional=!0)),a&&(u._scopeId=a),s?(d=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(s)},u._ssrRegister=d):t&&(d=o?function(){t.call(this,c(this.$root.$options.shadowRoot))}:function(e){t.call(this,n(e))}),d)if(u.functional){var h=u.render;u.render=function(e,t){return d.call(t),h(e,t)}}else{var m=u.beforeCreate;u.beforeCreate=m?[].concat(m,d):[d]}return i};var o=s({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"accessibilityPlot",data:()=>({divId:r("acc_plot")}),props:{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},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})`),("string"!=typeof e[t].date||isNaN(Date.parse(e[t].date)))&&console.error(`[oeb-visualizations warn] date must be a string containing a date in dataItems prop item (at position ${t})`),null===e[t].date&&console.error(`[oeb-visualizations warn] date cannot be null in dataItems prop item (at position ${t})`);return!0}}},mounted(){var e=this.buildOnlineTraces(this.dataItems);e=e.concat(this.buildOfflineNATraces(this.dataItems));const t={bargap:0,barmode:"stack",showlegend:!0,autosize:!0,height:this.height,margin:{l:50,r:50,b:70,t:70,pad:4},xaxis:{type:"date",title:this.xaxisTitle,font:{size:10},tickfont:{size:10},tickmode:"linear",tick0:this.dataItems[0].date,dtick:this.dtick,tickangle:45,tickformat:"%d %b"},yaxis:{title:this.yaxisTitle,titlefont:{size:10},tickfont:{size:10}},template:"plotly_white",legend:{orientation:"h",yanchor:"bottom",y:1.02,xanchor:"right",x:1,font:{size:8}},hoverlabel:{bgcolor:"#FFF"},hovermode:"closest"};a.default.newPlot(this.divId,e,t)},methods:{generateColor(e,t){let i=[];for(let a=0;a<30;a++)switch(e[a]){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=[],a=[],r=0,s=0;for(let o=0;o<e.length;o++)null!==e[o].access_time?(i.push(e[o].access_time),a.push(e[o].date),r+=e[o].access_time,s+=1):i.length>0&&(t.access_time.push(i),t.date.push(a),i=[],a=[]);return t.access_time.push(i),t.date.push(a),t.average_access_time=r/s,t},buildAccessTimeTraces(e){var t=[];for(let i=0;i<e.access_time.length;i++){const a=e.access_time[i],r={x:e.date[i],y:a,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(r)}return t},buildAvgAccessTimeTrace(e){const t=new Date(this.dataItems[0].date);t.setDate(t.getDate()-1);const i=new Date(this.dataItems[this.dataItems.length-1].date);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},extractOfflineNADates(e){const t=[404,500,502,503,504],i=[],a=[];for(let r=0;r<e.length;r++)null===e[r].access_time&&null===e[r].code?i.push(e[r].date):null===e[r].access_time&&t.includes(e[r].code)&&a.push(e[r].date);return{NA:i,down:a}},barTrace:(e,t,i,a,r)=>({x:e.dates,y:e.access_times,marker:{color:e.colors},name:t,type:"bar",legendgroup:t,showlegend:i,hoverinfo:a,hovertemplate:r}),buildBarTraces(e,t,i){const a=`rgba(${t},.8)`,r=`rgba(${t},.2)`,s={dates:e,access_times:Array(e.length).fill(2),colors:Array(e.length).fill(a)},o={dates:e,access_times:Array(e.length).fill(120),colors:Array(e.length).fill(r)},n=`<b>${i}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;return[this.barTrace(s,i,!1,"skip",""),this.barTrace(o,i,!0,"all",n)]},buildOfflineNATraces(e){var t=[];const i=this.extractOfflineNADates(e);return t=(t=t.concat(this.buildBarTraces(i.down,this.colorOffline,"Offline"))).concat(this.buildBarTraces(i.NA,this.colorNA,"No information available"))}}},undefined,!1,undefined,void 0,void 0);var n=s({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{attrs:{id:e.divId}})},staticRenderFns:[]},undefined,{name:"citationsPlot",data:()=>({divId:r("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"};a.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 c=function(e){c.installed||(c.installed=!0,Object.entries(l).forEach((([t,i])=>{e.component(t,i)})))},d={install:c};{let e=null;"undefined"!=typeof window?e=window.Vue:"undefined"!=typeof global&&(e=global.Vue),e&&e.use(d)}return e.accessibilityPlot=o,e.citationsPlot=n,e.default=d,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,c){"boolean"!=typeof o&&(l=n,n=o,o=!1);var d,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?(d=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=d):t&&(d=o?function(){t.call(this,c(this.$root.$options.shadowRoot))}:function(e){t.call(this,n(e))}),d)if(h.functional){var u=h.render;h.render=function(e,t){return d.call(t),u(e,t)}}else{var m=h.beforeCreate;h.beforeCreate=m?[].concat(m,d):[d]}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:{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},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})`),("string"!=typeof e[t].date||isNaN(Date.parse(e[t].date)))&&console.error(`[oeb-visualizations warn] date must be a string containing a date in dataItems prop item (at position ${t})`),null===e[t].date&&console.error(`[oeb-visualizations warn] date cannot be null in dataItems prop item (at position ${t})`);return!0}}},mounted(){this.max_access_time=Math.max(...this.dataItems.map((e=>e.access_time)));var e=this.buildOnlineTraces(this.dataItems);e=e.concat(this.buildOfflineNATraces(this.dataItems));const t={bargap:0,barmode:"stack",showlegend:!0,autosize:!0,height:this.height,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()},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,e,t,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?(i.push(e[o].access_time),s.push(e[o].date),a+=e[o].access_time,r+=1):i.length>0&&(t.access_time.push(i),t.date.push(s),i=[],s=[]);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},extractOfflineNADates(e){const t=[],i=[];for(let s=0;s<e.length;s++)null===e[s].access_time&&null===e[s].code?t.push(e[s].date):null===e[s].access_time&&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?"%b":"%d %b"},xaxisTickAngle(){return this.week||this.sixMonths?0: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"}}},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 c=function(e){c.installed||(c.installed=!0,Object.entries(l).forEach((([t,i])=>{e.component(t,i)})))},d={install:c};{let e=null;"undefined"!=typeof window?e=window.Vue:"undefined"!=typeof global&&(e=global.Vue),e&&e.use(d)}return e.accessibilityPlot=o,e.citationsPlot=n,e.default=d,Object.defineProperty(e,"__esModule",{value:!0}),e}({},Plotly);
@@ -4,7 +4,13 @@
4
4
  var script$1 = {
5
5
  name: 'accessibilityPlot',
6
6
  data: () => ({
7
- divId: randstr('acc_plot')
7
+ divId: randstr('acc_plot_'),
8
+ max_access_time: 0,
9
+ config: {
10
+ displaylogo: false,
11
+ responsive: true,
12
+ modeBarButtonsToRemove: ['lasso']
13
+ }
8
14
  }),
9
15
  props: {
10
16
  dtick: {
@@ -66,6 +72,24 @@ var script$1 = {
66
72
  required: false,
67
73
  default: 350
68
74
  },
75
+ week: {
76
+ /*
77
+ whether the plot is used to show data of one week
78
+ If true, days of the week are shown on the x axis
79
+ */
80
+ type: Boolean,
81
+ required: false,
82
+ default: false
83
+ },
84
+ sixMonths: {
85
+ /*
86
+ whether the plot is used to show data of six months
87
+ If true, months are shown on the x axis
88
+ */
89
+ type: Boolean,
90
+ required: false,
91
+ default: false
92
+ },
69
93
  dataItems: {
70
94
  /*
71
95
  dataItems is an array of objects with keys "access_time", "date" and "code".
@@ -114,6 +138,7 @@ var script$1 = {
114
138
  }
115
139
  },
116
140
  mounted() {
141
+ this.max_access_time = Math.max(...this.dataItems.map(item => item.access_time));
117
142
  var traces = this.buildOnlineTraces(this.dataItems); // generate line traces
118
143
 
119
144
  traces = traces.concat(this.buildOfflineNATraces(this.dataItems)); // generate bar traces
@@ -127,12 +152,13 @@ var script$1 = {
127
152
  margin: {
128
153
  l: 50,
129
154
  r: 50,
130
- b: 70,
131
- t: 70,
155
+ b: 50,
156
+ t: 20,
132
157
  pad: 4
133
158
  },
134
159
  xaxis: {
135
160
  type: 'date',
161
+ ticklabelmode: this.xaxisMode(),
136
162
  title: this.xaxisTitle,
137
163
  font: {
138
164
  size: 10
@@ -140,11 +166,17 @@ var script$1 = {
140
166
  tickfont: {
141
167
  size: 10
142
168
  },
143
- tickmode: 'linear',
144
- tick0: this.dataItems[0].date,
145
- dtick: this.dtick,
146
- tickangle: 45,
147
- tickformat: "%d %b"
169
+ showgrid: this.sixMonths ? true : false,
170
+ griddash: "dot",
171
+ gridwidth: 1,
172
+ gridcolor: "#d9d7d7",
173
+ showspikes: true,
174
+ spikedash: "4px",
175
+ spikethickness: 1,
176
+ tick0: this.xaxisTickZero(),
177
+ dtick: this.xaxisTickD(),
178
+ tickangle: this.xaxisTickAngle(),
179
+ tickformat: this.xaxisTickFormat()
148
180
  },
149
181
  yaxis: {
150
182
  title: this.yaxisTitle,
@@ -159,9 +191,9 @@ var script$1 = {
159
191
  legend: {
160
192
  orientation: 'h',
161
193
  yanchor: 'bottom',
162
- y: 1.02,
163
- xanchor: 'right',
164
- x: 1,
194
+ y: -0.5,
195
+ xanchor: 'left',
196
+ x: 0.05,
165
197
  font: {
166
198
  size: 8
167
199
  }
@@ -171,7 +203,8 @@ var script$1 = {
171
203
  },
172
204
  hovermode: 'closest'
173
205
  };
174
- Plotly__default["default"].newPlot(this.divId, traces, layout);
206
+ console.log(this.divId);
207
+ Plotly__default["default"].newPlot(this.divId, traces, layout, this.config);
175
208
  },
176
209
  methods: {
177
210
  generateColor(values, transparency) {
@@ -298,10 +331,18 @@ var script$1 = {
298
331
 
299
332
  // set start and end dates so that the line spands the whole plot
300
333
  const firstDate = new Date(this.dataItems[0].date);
301
- firstDate.setDate(firstDate.getDate() - 1); // one day before the first date in data
334
+ if (this.week) {
335
+ firstDate.setDate(firstDate.getDate() - 0.3); // one day before the first date in data
336
+ } else {
337
+ firstDate.setDate(firstDate.getDate() - 1); // one month before the first date in data
338
+ }
302
339
 
303
340
  const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
304
- lastDate.setDate(lastDate.getDate() + 1); // one day after the last date in data
341
+ if (this.week) {
342
+ lastDate.setDate(lastDate.getDate() + 0.3);
343
+ } else {
344
+ lastDate.setDate(lastDate.getDate() + 1); // one month after the last date in data
345
+ }
305
346
 
306
347
  const trace = {
307
348
  x: [firstDate, lastDate],
@@ -340,17 +381,6 @@ var script$1 = {
340
381
  return traces;
341
382
  },
342
383
  extractOfflineNADates(data) {
343
- /*
344
- This function extracts dates with access_time null.
345
- Depending on the code, the server is offline or NA on those dates.
346
- Arguments:
347
- - data: array of objects with keys "access_time", "date" and "code". access_time and code can be null
348
-
349
- Returns an object with keys:
350
- - NA: array of dates with access_time null and code null
351
- - down: array of dates with access_time null and code in errorCodes
352
- */
353
- const errorCodes = [404, 500, 502, 503, 504];
354
384
  const resultNA = [];
355
385
  const resultOffline = [];
356
386
  for (let i = 0; i < data.length; i++) {
@@ -358,7 +388,7 @@ var script$1 = {
358
388
  if (data[i].access_time === null && data[i].code === null) {
359
389
  resultNA.push(data[i].date);
360
390
  // if the access_time is null and the code is in errorCodes, it means that the server is offline
361
- } else if (data[i].access_time === null && errorCodes.includes(data[i].code)) {
391
+ } else if (data[i].access_time === null) {
362
392
  resultOffline.push(data[i].date);
363
393
  }
364
394
  }
@@ -367,7 +397,7 @@ var script$1 = {
367
397
  down: resultOffline
368
398
  };
369
399
  },
370
- barTrace(data, name, showlegend, hoverinfo, hovertemplate) {
400
+ barTrace(data, name, showlegend, hoverinfo, hovertemplate, group) {
371
401
  /*
372
402
  This function builds a bar trace.
373
403
  Arguments:
@@ -385,14 +415,17 @@ var script$1 = {
385
415
  },
386
416
  name: name,
387
417
  type: "bar",
388
- legendgroup: name,
418
+ legendgroup: group,
389
419
  showlegend: showlegend,
390
420
  hoverinfo: hoverinfo,
391
- hovertemplate: hovertemplate
421
+ hovertemplate: hovertemplate,
422
+ width: 1000 * 3600 * 24 * 1 // 100% of the space between two dates
392
423
  };
424
+
425
+ console.log(trace);
393
426
  return trace;
394
427
  },
395
- buildBarTraces(dates, color, label) {
428
+ buildBarTraces(dates, color, label, group) {
396
429
  /*
397
430
  This function builds the series used to display the offline/NA bars.
398
431
  For each date, two columns are created: one very short and one tall.
@@ -413,12 +446,12 @@ var script$1 = {
413
446
  };
414
447
  const dataTall = {
415
448
  dates: dates,
416
- access_times: Array(dates.length).fill(120),
449
+ access_times: Array(dates.length).fill(this.max_access_time * 1.1),
417
450
  colors: Array(dates.length).fill(colorLight)
418
451
  };
419
452
  const hovertemplate = `<b>${label}</b><br>%{x|%d %b %Y}<br>%{y} ms <extra></extra>`;
420
- const traceShort = this.barTrace(dataShort, label, false, 'skip', '');
421
- const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate);
453
+ const traceShort = this.barTrace(dataShort, label, false, 'skip', '', group);
454
+ const traceTall = this.barTrace(dataTall, label, true, 'all', hovertemplate, group);
422
455
  return [traceShort, traceTall];
423
456
  },
424
457
  buildOfflineNATraces(data) {
@@ -434,11 +467,73 @@ var script$1 = {
434
467
  const arrays = this.extractOfflineNADates(data);
435
468
 
436
469
  // Down arrays
437
- traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline'));
438
-
470
+ if (arrays.down.length > 0) {
471
+ traces = traces.concat(this.buildBarTraces(arrays.down, this.colorOffline, 'Offline', 'down'));
472
+ console.log(arrays.down);
473
+ }
439
474
  // NA arrays
440
- traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available'));
475
+ if (arrays.NA.length > 0) {
476
+ traces = traces.concat(this.buildBarTraces(arrays.NA, this.colorNA, 'No information available', 'na'));
477
+ console.log(arrays.NA);
478
+ }
441
479
  return traces;
480
+ },
481
+ xaxisTickFormat() {
482
+ /*
483
+ This function returns the tickformat of the x axis.
484
+ If the plot is used to show data of one week, it returns the day of the week and the day.
485
+ Otherwise, it returns the day and the month.
486
+ */
487
+
488
+ if (this.week) {
489
+ return "%A<br>%d %b";
490
+ }
491
+ if (this.sixMonths) {
492
+ return "%b";
493
+ } else {
494
+ return "%d %b";
495
+ }
496
+ },
497
+ xaxisTickAngle() {
498
+ /*
499
+ This function returns the tickangle of the x axis.
500
+ If the plot is used to show data of one week, it returns 0.
501
+ Otherwise, it returns 45.
502
+ */
503
+ if (this.week) {
504
+ return 0;
505
+ }
506
+ if (this.sixMonths) {
507
+ return 0;
508
+ } else {
509
+ return 45;
510
+ }
511
+ },
512
+ xaxisTickD() {
513
+ if (this.sixMonths === true) {
514
+ return "M1";
515
+ } else {
516
+ return this.dtick;
517
+ }
518
+ },
519
+ xaxisTickZero() {
520
+ if (this.sixMonths === true) {
521
+ console.log('zero six months ago');
522
+ const lastDate = new Date(this.dataItems[this.dataItems.length - 1].date);
523
+ //return lastDate minus six months
524
+ console.log(lastDate);
525
+ console.log('six months ago: ' + new Date(lastDate.setMonth(lastDate.getMonth() - 6)));
526
+ return new Date(lastDate.setMonth(lastDate.getMonth() - 6));
527
+ } else {
528
+ return this.dataItems[0];
529
+ }
530
+ },
531
+ xaxisMode() {
532
+ if (this.sixMonths === true) {
533
+ return "period";
534
+ } else {
535
+ return "instant";
536
+ }
442
537
  }
443
538
  }
444
539
  };function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier
@@ -545,7 +640,7 @@ const __vue_inject_styles__$1 = undefined;
545
640
  /* scoped */
546
641
  const __vue_scope_id__$1 = undefined;
547
642
  /* module identifier */
548
- const __vue_module_identifier__$1 = "data-v-3124a55a";
643
+ const __vue_module_identifier__$1 = "data-v-77c84891";
549
644
  /* functional template */
550
645
  const __vue_is_functional_template__$1 = false;
551
646
  /* style inject */
@@ -559,7 +654,7 @@ var accessibilityPlot = normalizeComponent_1({
559
654
  var script = {
560
655
  name: 'citationsPlot',
561
656
  data: () => ({
562
- divId: randstr('cit_plot')
657
+ divId: randstr('cit_plot_')
563
658
  }),
564
659
  props: {
565
660
  dataTraces: {
@@ -731,7 +826,7 @@ const __vue_inject_styles__ = undefined;
731
826
  /* scoped */
732
827
  const __vue_scope_id__ = undefined;
733
828
  /* module identifier */
734
- const __vue_module_identifier__ = "data-v-64c53c55";
829
+ const __vue_module_identifier__ = "data-v-4ac5e814";
735
830
  /* functional template */
736
831
  const __vue_is_functional_template__ = false;
737
832
  /* style inject */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inb/oeb_visualizations",
3
- "version": "0.0.6",
3
+ "version": "0.0.8-beta",
4
4
  "description": "Collection of Vue components for data visualization in OpenEBench.",
5
5
  "author": "evamart",
6
6
  "license": "MIT",