|
7 | 7 | :items="instanceItems"
|
8 | 8 | validate-on="lazy input"
|
9 | 9 | :rules="rules"
|
10 |
| - ></v-autocomplete> |
| 10 | + item-value="value" |
| 11 | + item-text="title" |
| 12 | + return-object |
| 13 | + > |
| 14 | + |
| 15 | + <template v-slot:item="data"> |
| 16 | + <v-list-item @click="console.log('add new item')" v-if="data.item.props.isButton"> |
| 17 | + <template v-slot:prepend> |
| 18 | + <v-icon icon="item.icon">mdi-plus-box</v-icon> |
| 19 | + </template> |
| 20 | + <v-list-item-title>{{ data.item.title }}</v-list-item-title> |
| 21 | + </v-list-item> |
| 22 | + <v-list-item @click="selectItem(data.item)" v-else> |
| 23 | + <v-list-item-title>{{ data.item.title }}</v-list-item-title> |
| 24 | + <v-list-item-subtitle>{{ data.item.props.subtitle }}</v-list-item-subtitle> |
| 25 | + </v-list-item> |
| 26 | + </template> |
| 27 | + </v-autocomplete> |
11 | 28 | </template>
|
12 | 29 |
|
13 | 30 | <script setup>
|
14 | 31 | import { inject, reactive, onMounted, ref, computed} from 'vue'
|
15 | 32 | import { useRules } from '../composables/rules'
|
16 | 33 | import rdf from 'rdf-ext'
|
17 |
| - import {SHACL, RDF, DLTHING, XSD} from '@/modules/namespaces' |
| 34 | + import {SHACL, RDF, RDFS, DLTHING, XSD} from '@/modules/namespaces' |
18 | 35 | import { toCURIE } from '../modules/utils';
|
19 | 36 |
|
20 |
| - const predicateSelector = DLTHING.meta_type |
21 |
| - // const predicateSelector = RDF.type.value |
| 37 | + // ----- // |
| 38 | + // Props // |
| 39 | + // ----- // |
22 | 40 |
|
23 | 41 | const props = defineProps({
|
24 | 42 | property_shape: Object,
|
25 | 43 | node_uid: String,
|
26 |
| - triple_uid: String |
| 44 | + triple_uid: String, |
| 45 | + triple_idx: Number, |
27 | 46 | })
|
| 47 | +
|
| 48 | + // ---- // |
| 49 | + // Data // |
| 50 | + // ---- // |
| 51 | + |
28 | 52 | const formData = inject('formData');
|
29 | 53 | const graphData = inject('graphData');
|
30 | 54 | const graphPrefixes = inject('graphPrefixes');
|
31 | 55 | const shapePrefixes = inject('shapePrefixes');
|
| 56 | + const classPrefixes = inject('classPrefixes'); |
| 57 | + const classData = inject('classData'); |
32 | 58 | const { rules } = useRules(props.property_shape)
|
33 |
| - // var classNodes = reactive(null) |
34 |
| - // var classNodes2 = reactive(null) |
35 | 59 | var propClass = ref(null)
|
36 | 60 | const combinedQuads = reactive([])
|
37 | 61 | const instanceItems = reactive([])
|
38 | 62 |
|
| 63 | + // ------------------- // |
| 64 | + // Computed properties // |
| 65 | + // ------------------- // |
| 66 | +
|
39 | 67 | const triple_object = computed({
|
40 | 68 | get() {
|
41 |
| - return formData[props.node_uid].at(-1)[props.triple_uid].at(-1); |
| 69 | + return formData[props.node_uid].at(-1)[props.triple_uid][props.triple_idx]; |
42 | 70 | },
|
43 | 71 | set(value) {
|
44 | 72 | const node_idx = formData[props.node_uid].length - 1
|
45 |
| - const triple_idx = formData[props.node_uid][node_idx][props.triple_uid].length - 1 |
46 |
| - formData[props.node_uid][node_idx][props.triple_uid][triple_idx] = value; |
| 73 | + formData[props.node_uid][node_idx][props.triple_uid][props.triple_idx] = value; |
47 | 74 | }
|
48 | 75 | });
|
49 | 76 |
|
50 |
| - onMounted(() => { |
51 |
| - propClass.value = props.property_shape[SHACL.class.value] ?? false // TODO: what should the correct default value be here? |
| 77 | + // ----------------- // |
| 78 | + // Lifecycle methods // |
| 79 | + // ----------------- // |
52 | 80 |
|
53 |
| - let allprefixes = {...shapePrefixes, ...graphPrefixes}; |
54 |
| - var propClassCurie = toCURIE(propClass.value, allprefixes) |
55 |
| - const literalNodes = rdf.grapoi({ dataset: graphData }) |
56 |
| - .hasOut(predicateSelector, rdf.literal(String(propClassCurie), XSD.anyURI)) |
57 |
| - .quads(); |
58 |
| - const uriNodes = rdf.grapoi({ dataset: graphData }) |
59 |
| - .hasOut(predicateSelector, propClass.value) |
| 81 | + onMounted(() => { |
| 82 | + // --- |
| 83 | + // The goal of this method is to populate the list of items for the |
| 84 | + // InstancesSelectEditor |
| 85 | + // --- |
| 86 | + // TODO: what should the correct default value be here? |
| 87 | + propClass.value = props.property_shape[SHACL.class.value] ?? false |
| 88 | + let allprefixes = {...shapePrefixes, ...graphPrefixes, ...classPrefixes}; |
| 89 | + // find nodes with predicate rdf:type and object being the property class |
| 90 | + var quads = getLiteralAndNamedNodes( |
| 91 | + graphData, |
| 92 | + rdf.namedNode(RDF.type), |
| 93 | + propClass.value, |
| 94 | + allprefixes |
| 95 | + ) |
| 96 | + // then find nodes with predicate rdfs:subClassOf and object being the property class |
| 97 | + // TODO: here we are only using a named node for the object because this is how the |
| 98 | + // tools/gen_owl_minimal.py script outputs the triples in the ttl file. This should be |
| 99 | + // generalised |
| 100 | + const subClasses = rdf.grapoi({ dataset: classData }) |
| 101 | + .hasOut(rdf.namedNode(RDFS.subClassOf.value), rdf.namedNode(propClass.value)) |
60 | 102 | .quads();
|
61 |
| - const combinedQuads = Array.from(literalNodes).concat(Array.from(uriNodes)); |
62 |
| - console.log("Concatenated results") |
| 103 | + // For each subclass, find the quads in graphData that has the class name as object |
| 104 | + // and RDF.type as predicate |
| 105 | + var myArr = [] |
| 106 | + Array.from(subClasses).forEach(quad => { |
| 107 | + const cl = quad.subject.value |
| 108 | + myArr = myArr.concat(getLiteralAndNamedNodes(graphData, rdf.namedNode(RDF.type), cl, allprefixes)) |
| 109 | + }); |
| 110 | + // Then combine all quad arrays |
| 111 | + const combinedQuads = quads.concat(myArr); |
| 112 | + // Finally, create list items from quads |
| 113 | + instanceItems.push( |
| 114 | + { |
| 115 | + title: "Add New Item", |
| 116 | + props: { subtitle: "bla", isButton: true, }, |
| 117 | + } |
| 118 | + ) |
63 | 119 | combinedQuads.forEach(quad => {
|
64 | 120 | console.log(`\t${quad.subject.value}`)
|
65 |
| - instanceItems.push(quad.subject.value) |
| 121 | + var extra = '' |
| 122 | + if (quad.subject.termType === 'BlankNode') { |
| 123 | + extra = ' (BlankNode)' |
| 124 | + } |
| 125 | + instanceItems.push( |
| 126 | + { |
| 127 | + title: quad.subject.value + extra, |
| 128 | + value: quad.subject.value, |
| 129 | + props: { subtitle: toCURIE(quad.object.value, allprefixes) }, |
| 130 | + } |
| 131 | + ) |
66 | 132 | });
|
67 | 133 | })
|
| 134 | +
|
| 135 | + // --------- // |
| 136 | + // Functions // |
| 137 | + // --------- // |
| 138 | +
|
| 139 | + function getLiteralAndNamedNodes(graphData, predicate, propertyClass, prefixes) { |
| 140 | + var propClassCurie = toCURIE(propertyClass, prefixes) |
| 141 | + // a) use the literal node with xsd data type |
| 142 | + const literalNodes = rdf.grapoi({ dataset: graphData }) |
| 143 | + .hasOut(predicate, rdf.literal(String(propClassCurie), XSD.anyURI)) |
| 144 | + .quads(); |
| 145 | + // b) and the named node |
| 146 | + const uriNodes = rdf.grapoi({ dataset: graphData }) |
| 147 | + .hasOut(predicate, rdf.namedNode(propClass.value)) |
| 148 | + .quads(); |
| 149 | + // return as a concatenated array of quads |
| 150 | + return Array.from(literalNodes).concat(Array.from(uriNodes)) |
| 151 | + } |
| 152 | +
|
| 153 | + function selectItem(item) { |
| 154 | + triple_object.value = item.value; |
| 155 | + } |
| 156 | +
|
| 157 | +
|
68 | 158 | </script>
|
69 | 159 |
|
| 160 | +<!-- Component matching logic --> |
70 | 161 |
|
71 | 162 | <script>
|
72 | 163 | import { SHACL } from '@/modules/namespaces'
|
|
0 commit comments