@teipublisher/pb-components 1.25.0 → 1.28.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.
@@ -29,7 +29,7 @@ export class PbOddParameterEditor extends LitElement {
29
29
  }
30
30
  .wrapper{
31
31
  display:grid;
32
- grid-template-columns:150px auto 50px;
32
+ grid-template-columns:150px auto 50px 50px;
33
33
  grid-column-gap:20px;
34
34
  grid-row-gap:20px;
35
35
  margin-bottom:10px;
@@ -37,8 +37,9 @@ export class PbOddParameterEditor extends LitElement {
37
37
  paper-dropdown-menu{
38
38
  align-self:start;
39
39
  }
40
- paper-icon-button{
41
- align-self:center;
40
+ paper-icon-button, paper-checkbox {
41
+ align-self: center;
42
+ margin-top: 16px;
42
43
  }
43
44
  `;
44
45
  }
@@ -56,7 +57,7 @@ export class PbOddParameterEditor extends LitElement {
56
57
  code="${this.value}"
57
58
  linter="${this.endpoint}/${cmpVersion(this.apiVersion, '1.0.0') ? 'modules/editor.xql' : 'api/lint'}"
58
59
  apiVersion="${this.apiVersion}"></pb-code-editor>
59
-
60
+ <paper-checkbox id="set" ?checked="${this.setParam}" @change="${this._handleCodeChange}">set</paper-checkbox>
60
61
  <paper-icon-button @click="${this._delete}" icon="delete" title="delete this parameter"></paper-icon-button>
61
62
  </div>
62
63
 
@@ -87,6 +88,10 @@ export class PbOddParameterEditor extends LitElement {
87
88
  parameters: {
88
89
  type: Object
89
90
  },
91
+ setParam: {
92
+ type: Boolean,
93
+ attribute: 'set'
94
+ },
90
95
  _currentParameters: {
91
96
  type: Array
92
97
  },
@@ -104,6 +109,7 @@ export class PbOddParameterEditor extends LitElement {
104
109
  super();
105
110
  this.name = '';
106
111
  this.value = '';
112
+ this.setParam = false;
107
113
  this.behaviour = '';
108
114
  this.currentParameters = [];
109
115
  this.parameters = {
@@ -189,7 +195,8 @@ export class PbOddParameterEditor extends LitElement {
189
195
  console.log('_handleCodeChange ', e);
190
196
  this.value = this.shadowRoot.getElementById('editor').getSource();
191
197
  this.name = this.shadowRoot.getElementById('combo').text;
192
- this.dispatchEvent(new CustomEvent('parameter-changed', { composed: true, bubbles: true, detail: { name: this.name, value: this.value } }));
198
+ this.setParam = this.shadowRoot.getElementById('set').checked;
199
+ this.dispatchEvent(new CustomEvent('parameter-changed', { composed: true, bubbles: true, detail: { name: this.name, value: this.value, set: this.setParam } }));
193
200
  }
194
201
 
195
202
 
@@ -0,0 +1,66 @@
1
+ import { LitElement } from 'lit-element';
2
+ import { html } from "gridjs";
3
+ import './pb-popover.js';
4
+
5
+ /**
6
+ * Defines a column within `pb-table-grid`.
7
+ */
8
+ export class PbTableColumn extends LitElement {
9
+ static get properties() {
10
+ return {
11
+ /**
12
+ * Column heading to display
13
+ */
14
+ label: {
15
+ type: String
16
+ },
17
+ /**
18
+ * Name of the JSON property containing the data
19
+ */
20
+ property: {
21
+ type: String
22
+ },
23
+ /**
24
+ * Should the column support sorting?
25
+ */
26
+ sort: {
27
+ type: Boolean
28
+ },
29
+ /**
30
+ * Optional fixed width of the column (e.g. '200px' or '30%')
31
+ */
32
+ width: {
33
+ type: String
34
+ },
35
+ ...super.properties
36
+ };
37
+ }
38
+
39
+ constructor() {
40
+ super();
41
+ this.label = 'no-label';
42
+ this.property = null;
43
+ this.sort = false;
44
+ this.width = null;
45
+ }
46
+
47
+ connectedCallback() {
48
+ super.connectedCallback();
49
+ }
50
+
51
+ data() {
52
+ const config = {
53
+ name: this.label,
54
+ sort: { enabled: this.sort },
55
+ formatter: (cell) => html(cell)
56
+ };
57
+ if (this.property) {
58
+ config.id = this.property;
59
+ }
60
+ if (this.width) {
61
+ config.width = this.width;
62
+ }
63
+ return config;
64
+ }
65
+ }
66
+ customElements.define('pb-table-column', PbTableColumn);
@@ -0,0 +1,212 @@
1
+ import { LitElement, html, css } from 'lit-element';
2
+ import { Grid } from "gridjs";
3
+ import { pbMixin } from './pb-mixin.js';
4
+ import { resolveURL } from './utils.js';
5
+ import '@polymer/paper-input/paper-input';
6
+ import '@polymer/iron-icons';
7
+ import '@polymer/iron-form';
8
+ import '@polymer/paper-icon-button';
9
+ import './pb-table-column.js';
10
+
11
+ /**
12
+ * A table grid based on [gridjs](https://gridjs.io/), which loads its data from a server endpoint
13
+ * specified in `source`. If `source` is a relative URI, it will be resolved relative to the
14
+ * TEI Publisher endpoint.
15
+ *
16
+ * The JSON data returned by the endpoint should be an object with two properties:
17
+ *
18
+ * * `count`: the overall number of rows available on the server
19
+ * * `results`: an array containing each record as an object
20
+ *
21
+ * The parameters send to the server are as follows:
22
+ *
23
+ *
24
+ * Parameter | Description
25
+ * ---------|----------
26
+ * limit | number of records to return for each page
27
+ * start | start offset from which to return records
28
+ * order | the id of the column to sort by
29
+ * dir | sort direction: either 'asc' or 'desc'
30
+ * search | an optional search string entered by the user
31
+ *
32
+ * Table columns are configured via nested `<pb-table-column>` elements:
33
+ *
34
+ * ```html
35
+ * <pb-table-column label="Name" property="name" sort width="33%"></pb-table-column>
36
+ * <pb-table-column label="Born" property="birth"></pb-table-column>
37
+ * <pb-table-column label="Died" property="death"></pb-table-column>
38
+ * ```
39
+ */
40
+ export class PbTableGrid extends pbMixin(LitElement) {
41
+ static get properties() {
42
+ return {
43
+ /**
44
+ * URI of the server-side endpoint to retrieve data from.
45
+ * Relative URIs are resolved relative to the configured TEI Publisher endpoint.
46
+ */
47
+ source: {
48
+ type: String
49
+ },
50
+ /**
51
+ * Path to the gridjs theme CSS files.
52
+ */
53
+ cssPath: {
54
+ type: String,
55
+ attribute: 'css-path'
56
+ },
57
+ /**
58
+ * If specified, columns (without a fixed width) will be resizable.
59
+ */
60
+ resizable: {
61
+ type: Boolean
62
+ },
63
+ perPage: {
64
+ type: Number,
65
+ attribute: 'per-page'
66
+ },
67
+ height: {
68
+ type: String
69
+ },
70
+ /**
71
+ * If specified, enable server-side search.
72
+ */
73
+ search: {
74
+ type: Boolean
75
+ },
76
+ _params: {
77
+ type: Object
78
+ },
79
+ ...super.properties
80
+ };
81
+ }
82
+
83
+ constructor() {
84
+ super();
85
+ this.cssPath = '../css/gridjs';
86
+ this._params = {};
87
+ this.resizable = false;
88
+ this.search = false;
89
+ this.perPage = 10;
90
+ this.height = null;
91
+ this.fixedHeader = false;
92
+ }
93
+
94
+ connectedCallback() {
95
+ super.connectedCallback();
96
+
97
+ this.subscribeTo('pb-search-resubmit', (ev) => {
98
+ this._params = Object.assign({}, ev.detail.params);
99
+ this._submit();
100
+ });
101
+
102
+ window.addEventListener('popstate', (ev) => {
103
+ this._params = ev.state;
104
+ this._submit();
105
+ });
106
+
107
+ if (!this.height) {
108
+ const property = getComputedStyle(this).getPropertyValue('--pb-table-grid-height');
109
+ if (property) {
110
+ this.height = property;
111
+ } else {
112
+ this.height = 'auto';
113
+ }
114
+ }
115
+ }
116
+
117
+ firstUpdated() {
118
+ const table = this.shadowRoot.getElementById('table');
119
+
120
+ const pbColumns = this.querySelectorAll('pb-table-column');
121
+ const columns = [];
122
+ pbColumns.forEach((column) => columns.push(column.data()));
123
+ PbTableGrid.waitOnce('pb-page-ready', () => {
124
+ this._params = this.getParameters();
125
+ const url = this.toAbsoluteURL(this.source);
126
+ const config = {
127
+ height: this.height,
128
+ fixedHeader: true,
129
+ columns,
130
+ resizable: this.resizable,
131
+ server: {
132
+ url,
133
+ then: data => data.results,
134
+ total: data => data.count
135
+ },
136
+ sort: {
137
+ multiColumn: false,
138
+ enabled: true,
139
+ server: {
140
+ url: (prev, cols) => {
141
+ if (!cols.length) return prev;
142
+ const col = cols[0];
143
+ return `${prev}${prev.indexOf('?') > -1 ? '&' : '?'}order=${columns[col.index].id}&dir=${col.direction === 1 ? 'asc' : 'desc'}`;
144
+ }
145
+ }
146
+ },
147
+ pagination: {
148
+ enabled: true,
149
+ limit: this.perPage,
150
+ server: {
151
+ url: (prev, page, limit) => {
152
+ const form = this.shadowRoot.getElementById('form');
153
+ if (form) {
154
+ Object.assign(this._params, form.serializeForm());
155
+ }
156
+ this._params.limit = limit;
157
+ this._params.start = page * limit;
158
+ this.setParameters(this._params);
159
+ this.pushHistory('grid', this._params);
160
+
161
+ return `${prev}${prev.indexOf('?') > -1 ? '&' : '?'}${new URLSearchParams(this._params).toString()}`;
162
+ }
163
+ }
164
+ }
165
+ };
166
+
167
+ this.grid = new Grid(config);
168
+ this.grid.on('load', () => {
169
+ this.emitTo('pb-results-received', {
170
+ "params": this._params
171
+ });
172
+ });
173
+
174
+ this.grid.render(table);
175
+ });
176
+ }
177
+
178
+ _submit() {
179
+ this.grid.forceRender();
180
+ }
181
+
182
+ render() {
183
+ const themes = resolveURL(this.cssPath);
184
+ return html`
185
+ <link href="${themes}/mermaid.min.css" rel="stylesheet">
186
+ ${
187
+ this.search ? html`
188
+ <iron-form id="form">
189
+ <form action="">
190
+ <paper-input id="search" name="search" label="Search" @keyup="${(e) => e.keyCode == 13 ? this._submit() : null}">
191
+ <paper-icon-button icon="search" @click="${this._submit}" slot="suffix"></paper-icon-button>
192
+ </paper-input>
193
+ </form>
194
+ </iron-form>
195
+ ` : null
196
+ }
197
+ <div id="table"></div>
198
+ `;
199
+ }
200
+
201
+ static get styles() {
202
+ return css`
203
+ :host {
204
+ display: block;
205
+ }
206
+ button {
207
+ border: 0;
208
+ }
209
+ `;
210
+ }
211
+ }
212
+ customElements.define('pb-table-grid', PbTableGrid);
@@ -454,7 +454,8 @@ class PbViewAnnotate extends PbView {
454
454
 
455
455
  console.log('<pb-view-annotate> Range: %o', range);
456
456
  const span = document.createElement('span');
457
- span.className = `annotation annotation-${teiRange.type} ${teiRange.type}`;
457
+ const addClass = teiRange.properties[this.key] === '' ? 'incomplete' : '';
458
+ span.className = `annotation annotation-${teiRange.type} ${teiRange.type} ${addClass}`;
458
459
  span.dataset.type = teiRange.type;
459
460
  span.dataset.annotation = JSON.stringify(teiRange.properties);
460
461
 
@@ -657,9 +658,12 @@ class PbViewAnnotate extends PbView {
657
658
  range = clearProperties(range);
658
659
  this.emitTo('pb-annotations-changed', { ranges: this._ranges });
659
660
  }
660
-
661
- const json = Object.assign(JSON.parse(span.dataset.annotation), properties);
661
+ const jsonOld = JSON.parse(span.dataset.annotation);
662
+ const json = Object.assign(jsonOld || {}, properties);
662
663
  span.dataset.annotation = JSON.stringify(json);
664
+ if (json[this.key] !== '') {
665
+ span.classList.remove('incomplete');
666
+ }
663
667
  }
664
668
 
665
669
  _editAnnotation(ev) {
@@ -753,7 +757,7 @@ class PbViewAnnotate extends PbView {
753
757
  ev.preventDefault();
754
758
  ev.stopPropagation();
755
759
  const type = span.dataset.type;
756
- const data = JSON.parse(span.dataset.annotation);
760
+ const data = JSON.parse(span.dataset.annotation) || {};
757
761
  const color = this._annotationColors.get(type);
758
762
  typeInd.innerHTML = type;
759
763
  typeInd.style.backgroundColor = `var(--pb-annotation-${type})`;
@@ -896,7 +900,7 @@ class PbViewAnnotate extends PbView {
896
900
  const annoData = node.parentNode.dataset.annotation;
897
901
  const annoType = node.parentNode.dataset.type;
898
902
  if (annoData && annoType) {
899
- const parsed = JSON.parse(annoData);
903
+ const parsed = JSON.parse(annoData) || {};
900
904
  isAnnotated = annoType === type;
901
905
  ref = parsed[this.key];
902
906
  }
@@ -1004,6 +1008,17 @@ class PbViewAnnotate extends PbView {
1004
1008
  classes.push(`
1005
1009
  .annotation-${type}::after {
1006
1010
  background-color: var(--pb-annotation-${type});
1011
+ border-color: var(--pb-annotation-${type});
1012
+ color: var(${color.isLight ? '--pb-color-primary' : '--pb-color-inverse'});
1013
+ }
1014
+ .annotation-${type}.incomplete::after {
1015
+ background: repeating-linear-gradient(
1016
+ 315deg,
1017
+ var(--pb-annotation-${type}),
1018
+ var(--pb-annotation-${type}) 5px,
1019
+ var(${color.isLight ? '--pb-annotation-stripes-light' : '--pb-annotation-stripes-dark'}) 5px,
1020
+ var(${color.isLight ? '--pb-annotation-stripes-light' : '--pb-annotation-stripes-dark'}) 10px
1021
+ );
1007
1022
  color: var(${color.isLight ? '--pb-color-primary' : '--pb-color-inverse'});
1008
1023
  }
1009
1024
  `);
@@ -1064,7 +1079,7 @@ class PbViewAnnotate extends PbView {
1064
1079
  font-variant: normal;
1065
1080
  padding: 2px;
1066
1081
  }
1067
-
1082
+
1068
1083
  [part=highlight] {
1069
1084
  border: 3px solid rgb(255, 174, 0);
1070
1085
  border-radius: 8px;