Skip to content

Commit

Permalink
More bug fixes:
Browse files Browse the repository at this point in the history
- introduce 'show_all_fields' flag to config, which can be set to true or false (default)
- adds 'active' state highlighting to the selected item in a an instancesSelectEditor dropdown
- switch instanceItems back to a computed property, instead of calling a function to get items
  on certain lifecycle hooks and other actions
- fix issue where RecordViewer did not show updated information upon form save; this was done
  by adding a reactivity trigger flag that is updated whenever a graphData watcher sees a
  difference, and it triggers the computed property recomputation and also updates the key of a
  RecordViewer component
- temporary fix of duplicate blank node creation when making GET requests to service. shacl-vue
  is in fact fetching the same record twice, the first time via the records endpoint (multiple)
  when a specific class is selected, and the second time via the record endpoint (singular) when
  the user clicks the edit button on a specific record. When the GET request interaction with the
  service was first introduced into shacl-vue, I implemented a layman's request caching approach
  where a set is maintained of all previous request URLs, and a second request won't be made to a
  URL already in a set. This was actually to prevent unnecessary requests, but the prevention of
  the current issue actually seems like an even more valid reason. The temporary fix is to
  disable the singular record GET request, because given the current workflow of the application
  it can safely be assumed that the 'multiple records by class' request would already have been
  made before a singular record request is attempted.
  • Loading branch information
