@teipublisher/pb-components 2.25.5 → 2.25.6

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 (128) 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 +8 -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-leaflet-map.html +1 -1
  9. package/dist/demo/pb-repeat.html +1 -3
  10. package/dist/demo/pb-view3.html +1 -1
  11. package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-72125e67.js} +1 -1
  12. package/dist/pb-code-editor.js +25 -20
  13. package/dist/pb-component-docs.js +58 -54
  14. package/dist/pb-components-bundle.js +1827 -1520
  15. package/dist/pb-edit-app.js +167 -107
  16. package/dist/pb-elements.json +54 -54
  17. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  18. package/dist/pb-leaflet-map.js +23 -23
  19. package/dist/pb-mei.js +56 -41
  20. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  21. package/dist/pb-odd-editor.js +925 -758
  22. package/dist/pb-tify.js +2 -2
  23. package/dist/{vaadin-element-mixin-859a0132.js → vaadin-element-mixin-ad07ba25.js} +88 -61
  24. package/gh-pages.js +5 -3
  25. package/package.json +2 -2
  26. package/pb-elements.json +54 -54
  27. package/src/assets/components.css +5 -5
  28. package/src/authority/airtable.js +20 -21
  29. package/src/authority/anton.js +129 -129
  30. package/src/authority/custom.js +23 -21
  31. package/src/authority/geonames.js +38 -32
  32. package/src/authority/gnd.js +47 -42
  33. package/src/authority/kbga.js +137 -134
  34. package/src/authority/metagrid.js +44 -46
  35. package/src/authority/reconciliation.js +66 -67
  36. package/src/authority/registry.js +4 -4
  37. package/src/docs/pb-component-docs.js +2 -2
  38. package/src/docs/pb-component-view.js +5 -5
  39. package/src/docs/pb-components-list.js +2 -2
  40. package/src/docs/pb-demo-snippet.js +2 -2
  41. package/src/dts-client.js +299 -297
  42. package/src/dts-select-endpoint.js +90 -82
  43. package/src/parse-date-service.js +184 -135
  44. package/src/pb-ajax.js +171 -167
  45. package/src/pb-authority-lookup.js +96 -81
  46. package/src/pb-autocomplete.js +292 -280
  47. package/src/pb-blacklab-highlight.js +264 -259
  48. package/src/pb-blacklab-results.js +236 -221
  49. package/src/pb-browse-docs.js +540 -475
  50. package/src/pb-browse.js +68 -65
  51. package/src/pb-clipboard.js +79 -76
  52. package/src/pb-code-editor.js +110 -102
  53. package/src/pb-code-highlight.js +209 -204
  54. package/src/pb-codepen.js +79 -72
  55. package/src/pb-collapse.js +149 -146
  56. package/src/pb-combo-box.js +190 -190
  57. package/src/pb-components-bundle.js +1 -1
  58. package/src/pb-custom-form.js +150 -149
  59. package/src/pb-document.js +89 -90
  60. package/src/pb-download.js +208 -195
  61. package/src/pb-drawer.js +145 -148
  62. package/src/pb-edit-app.js +301 -229
  63. package/src/pb-edit-xml.js +99 -96
  64. package/src/pb-events.js +114 -107
  65. package/src/pb-facs-link.js +104 -102
  66. package/src/pb-facsimile.js +411 -413
  67. package/src/pb-formula.js +151 -153
  68. package/src/pb-geolocation.js +129 -131
  69. package/src/pb-grid-action.js +53 -56
  70. package/src/pb-grid.js +231 -228
  71. package/src/pb-highlight.js +140 -140
  72. package/src/pb-hotkeys.js +40 -42
  73. package/src/pb-i18n.js +101 -104
  74. package/src/pb-image-strip.js +84 -78
  75. package/src/pb-lang.js +83 -70
  76. package/src/pb-leaflet-map.js +488 -485
  77. package/src/pb-link.js +126 -124
  78. package/src/pb-load.js +431 -426
  79. package/src/pb-login.js +275 -254
  80. package/src/pb-manage-odds.js +364 -318
  81. package/src/pb-map-icon.js +89 -89
  82. package/src/pb-map-layer.js +85 -85
  83. package/src/pb-markdown.js +90 -99
  84. package/src/pb-media-query.js +74 -72
  85. package/src/pb-mei.js +306 -295
  86. package/src/pb-message.js +143 -130
  87. package/src/pb-mixin.js +269 -264
  88. package/src/pb-navigation.js +80 -82
  89. package/src/pb-observable.js +38 -38
  90. package/src/pb-odd-editor.js +1056 -958
  91. package/src/pb-odd-elementspec-editor.js +348 -297
  92. package/src/pb-odd-model-editor.js +1058 -898
  93. package/src/pb-odd-parameter-editor.js +200 -178
  94. package/src/pb-odd-rendition-editor.js +136 -124
  95. package/src/pb-page.js +432 -422
  96. package/src/pb-paginate.js +202 -190
  97. package/src/pb-panel.js +191 -179
  98. package/src/pb-popover-themes.js +7 -5
  99. package/src/pb-popover.js +296 -287
  100. package/src/pb-print-preview.js +127 -127
  101. package/src/pb-progress.js +49 -49
  102. package/src/pb-repeat.js +105 -104
  103. package/src/pb-restricted.js +84 -77
  104. package/src/pb-search.js +238 -221
  105. package/src/pb-select-feature.js +127 -120
  106. package/src/pb-select-odd.js +132 -124
  107. package/src/pb-select-template.js +89 -78
  108. package/src/pb-select.js +251 -227
  109. package/src/pb-split-list.js +179 -174
  110. package/src/pb-svg.js +80 -79
  111. package/src/pb-table-column.js +54 -54
  112. package/src/pb-table-grid.js +221 -203
  113. package/src/pb-tabs.js +61 -63
  114. package/src/pb-tify.js +154 -154
  115. package/src/pb-timeline.js +271 -229
  116. package/src/pb-toggle-feature.js +198 -185
  117. package/src/pb-upload.js +184 -174
  118. package/src/pb-version.js +30 -30
  119. package/src/pb-view-annotate.js +132 -98
  120. package/src/pb-view.js +1282 -1263
  121. package/src/pb-zoom.js +40 -40
  122. package/src/polymer-hack.js +1 -1
  123. package/src/search-result-service.js +256 -223
  124. package/src/seed-element.js +13 -20
  125. package/src/settings.js +4 -4
  126. package/src/theming.js +91 -91
  127. package/src/urls.js +289 -289
  128. 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);