@teipublisher/pb-components 2.26.0-next-3.12 → 2.26.0-next-3.13
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/.github/workflows/main.yml +3 -3
- package/.github/workflows/node.js.yml +3 -3
- package/.github/workflows/release.js.yml +3 -3
- package/CHANGELOG.md +30 -0
- package/Dockerfile +78 -70
- package/css/components.css +5 -5
- package/dist/demo/pb-drawer2.html +1 -1
- package/dist/demo/pb-leaflet-map.html +1 -1
- package/dist/demo/pb-progress.html +2 -2
- package/dist/demo/pb-repeat.html +1 -3
- package/dist/demo/pb-view3.html +1 -1
- package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-72125e67.js} +1 -1
- package/dist/pb-code-editor.js +25 -20
- package/dist/pb-component-docs.js +58 -54
- package/dist/pb-components-bundle.js +1937 -1782
- package/dist/pb-edit-app.js +167 -107
- package/dist/pb-elements.json +45 -45
- package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
- package/dist/pb-leaflet-map.js +23 -23
- package/dist/pb-mei.js +56 -41
- package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
- package/dist/pb-odd-editor.js +923 -756
- package/dist/pb-tify.js +2 -2
- package/dist/{vaadin-element-mixin-49ab4037.js → vaadin-element-mixin-84fb7d82.js} +178 -163
- package/gh-pages.js +5 -3
- package/i18n/common/pl.json +2 -2
- package/lib/openseadragon.min.js +1 -1
- package/package.json +2 -2
- package/pb-elements.json +45 -45
- package/src/assets/components.css +5 -5
- package/src/authority/airtable.js +20 -21
- package/src/authority/anton.js +129 -129
- package/src/authority/custom.js +23 -21
- package/src/authority/geonames.js +38 -32
- package/src/authority/gnd.js +47 -42
- package/src/authority/kbga.js +137 -134
- package/src/authority/metagrid.js +44 -46
- package/src/authority/reconciliation.js +66 -67
- package/src/authority/registry.js +4 -4
- package/src/docs/pb-component-docs.js +2 -2
- package/src/docs/pb-component-view.js +5 -5
- package/src/docs/pb-components-list.js +2 -2
- package/src/docs/pb-demo-snippet.js +2 -2
- package/src/dts-client.js +299 -297
- package/src/dts-select-endpoint.js +90 -82
- package/src/parse-date-service.js +184 -135
- package/src/pb-ajax.js +150 -146
- package/src/pb-authority-lookup.js +183 -146
- package/src/pb-autocomplete.js +292 -280
- package/src/pb-blacklab-highlight.js +264 -259
- package/src/pb-blacklab-results.js +236 -221
- package/src/pb-browse-docs.js +540 -475
- package/src/pb-browse.js +68 -65
- package/src/pb-clipboard.js +79 -76
- package/src/pb-code-editor.js +110 -102
- package/src/pb-code-highlight.js +209 -204
- package/src/pb-codepen.js +79 -72
- package/src/pb-collapse.js +212 -207
- package/src/pb-combo-box.js +190 -190
- package/src/pb-components-bundle.js +1 -1
- package/src/pb-custom-form.js +151 -149
- package/src/pb-dialog.js +94 -85
- package/src/pb-document.js +89 -90
- package/src/pb-download.js +210 -198
- package/src/pb-drawer.js +145 -148
- package/src/pb-edit-app.js +301 -229
- package/src/pb-edit-xml.js +98 -96
- package/src/pb-events.js +114 -107
- package/src/pb-facs-link.js +104 -102
- package/src/pb-facsimile.js +411 -413
- package/src/pb-formula.js +151 -153
- package/src/pb-geolocation.js +129 -131
- package/src/pb-grid-action.js +53 -56
- package/src/pb-grid.js +231 -228
- package/src/pb-highlight.js +140 -140
- package/src/pb-hotkeys.js +40 -42
- package/src/pb-i18n.js +101 -104
- package/src/pb-image-strip.js +84 -78
- package/src/pb-lang.js +132 -128
- package/src/pb-leaflet-map.js +488 -485
- package/src/pb-link.js +126 -124
- package/src/pb-load.js +431 -426
- package/src/pb-login.js +291 -248
- package/src/pb-manage-odds.js +364 -318
- package/src/pb-map-icon.js +89 -89
- package/src/pb-map-layer.js +85 -85
- package/src/pb-markdown.js +90 -99
- package/src/pb-media-query.js +74 -72
- package/src/pb-mei.js +306 -295
- package/src/pb-message.js +144 -144
- package/src/pb-mixin.js +269 -264
- package/src/pb-navigation.js +80 -82
- package/src/pb-observable.js +38 -38
- package/src/pb-odd-editor.js +1053 -955
- package/src/pb-odd-elementspec-editor.js +348 -297
- package/src/pb-odd-model-editor.js +1061 -901
- package/src/pb-odd-parameter-editor.js +200 -178
- package/src/pb-odd-rendition-editor.js +136 -124
- package/src/pb-page.js +431 -421
- package/src/pb-paginate.js +202 -190
- package/src/pb-panel.js +191 -179
- package/src/pb-popover-themes.js +7 -5
- package/src/pb-popover.js +296 -287
- package/src/pb-print-preview.js +127 -127
- package/src/pb-progress.js +51 -51
- package/src/pb-repeat.js +105 -104
- package/src/pb-restricted.js +84 -77
- package/src/pb-search.js +252 -241
- package/src/pb-select-feature.js +127 -120
- package/src/pb-select-odd.js +132 -124
- package/src/pb-select-template.js +89 -78
- package/src/pb-select.js +251 -227
- package/src/pb-split-list.js +179 -174
- package/src/pb-svg.js +80 -79
- package/src/pb-table-column.js +54 -54
- package/src/pb-table-grid.js +221 -203
- package/src/pb-tabs.js +61 -63
- package/src/pb-tify.js +154 -154
- package/src/pb-timeline.js +271 -229
- package/src/pb-toggle-feature.js +182 -175
- package/src/pb-upload.js +184 -174
- package/src/pb-version.js +30 -30
- package/src/pb-view-annotate.js +132 -98
- package/src/pb-view.js +1289 -1270
- package/src/pb-zoom.js +75 -59
- package/src/polymer-hack.js +1 -1
- package/src/search-result-service.js +256 -223
- package/src/seed-element.js +13 -20
- package/src/settings.js +4 -4
- package/src/theming.js +96 -96
- package/src/urls.js +289 -289
- package/src/utils.js +53 -51
package/src/pb-timeline.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
|
-
import { SearchResultService } from
|
|
4
|
-
import { ParseDateService } from
|
|
5
|
-
import { pbMixin } from
|
|
3
|
+
import { SearchResultService } from './search-result-service.js';
|
|
4
|
+
import { ParseDateService } from './parse-date-service.js';
|
|
5
|
+
import { pbMixin } from './pb-mixin.js';
|
|
6
6
|
import '@polymer/iron-ajax';
|
|
7
7
|
import '@polymer/iron-icons';
|
|
8
8
|
import '@polymer/paper-icon-button';
|
|
9
|
-
import { translate } from
|
|
9
|
+
import { translate } from './pb-i18n.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* A timeline component to display time series data in a bar chart like view.
|
|
13
13
|
*
|
|
14
14
|
* Time series data can be displayed in one of 6 different scales:
|
|
15
|
-
*
|
|
15
|
+
*
|
|
16
16
|
* - by decade (10Y)
|
|
17
17
|
* - by 5 years (5Y)
|
|
18
18
|
* - by years (Y)
|
|
19
19
|
* - by month (M)
|
|
20
20
|
* - by week (W)
|
|
21
21
|
* - by day (D)
|
|
22
|
-
*
|
|
22
|
+
*
|
|
23
23
|
* The endpoint is expected to return a JSON object. Each property should either be a date or the special
|
|
24
24
|
* marker `?`, which indicates undated resources.
|
|
25
25
|
* The value associated with each entry
|
|
26
|
-
* should either correspond to a count of resources or an object with properties `count` and `info`.
|
|
26
|
+
* should either correspond to a count of resources or an object with properties `count` and `info`.
|
|
27
27
|
* `info` should be an array, containing HTML to be shown in a list within the tooltips.
|
|
28
|
-
* Expected JSON:
|
|
28
|
+
* Expected JSON:
|
|
29
29
|
* ```javascript
|
|
30
30
|
* {
|
|
31
31
|
* "1852-01-14": {
|
|
@@ -52,17 +52,17 @@ import { translate } from "./pb-i18n.js";
|
|
|
52
52
|
* <span slot="label">Angezeigter Zeitraum: </span>
|
|
53
53
|
* </pb-timeline>
|
|
54
54
|
* ```
|
|
55
|
-
* See https://www.briefedition.alfred-escher.ch/briefe/ for a running sample. The source code of the webpage is here: https://github.com/stazh/briefedition-escher. Relevant files are:
|
|
55
|
+
* See https://www.briefedition.alfred-escher.ch/briefe/ for a running sample. The source code of the webpage is here: https://github.com/stazh/briefedition-escher. Relevant files are:
|
|
56
56
|
* - [templates/people.html](https://github.com/stazh/briefedition-escher/blob/master/templates/people.html#L91) - usage of pb-timeline
|
|
57
57
|
* - [modules/custom-api.json](https://github.com/stazh/briefedition-escher/blob/master/modules/custom-api.json#L1080) - `/api/timeline` endpoint delivering required JSON object
|
|
58
|
-
*
|
|
58
|
+
*
|
|
59
59
|
* @slot label - Inserted before the label showing the currently displayed time range
|
|
60
|
-
*
|
|
60
|
+
*
|
|
61
61
|
* @fires pb-timeline-date-changed - Triggered when user clicks on a single entry
|
|
62
62
|
* @fires pb-timeline-daterange-changed - Triggered when user selects a range of entries
|
|
63
63
|
* @fires pb-timeline-reset-selection - Requests that the timeline is reset to initial state
|
|
64
64
|
* @fires pb-timeline-loaded - Timeline was loaded
|
|
65
|
-
*
|
|
65
|
+
*
|
|
66
66
|
* @cssprop --pb-timeline-height
|
|
67
67
|
* @cssprop --pb-timeline-padding
|
|
68
68
|
* @cssprop --pb-timeline-color-highlight
|
|
@@ -72,17 +72,15 @@ import { translate } from "./pb-i18n.js";
|
|
|
72
72
|
* @cssprop --pb-timeline-color-bin
|
|
73
73
|
* @cssprop --pb-timeline-title-font-size
|
|
74
74
|
* @cssprop --pb-timeline-tooltip-font-size
|
|
75
|
-
*
|
|
75
|
+
*
|
|
76
76
|
* @csspart label
|
|
77
77
|
* @csspart tooltip
|
|
78
78
|
* @csspart title
|
|
79
79
|
*/
|
|
80
80
|
export class PbTimeline extends pbMixin(LitElement) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
static get styles() {
|
|
81
|
+
static get styles() {
|
|
84
82
|
return css`
|
|
85
|
-
:host{
|
|
83
|
+
:host {
|
|
86
84
|
display: block;
|
|
87
85
|
}
|
|
88
86
|
.hidden {
|
|
@@ -121,8 +119,9 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
121
119
|
// justify-content: center;
|
|
122
120
|
position: relative;
|
|
123
121
|
}
|
|
124
|
-
.bin-container.border-left,
|
|
125
|
-
|
|
122
|
+
.bin-container.border-left,
|
|
123
|
+
.bin-container.unknown {
|
|
124
|
+
border-left: 1px solid rgba(0, 0, 0, 0.4);
|
|
126
125
|
}
|
|
127
126
|
.bin-container.unknown {
|
|
128
127
|
margin-left: 40px;
|
|
@@ -221,8 +220,9 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
221
220
|
top: -13px;
|
|
222
221
|
right: -10px;
|
|
223
222
|
}
|
|
224
|
-
#tooltip::after {
|
|
225
|
-
|
|
223
|
+
#tooltip::after {
|
|
224
|
+
/* small triangle that points to top */
|
|
225
|
+
content: '';
|
|
226
226
|
position: absolute;
|
|
227
227
|
bottom: 100%;
|
|
228
228
|
left: 10px;
|
|
@@ -236,7 +236,7 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
236
236
|
left: auto;
|
|
237
237
|
}
|
|
238
238
|
/* pure css close button for tooltip */
|
|
239
|
-
.close{
|
|
239
|
+
.close {
|
|
240
240
|
position: relative;
|
|
241
241
|
display: inline-block;
|
|
242
242
|
width: 50px;
|
|
@@ -247,7 +247,8 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
247
247
|
.close.rounded.black {
|
|
248
248
|
cursor: pointer;
|
|
249
249
|
}
|
|
250
|
-
.close::before,
|
|
250
|
+
.close::before,
|
|
251
|
+
.close::after {
|
|
251
252
|
content: '';
|
|
252
253
|
position: absolute;
|
|
253
254
|
height: 2px;
|
|
@@ -263,82 +264,85 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
263
264
|
.close::after {
|
|
264
265
|
transform: rotate(-45deg);
|
|
265
266
|
}
|
|
266
|
-
.close.thick::before,
|
|
267
|
+
.close.thick::before,
|
|
268
|
+
.close.thick::after {
|
|
267
269
|
height: 4px;
|
|
268
270
|
margin-top: -2px;
|
|
269
271
|
}
|
|
270
|
-
.close.black::before,
|
|
272
|
+
.close.black::before,
|
|
273
|
+
.close.black::after {
|
|
271
274
|
height: 8px;
|
|
272
275
|
margin-top: -4px;
|
|
273
276
|
}
|
|
274
|
-
.close.rounded::before,
|
|
277
|
+
.close.rounded::before,
|
|
278
|
+
.close.rounded::after {
|
|
275
279
|
border-radius: 5px;
|
|
276
280
|
}
|
|
277
281
|
`;
|
|
278
282
|
}
|
|
279
283
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
284
|
+
static get properties() {
|
|
285
|
+
return {
|
|
286
|
+
...super.properties,
|
|
287
|
+
/**
|
|
288
|
+
* start date for timeline to display
|
|
289
|
+
*/
|
|
290
|
+
startDate: {
|
|
291
|
+
type: String,
|
|
292
|
+
reflect: true,
|
|
293
|
+
attribute: 'start-date',
|
|
294
|
+
},
|
|
295
|
+
/**
|
|
296
|
+
* endDate for timeline to display
|
|
297
|
+
*/
|
|
298
|
+
endDate: {
|
|
299
|
+
type: String,
|
|
300
|
+
reflect: true,
|
|
301
|
+
attribute: 'end-date',
|
|
302
|
+
},
|
|
303
|
+
/**
|
|
304
|
+
* The scope for the timeline. Must be one of the pre-defined scopes.
|
|
305
|
+
* If not set, the component automatically tries to determine the best scope fitting the
|
|
306
|
+
* given time series.
|
|
307
|
+
*/
|
|
308
|
+
scope: {
|
|
309
|
+
type: String,
|
|
310
|
+
},
|
|
311
|
+
/**
|
|
312
|
+
* The scopes to consider for automatic scoping.
|
|
313
|
+
*
|
|
314
|
+
* Defaults to ["D", "W", "M", "Y", "5Y", "10Y"]
|
|
315
|
+
*/
|
|
316
|
+
scopes: {
|
|
317
|
+
type: Array,
|
|
318
|
+
},
|
|
319
|
+
maxInterval: {
|
|
320
|
+
type: Number,
|
|
321
|
+
attribute: 'max-interval',
|
|
322
|
+
},
|
|
323
|
+
/**
|
|
324
|
+
* Endpoint to load timeline data from. Expects response to be an
|
|
325
|
+
* object with key value pairs for (date, hits).
|
|
326
|
+
*
|
|
327
|
+
* Will be reloaded whenever 'start-date' or 'end-date' attributes change.
|
|
328
|
+
*/
|
|
329
|
+
url: {
|
|
330
|
+
type: String,
|
|
331
|
+
},
|
|
332
|
+
/**
|
|
333
|
+
* If set, data will be retrieved automatically on first load.
|
|
334
|
+
*/
|
|
335
|
+
auto: {
|
|
336
|
+
type: Boolean,
|
|
337
|
+
},
|
|
338
|
+
resettable: {
|
|
339
|
+
type: Boolean,
|
|
340
|
+
},
|
|
341
|
+
_language: {
|
|
342
|
+
type: String,
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
}
|
|
342
346
|
|
|
343
347
|
constructor() {
|
|
344
348
|
super();
|
|
@@ -348,7 +352,7 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
348
352
|
this.startDate = '';
|
|
349
353
|
this.endDate = '';
|
|
350
354
|
this.scope = '';
|
|
351
|
-
this.scopes = [
|
|
355
|
+
this.scopes = ['D', 'W', 'M', 'Y', '5Y', '10Y'];
|
|
352
356
|
this.maxInterval = 60;
|
|
353
357
|
this.url = '';
|
|
354
358
|
this.auto = false;
|
|
@@ -366,29 +370,29 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
366
370
|
loader.url = url;
|
|
367
371
|
loader.generateRequest();
|
|
368
372
|
});
|
|
369
|
-
this.subscribeTo('pb-i18n-update',
|
|
373
|
+
this.subscribeTo('pb-i18n-update', ev => {
|
|
370
374
|
this._language = ev.detail.language;
|
|
371
375
|
});
|
|
372
376
|
}
|
|
373
377
|
|
|
374
378
|
firstUpdated() {
|
|
375
|
-
this.bins = this.shadowRoot.querySelectorAll(
|
|
376
|
-
this.tooltip = this.shadowRoot.getElementById(
|
|
379
|
+
this.bins = this.shadowRoot.querySelectorAll('.bin-container');
|
|
380
|
+
this.tooltip = this.shadowRoot.getElementById('tooltip');
|
|
377
381
|
|
|
378
382
|
// global mouseup event
|
|
379
|
-
document.addEventListener(
|
|
383
|
+
document.addEventListener('mouseup', () => {
|
|
380
384
|
this._mouseUp();
|
|
381
|
-
})
|
|
385
|
+
});
|
|
382
386
|
// pb-timeline-daterange-changed event:
|
|
383
387
|
// changes daterange selection (marks bins on histogram)
|
|
384
388
|
// is triggered by the componeent itself but can be also triggered
|
|
385
389
|
// from outside by another component
|
|
386
|
-
document.addEventListener(
|
|
387
|
-
const startDateStr = event.detail
|
|
388
|
-
const endDateStr = event.detail
|
|
389
|
-
if (this._fullRangeSelected(startDateStr, endDateStr)){
|
|
390
|
+
document.addEventListener('pb-timeline-daterange-changed', event => {
|
|
391
|
+
const { startDateStr } = event.detail;
|
|
392
|
+
const { endDateStr } = event.detail;
|
|
393
|
+
if (this._fullRangeSelected(startDateStr, endDateStr)) {
|
|
390
394
|
// do not mark the whole histogram, reset selection instead
|
|
391
|
-
console.log(
|
|
395
|
+
console.log('_fullRangeSelected() is true');
|
|
392
396
|
this.resetSelection();
|
|
393
397
|
return;
|
|
394
398
|
}
|
|
@@ -398,38 +402,35 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
398
402
|
// resets selection (remove marking of all selected bins)
|
|
399
403
|
// is triggered by the componeent itself but can be also triggered
|
|
400
404
|
// from outside by another component
|
|
401
|
-
document.addEventListener(
|
|
405
|
+
document.addEventListener('pb-timeline-reset-selection', () => {
|
|
402
406
|
this.resetSelection();
|
|
403
407
|
this._hideTooltip();
|
|
404
408
|
});
|
|
405
409
|
}
|
|
406
410
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
updated
|
|
413
|
-
if(changedProperties.has('scope')){
|
|
414
|
-
|
|
415
|
-
if(this.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
console.error('unknown scope ', this.scope);
|
|
420
|
-
}
|
|
411
|
+
/**
|
|
412
|
+
* checks if 'scope' has changed and re-applies dataset accordingly
|
|
413
|
+
*
|
|
414
|
+
* @param changedProperties
|
|
415
|
+
*/
|
|
416
|
+
updated(changedProperties) {
|
|
417
|
+
if (changedProperties.has('scope')) {
|
|
418
|
+
if (this.searchResult) {
|
|
419
|
+
if (this.scopes.includes(this.scope)) {
|
|
420
|
+
this.setData(this.searchResult.export(this.scope));
|
|
421
|
+
} else {
|
|
422
|
+
console.error('unknown scope ', this.scope);
|
|
421
423
|
}
|
|
422
|
-
|
|
424
|
+
}
|
|
423
425
|
}
|
|
424
426
|
}
|
|
425
427
|
|
|
426
|
-
|
|
427
428
|
setData(dataObj) {
|
|
428
429
|
this.dataObj = dataObj;
|
|
429
430
|
this.maxValue = Math.max(...this.dataObj.data.map(binObj => binObj.value));
|
|
430
431
|
this.requestUpdate();
|
|
431
432
|
this.updateComplete.then(() => {
|
|
432
|
-
this.bins = this.shadowRoot.querySelectorAll(
|
|
433
|
+
this.bins = this.shadowRoot.querySelectorAll('.bin-container');
|
|
433
434
|
this.resetSelection();
|
|
434
435
|
this._resetTooltip();
|
|
435
436
|
});
|
|
@@ -442,35 +443,39 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
442
443
|
if (this.dataObj.data.length === 1) {
|
|
443
444
|
return this.dataObj.data[0].category;
|
|
444
445
|
}
|
|
445
|
-
return `${this.dataObj.data[0].selectionStart} – ${
|
|
446
|
+
return `${this.dataObj.data[0].selectionStart} – ${
|
|
447
|
+
this.dataObj.data[this.dataObj.data.length - 1].selectionEnd
|
|
448
|
+
}`;
|
|
446
449
|
}
|
|
447
450
|
|
|
448
451
|
getSelectedStartDateStr() {
|
|
449
|
-
return this.shadowRoot.querySelectorAll(
|
|
452
|
+
return this.shadowRoot.querySelectorAll('.bin-container.selected')[0].dataset.selectionstart;
|
|
450
453
|
}
|
|
451
454
|
|
|
452
455
|
getSelectedEndDateStr() {
|
|
453
|
-
const selectedBins = this.shadowRoot.querySelectorAll(
|
|
456
|
+
const selectedBins = this.shadowRoot.querySelectorAll('.bin-container.selected');
|
|
454
457
|
return selectedBins[selectedBins.length - 1].dataset.selectionend;
|
|
455
458
|
}
|
|
456
459
|
|
|
457
460
|
getSelectedCategories() {
|
|
458
|
-
const selectedBins = this.shadowRoot.querySelectorAll(
|
|
461
|
+
const selectedBins = this.shadowRoot.querySelectorAll('.bin-container.selected');
|
|
459
462
|
const categories = [];
|
|
460
|
-
selectedBins.forEach(
|
|
463
|
+
selectedBins.forEach(bin => categories.push(bin.dataset.category));
|
|
461
464
|
return categories;
|
|
462
465
|
}
|
|
463
466
|
|
|
464
467
|
getSelectedItemCount() {
|
|
465
|
-
const selectedBins = this.shadowRoot.querySelectorAll(
|
|
468
|
+
const selectedBins = this.shadowRoot.querySelectorAll('.bin-container.selected');
|
|
466
469
|
let count = 0;
|
|
467
|
-
selectedBins.forEach(
|
|
470
|
+
selectedBins.forEach(bin => {
|
|
471
|
+
count += parseInt(bin.dataset.value);
|
|
472
|
+
});
|
|
468
473
|
return count;
|
|
469
474
|
}
|
|
470
475
|
|
|
471
476
|
resetSelection() {
|
|
472
477
|
this.bins.forEach(bin => {
|
|
473
|
-
bin.classList.remove(
|
|
478
|
+
bin.classList.remove('selected');
|
|
474
479
|
});
|
|
475
480
|
this._resetSelectionProperty();
|
|
476
481
|
this._hideTooltip();
|
|
@@ -479,8 +484,9 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
479
484
|
select(startDateStr, endDateStr) {
|
|
480
485
|
this.bins.forEach(bin => {
|
|
481
486
|
if (bin.dataset.isodatestr >= startDateStr && bin.dataset.isodatestr <= endDateStr) {
|
|
482
|
-
bin.classList.add(
|
|
483
|
-
} else {
|
|
487
|
+
bin.classList.add('selected');
|
|
488
|
+
} else {
|
|
489
|
+
bin.classList.remove('selected');
|
|
484
490
|
}
|
|
485
491
|
});
|
|
486
492
|
this._displayTooltip();
|
|
@@ -488,7 +494,7 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
488
494
|
}
|
|
489
495
|
|
|
490
496
|
_fullRangeSelected(startDateStr, endDateStr) {
|
|
491
|
-
const matchingStartDate = startDateStr = this.bins[0].dataset.isodatestr;
|
|
497
|
+
const matchingStartDate = (startDateStr = this.bins[0].dataset.isodatestr);
|
|
492
498
|
const matchingEndDate = endDateStr === this.bins[this.bins.length - 1].dataset.isodatestr;
|
|
493
499
|
return matchingStartDate && matchingEndDate;
|
|
494
500
|
}
|
|
@@ -509,7 +515,12 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
509
515
|
const startDateStr = new ParseDateService().run(start);
|
|
510
516
|
const endDateStr = new ParseDateService().run(end);
|
|
511
517
|
const itemCount = this.getSelectedItemCount();
|
|
512
|
-
this._dispatchTimelineDaterangeChangedEvent(
|
|
518
|
+
this._dispatchTimelineDaterangeChangedEvent(
|
|
519
|
+
startDateStr,
|
|
520
|
+
endDateStr,
|
|
521
|
+
this.getSelectedCategories(),
|
|
522
|
+
itemCount,
|
|
523
|
+
);
|
|
513
524
|
}
|
|
514
525
|
}
|
|
515
526
|
}
|
|
@@ -518,22 +529,24 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
518
529
|
if (this.mousedown) {
|
|
519
530
|
this._brushing(event);
|
|
520
531
|
this._showtooltipSelection();
|
|
521
|
-
} else if (this.selection.start === undefined) {
|
|
532
|
+
} else if (this.selection.start === undefined) {
|
|
533
|
+
// no selection currently made
|
|
522
534
|
this._showtooltip(event);
|
|
523
535
|
}
|
|
524
536
|
}
|
|
525
537
|
|
|
526
538
|
_mouseenter() {
|
|
527
|
-
if (this.dataObj) {
|
|
539
|
+
if (this.dataObj) {
|
|
540
|
+
// if data is loaded
|
|
528
541
|
this._displayTooltip();
|
|
529
542
|
}
|
|
530
543
|
}
|
|
531
544
|
|
|
532
545
|
_getMousePosition(mouseEvent) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return { x
|
|
546
|
+
const rect = this.shadowRoot.querySelector('.wrapper').getBoundingClientRect();
|
|
547
|
+
const x = mouseEvent.clientX - rect.left + 1; // x position within the element.
|
|
548
|
+
const y = mouseEvent.clientY - rect.top + 1; // y position within the element.
|
|
549
|
+
return { x, y };
|
|
537
550
|
}
|
|
538
551
|
|
|
539
552
|
_brushing(event) {
|
|
@@ -543,8 +556,13 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
543
556
|
|
|
544
557
|
_dispatchTimelineDaterangeChangedEvent(startDateStr, endDateStr, categories, itemCount) {
|
|
545
558
|
if (startDateStr === '????-??-??') {
|
|
546
|
-
this.emitTo('pb-timeline-date-changed', {
|
|
547
|
-
|
|
559
|
+
this.emitTo('pb-timeline-date-changed', {
|
|
560
|
+
startDateStr: null,
|
|
561
|
+
endDateStr: null,
|
|
562
|
+
categories: ['?'],
|
|
563
|
+
count: itemCount,
|
|
564
|
+
});
|
|
565
|
+
} else if (startDateStr === endDateStr) {
|
|
548
566
|
if (this.dataObj.scope !== 'D') {
|
|
549
567
|
this.emitTo('pb-timeline-daterange-changed', {
|
|
550
568
|
startDateStr,
|
|
@@ -552,16 +570,16 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
552
570
|
scope: this.dataObj.scope,
|
|
553
571
|
categories,
|
|
554
572
|
count: itemCount,
|
|
555
|
-
label: this.label
|
|
573
|
+
label: this.label,
|
|
556
574
|
});
|
|
557
575
|
} else {
|
|
558
|
-
this.emitTo('pb-timeline-date-changed', {
|
|
559
|
-
startDateStr,
|
|
560
|
-
endDateStr: null,
|
|
561
|
-
scope: this.dataObj.scope,
|
|
562
|
-
categories,
|
|
576
|
+
this.emitTo('pb-timeline-date-changed', {
|
|
577
|
+
startDateStr,
|
|
578
|
+
endDateStr: null,
|
|
579
|
+
scope: this.dataObj.scope,
|
|
580
|
+
categories,
|
|
563
581
|
count: itemCount,
|
|
564
|
-
label: this.label
|
|
582
|
+
label: this.label,
|
|
565
583
|
});
|
|
566
584
|
}
|
|
567
585
|
} else {
|
|
@@ -571,7 +589,7 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
571
589
|
categories,
|
|
572
590
|
scope: this.dataObj.scope,
|
|
573
591
|
count: itemCount,
|
|
574
|
-
label: this.label
|
|
592
|
+
label: this.label,
|
|
575
593
|
});
|
|
576
594
|
}
|
|
577
595
|
}
|
|
@@ -584,59 +602,69 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
584
602
|
const interval = this._getElementInterval(event.currentTarget);
|
|
585
603
|
let offset;
|
|
586
604
|
if (interval[0] < interval[2]) {
|
|
587
|
-
offset = Math.round((
|
|
605
|
+
offset = Math.round((interval[0] + interval[1]) / 2 - 10);
|
|
588
606
|
this.tooltip.classList.remove('right');
|
|
589
607
|
} else {
|
|
590
|
-
offset = Math.round((
|
|
608
|
+
offset = Math.round((interval[0] + interval[1]) / 2 - this.tooltip.offsetWidth) + 10;
|
|
591
609
|
this.tooltip.classList.add('right');
|
|
592
610
|
}
|
|
593
|
-
this.tooltip.style.left = offset
|
|
611
|
+
this.tooltip.style.left = `${offset}px`;
|
|
594
612
|
const datestr = event.currentTarget.dataset.tooltip;
|
|
595
613
|
const value = this._numberWithCommas(event.currentTarget.dataset.value);
|
|
596
614
|
const info = event.currentTarget.querySelector('.info');
|
|
597
|
-
this.tooltip.querySelector(
|
|
598
|
-
|
|
615
|
+
this.tooltip.querySelector(
|
|
616
|
+
'#tooltip-text',
|
|
617
|
+
).innerHTML = `<div><strong>${datestr}</strong>: ${value}</div><ul>${
|
|
618
|
+
info ? info.innerHTML : ''
|
|
619
|
+
}</ul>`;
|
|
599
620
|
}
|
|
600
621
|
|
|
601
622
|
_showtooltipSelection() {
|
|
602
623
|
const selectedBins = this._getSelectedBins();
|
|
603
624
|
const intervalStart = this._getElementInterval(selectedBins[0])[0]; // get first selected element left boundary
|
|
604
|
-
const intervalEnd = this._getElementInterval(selectedBins[selectedBins.length-1])[1]; // get last selected element right boundary
|
|
625
|
+
const intervalEnd = this._getElementInterval(selectedBins[selectedBins.length - 1])[1]; // get last selected element right boundary
|
|
605
626
|
const interval = [intervalStart, intervalEnd];
|
|
606
|
-
const label = `${selectedBins[0].dataset.selectionstart} - ${
|
|
627
|
+
const label = `${selectedBins[0].dataset.selectionstart} - ${
|
|
628
|
+
selectedBins[selectedBins.length - 1].dataset.selectionend
|
|
629
|
+
}`;
|
|
607
630
|
const value = selectedBins.map(bin => Number(bin.dataset.value)).reduce((a, b) => a + b);
|
|
608
631
|
const valueFormatted = this._numberWithCommas(value);
|
|
609
|
-
this.tooltip.querySelector(
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
this.tooltip.
|
|
632
|
+
this.tooltip.querySelector(
|
|
633
|
+
'#tooltip-text',
|
|
634
|
+
).innerHTML = `<strong>${label}</strong>: ${valueFormatted}`;
|
|
635
|
+
this.tooltip.querySelector('#tooltip-close').classList.remove('hidden');
|
|
636
|
+
this.tooltip.classList.add('draggable');
|
|
637
|
+
const offset = Math.round((interval[0] + interval[1]) / 2 - this.tooltip.offsetWidth / 2);
|
|
638
|
+
this.tooltip.style.left = `${offset}px`;
|
|
614
639
|
}
|
|
615
640
|
|
|
616
641
|
_resetTooltip() {
|
|
617
642
|
this._hideTooltip();
|
|
618
643
|
this.tooltip.style.left = '-1000px';
|
|
619
|
-
this.tooltip.querySelector(
|
|
644
|
+
this.tooltip.querySelector('#tooltip-text').innerHTML = '';
|
|
620
645
|
}
|
|
621
646
|
|
|
622
647
|
_hideTooltip() {
|
|
623
648
|
if (this.selection.start === undefined) {
|
|
624
|
-
this.tooltip.classList.add(
|
|
625
|
-
this.tooltip.classList.remove(
|
|
626
|
-
this.tooltip.querySelector(
|
|
649
|
+
this.tooltip.classList.add('hidden');
|
|
650
|
+
this.tooltip.classList.remove('draggable');
|
|
651
|
+
this.tooltip.querySelector('#tooltip-close').classList.add('hidden');
|
|
627
652
|
}
|
|
628
653
|
}
|
|
629
654
|
|
|
630
655
|
_displayTooltip() {
|
|
631
|
-
this.tooltip.classList.remove(
|
|
656
|
+
this.tooltip.classList.remove('hidden');
|
|
632
657
|
}
|
|
633
658
|
|
|
634
659
|
_getElementInterval(nodeElement) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
660
|
+
const rect = this.shadowRoot.querySelector('.wrapper').getBoundingClientRect();
|
|
661
|
+
const bin = nodeElement;
|
|
662
|
+
const interval = [
|
|
663
|
+
bin.getBoundingClientRect().x,
|
|
664
|
+
bin.getBoundingClientRect().x + bin.getBoundingClientRect().width,
|
|
665
|
+
];
|
|
666
|
+
const x1 = interval[0] - rect.left + 1; // x position within the element.
|
|
667
|
+
const x2 = interval[1] - rect.left + 1; // x position within the element.
|
|
640
668
|
return [x1, x2, rect.width / 2];
|
|
641
669
|
}
|
|
642
670
|
|
|
@@ -645,16 +673,16 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
645
673
|
}
|
|
646
674
|
|
|
647
675
|
_getSelectedBins() {
|
|
648
|
-
return Array.prototype.slice
|
|
649
|
-
|
|
650
|
-
|
|
676
|
+
return Array.prototype.slice
|
|
677
|
+
.call(this.bins)
|
|
678
|
+
.filter(binContainer => binContainer.classList.contains('selected'));
|
|
651
679
|
}
|
|
652
680
|
|
|
653
681
|
_resetSelectionProperty() {
|
|
654
682
|
this.selection = {
|
|
655
683
|
start: undefined,
|
|
656
|
-
end: undefined
|
|
657
|
-
}
|
|
684
|
+
end: undefined,
|
|
685
|
+
};
|
|
658
686
|
}
|
|
659
687
|
|
|
660
688
|
_applySelectionToBins() {
|
|
@@ -663,18 +691,19 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
663
691
|
const elInterval = this._getElementInterval(bin);
|
|
664
692
|
// if (this.intervalsOverlapping(elInterval, selectionInterval)) {
|
|
665
693
|
if (this._areOverlapping(elInterval, selectionInterval)) {
|
|
666
|
-
bin.classList.add(
|
|
694
|
+
bin.classList.add('selected');
|
|
667
695
|
} else {
|
|
668
|
-
bin.classList.remove(
|
|
696
|
+
bin.classList.remove('selected');
|
|
669
697
|
}
|
|
670
|
-
})
|
|
698
|
+
});
|
|
671
699
|
}
|
|
672
700
|
|
|
673
701
|
_numberWithCommas(input) {
|
|
674
|
-
return new Intl.NumberFormat(this._language, {style: 'decimal'}).format(input);
|
|
702
|
+
return new Intl.NumberFormat(this._language, { style: 'decimal' }).format(input);
|
|
675
703
|
}
|
|
676
704
|
|
|
677
|
-
_areOverlapping(A, B) {
|
|
705
|
+
_areOverlapping(A, B) {
|
|
706
|
+
// check if 2 intervals are overlapping
|
|
678
707
|
return B[0] < A[0] ? B[1] > A[0] : B[0] < A[1];
|
|
679
708
|
}
|
|
680
709
|
|
|
@@ -682,27 +711,33 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
682
711
|
return html`
|
|
683
712
|
<div class="label" part="label">
|
|
684
713
|
<span class="label"><slot name="label"></slot>${this.label}</span>
|
|
685
|
-
${
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
714
|
+
${this.resettable
|
|
715
|
+
? html`
|
|
716
|
+
<paper-icon-button
|
|
717
|
+
id="clear"
|
|
718
|
+
icon="icons:clear"
|
|
719
|
+
title="${translate('timeline.clear')}"
|
|
720
|
+
@click="${this._dispatchPbTimelineResetSelectionEvent}"
|
|
721
|
+
></paper-icon-button>
|
|
722
|
+
`
|
|
723
|
+
: null}
|
|
691
724
|
</div>
|
|
692
|
-
<div
|
|
725
|
+
<div
|
|
726
|
+
class="wrapper ${!this.dataObj || this.dataObj.data.length <= 1 ? 'empty' : ''}"
|
|
693
727
|
@mouseenter="${this._mouseenter}"
|
|
694
|
-
@mouseleave="${this._hideTooltip}"
|
|
695
|
-
|
|
696
|
-
${this.renderTooltip()}
|
|
728
|
+
@mouseleave="${this._hideTooltip}"
|
|
729
|
+
>
|
|
730
|
+
${this.dataObj ? this.renderBins() : ''} ${this.renderTooltip()}
|
|
697
731
|
<iron-ajax
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
732
|
+
id="loadData"
|
|
733
|
+
verbose
|
|
734
|
+
handle-as="json"
|
|
735
|
+
method="get"
|
|
736
|
+
with-credentials
|
|
737
|
+
@response="${this._handleResponse}"
|
|
738
|
+
url="${this.url}?start=${this.startDate}&end=${this.endDate}"
|
|
739
|
+
?auto="${this.auto}"
|
|
740
|
+
></iron-ajax>
|
|
706
741
|
</div>
|
|
707
742
|
`;
|
|
708
743
|
}
|
|
@@ -715,7 +750,8 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
715
750
|
id="tooltip-close"
|
|
716
751
|
class="hidden"
|
|
717
752
|
@click="${this._dispatchPbTimelineResetSelectionEvent}"
|
|
718
|
-
|
|
753
|
+
>
|
|
754
|
+
<span class="close rounded black"></span>
|
|
719
755
|
</div>
|
|
720
756
|
</div>
|
|
721
757
|
`;
|
|
@@ -723,10 +759,11 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
723
759
|
|
|
724
760
|
renderBins() {
|
|
725
761
|
return html`
|
|
726
|
-
${this.dataObj.data.map(
|
|
727
|
-
|
|
728
|
-
<div
|
|
729
|
-
|
|
762
|
+
${this.dataObj.data.map(
|
|
763
|
+
(binObj, indx) => html`
|
|
764
|
+
<div
|
|
765
|
+
class="bin-container ${binObj.seperator ? 'border-left' : ''}
|
|
766
|
+
${indx % 2 === 0 ? 'grey' : 'white'} ${binObj.category === '?' ? 'unknown' : ''}"
|
|
730
767
|
data-tooltip="${binObj.tooltip}"
|
|
731
768
|
data-category="${binObj.category}"
|
|
732
769
|
data-selectionstart="${binObj.selectionStart}"
|
|
@@ -735,20 +772,24 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
735
772
|
data-datestr="${binObj.dateStr}"
|
|
736
773
|
data-value="${binObj.value}"
|
|
737
774
|
@mousemove="${this._mouseMove}"
|
|
738
|
-
@mousedown="${this._mouseDown}"
|
|
739
|
-
|
|
740
|
-
<
|
|
741
|
-
|
|
775
|
+
@mousedown="${this._mouseDown}"
|
|
776
|
+
>
|
|
777
|
+
<div
|
|
778
|
+
class="bin"
|
|
779
|
+
style="height: ${(binObj.value / this.maxValue) * this.maxHeight * this.multiplier}px"
|
|
780
|
+
></div>
|
|
781
|
+
<p
|
|
782
|
+
class="bin-title
|
|
783
|
+
${this.dataObj.binTitleRotated ? 'rotated' : ''}
|
|
742
784
|
${this.scope}"
|
|
743
|
-
|
|
785
|
+
>
|
|
786
|
+
${binObj.binTitle ? binObj.binTitle : ''}
|
|
744
787
|
</p>
|
|
745
|
-
${binObj.title ? html`
|
|
746
|
-
<p class="bins-title" part="title">${binObj.title}</p>
|
|
747
|
-
` : ""}
|
|
788
|
+
${binObj.title ? html` <p class="bins-title" part="title">${binObj.title}</p> ` : ''}
|
|
748
789
|
${this.renderInfo(binObj)}
|
|
749
790
|
</div>
|
|
750
|
-
|
|
751
|
-
|
|
791
|
+
`,
|
|
792
|
+
)}
|
|
752
793
|
`;
|
|
753
794
|
}
|
|
754
795
|
|
|
@@ -756,34 +797,35 @@ export class PbTimeline extends pbMixin(LitElement) {
|
|
|
756
797
|
if (binObj.info && binObj.info.length > 0 && binObj.info.length <= 10) {
|
|
757
798
|
return html`
|
|
758
799
|
<ul class="info">
|
|
759
|
-
|
|
800
|
+
${binObj.info.map(info => html`<li>${unsafeHTML(info)}</li>`)}
|
|
760
801
|
</ul>
|
|
761
802
|
`;
|
|
762
803
|
}
|
|
763
804
|
return null;
|
|
764
805
|
}
|
|
765
806
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
807
|
+
async _handleResponse() {
|
|
808
|
+
await this.updateComplete;
|
|
809
|
+
const loader = this.shadowRoot.getElementById('loadData');
|
|
810
|
+
const data = loader.lastResponse;
|
|
770
811
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
newJsonData = data;
|
|
778
|
-
}
|
|
779
|
-
this.searchResult = new SearchResultService(newJsonData, this.maxInterval, this.scopes);
|
|
780
|
-
this.setData(this.searchResult.export(this.scope));
|
|
781
|
-
this.emitTo('pb-timeline-loaded', {
|
|
782
|
-
value: true,
|
|
783
|
-
label: this.label
|
|
812
|
+
let newJsonData = {};
|
|
813
|
+
if (this.startDate && this.endDate) {
|
|
814
|
+
Object.keys(data)
|
|
815
|
+
.filter(key => key >= this.startDate && key < this.endDate)
|
|
816
|
+
.forEach(key => {
|
|
817
|
+
newJsonData[key] = data[key];
|
|
784
818
|
});
|
|
819
|
+
} else {
|
|
820
|
+
newJsonData = data;
|
|
785
821
|
}
|
|
786
|
-
|
|
822
|
+
this.searchResult = new SearchResultService(newJsonData, this.maxInterval, this.scopes);
|
|
823
|
+
this.setData(this.searchResult.export(this.scope));
|
|
824
|
+
this.emitTo('pb-timeline-loaded', {
|
|
825
|
+
value: true,
|
|
826
|
+
label: this.label,
|
|
827
|
+
});
|
|
828
|
+
}
|
|
787
829
|
}
|
|
788
830
|
|
|
789
831
|
customElements.define('pb-timeline', PbTimeline);
|