@teipublisher/pb-components 2.26.1-next.3 → 3.0.0

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 (154) 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 +4 -4
  4. package/.releaserc.json +2 -2
  5. package/CHANGELOG.md +262 -11
  6. package/Dockerfile +78 -70
  7. package/css/components.css +5 -5
  8. package/css/leaflet/images/layers.png +0 -0
  9. package/dist/demo/components.css +46 -1
  10. package/dist/demo/pb-browse-docs2.html +1 -1
  11. package/dist/demo/pb-dialog.html +3 -5
  12. package/dist/demo/pb-drawer2.html +1 -1
  13. package/dist/demo/pb-facsimile.html +2 -2
  14. package/dist/demo/pb-grid.html +19 -6
  15. package/dist/demo/pb-leaflet-map.html +1 -1
  16. package/dist/demo/pb-login.html +0 -2
  17. package/dist/demo/pb-message.html +1 -2
  18. package/dist/demo/pb-progress.html +2 -2
  19. package/dist/demo/pb-repeat.html +1 -3
  20. package/dist/demo/pb-search.html +7 -4
  21. package/dist/demo/pb-search3.html +1 -1
  22. package/dist/demo/pb-search4.html +2 -2
  23. package/dist/demo/pb-view3.html +1 -1
  24. package/dist/{iron-form-3b8dcaa7.js → iron-form-dfb3e3b1.js} +95 -95
  25. package/dist/paper-checkbox-645e1077.js +200 -0
  26. package/dist/{paper-icon-button-b1d31571.js → paper-icon-button-984162bd.js} +1 -1
  27. package/dist/{paper-checkbox-515a5284.js → paper-inky-focus-behavior-fa16796b.js} +58 -247
  28. package/dist/{paper-listbox-a3b7175c.js → paper-listbox-5f5d1cec.js} +152 -162
  29. package/dist/pb-code-editor.js +25 -20
  30. package/dist/pb-component-docs.js +68 -64
  31. package/dist/pb-components-bundle.js +1983 -2293
  32. package/dist/pb-edit-app.js +167 -107
  33. package/dist/pb-elements.json +176 -120
  34. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  35. package/dist/pb-leaflet-map.js +23 -23
  36. package/dist/pb-mei.js +56 -41
  37. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  38. package/dist/pb-odd-editor.js +1023 -782
  39. package/dist/pb-tify.js +2 -2
  40. package/dist/vaadin-element-mixin-beb74ffd.js +545 -0
  41. package/gh-pages.js +5 -3
  42. package/i18n/common/en.json +6 -0
  43. package/i18n/common/pl.json +2 -2
  44. package/lib/openseadragon.min.js +6 -6
  45. package/package.json +3 -3
  46. package/pb-elements.json +176 -120
  47. package/src/assets/components.css +5 -5
  48. package/src/authority/airtable.js +20 -21
  49. package/src/authority/anton.js +129 -129
  50. package/src/authority/custom.js +23 -21
  51. package/src/authority/geonames.js +38 -32
  52. package/src/authority/gnd.js +50 -42
  53. package/src/authority/kbga.js +137 -134
  54. package/src/authority/metagrid.js +44 -46
  55. package/src/authority/reconciliation.js +66 -67
  56. package/src/authority/registry.js +4 -4
  57. package/src/docs/pb-component-docs.js +2 -2
  58. package/src/docs/pb-component-view.js +5 -5
  59. package/src/docs/pb-components-list.js +2 -2
  60. package/src/docs/pb-demo-snippet.js +2 -2
  61. package/src/dts-client.js +299 -297
  62. package/src/dts-select-endpoint.js +90 -82
  63. package/src/parse-date-service.js +184 -135
  64. package/src/pb-ajax.js +158 -171
  65. package/src/pb-authority-lookup.js +191 -156
  66. package/src/pb-autocomplete.js +292 -280
  67. package/src/pb-blacklab-highlight.js +264 -259
  68. package/src/pb-blacklab-results.js +236 -221
  69. package/src/pb-browse-docs.js +540 -475
  70. package/src/pb-browse.js +68 -65
  71. package/src/pb-clipboard.js +79 -76
  72. package/src/pb-code-editor.js +110 -102
  73. package/src/pb-code-highlight.js +209 -204
  74. package/src/pb-codepen.js +79 -72
  75. package/src/pb-collapse.js +211 -151
  76. package/src/pb-combo-box.js +190 -190
  77. package/src/pb-components-bundle.js +1 -1
  78. package/src/pb-components.js +1 -0
  79. package/src/pb-custom-form.js +173 -153
  80. package/src/pb-dialog.js +98 -62
  81. package/src/pb-document.js +89 -90
  82. package/src/pb-download.js +212 -196
  83. package/src/pb-drawer.js +145 -148
  84. package/src/pb-edit-app.js +301 -229
  85. package/src/pb-edit-xml.js +100 -97
  86. package/src/pb-events.js +114 -107
  87. package/src/pb-facs-link.js +104 -102
  88. package/src/pb-facsimile.js +474 -410
  89. package/src/pb-formula.js +151 -153
  90. package/src/pb-geolocation.js +129 -131
  91. package/src/pb-grid-action.js +53 -56
  92. package/src/pb-grid.js +231 -228
  93. package/src/pb-highlight.js +140 -140
  94. package/src/pb-hotkeys.js +40 -42
  95. package/src/pb-i18n.js +101 -104
  96. package/src/pb-image-strip.js +84 -78
  97. package/src/pb-lang.js +142 -57
  98. package/src/pb-leaflet-map.js +488 -485
  99. package/src/pb-link.js +126 -124
  100. package/src/pb-load.js +431 -429
  101. package/src/pb-login.js +299 -244
  102. package/src/pb-manage-odds.js +352 -336
  103. package/src/pb-map-icon.js +89 -89
  104. package/src/pb-map-layer.js +85 -85
  105. package/src/pb-markdown.js +90 -99
  106. package/src/pb-media-query.js +74 -72
  107. package/src/pb-mei.js +306 -295
  108. package/src/pb-message.js +139 -97
  109. package/src/pb-mixin.js +269 -264
  110. package/src/pb-navigation.js +80 -95
  111. package/src/pb-observable.js +38 -38
  112. package/src/pb-odd-editor.js +1054 -958
  113. package/src/pb-odd-elementspec-editor.js +349 -298
  114. package/src/pb-odd-model-editor.js +1075 -909
  115. package/src/pb-odd-parameter-editor.js +200 -178
  116. package/src/pb-odd-rendition-editor.js +136 -124
  117. package/src/pb-page.js +431 -422
  118. package/src/pb-paginate.js +228 -179
  119. package/src/pb-panel.js +198 -182
  120. package/src/pb-popover-themes.js +15 -8
  121. package/src/pb-popover.js +296 -287
  122. package/src/pb-print-preview.js +127 -127
  123. package/src/pb-progress.js +51 -51
  124. package/src/pb-repeat.js +105 -104
  125. package/src/pb-restricted.js +84 -77
  126. package/src/pb-search.js +256 -228
  127. package/src/pb-select-feature.js +127 -120
  128. package/src/pb-select-odd.js +132 -124
  129. package/src/pb-select-template.js +89 -78
  130. package/src/pb-select.js +251 -227
  131. package/src/pb-split-list.js +179 -174
  132. package/src/pb-svg.js +80 -79
  133. package/src/pb-table-column.js +54 -54
  134. package/src/pb-table-grid.js +221 -203
  135. package/src/pb-tabs.js +61 -63
  136. package/src/pb-tify.js +154 -154
  137. package/src/pb-timeline.js +382 -249
  138. package/src/pb-toggle-feature.js +195 -187
  139. package/src/pb-upload.js +184 -174
  140. package/src/pb-version.js +30 -30
  141. package/src/pb-view-annotate.js +135 -98
  142. package/src/pb-view.js +1282 -1270
  143. package/src/pb-zoom.js +127 -45
  144. package/src/polymer-hack.js +1 -1
  145. package/src/search-result-service.js +256 -223
  146. package/src/seed-element.js +13 -20
  147. package/src/settings.js +4 -4
  148. package/src/theming.js +98 -91
  149. package/src/urls.js +289 -289
  150. package/src/utils.js +53 -51
  151. package/css/pb-styles.css +0 -51
  152. package/dist/vaadin-element-mixin-fe4a4883.js +0 -527
  153. package/src/assets/pb-styles.css +0 -51
  154. package/src/pb-light-dom.js +0 -41
@@ -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);