@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.
- package/.github/workflows/node.js.yml +6 -5
- package/CHANGELOG.md +41 -0
- package/css/gridjs/mermaid.min.css +1 -0
- package/dist/demo/demos.json +4 -1
- package/dist/demo/pb-table-grid.html +17 -0
- package/dist/demo/people.json +35 -0
- package/dist/pb-components-bundle.js +182 -163
- package/dist/pb-elements.json +231 -0
- package/dist/pb-odd-editor.js +23 -14
- package/i18n/common/de.json +8 -1
- package/i18n/common/en.json +11 -3
- package/package.json +2 -1
- package/pb-elements.json +231 -0
- package/src/authority/connectors.js +8 -0
- package/src/authority/gf.js +152 -0
- package/src/authority/reconciliation.js +124 -0
- package/src/pb-components.js +1 -0
- package/src/pb-odd-editor.js +6 -2
- package/src/pb-odd-elementspec-editor.js +2 -0
- package/src/pb-odd-model-editor.js +17 -0
- package/src/pb-odd-parameter-editor.js +12 -5
- package/src/pb-table-column.js +66 -0
- package/src/pb-table-grid.js +212 -0
- package/src/pb-view-annotate.js +21 -6
|
@@ -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.
|
|
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);
|
package/src/pb-view-annotate.js
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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;
|