@ulb-darmstadt/shacl-form 1.8.0 → 1.8.2
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/README.md +7 -4
- package/dist/constants.d.ts +1 -2
- package/dist/form-bootstrap.js +86 -85
- package/dist/form-default.js +83 -82
- package/dist/form-material.js +119 -118
- package/dist/plugins/leaflet.js +8 -8
- package/dist/plugins/mapbox.js +16 -16
- package/dist/property.d.ts +1 -0
- package/dist/theme.d.ts +1 -1
- package/dist/util.d.ts +2 -2
- package/package.json +8 -6
- package/src/constants.ts +2 -3
- package/src/constraints.ts +0 -1
- package/src/form.ts +17 -5
- package/src/group.ts +17 -18
- package/src/property-template.ts +1 -0
- package/src/property.ts +24 -22
- package/src/styles.css +12 -20
- package/src/theme.ts +1 -1
- package/src/themes/default.css +1 -1
- package/src/themes/default.ts +55 -44
- package/src/themes/material.ts +38 -37
- package/src/util.ts +19 -11
- package/dist/node-template.d.ts +0 -17
- package/src/node-template.ts +0 -82
package/src/themes/material.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ShaclPropertyTemplate } from '../property-template'
|
|
2
2
|
import { Term } from '@rdfjs/types'
|
|
3
|
-
import { Button, TextField,
|
|
3
|
+
import { Button, TextField, Checkbox } from 'mdui'
|
|
4
4
|
import { Theme } from '../theme'
|
|
5
5
|
import { InputListEntry, Editor } from '../theme'
|
|
6
|
-
import { Literal } from 'n3'
|
|
6
|
+
import { Literal, NamedNode } from 'n3'
|
|
7
7
|
import { Term as N3Term } from 'n3'
|
|
8
8
|
import css from './material.css?raw'
|
|
9
|
-
import { PREFIX_XSD } from '../constants'
|
|
9
|
+
import { PREFIX_SHACL, PREFIX_XSD, XSD_DATATYPE_STRING } from '../constants'
|
|
10
|
+
import { RokitSelect } from '@ro-kit/ui-widgets'
|
|
10
11
|
|
|
11
12
|
export class MaterialTheme extends Theme {
|
|
12
13
|
constructor() {
|
|
@@ -29,6 +30,8 @@ export class MaterialTheme extends Theme {
|
|
|
29
30
|
}
|
|
30
31
|
if (template?.nodeKind) {
|
|
31
32
|
editor.dataset.nodeKind = template.nodeKind.value
|
|
33
|
+
} else if (value instanceof NamedNode) {
|
|
34
|
+
editor.dataset.nodeKind = PREFIX_SHACL + 'IRI'
|
|
32
35
|
}
|
|
33
36
|
if (template?.hasValue || template?.readonly) {
|
|
34
37
|
editor.disabled = true
|
|
@@ -92,47 +95,45 @@ export class MaterialTheme extends Theme {
|
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
createListEditor(label: string, value: Term | null, required: boolean, listEntries: InputListEntry[], template?: ShaclPropertyTemplate): HTMLElement {
|
|
95
|
-
const editor = new
|
|
96
|
-
editor.variant = 'outlined'
|
|
97
|
-
editor.label = label
|
|
98
|
-
editor.helper = template?.description?.value
|
|
98
|
+
const editor = new RokitSelect()
|
|
99
99
|
editor.clearable = true
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
let
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
const result = this.createDefaultTemplate(label, null, required, editor, template)
|
|
101
|
+
const ul = document.createElement('ul')
|
|
102
|
+
let isFlatList = true
|
|
103
|
+
|
|
104
|
+
const appendListEntry = (entry: InputListEntry, parent: HTMLUListElement) => {
|
|
105
|
+
const li = document.createElement('li')
|
|
106
|
+
if (typeof entry.value === 'string') {
|
|
107
|
+
li.dataset.value = entry.value
|
|
108
|
+
li.innerText = entry.label ? entry.label : entry.value
|
|
109
109
|
} else {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
option.textContent = itemLabel || itemValue
|
|
116
|
-
// if (value && value.value === itemValue) {
|
|
117
|
-
// option.selected = true
|
|
118
|
-
// }
|
|
119
|
-
if (item.indent) {
|
|
120
|
-
for (let i = 0; i < item.indent; i++) {
|
|
121
|
-
option.innerHTML = '  ' + option.innerHTML
|
|
110
|
+
if (entry.value instanceof Literal && entry.value.datatype.equals(XSD_DATATYPE_STRING)) {
|
|
111
|
+
li.dataset.value = entry.value.value
|
|
112
|
+
} else {
|
|
113
|
+
// this is needed for typed rdf literals
|
|
114
|
+
li.dataset.value = (entry.value as N3Term).id
|
|
122
115
|
}
|
|
116
|
+
li.innerText = entry.label ? entry.label : entry.value.value
|
|
123
117
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
118
|
+
parent.appendChild(li)
|
|
119
|
+
if (entry.children?.length) {
|
|
120
|
+
isFlatList = false
|
|
121
|
+
const ul = document.createElement('ul')
|
|
122
|
+
li.appendChild(ul)
|
|
123
|
+
for (const child of entry.children) {
|
|
124
|
+
appendListEntry(child, ul)
|
|
125
|
+
}
|
|
127
126
|
}
|
|
128
|
-
editor.appendChild(option)
|
|
129
127
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
|
|
129
|
+
for (const item of listEntries) {
|
|
130
|
+
appendListEntry(item, ul)
|
|
131
|
+
}
|
|
132
|
+
if (!isFlatList) {
|
|
133
|
+
editor.collapse = true
|
|
135
134
|
}
|
|
135
|
+
|
|
136
|
+
editor.appendChild(ul)
|
|
136
137
|
if (value) {
|
|
137
138
|
editor.value = value.value
|
|
138
139
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Literal, NamedNode, Prefixes, Quad, Store } from 'n3'
|
|
2
|
-
import { DATA_GRAPH,
|
|
2
|
+
import { DATA_GRAPH, PREFIX_FOAF, PREFIX_RDFS, PREFIX_SHACL, PREFIX_SKOS, RDFS_PREDICATE_SUBCLASS_OF, RDF_PREDICATE_TYPE, SHAPES_GRAPH } from './constants'
|
|
3
3
|
import { Term } from '@rdfjs/types'
|
|
4
4
|
import { InputListEntry } from './theme'
|
|
5
5
|
import { ShaclPropertyTemplate } from './property-template'
|
|
@@ -53,10 +53,10 @@ export function findLabel(quads: Quad[], languages: string[]): string {
|
|
|
53
53
|
findObjectValueByPredicate(quads, 'name', PREFIX_FOAF, languages)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export function createInputListEntries(subjects: Term[], shapesGraph: Store, languages: string[]
|
|
56
|
+
export function createInputListEntries(subjects: Term[], shapesGraph: Store, languages: string[]): InputListEntry[] {
|
|
57
57
|
const entries: InputListEntry[] = []
|
|
58
58
|
for (const subject of subjects) {
|
|
59
|
-
entries.push({ value: subject, label: findLabel(shapesGraph.getQuads(subject, null, null, null), languages),
|
|
59
|
+
entries.push({ value: subject, label: findLabel(shapesGraph.getQuads(subject, null, null, null), languages), children: [] })
|
|
60
60
|
}
|
|
61
61
|
return entries
|
|
62
62
|
}
|
|
@@ -82,7 +82,7 @@ function findClassInstancesFromOwlImports(clazz: NamedNode, context: ShaclNode |
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
export function findInstancesOf(clazz: NamedNode, template: ShaclPropertyTemplate
|
|
85
|
+
export function findInstancesOf(clazz: NamedNode, template: ShaclPropertyTemplate): InputListEntry[] {
|
|
86
86
|
let instances: Term[]
|
|
87
87
|
// if template has sh:in, then just use that as class instances
|
|
88
88
|
if (template.shaclIn) {
|
|
@@ -97,16 +97,24 @@ export function findInstancesOf(clazz: NamedNode, template: ShaclPropertyTemplat
|
|
|
97
97
|
findClassInstancesFromOwlImports(clazz, template, template.config.store, instances)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
const entries = createInputListEntries(instances, template.config.store, template.config.languages
|
|
100
|
+
const entries = createInputListEntries(instances, template.config.store, template.config.languages)
|
|
101
101
|
// build inheritance tree only if sh:in is not defined
|
|
102
102
|
if (template.shaclIn === undefined) {
|
|
103
|
+
// find sub classes via rdfs:subClassOf
|
|
103
104
|
for (const subClass of template.config.store.getSubjects(RDFS_PREDICATE_SUBCLASS_OF, clazz, null)) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
const subClassIntances = findInstancesOf(subClass as NamedNode, template)
|
|
106
|
+
for (const subClassIntance of subClassIntances) {
|
|
107
|
+
let isChild = false
|
|
108
|
+
// check if found sub class also is an instance of its super class. if yes, add it to the children of the InputListEntry.
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (template.config.store.countQuads(subClassIntance.value, RDF_PREDICATE_TYPE, entry.value, null) > 0) {
|
|
111
|
+
entry.children!.push(subClassIntance)
|
|
112
|
+
isChild = true
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!isChild) {
|
|
116
|
+
entries.push(subClassIntance)
|
|
117
|
+
}
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
}
|
package/dist/node-template.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { BlankNode, NamedNode, Quad } from 'n3';
|
|
2
|
-
import { Config } from './config';
|
|
3
|
-
import { Term } from '@rdfjs/types';
|
|
4
|
-
export declare class ShaclNodeTemplate {
|
|
5
|
-
properties: (NamedNode | BlankNode)[];
|
|
6
|
-
node: NamedNode | undefined;
|
|
7
|
-
shaclAnd: string | undefined;
|
|
8
|
-
shaclOr: Term[] | undefined;
|
|
9
|
-
shaclXone: Term[] | undefined;
|
|
10
|
-
targetClass: NamedNode | undefined;
|
|
11
|
-
owlImports: NamedNode[];
|
|
12
|
-
config: Config;
|
|
13
|
-
extendedShapes: NamedNode[];
|
|
14
|
-
constructor(quads: Quad[], config: Config);
|
|
15
|
-
merge(quads: Quad[]): ShaclNodeTemplate;
|
|
16
|
-
clone(): ShaclNodeTemplate;
|
|
17
|
-
}
|
package/src/node-template.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { BlankNode, NamedNode, Quad } from "n3"
|
|
2
|
-
import { Config } from "./config"
|
|
3
|
-
import { OWL_PREDICATE_IMPORTS, PREFIX_SHACL } from "./constants";
|
|
4
|
-
import { Term } from "@rdfjs/types";
|
|
5
|
-
|
|
6
|
-
const mappers: Record<string, (template: ShaclNodeTemplate, term: Term) => void> = {
|
|
7
|
-
[`${PREFIX_SHACL}property`]: (template, term) => { template.properties.push(term as (BlankNode | NamedNode)) },
|
|
8
|
-
[`${PREFIX_SHACL}and`]: (template, term) => { template.shaclAnd = term.value },
|
|
9
|
-
[`${PREFIX_SHACL}node`]: (template, term) => { template.node = term as NamedNode },
|
|
10
|
-
[`${PREFIX_SHACL}targetClass`]: (template, term) => { template.targetClass = term as NamedNode },
|
|
11
|
-
[`${PREFIX_SHACL}or`]: (template, term) => {
|
|
12
|
-
const list = template.config.lists[term.value]
|
|
13
|
-
if (list?.length) {
|
|
14
|
-
template.shaclOr = list
|
|
15
|
-
} else {
|
|
16
|
-
console.error('list for sh:or not found:', term.value, 'existing lists:', template.config.lists)
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
[`${PREFIX_SHACL}xone`]: (template, term) => {
|
|
20
|
-
const list = template.config.lists[term.value]
|
|
21
|
-
if (list?.length) {
|
|
22
|
-
template.shaclXone = list
|
|
23
|
-
} else {
|
|
24
|
-
console.error('list for sh:xone not found:', term.value, 'existing lists:', template.config.lists)
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
[OWL_PREDICATE_IMPORTS.id]: (template, term) => { template.owlImports.push(term as NamedNode) }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class ShaclNodeTemplate {
|
|
31
|
-
properties: (NamedNode | BlankNode)[] = []
|
|
32
|
-
node: NamedNode | undefined
|
|
33
|
-
shaclAnd: string | undefined
|
|
34
|
-
shaclOr: Term[] | undefined
|
|
35
|
-
shaclXone: Term[] | undefined
|
|
36
|
-
targetClass: NamedNode | undefined
|
|
37
|
-
|
|
38
|
-
owlImports: NamedNode[] = []
|
|
39
|
-
config: Config
|
|
40
|
-
extendedShapes: NamedNode[] = []
|
|
41
|
-
|
|
42
|
-
constructor(quads: Quad[], config: Config) {
|
|
43
|
-
this.config = config
|
|
44
|
-
this.merge(quads)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
merge(quads: Quad[]): ShaclNodeTemplate {
|
|
48
|
-
for (const quad of quads) {
|
|
49
|
-
mappers[quad.predicate.id]?.call(this, this, quad.object)
|
|
50
|
-
}
|
|
51
|
-
// resolve extended shapes
|
|
52
|
-
if (this.node || this.shaclAnd) {
|
|
53
|
-
if (this.node) {
|
|
54
|
-
this.extendedShapes.push(this.node)
|
|
55
|
-
}
|
|
56
|
-
if (this.shaclAnd) {
|
|
57
|
-
const list = this.config.lists[this.shaclAnd]
|
|
58
|
-
if (list?.length) {
|
|
59
|
-
for (const node of list) {
|
|
60
|
-
this.extendedShapes.push(node as NamedNode)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return this
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
clone(): ShaclNodeTemplate {
|
|
69
|
-
const copy = Object.assign({}, this)
|
|
70
|
-
// arrays are not cloned but referenced, so create them manually
|
|
71
|
-
copy.owlImports = [ ...this.owlImports ]
|
|
72
|
-
if (this.shaclOr) {
|
|
73
|
-
copy.shaclOr = [ ...this.shaclOr ]
|
|
74
|
-
}
|
|
75
|
-
if (this.shaclXone) {
|
|
76
|
-
copy.shaclXone = [ ...this.shaclXone ]
|
|
77
|
-
}
|
|
78
|
-
copy.merge = this.merge.bind(copy)
|
|
79
|
-
copy.clone = this.clone.bind(copy)
|
|
80
|
-
return copy
|
|
81
|
-
}
|
|
82
|
-
}
|