@teipublisher/pb-components 2.26.0-next-3.12 → 2.26.0-next-3.14

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.
Files changed (136) hide show
  1. package/.github/workflows/main.yml +3 -3
  2. package/.github/workflows/node.js.yml +3 -3
  3. package/.github/workflows/release.js.yml +3 -3
  4. package/CHANGELOG.md +43 -0
  5. package/Dockerfile +78 -70
  6. package/css/components.css +5 -5
  7. package/dist/demo/pb-drawer2.html +1 -1
  8. package/dist/demo/pb-grid.html +19 -6
  9. package/dist/demo/pb-leaflet-map.html +1 -1
  10. package/dist/demo/pb-progress.html +2 -2
  11. package/dist/demo/pb-repeat.html +1 -3
  12. package/dist/demo/pb-view3.html +1 -1
  13. package/dist/{iron-form-277f9d42.js → iron-form-78b43d38.js} +1 -1
  14. package/dist/{paper-checkbox-4f410b1f.js → paper-checkbox-d16f23be.js} +44 -44
  15. package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-2cd9e0b4.js} +3 -3
  16. package/dist/{paper-listbox-c2468542.js → paper-listbox-2ad5c882.js} +7 -7
  17. package/dist/pb-code-editor.js +25 -20
  18. package/dist/pb-component-docs.js +58 -54
  19. package/dist/pb-components-bundle.js +2057 -2351
  20. package/dist/pb-edit-app.js +167 -107
  21. package/dist/pb-elements.json +45 -45
  22. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  23. package/dist/pb-leaflet-map.js +23 -23
  24. package/dist/pb-mei.js +56 -41
  25. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  26. package/dist/pb-odd-editor.js +923 -756
  27. package/dist/pb-tify.js +2 -2
  28. package/dist/{vaadin-element-mixin-49ab4037.js → vaadin-element-mixin-c200b196.js} +179 -164
  29. package/gh-pages.js +5 -3
  30. package/i18n/common/pl.json +2 -2
  31. package/lib/openseadragon.min.js +1 -1
  32. package/package.json +2 -2
  33. package/pb-elements.json +45 -45
  34. package/src/assets/components.css +5 -5
  35. package/src/authority/airtable.js +20 -21
  36. package/src/authority/anton.js +129 -129
  37. package/src/authority/custom.js +23 -21
  38. package/src/authority/geonames.js +38 -32
  39. package/src/authority/gnd.js +47 -42
  40. package/src/authority/kbga.js +137 -134
  41. package/src/authority/metagrid.js +44 -46
  42. package/src/authority/reconciliation.js +66 -67
  43. package/src/authority/registry.js +4 -4
  44. package/src/docs/pb-component-docs.js +2 -2
  45. package/src/docs/pb-component-view.js +5 -5
  46. package/src/docs/pb-components-list.js +2 -2
  47. package/src/docs/pb-demo-snippet.js +2 -2
  48. package/src/dts-client.js +299 -297
  49. package/src/dts-select-endpoint.js +90 -82
  50. package/src/parse-date-service.js +184 -135
  51. package/src/pb-ajax.js +150 -146
  52. package/src/pb-authority-lookup.js +183 -146
  53. package/src/pb-autocomplete.js +292 -280
  54. package/src/pb-blacklab-highlight.js +264 -259
  55. package/src/pb-blacklab-results.js +236 -221
  56. package/src/pb-browse-docs.js +540 -475
  57. package/src/pb-browse.js +68 -65
  58. package/src/pb-clipboard.js +79 -76
  59. package/src/pb-code-editor.js +110 -102
  60. package/src/pb-code-highlight.js +209 -204
  61. package/src/pb-codepen.js +79 -72
  62. package/src/pb-collapse.js +212 -207
  63. package/src/pb-combo-box.js +190 -190
  64. package/src/pb-components-bundle.js +1 -1
  65. package/src/pb-custom-form.js +151 -149
  66. package/src/pb-dialog.js +94 -85
  67. package/src/pb-document.js +89 -90
  68. package/src/pb-download.js +210 -198
  69. package/src/pb-drawer.js +145 -148
  70. package/src/pb-edit-app.js +301 -229
  71. package/src/pb-edit-xml.js +98 -96
  72. package/src/pb-events.js +114 -107
  73. package/src/pb-facs-link.js +104 -102
  74. package/src/pb-facsimile.js +419 -414
  75. package/src/pb-formula.js +151 -153
  76. package/src/pb-geolocation.js +129 -131
  77. package/src/pb-grid-action.js +53 -56
  78. package/src/pb-grid.js +231 -228
  79. package/src/pb-highlight.js +140 -140
  80. package/src/pb-hotkeys.js +40 -42
  81. package/src/pb-i18n.js +101 -104
  82. package/src/pb-image-strip.js +84 -78
  83. package/src/pb-lang.js +132 -128
  84. package/src/pb-leaflet-map.js +488 -485
  85. package/src/pb-link.js +126 -124
  86. package/src/pb-load.js +431 -426
  87. package/src/pb-login.js +291 -248
  88. package/src/pb-manage-odds.js +364 -318
  89. package/src/pb-map-icon.js +89 -89
  90. package/src/pb-map-layer.js +85 -85
  91. package/src/pb-markdown.js +90 -99
  92. package/src/pb-media-query.js +74 -72
  93. package/src/pb-mei.js +306 -295
  94. package/src/pb-message.js +144 -144
  95. package/src/pb-mixin.js +269 -264
  96. package/src/pb-navigation.js +80 -82
  97. package/src/pb-observable.js +38 -38
  98. package/src/pb-odd-editor.js +1053 -955
  99. package/src/pb-odd-elementspec-editor.js +348 -297
  100. package/src/pb-odd-model-editor.js +1061 -901
  101. package/src/pb-odd-parameter-editor.js +200 -178
  102. package/src/pb-odd-rendition-editor.js +136 -124
  103. package/src/pb-page.js +431 -421
  104. package/src/pb-paginate.js +202 -190
  105. package/src/pb-panel.js +198 -182
  106. package/src/pb-popover-themes.js +7 -5
  107. package/src/pb-popover.js +296 -287
  108. package/src/pb-print-preview.js +127 -127
  109. package/src/pb-progress.js +51 -51
  110. package/src/pb-repeat.js +105 -104
  111. package/src/pb-restricted.js +84 -77
  112. package/src/pb-search.js +252 -241
  113. package/src/pb-select-feature.js +127 -120
  114. package/src/pb-select-odd.js +132 -124
  115. package/src/pb-select-template.js +89 -78
  116. package/src/pb-select.js +251 -227
  117. package/src/pb-split-list.js +179 -174
  118. package/src/pb-svg.js +80 -79
  119. package/src/pb-table-column.js +54 -54
  120. package/src/pb-table-grid.js +221 -203
  121. package/src/pb-tabs.js +61 -63
  122. package/src/pb-tify.js +154 -154
  123. package/src/pb-timeline.js +271 -229
  124. package/src/pb-toggle-feature.js +182 -175
  125. package/src/pb-upload.js +184 -174
  126. package/src/pb-version.js +30 -30
  127. package/src/pb-view-annotate.js +132 -98
  128. package/src/pb-view.js +1290 -1270
  129. package/src/pb-zoom.js +75 -59
  130. package/src/polymer-hack.js +1 -1
  131. package/src/search-result-service.js +256 -223
  132. package/src/seed-element.js +13 -20
  133. package/src/settings.js +4 -4
  134. package/src/theming.js +96 -96
  135. package/src/urls.js +289 -289
  136. package/src/utils.js +53 -51