jsheunis committed Feb 12, 2025
1 parent 5bb7867 commit 727854e
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 58 deletions.
1 change: 1 addition & 0 deletions public/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"id_iri": "https://concepts.datalad.org/s/things/v1/id",
"show_shapes_wo_id": false,
"show_all_fields": false,
"use_service": false,
"use_token": false,
"token_info": false,
Expand Down
9 changes: 8 additions & 1 deletion src/components/FormEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
// ---- //
const localShapeIri = ref(props.shape_iri);
const localNodeIdx = ref(props.node_idx);
const show_all_fields = ref(true)
const config = inject('config')
const show_all_fields = ref(false)
const ID_IRI = inject('ID_IRI')
const save_node = inject('save_node')
const clear_current_node = inject('clear_current_node')
Expand Down Expand Up @@ -120,6 +121,12 @@
onBeforeMount(() => {
console.log(`the FormEditor component is about to be mounted.`)
add_empty_node(localShapeIri.value, localNodeIdx.value)
if (config.value.hasOwnProperty("show_all_fields")) {
if (typeof config.value.show_all_fields == "boolean" && config.value.show_all_fields) {
show_all_fields.value = true
}
}
})
onBeforeUnmount(() => {
Expand Down
10 changes: 5 additions & 5 deletions src/components/InstancesSelectEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<template v-slot:item="data">
<!-- Show the "Add Item" button first -->
<div v-if="data.item.props.isButton">
<v-list-item @click.stop>
<v-list-item @click.stop :active="false">
<v-list-item-title>
<v-menu v-model="menu" location="end">
<template v-slot:activator="{ props }">
Expand All @@ -47,13 +47,12 @@
</v-list-item>
</v-list>
</v-menu>

</v-list-item-title>
</v-list-item>
</div>
<!-- Then show all other items -->
<div v-else>
<v-list-item @click.stop="selectItem(data.item)" rounded>
<v-list-item @click.stop="selectItem(data.item)" rounded :active="subValues.selectedInstance?.value == data.item.value" class="myInstancesList">
<template v-slot:prepend>
<v-icon>{{ getClassIcon(toIRI(data.item.props[toCURIE(RDF.type.value, allPrefixes)], allPrefixes)) }}</v-icon>
</template>
Expand Down Expand Up @@ -186,7 +185,9 @@
function valueParser(value) {
// Parsing internalValue into ref values for separate subcomponent(s)
if (!itemsToList.value) return { selectedInstance: null };
if (!itemsToList.value) {
return { selectedInstance: null };
}
var inst = findObjectByKey(itemsToList.value, "value", value)
return { selectedInstance: inst ?? null }
}
Expand Down Expand Up @@ -295,7 +296,6 @@
});
itemsToList.value = itemsToListArr
}
</script>
<!-- Component matching logic -->
Expand Down
6 changes: 0 additions & 6 deletions src/components/NodeShapeEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,20 @@
const usedPropertyGroups = shallowRef({});
onMounted(() => {
usedPropertyGroups.value = computeUsedPropertyGroups();
ready.value = true;
console.log("NodeShapeEditor is MOUNTED")
})
onBeforeMount(() => {
console.log(`NodeShapeEditor is about to be mounted.`)
if (config.value.hasOwnProperty("group_layout") && config.value.group_layout == "tabs") {
group_layout.value = "tabs"
}
})
onBeforeUpdate(() => {
console.log(`the NodeShapeEditor component is about to be updated.`)
})
onBeforeUnmount(() => {
console.log(`NodeShapeEditor is about to be UNMOUNTED.`)
localShapeIri.value = null
localNodeIdx.value = null
});
Expand All @@ -109,7 +104,6 @@
function computeUsedPropertyGroups() {
console.log("usedPropertyGroups recomputed");
// first get a list of all the sh:PropertyGroup instances
// that are provided for any property via sh:group
var group_instances = shape_obj.properties.map(function(shape_prop) {
Expand Down
12 changes: 5 additions & 7 deletions src/components/PropertyShapeEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,25 +95,23 @@
// ----------------- //
onMounted(() => {
console.log(`PropertyShapeEditor is MOUNTED.`)
console.log(`PropertyShapeEditor is MOUNTED:`)
if ((editMode.graph || editMode.form) && openForms.value.length == 1) {
// if we're busy editing the FIRST form, and if the triple already has a value,
// don't add another empty element
if (formData[localNodeUid.value][localNodeIdx.value][my_uid.value]) return;
if (formData[localNodeUid.value][localNodeIdx.value][my_uid.value]) {
return;
}
}
add_empty_triple(localNodeUid.value, localNodeIdx.value, my_uid.value)
add_empty_triple(localNodeUid.value, localNodeIdx.value, my_uid.value, "propertyShapeEditor onMounted")
})
onBeforeMount(() => {
console.log(`PropertyShapeEditor is about to be MOUNTED.`)
my_uid.value = localPropertyShape.value[SHACL.path.value]
})
onBeforeUnmount(() => {
console.log(`PropertyShapeEditor is about to be UNMOUNTED.`)
})
// ------------------- //
Expand Down
4 changes: 1 addition & 3 deletions src/components/RecordViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
</template>

<script setup>
import { inject, onBeforeMount, ref} from 'vue';
import { inject, onBeforeMount, onUpdated, ref} from 'vue';
import { toCURIE, makeReadable, isObject, toIRI} from '@/modules/utils';
import { RDF, DLTHINGS } from '@/modules/namespaces';
import TextOrLinkViewer from './TextOrLinkViewer.vue';
Expand All @@ -71,8 +71,6 @@
const prefLabel = ref("")
onBeforeMount(()=>{
console.log("props.record.props")
console.log(props.record.props)
const keys = Object.keys(props.record.props)
for (var k of keys) {
if (['subtitle', 'quad', RDF.type.value].indexOf(k) >= 0) {
Expand Down
58 changes: 30 additions & 28 deletions src/components/ShaclVue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
<v-skeleton-loader type="list-item-avatar"></v-skeleton-loader>
</span>
<span v-else>
<div v-if="instanceItems.length">
<span v-for="r in instanceItems">
<RecordViewer :classIRI="selectedIRI" :record="r" :key="selectedIRI + '-' + r.title" :formOpen="formOpen" :variant="r.title == queried_id ? 'outlined' : 'tonal'"></RecordViewer>
<div v-if="instanceItemsComp.length">
<span v-for="r in instanceItemsComp">
<RecordViewer :classIRI="selectedIRI" :record="r" :key="selectedIRI + '-' + r.title + '-' + itemsTrigger" :formOpen="formOpen" :variant="r.title == queried_id ? 'outlined' : 'tonal'"></RecordViewer>
</span>
</div>
<div v-else style="margin-top: 1em; margin-left: 1em;">
Expand Down Expand Up @@ -99,7 +99,7 @@


<script setup>
import { ref, computed, provide, watch, reactive, onBeforeUpdate, nextTick, inject, toRaw} from 'vue'
import { ref, computed, provide, watch, reactive, onBeforeUpdate, nextTick, inject, toRaw, onUpdated} from 'vue'
import rdf from 'rdf-ext';
import { useConfig } from '@/composables/configuration';
import { useGraphData } from '@/composables/graphdata';
Expand All @@ -123,6 +123,7 @@ import SubmitComp from './SubmitComp.vue';
configUrl: String
})
const itemsTrigger = ref(false)
const queried_id = ref(null)
const showShapesWoID = ref(true)
const { config, configFetched, configError} = useConfig(props.configUrl);
Expand Down Expand Up @@ -259,8 +260,6 @@ import SubmitComp from './SubmitComp.vue';
// Select a data type
var selectedShape = ref(null)
var selectedIRI = ref(null)
const instanceItems = ref([])
// Select a data item
var selectedItem = ref(null)
Expand All @@ -281,9 +280,6 @@ import SubmitComp from './SubmitComp.vue';
console.log("onBeforeUpdate ShaclVue")
editItemIdx.value = null
editShapeIRI.value = null
if (selectedIRI.value) {
instanceItems.value = getInstanceItems()
}
})
const idFilteredNodeShapeNames = computed(() =>{
Expand All @@ -306,7 +302,6 @@ import SubmitComp from './SubmitComp.vue';
watch(prefixes_ready, (newValue) => {
// console.log("CHECK: prefixesready")
if (newValue) {
// Get all prefixes and derive context from it
Object.assign(allPrefixes, shapePrefixes, graphPrefixes, classPrefixes)
Expand All @@ -323,6 +318,12 @@ import SubmitComp from './SubmitComp.vue';
}, {immediate: true });
watch(graphData, () => {
console.log("Graphdata UPDATED SHACLVUE")
itemsTrigger.value = !itemsTrigger.value
}, { deep: true });
const formattedDescription = computed(() => {
// For the class description, use a regular expression to replace text between backticks with <code> tags
if (selectedShape.value) {
Expand All @@ -331,10 +332,8 @@ import SubmitComp from './SubmitComp.vue';
})
async function selectType(IRI, fromUser) {
instanceItems.value = []
selectedIRI.value = IRI
selectedShape.value = nodeShapes.value[IRI]
if (config.value.use_service) {
classRecordsLoading.value = true
// First fetch rdf data from configured service
Expand All @@ -343,7 +342,6 @@ import SubmitComp from './SubmitComp.vue';
// Then continue with the rest
await nextTick();
}
instanceItems.value = getInstanceItems()
if (fromUser) updateURL(IRI)
}
Expand Down Expand Up @@ -398,8 +396,6 @@ import SubmitComp from './SubmitComp.vue';
newItemIdx.value = null
editItem.value = false
addItem.value = false
// selectedIRI.value = IRI
// selectedShape.value = nodeShapes.value[IRI]
newItemIdx.value = '_:' + crypto.randomUUID()
addForm(selectedIRI.value, newItemIdx.value, 'new')
addItem.value = true
Expand All @@ -424,20 +420,21 @@ import SubmitComp from './SubmitComp.vue';
editShapeIRI.value = toIRI(objectTerm.value, allPrefixes)
}
editItemIdx.value = instance.value // this is the id
console.log(editShapeIRI.value)
console.log(editItemIdx.value)
if (config.value.use_service) {
idRecordLoading.value = true
// First fetch rdf data from configured service
await fetchFromService('get-record', editItemIdx.value, allPrefixes)
idRecordLoading.value = false
// Then continue with the rest
await nextTick();
}
// See: https://hub.datalad.org/datalink/annotate-trr379-demo/issues/32
// leaving the following commented out for now:
// if (config.value.use_service) {
// idRecordLoading.value = true
// // First fetch rdf data from configured service
// await fetchFromService('get-record', editItemIdx.value, allPrefixes)
// idRecordLoading.value = false
// // Then continue with the rest
// await nextTick();
// }
// if the node is already in the formData, edit that
if (formData[editShapeIRI.value]?.[editItemIdx.value]) {
console.log("The node is already in the formData, we will edit that")
editMode.form = true
editMode.graph = false
} else {
Expand All @@ -456,10 +453,16 @@ import SubmitComp from './SubmitComp.vue';
provide('editInstanceItem', editInstanceItem)
function getInstanceItems() {
const instanceItemsComp = computed(() =>{
// ---
// The goal of this method is to populate the list of data objects of the selected type
// ---
var x = itemsTrigger.value
if (!selectedIRI.value) {
return []
}
// find nodes with triple predicate == rdf:type, and triple object == the selected class
var quads = getLiteralAndNamedNodes(
graphData,
Expand Down Expand Up @@ -498,7 +501,7 @@ import SubmitComp from './SubmitComp.vue';
instanceItemsArr.push(item)
});
return instanceItemsArr
}
})
const openForms = ref([])
const currentOpenForm = computed(() => {
Expand Down Expand Up @@ -529,7 +532,6 @@ import SubmitComp from './SubmitComp.vue';
formOpen.value = false
canSubmit.value = true
editMode.form = editMode.graph = false
instanceItems.value = getInstanceItems()
}
}
provide('addForm', addForm)
Expand Down
2 changes: 1 addition & 1 deletion src/composables/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ref, onMounted } from 'vue'
const basePath = import.meta.env.BASE_URL || '/';

export function useConfig(url) {
const defaultURL = `${basePath}config.json`
const defaultURL = `${basePath}config_test.json`
var configURL
if (url) {
if (url.indexOf('http')) {
Expand Down
10 changes: 6 additions & 4 deletions src/composables/formdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// "https://concepts.datalad.org/s/distribution/unreleased/Person": { // RDF type of a subject
// "https://example.org/ns/dataset/#ahorst": { // A subject: named or blank node
// "https://concepts.datalad.org/s/distribution/unreleased/email": [] // A predicate: named node
// "shaclvue:termType": "NamedNode" // the nodetype of te subject: NamedNode or BlankNode
// }
// },
// "https://concepts.datalad.org/s/prov/unreleased/Attribution": { // type
Expand Down Expand Up @@ -85,8 +86,8 @@ export function useFormData() {
}


function add_empty_triple(nodeshape_iri, node_iri, triple_uid) {
// console.log(`Adding empty triple:\nnodeshape_iri: ${nodeshape_iri}\nnode_iri: ${node_iri}\ntriple_uid: ${triple_uid}`)
function add_empty_triple(nodeshape_iri, node_iri, triple_uid, source) {
console.log(`Adding empty triple from '${source}':\n\tnodeshape_iri: ${nodeshape_iri}\n\tnode_iri: ${node_iri}\n\ttriple_uid: ${triple_uid}`)
// if the node shape+iri exist and the triple uid (predicate) does not exist, add it
// if the node shape+iri exist and the triple uid already exists, add empty value to array
// if the node shape+iri do not exist, print console error because this should not be possible
Expand Down Expand Up @@ -429,17 +430,18 @@ export function useFormData() {
var quadArray = getSubjectTriples(graphData, subject_term)
var IdQuadExists = false
quadArray.forEach((quad) => {
// console.log(`-- adding: ${quad.subject.value} - ${quad.predicate.value} - ${quad.object.value}`)
var triple_uid = toIRI(quad.predicate.value, prefixes)
if (triple_uid === id_iri) {
IdQuadExists = true
}
add_empty_triple(nodeshape_iri, node_iri, triple_uid)
add_empty_triple(nodeshape_iri, node_iri, triple_uid, "quadsToFormData quad")
var length = formData[nodeshape_iri][node_iri][triple_uid].length
formData[nodeshape_iri][node_iri][triple_uid][length-1] = quad.object.value
});
// Here we deal with explicitly adding the id_iri quad, if necessary
if (subject_term.termType === "NamedNode" && !IdQuadExists) {
add_empty_triple(nodeshape_iri, node_iri, id_iri)
add_empty_triple(nodeshape_iri, node_iri, id_iri, "quadsToFormData ID_IRI")
var l = formData[nodeshape_iri][node_iri][id_iri].length
formData[nodeshape_iri][node_iri][id_iri][l-1] = node_iri
}
Expand Down
5 changes: 5 additions & 0 deletions src/composables/graphdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export function useGraphData(config) {
})
// Load data
quadStream.on('data', quad => {
// the following line was an attempt to solve https://hub.datalad.org/datalink/annotate-trr379-demo/issues/32
// but it was a faulty attempt, since the object was different. but leaving it here since deleting matches
// would prospectively solve the duplication of named node or literal objects
graphData.deleteMatches(quad.subject, quad.predicate, quad.object, null)
// add quad to store
graphData.add(quad)
}).on('end', () => {
updateSerializedData();
Expand Down
Loading

0 comments on commit 727854e

Please sign in to comment.