@@ -1,10 +1,10 @@
1
1
  import { html, css } from 'lit-element';
2
2
  import { PbLoad } from './pb-load.js';
3
3
  import { waitOnce } from './pb-mixin.js';
4
- import { translate } from "./pb-i18n.js";
5
- import { themableMixin } from "./theming.js";
4
+ import { translate } from './pb-i18n.js';
5
+ import { themableMixin } from './theming.js';
6
6
  import { cmpVersion } from './utils.js';
7
- import { registry } from "./urls.js";
7
+ import { registry } from './urls.js';
8
8
 
9
9
  import '@polymer/paper-input/paper-input.js';
10
10
  import '@polymer/paper-button';
@@ -21,520 +21,585 @@ import '@cwmr/paper-autocomplete/paper-autocomplete-suggestions.js';
21
21
  * @slot toolbar - toolbar area
22
22
  * @slot - unnamed default slot
23
23
  * @slot footer - footer area
24
- *
24
+ *
25
25
  * @fires pb-collection - Sent to inform e.g. pb-upload about current collection
26
26
  * @fires pb-search-resubmit - When received, set facet values as received from the event
27
27
  * @fires pb-login - When received, refresh the view if the user changed
28
- *
28
+ *
29
29
  * @cssprop --pb-search-suggestions-background - Background for the autocomplete suggestions for the filter field
30
30
  * @cssprop --pb-search-suggestions-color - Text color for the autocomplete suggestion for the filter field
31
31
  * @cssprop --pb-search-label-color - Determines the color of small label above the sort by/filter by/filter fields
32
32
  * @cssprop --pb-search-input-color - Determines the color of the text in the sort by/filter by/filter fields
33
33
  * @cssprop --pb-search-focus-color - Color of the field labels and underline when in focus
34
34
  * @cssprop --pb-browse-toolbar-justify-content - How to justify the browse toolbar content, following flexbox justify-content property e.g. center, space-evenly, start...
35
- *
35
+ *
36
36
  * @csspart delete-button - the delete button
37
37
  * @csspart sort-dropdown - dropdown for sorting
38
38
  * @csspart filter-dropdown - dropdown for filtering
39
39
  * @csspart filter-input - input for filtering
40
40
  */
41
41
  export class PbBrowseDocs extends themableMixin(PbLoad) {
42
+ static get properties() {
43
+ return {
44
+ ...super.properties,
45
+ sortBy: {
46
+ type: String,
47
+ attribute: 'sort-by',
48
+ },
49
+ sortOptions: {
50
+ type: Array,
51
+ attribute: 'sort-options',
52
+ },
53
+ sortLabel: {
54
+ type: String,
55
+ },
56
+ filter: {
57
+ type: String,
58
+ },
59
+ filterBy: {
60
+ type: String,
61
+ attribute: 'filter-by',
62
+ },
63
+ filterOptions: {
64
+ type: Array,
65
+ attribute: 'filter-options',
66
+ },
67
+ filterByLabel: {
68
+ type: String,
69
+ },
70
+ filterPlaceholderLabel: {
71
+ type: String,
72
+ },
73
+ collection: {
74
+ type: String,
75
+ },
76
+ facets: {
77
+ type: Object,
78
+ },
79
+ /** Id of the pb-login element to connect to */
80
+ login: {
81
+ type: String,
82
+ },
83
+ /**
84
+ * If set, requires the logged in user to be member of
85
+ * the given group.
86
+ */
87
+ group: {
88
+ type: String,
89
+ },
90
+ subforms: {
91
+ type: String,
92
+ },
93
+ /**
94
+ * If set, rewrite URLs to load pages as static HTML files,
95
+ * so no TEI Publisher instance is required
96
+ */
97
+ static: {
98
+ type: Boolean,
99
+ },
100
+ _file: {
101
+ type: String,
102
+ },
103
+ _selected: {
104
+ type: Array,
105
+ },
106
+ _allowModification: {
107
+ type: Boolean,
108
+ },
109
+ _suggestions: {
110
+ type: Array,
111
+ },
112
+ };
113
+ }
114
+
115
+ constructor() {
116
+ super();
117
+ this.sortOptions = [];
118
+ this.sortLabel = 'browse.sort';
119
+ this.sortBy = 'default';
120
+ this.filter = '';
121
+ this.filterOptions = [
122
+ {
123
+ label: 'Title',
124
+ value: 'title',
125
+ },
126
+ ];
127
+ this.filterByLabel = 'browse.filter';
128
+ this.filterPlaceholderLabel = 'browse.filterPlaceholder';
129
+
130
+ this.filterBy = 'title';
131
+ this._allowModification = false;
132
+ this._suggestions = [];
133
+
134
+ this.static = false;
135
+ }
136
+
137
+ connectedCallback() {
138
+ super.connectedCallback();
139
+
140
+ waitOnce('pb-page-ready', () => {
141
+ if (registry.state.sort) {
142
+ this.sortBy = registry.state.sort;
143
+ }
144
+
145
+ if (registry.state.filter) {
146
+ this.filter = registry.state.filter;
147
+ this.filterBy = registry.state.filterBy || this.filterBy;
148
+ }
149
+
150
+ this.facets = {};
151
+ // registry get state by regex
152
+ // this.facets = registry.getParametersMatching(this, /^facet-.*$/)
153
+ Object.keys(registry.state).forEach(key => {
154
+ if (/^facet-.*$/.test(key)) {
155
+ const param = registry.state[key];
156
+ if (this.facets[key]) {
157
+ this.facets[key].push(param);
158
+ } else if (Array.isArray(param)) {
159
+ this.facets[key] = param;
160
+ } else {
161
+ this.facets[key] = [param];
162
+ }
163
+ }
164
+ });
42
165
 
43
- static get properties() {
44
- return {
45
- ...super.properties,
46
- sortBy: {
47
- type: String,
48
- attribute: 'sort-by'
49
- },
50
- sortOptions: {
51
- type: Array,
52
- attribute: 'sort-options'
53
- },
54
- sortLabel: {
55
- type: String
56
- },
57
- filter: {
58
- type: String
59
- },
60
- filterBy: {
61
- type: String,
62
- attribute: 'filter-by'
63
- },
64
- filterOptions: {
65
- type: Array,
66
- attribute: 'filter-options'
67
- },
68
- filterByLabel: {
69
- type: String
70
- },
71
- filterPlaceholderLabel: {
72
- type: String
73
- },
74
- collection: {
75
- type: String
76
- },
77
- facets: {
78
- type: Object
79
- },
80
- /** Id of the pb-login element to connect to */
81
- login: {
82
- type: String
83
- },
84
- /**
85
- * If set, requires the logged in user to be member of
86
- * the given group.
87
- */
88
- group: {
89
- type: String
90
- },
91
- subforms: {
92
- type: String
93
- },
94
- /**
95
- * If set, rewrite URLs to load pages as static HTML files,
96
- * so no TEI Publisher instance is required
97
- */
98
- static: {
99
- type: Boolean
100
- },
101
- _file: {
102
- type: String
103
- },
104
- _selected: {
105
- type: Array
106
- },
107
- _allowModification: {
108
- type: Boolean,
109
- },
110
- _suggestions: {
111
- type: Array
112
- }
113
- };
114
- }
115
-
116
- constructor() {
117
- super();
118
- this.sortOptions = [];
119
- this.sortLabel = 'browse.sort';
120
- this.sortBy = 'default';
121
- this.filter = '';
122
- this.filterOptions = [
123
- {
124
- label: 'Title',
125
- value: 'title'
126
- }
127
- ];
128
- this.filterByLabel = 'browse.filter';
129
- this.filterPlaceholderLabel = 'browse.filterPlaceholder';
130
-
131
- this.filterBy = 'title';
132
- this._allowModification = false;
133
- this._suggestions = [];
134
-
135
- this.static = false;
136
- }
137
-
138
- connectedCallback() {
139
- super.connectedCallback();
166
+ this.collection = registry.state.collection;
140
167
 
141
- waitOnce('pb-page-ready', () => {
142
- if (registry.state.sort) {
143
- this.sortBy = registry.state.sort;
144
- }
145
-
146
- if (registry.state.filter) {
147
- this.filter = registry.state.filter;
148
- this.filterBy = registry.state.filterBy || this.filterBy;
149
- }
150
-
151
- this.facets = {};
152
- // registry get state by regex
153
- // this.facets = registry.getParametersMatching(this, /^facet-.*$/)
154
- Object.keys(registry.state).forEach((key) => {
155
- if (/^facet-.*$/.test(key)) {
156
- const param = registry.state[key];
157
- if (this.facets[key]) {
158
- this.facets[key].push(param);
159
- } else if (Array.isArray(param)) {
160
- this.facets[key] = param;
161
- } else {
162
- this.facets[key] = [param];
163
- }
164
- }
165
- });
166
-
167
- this.collection = registry.state.collection;
168
-
169
- if (this.collection) {
170
- registry.replace(this, {
171
- collection: this.collection
172
- });
173
- }
174
- registry.subscribe(this, (state) => {
175
- this.collection = state.collection;
176
- this.load();
177
- });
178
- });
179
-
180
- this.subscribeTo('pb-search-resubmit', this._facets.bind(this));
181
- this.subscribeTo('pb-login', (ev) => {
182
- if (ev.detail.userChanged) {
183
- this._facets(ev);
184
- }
185
- }, []);
186
- document.addEventListener('pb-i18n-update', () => {
187
- // clear paper-listbox selection after language updates
188
- const lb = this.shadowRoot.getElementById('sort-list');
189
- let old = lb.selected;
190
- lb.selected = undefined;
191
- lb.selected = old;
192
-
193
- const fl = this.shadowRoot.getElementById('filter-list');
194
- old = fl.selected;
195
- fl.selected = undefined;
196
- fl.selected = old;
168
+ if (this.collection) {
169
+ registry.replace(this, {
170
+ collection: this.collection,
197
171
  });
198
- }
199
-
200
- firstUpdated() {
201
- waitOnce('pb-page-ready', (options) => {
202
- const loader = this.shadowRoot.getElementById('autocompleteLoader');
203
- if (cmpVersion(options.apiVersion, '1.0.0') >= 0) {
204
- loader.url = `${options.endpoint}/api/search/autocomplete`;
205
- if (!this.url) {
206
- this.url = 'api/collection';
207
- }
208
- } else {
209
- loader.url = `${options.endpoint}/modules/autocomplete.xql`;
210
- if (!this.url) {
211
- this.url = 'collection/';
212
- }
213
- }
214
- });
215
- this.shadowRoot.getElementById('autocomplete').addEventListener('autocomplete-change', this._autocomplete.bind(this));
216
-
217
- if (this.login) {
218
- const login = document.getElementById(this.login);
219
- if (!login) {
220
- console.error('<pb-browse-docs> connected pb-login element not found!');
221
- } else {
222
- this.subscribeTo('pb-login', (ev) => {
223
- this._allowModification = this._loggedIn(ev.detail.user, ev.detail.group);
224
- }, []);
225
- this._allowModification = login.loggedIn && this._loggedIn(login.user, login.groups);
226
- }
172
+ }
173
+ registry.subscribe(this, state => {
174
+ this.collection = state.collection;
175
+ this.load();
176
+ });
177
+ });
178
+
179
+ this.subscribeTo('pb-search-resubmit', this._facets.bind(this));
180
+ this.subscribeTo(
181
+ 'pb-login',
182
+ ev => {
183
+ if (ev.detail.userChanged) {
184
+ this._facets(ev);
227
185
  }
228
-
229
- this.shadowRoot.getElementById('sort-list').addEventListener('selected-item-changed', this._sort.bind(this));
230
- this.shadowRoot.getElementById('delete').addEventListener('click', this._handleDelete.bind(this));
231
- super.firstUpdated();
232
- }
233
-
234
- render() {
235
- return html`
236
- <custom-style>
237
- <style>
238
- :host {
239
- --suggestions-item: {
240
- color: var(--pb-search-suggestions-color, black);
241
- };
242
- --suggestions-wrapper: {
243
- background: var(--pb-search-suggestions-background, white);
244
- }
245
- }
246
- </style>
247
- </custom-style>
248
- <slot name="header"></slot>
249
- <div class="toolbar">
250
- <paper-dropdown-menu id="sort" label="${translate(this.sortLabel)}" part="sort-dropdown">
251
- <paper-listbox id="sort-list" selected="${this.sortBy}" slot="dropdown-content" class="dropdown-content" attr-for-selected="value">
252
- ${this.sortOptions.map(option =>
253
- html`<paper-item value="${option.value}">${translate(option.label)}</paper-item>`
254
- )}
255
- </paper-listbox>
256
- </paper-dropdown-menu>
257
- <div>
258
- <paper-dropdown-menu id="filterSelect" label="${translate(this.filterByLabel)}" part="filter-dropdown">
259
- <paper-listbox id="filter-list" selected="${this.filterBy}" slot="dropdown-content" class="dropdown-content" attr-for-selected="value" @selected-item-changed="${this._filterChanged}">
260
- ${this.filterOptions.map(option =>
261
- html`<paper-item value="${option.value}">${translate(option.label)}</paper-item>`
262
- )}
263
- </paper-listbox>
264
- </paper-dropdown-menu>
265
- <paper-input id="filterString" type="search" name="filter" label="${translate(this.filterPlaceholderLabel)}" value="${this.filter}"
266
- @keyup="${this._handleEnter}" part="filter-input">
267
- <iron-icon icon="search" @click="${this._filter}" slot="prefix"></iron-icon>
268
- </paper-input>
269
- <paper-autocomplete-suggestions id="autocomplete" for="filterString" source="${this._suggestions}" remote-source></paper-autocomplete-suggestions>
270
- </div>
271
- </div>
272
- <div class="toolbar">
273
- <slot name="toolbar"></slot>
274
- <paper-button id="delete" part="delete-button" title="${translate('browse.delete')}" class="${this._canModify(this._allowModification)}">
275
- <iron-icon icon="delete"></iron-icon>
276
- <span class="label">${translate('browse.delete')}</span>
277
- </paper-button>
278
- </div>
279
- <slot></slot>
280
- <slot name="footer"></slot>
281
-
282
- <iron-ajax
283
- id="loadContent"
284
- verbose
285
- handle-as="text"
286
- method="get"
287
- with-credentials
288
- @response="${this._handleContent}"
289
- @error="${this._handleError}"></iron-ajax>
290
- <iron-ajax
291
- id="autocompleteLoader"
292
- verbose
293
- handle-as="json"
294
- method="get"
295
- with-credentials
296
- @response="${this._updateSuggestions}"></iron-ajax>
297
-
298
- <paper-dialog id="deleteDialog">
299
- <h2>${translate('browse.delete')}</h2>
300
- <paper-dialog-scrollable>
301
- <p>${translate('browse.confirmDeletion', { count: (this._selected ? this._selected.length : 0) })}</p>
302
- </paper-dialog-scrollable>
303
- <div class="buttons">
304
- <paper-button dialog-confirm="dialog-confirm" autofocus @click="${this._confirmDelete}">${translate('dialogs.yes')}</paper-button>
305
- <paper-button dialog-confirm="dialog-cancel">${translate('dialogs.no')}</paper-button>
306
- </div>
307
- </paper-dialog>
308
- <paper-dialog id="errorDialog">
309
- <h2>${translate('dialogs.error')}</h2>
310
- <paper-dialog-scrollable></paper-dialog-scrollable>
311
- <div class="buttons">
312
- <paper-button dialog-confirm="dialog-confirm" autofocus="autofocus">
313
- ${translate('dialogs.close')}
314
- </paper-button>
315
- </div>
316
- </paper-dialog>
317
- `;
186
+ },
187
+ [],
188
+ );
189
+ document.addEventListener('pb-i18n-update', () => {
190
+ // clear paper-listbox selection after language updates
191
+ const lb = this.shadowRoot.getElementById('sort-list');
192
+ let old = lb.selected;
193
+ lb.selected = undefined;
194
+ lb.selected = old;
195
+
196
+ const fl = this.shadowRoot.getElementById('filter-list');
197
+ old = fl.selected;
198
+ fl.selected = undefined;
199
+ fl.selected = old;
200
+ });
201
+ }
202
+
203
+ firstUpdated() {
204
+ waitOnce('pb-page-ready', options => {
205
+ const loader = this.shadowRoot.getElementById('autocompleteLoader');
206
+ if (cmpVersion(options.apiVersion, '1.0.0') >= 0) {
207
+ loader.url = `${options.endpoint}/api/search/autocomplete`;
208
+ if (!this.url) {
209
+ this.url = 'api/collection';
210
+ }
211
+ } else {
212
+ loader.url = `${options.endpoint}/modules/autocomplete.xql`;
213
+ if (!this.url) {
214
+ this.url = 'collection/';
215
+ }
216
+ }
217
+ });
218
+ this.shadowRoot
219
+ .getElementById('autocomplete')
220
+ .addEventListener('autocomplete-change', this._autocomplete.bind(this));
221
+
222
+ if (this.login) {
223
+ const login = document.getElementById(this.login);
224
+ if (!login) {
225
+ console.error('<pb-browse-docs> connected pb-login element not found!');
226
+ } else {
227
+ this.subscribeTo(
228
+ 'pb-login',
229
+ ev => {
230
+ this._allowModification = this._loggedIn(ev.detail.user, ev.detail.group);
231
+ },
232
+ [],
233
+ );
234
+ this._allowModification = login.loggedIn && this._loggedIn(login.user, login.groups);
235
+ }
318
236
  }
319
237
 
320
- static get styles() {
321
- return css`
322
- :host {
323
- display: block;
324
- --paper-input-container-color: var(--pb-search-label-color, var(--paper-grey-500, #303030));
325
- --paper-input-container-input-color: var(--pb-search-input-color, var(--pb-color-primary, #000000));
326
- --paper-input-container-focus-color: var(--pb-search-focus-color, var(--paper-grey-500, #303030));
327
- }
328
-
329
- .toolbar {
330
- display: flex;
331
- justify-content: var(--pb-browse-toolbar-justify-content);
332
- }
333
-
334
- [name="toolbar"] {
335
- flex: 1 0;
336
- }
337
-
338
- #sort {
339
- display: block;
340
- }
341
-
342
- #filterString {
343
- position: relative;
344
- display: inline-block;
345
- vertical-align: bottom;
238
+ this.shadowRoot
239
+ .getElementById('sort-list')
240
+ .addEventListener('selected-item-changed', this._sort.bind(this));
241
+ this.shadowRoot
242
+ .getElementById('delete')
243
+ .addEventListener('click', this._handleDelete.bind(this));
244
+ super.firstUpdated();
245
+ }
246
+
247
+ render() {
248
+ return html`
249
+ <custom-style>
250
+ <style>
251
+ :host {
252
+ --suggestions-item: {
253
+ color: var(--pb-search-suggestions-color, black);
346
254
  }
347
-
348
- .hidden {
349
- display: none;
255
+ --suggestions-wrapper: {
256
+ background: var(--pb-search-suggestions-background, white);
350
257
  }
351
- `;
258
+ }
259
+ </style>
260
+ </custom-style>
261
+ <slot name="header"></slot>
262
+ <div class="toolbar">
263
+ <paper-dropdown-menu id="sort" label="${translate(this.sortLabel)}" part="sort-dropdown">
264
+ <paper-listbox
265
+ id="sort-list"
266
+ selected="${this.sortBy}"
267
+ slot="dropdown-content"
268
+ class="dropdown-content"
269
+ attr-for-selected="value"
270
+ >
271
+ ${this.sortOptions.map(
272
+ option =>
273
+ html`<paper-item value="${option.value}">${translate(option.label)}</paper-item>`,
274
+ )}
275
+ </paper-listbox>
276
+ </paper-dropdown-menu>
277
+ <div>
278
+ <paper-dropdown-menu
279
+ id="filterSelect"
280
+ label="${translate(this.filterByLabel)}"
281
+ part="filter-dropdown"
282
+ >
283
+ <paper-listbox
284
+ id="filter-list"
285
+ selected="${this.filterBy}"
286
+ slot="dropdown-content"
287
+ class="dropdown-content"
288
+ attr-for-selected="value"
289
+ @selected-item-changed="${this._filterChanged}"
290
+ >
291
+ ${this.filterOptions.map(
292
+ option =>
293
+ html`<paper-item value="${option.value}">${translate(option.label)}</paper-item>`,
294
+ )}
295
+ </paper-listbox>
296
+ </paper-dropdown-menu>
297
+ <paper-input
298
+ id="filterString"
299
+ type="search"
300
+ name="filter"
301
+ label="${translate(this.filterPlaceholderLabel)}"
302
+ value="${this.filter}"
303
+ @keyup="${this._handleEnter}"
304
+ part="filter-input"
305
+ >
306
+ <iron-icon icon="search" @click="${this._filter}" slot="prefix"></iron-icon>
307
+ </paper-input>
308
+ <paper-autocomplete-suggestions
309
+ id="autocomplete"
310
+ for="filterString"
311
+ source="${this._suggestions}"
312
+ remote-source
313
+ ></paper-autocomplete-suggestions>
314
+ </div>
315
+ </div>
316
+ <div class="toolbar">
317
+ <slot name="toolbar"></slot>
318
+ <paper-button
319
+ id="delete"
320
+ part="delete-button"
321
+ title="${translate('browse.delete')}"
322
+ class="${this._canModify(this._allowModification)}"
323
+ >
324
+ <iron-icon icon="delete"></iron-icon>
325
+ <span class="label">${translate('browse.delete')}</span>
326
+ </paper-button>
327
+ </div>
328
+ <slot></slot>
329
+ <slot name="footer"></slot>
330
+
331
+ <iron-ajax
332
+ id="loadContent"
333
+ verbose
334
+ handle-as="text"
335
+ method="get"
336
+ with-credentials
337
+ @response="${this._handleContent}"
338
+ @error="${this._handleError}"
339
+ ></iron-ajax>
340
+ <iron-ajax
341
+ id="autocompleteLoader"
342
+ verbose
343
+ handle-as="json"
344
+ method="get"
345
+ with-credentials
346
+ @response="${this._updateSuggestions}"
347
+ ></iron-ajax>
348
+
349
+ <paper-dialog id="deleteDialog">
350
+ <h2>${translate('browse.delete')}</h2>
351
+ <paper-dialog-scrollable>
352
+ <p>
353
+ ${translate('browse.confirmDeletion', {
354
+ count: this._selected ? this._selected.length : 0,
355
+ })}
356
+ </p>
357
+ </paper-dialog-scrollable>
358
+ <div class="buttons">
359
+ <paper-button dialog-confirm="dialog-confirm" autofocus @click="${this._confirmDelete}"
360
+ >${translate('dialogs.yes')}</paper-button
361
+ >
362
+ <paper-button dialog-confirm="dialog-cancel">${translate('dialogs.no')}</paper-button>
363
+ </div>
364
+ </paper-dialog>
365
+ <paper-dialog id="errorDialog">
366
+ <h2>${translate('dialogs.error')}</h2>
367
+ <paper-dialog-scrollable></paper-dialog-scrollable>
368
+ <div class="buttons">
369
+ <paper-button dialog-confirm="dialog-confirm" autofocus="autofocus">
370
+ ${translate('dialogs.close')}
371
+ </paper-button>
372
+ </div>
373
+ </paper-dialog>
374
+ `;
375
+ }
376
+
377
+ static get styles() {
378
+ return css`
379
+ :host {
380
+ display: block;
381
+ --paper-input-container-color: var(--pb-search-label-color, var(--paper-grey-500, #303030));
382
+ --paper-input-container-input-color: var(
383
+ --pb-search-input-color,
384
+ var(--pb-color-primary, #000000)
385
+ );
386
+ --paper-input-container-focus-color: var(
387
+ --pb-search-focus-color,
388
+ var(--paper-grey-500, #303030)
389
+ );
390
+ }
391
+
392
+ .toolbar {
393
+ display: flex;
394
+ justify-content: var(--pb-browse-toolbar-justify-content);
395
+ }
396
+
397
+ [name='toolbar'] {
398
+ flex: 1 0;
399
+ }
400
+
401
+ #sort {
402
+ display: block;
403
+ }
404
+
405
+ #filterString {
406
+ position: relative;
407
+ display: inline-block;
408
+ vertical-align: bottom;
409
+ }
410
+
411
+ .hidden {
412
+ display: none;
413
+ }
414
+ `;
415
+ }
416
+
417
+ getURL(params) {
418
+ if (this.static) {
419
+ // use a static URL
420
+ return `collections/${this.collection ? `${this.collection}/` : ''}${
421
+ params.start || '1'
422
+ }.html`;
352
423
  }
353
-
354
- getURL(params) {
355
- if (this.static) {
356
- // use a static URL
357
- return `collections/${this.collection ? this.collection + '/' : ''}${params.start || '1'}.html`;
358
- }
359
- const url = super.getURL(params);
360
- return this.collection ? `${url}/${this.collection}` : url;
424
+ const url = super.getURL(params);
425
+ return this.collection ? `${url}/${this.collection}` : url;
426
+ }
427
+
428
+ prepareParameters(params) {
429
+ params = this._paramsFromSubforms(params);
430
+ params.sort = this.sortBy;
431
+ if (this.filter) {
432
+ params.filter = this.filter;
433
+ params.browse = this.filterBy;
361
434
  }
362
-
363
- prepareParameters(params) {
364
- params = this._paramsFromSubforms(params);
365
- params.sort = this.sortBy;
366
- if (this.filter) {
367
- params.filter = this.filter;
368
- params.browse = this.filterBy;
369
- }
370
- if (this.facets) {
371
- params = Object.assign(params, this.facets);
372
- }
373
- return params;
435
+ if (this.facets) {
436
+ params = Object.assign(params, this.facets);
374
437
  }
375
-
376
- _paramsFromSubforms(params) {
377
- if (this.subforms) {
378
- document.querySelectorAll(this.subforms).forEach((form) => {
379
- if (form.serializeForm) {
380
- Object.assign(params, form.serializeForm());
381
- }
382
- });
438
+ return params;
439
+ }
440
+
441
+ _paramsFromSubforms(params) {
442
+ if (this.subforms) {
443
+ document.querySelectorAll(this.subforms).forEach(form => {
444
+ if (form.serializeForm) {
445
+ Object.assign(params, form.serializeForm());
383
446
  }
384
- return params;
447
+ });
385
448
  }
386
-
387
- /**
388
- * returns selected documents.
389
- *
390
- * @returns {Array}
391
- */
392
- getSelected() {
393
- const selected = [];
394
- if (this.container) {
395
- document.querySelectorAll(this.container).forEach((container) =>
396
- container.querySelectorAll('.document-select paper-checkbox[checked]').forEach((checkbox) => {
397
- selected.push(checkbox.value);
398
- })
399
- );
400
- } else {
401
- this.querySelectorAll('.document-select paper-checkbox[checked]').forEach((checkbox) => {
402
- selected.push(checkbox.value);
403
- });
404
- }
405
- return selected;
449
+ return params;
450
+ }
451
+
452
+ /**
453
+ * returns selected documents.
454
+ *
455
+ * @returns {Array}
456
+ */
457
+ getSelected() {
458
+ const selected = [];
459
+ if (this.container) {
460
+ document.querySelectorAll(this.container).forEach(container =>
461
+ container.querySelectorAll('.document-select paper-checkbox[checked]').forEach(checkbox => {
462
+ selected.push(checkbox.value);
463
+ }),
464
+ );
465
+ } else {
466
+ this.querySelectorAll('.document-select paper-checkbox[checked]').forEach(checkbox => {
467
+ selected.push(checkbox.value);
468
+ });
406
469
  }
407
-
408
- _filter() {
409
- const filter = this.shadowRoot.getElementById('filterString').value;
410
- const filterBy = this.shadowRoot.getElementById('filter-list').selected;
411
- if (typeof filter !== 'undefined') {
412
- console.log('<pb-browse-docs> Filter by %s', filter);
413
- this.filter = filter;
414
- registry.commit(this, { filter, filterBy })
415
- this.load();
416
- }
470
+ return selected;
471
+ }
472
+
473
+ _filter() {
474
+ const filter = this.shadowRoot.getElementById('filterString').value;
475
+ const filterBy = this.shadowRoot.getElementById('filter-list').selected;
476
+ if (typeof filter !== 'undefined') {
477
+ console.log('<pb-browse-docs> Filter by %s', filter);
478
+ this.filter = filter;
479
+ registry.commit(this, { filter, filterBy });
480
+ this.load();
417
481
  }
482
+ }
418
483
 
419
- _filterChanged() {
420
- const filterBy = this.shadowRoot.getElementById('filter-list').selected;
421
- if (filterBy && filterBy !== this.filterBy) {
422
- console.log('<pb-browse-docs> Filtering on %s', filterBy);
423
- this.filterBy = filterBy;
424
- }
484
+ _filterChanged() {
485
+ const filterBy = this.shadowRoot.getElementById('filter-list').selected;
486
+ if (filterBy && filterBy !== this.filterBy) {
487
+ console.log('<pb-browse-docs> Filtering on %s', filterBy);
488
+ this.filterBy = filterBy;
425
489
  }
490
+ }
426
491
 
427
- _sort() {
428
- const sortBy = this.shadowRoot.getElementById('sort-list').selected;
429
- if (sortBy && sortBy !== this.sortBy) {
430
- console.log('<pb-browse-docs> Sorting by %s', sortBy);
431
- this.sortBy = sortBy;
432
- registry.commit(this, { sort: sortBy })
492
+ _sort() {
493
+ const sortBy = this.shadowRoot.getElementById('sort-list').selected;
494
+ if (sortBy && sortBy !== this.sortBy) {
495
+ console.log('<pb-browse-docs> Sorting by %s', sortBy);
496
+ this.sortBy = sortBy;
497
+ registry.commit(this, { sort: sortBy });
433
498
 
434
- this.load();
435
- }
499
+ this.load();
436
500
  }
437
-
438
- _facets(ev) {
439
- if (ev.detail && ev.detail.params) {
440
- registry.clearParametersMatching(this, /^(all-|facet-).*/);
441
- this.facets = ev.detail.params;
442
- this.start = 1;
443
- registry.commit(this, ev.detail.params)
444
- }
445
- this.load();
501
+ }
502
+
503
+ _facets(ev) {
504
+ if (ev.detail && ev.detail.params) {
505
+ registry.clearParametersMatching(this, /^(all-|facet-).*/);
506
+ this.facets = ev.detail.params;
507
+ this.start = 1;
508
+ registry.commit(this, ev.detail.params);
446
509
  }
447
-
448
- _onLoad(content) {
449
- window.scrollTo(0, 0);
450
- const div = content.querySelector('[data-root]');
451
- const collection = div && div.getAttribute('data-root');
452
- const writable = div && div.classList.contains('writable');
453
- this.emitTo('pb-collection', {
454
- writable,
455
- collection
456
- });
457
- document.querySelectorAll('[can-write]').forEach((elem) => {
458
- elem.disabled = !writable;
459
- });
460
- content.querySelectorAll('[data-collection]').forEach(link => {
461
- link.addEventListener('click', (ev) => {
462
- ev.preventDefault();
463
- this.collection = link.getAttribute('data-collection');
464
- this.start = 1;
465
- registry.commit(this, { collection: this.collection });
466
- console.log('<pb-browse-docs> loading collection %s', this.collection);
467
- this.load();
468
- });
469
- });
470
- }
471
-
472
- _handleDelete(target, ev) {
473
- const deleteDialog = this.shadowRoot.getElementById('deleteDialog');
474
- const selected = this.getSelected();
475
- if (selected.length > 0) {
476
- this._selected = selected;
477
- deleteDialog.open();
478
- }
479
- }
480
-
481
- _confirmDelete() {
482
- if (!(this._file || this._selected)) {
483
- return;
484
- }
485
-
486
- let files;
487
- if (this._selected) {
488
- files = this._selected;
489
- } else {
490
- files = [this._file];
491
- }
492
- console.log('<pb-browse-docs> Deleting %o', this._file);
493
- const params = {
494
- action: 'delete',
495
- 'docs[]': files
496
- };
497
- this._file = null;
498
- this._selected = null;
499
- this.load(params);
510
+ this.load();
511
+ }
512
+
513
+ _onLoad(content) {
514
+ window.scrollTo(0, 0);
515
+ const div = content.querySelector('[data-root]');
516
+ const collection = div && div.getAttribute('data-root');
517
+ const writable = div && div.classList.contains('writable');
518
+ this.emitTo('pb-collection', {
519
+ writable,
520
+ collection,
521
+ });
522
+ document.querySelectorAll('[can-write]').forEach(elem => {
523
+ elem.disabled = !writable;
524
+ });
525
+ content.querySelectorAll('[data-collection]').forEach(link => {
526
+ link.addEventListener('click', ev => {
527
+ ev.preventDefault();
528
+ this.collection = link.getAttribute('data-collection');
529
+ this.start = 1;
530
+ registry.commit(this, { collection: this.collection });
531
+ console.log('<pb-browse-docs> loading collection %s', this.collection);
532
+ this.load();
533
+ });
534
+ });
535
+ }
536
+
537
+ _handleDelete(target, ev) {
538
+ const deleteDialog = this.shadowRoot.getElementById('deleteDialog');
539
+ const selected = this.getSelected();
540
+ if (selected.length > 0) {
541
+ this._selected = selected;
542
+ deleteDialog.open();
500
543
  }
544
+ }
501
545
 
502
- _loggedIn(user, groups) {
503
- if (user == null) {
504
- return false;
505
- }
506
- if (this.group) {
507
- if (!groups) {
508
- return false;
509
- }
510
- return groups.indexOf(this.group) > -1;
511
- }
512
- return true;
546
+ _confirmDelete() {
547
+ if (!(this._file || this._selected)) {
548
+ return;
513
549
  }
514
550
 
515
- _canModify(allowModification) {
516
- return allowModification ? '' : 'hidden';
551
+ let files;
552
+ if (this._selected) {
553
+ files = this._selected;
554
+ } else {
555
+ files = [this._file];
517
556
  }
518
-
519
- _autocomplete(ev) {
520
- const autocompleteLoader = this.shadowRoot.getElementById('autocompleteLoader');
521
- autocompleteLoader.params = {
522
- query: ev.detail.option.text,
523
- field: this.filterBy
524
- };
525
- autocompleteLoader.generateRequest();
557
+ console.log('<pb-browse-docs> Deleting %o', this._file);
558
+ const params = {
559
+ action: 'delete',
560
+ 'docs[]': files,
561
+ };
562
+ this._file = null;
563
+ this._selected = null;
564
+ this.load(params);
565
+ }
566
+
567
+ _loggedIn(user, groups) {
568
+ if (user == null) {
569
+ return false;
526
570
  }
527
-
528
- _updateSuggestions() {
529
- const autocomplete = this.shadowRoot.getElementById('autocomplete');
530
- const autocompleteLoader = this.shadowRoot.getElementById('autocompleteLoader');
531
- autocomplete.suggestions(autocompleteLoader.lastResponse);
571
+ if (this.group) {
572
+ if (!groups) {
573
+ return false;
574
+ }
575
+ return groups.indexOf(this.group) > -1;
532
576
  }
533
-
534
- _handleEnter(e) {
535
- if (e.keyCode === 13) {
536
- this._filter();
537
- }
577
+ return true;
578
+ }
579
+
580
+ _canModify(allowModification) {
581
+ return allowModification ? '' : 'hidden';
582
+ }
583
+
584
+ _autocomplete(ev) {
585
+ const autocompleteLoader = this.shadowRoot.getElementById('autocompleteLoader');
586
+ autocompleteLoader.params = {
587
+ query: ev.detail.option.text,
588
+ field: this.filterBy,
589
+ };
590
+ autocompleteLoader.generateRequest();
591
+ }
592
+
593
+ _updateSuggestions() {
594
+ const autocomplete = this.shadowRoot.getElementById('autocomplete');
595
+ const autocompleteLoader = this.shadowRoot.getElementById('autocompleteLoader');
596
+ autocomplete.suggestions(autocompleteLoader.lastResponse);
597
+ }
598
+
599
+ _handleEnter(e) {
600
+ if (e.keyCode === 13) {
601
+ this._filter();
538
602
  }
603
+ }
539
604
  }
540
- customElements.define('pb-browse-docs', PbBrowseDocs);
605
+ customElements.define('pb-browse-docs', PbBrowseDocs);