Introduce BackLinkViewer component and associated config #342
4 changed files with 235 additions and 116 deletions
48
src/components/BackLinkViewer.vue
Normal file
48
src/components/BackLinkViewer.vue
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<h4 v-if="Object.keys(refRecords).length" style="margin-bottom: 1em;" >Records referencing <em>{{props.record.displayLabel}}</em>:</h4>
|
||||
<div v-for="(arr, key) in refRecords" style="margin-bottom: 0.5em;">
|
||||
<em>via <strong>{{makeReadable(toCURIE(key, allPrefixes, 'parts').property)}}</strong></em>:
|
||||
<span v-for="r in arr">
|
||||
<br> -
|
||||
<NamedNodeViewer
|
||||
:textVal="r.record_id"
|
||||
:prefLabel="getPrefLabel(r.quad.subject, rdfDS, allPrefixes)"
|
||||
:displayLabel="getRecordDisplayLabel(r.quad.subject, rdfDS, allPrefixes, configVarsMain)"
|
||||
:quad="r.quad"
|
||||
:targetClass="r.class_iri"
|
||||
:allowLink="true"
|
||||
>
|
||||
</NamedNodeViewer>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import { inject, onMounted, ref } from 'vue';
|
||||
import { toCURIE, getReferencingRecords, getPrefLabel, getRecordDisplayLabel, makeReadable} from '@/modules/utils';
|
||||
|
||||
const props = defineProps({
|
||||
record: Object,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['has-referencing-records'])
|
||||
|
||||
const fetchFromService = inject('fetchFromService')
|
||||
const allPrefixes = inject('allPrefixes')
|
||||
const rdfDS = inject('rdfDS')
|
||||
const configVarsMain = inject('configVarsMain')
|
||||
const refRecords = ref({});
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
const arg = allPrefixes['dlthings'] + 'Thing';
|
||||
await fetchFromService('get-paginated-records-constrained', arg, allPrefixes, props.record.title )
|
||||
await fetchFromService('get-paginated-records-constrained', arg, allPrefixes, toCURIE(props.record.title, allPrefixes))
|
||||
refRecords.value = getReferencingRecords(props.record.title, rdfDS.data.graph)
|
||||
if (Object.keys(refRecords.value).length > 0) {
|
||||
emit('has-referencing-records')
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
@ -75,6 +75,8 @@
|
|||
</span>
|
||||
</v-card-subtitle>
|
||||
<v-card-text v-if="!props.formOpen" :class="mobile ? 'text-caption' : ''">
|
||||
<v-row align="stretch">
|
||||
<v-col :cols="showBackLinks ? 6 : 12">
|
||||
<strong>Persistent Identifier</strong>: {{ record.title}}<br/>
|
||||
|
||||
<!-- Literal nodes -->
|
||||
|
|
@ -208,8 +210,16 @@
|
|||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</v-col>
|
||||
<v-col v-if="showBackLinks && !hideBackLinks" cols="auto" class="d-flex">
|
||||
<v-divider vertical />
|
||||
</v-col>
|
||||
<v-col>
|
||||
<BackLinkViewer v-if="firstUpdateDone && !hideBackLinks" v-show="showBackLinks" :record="record" @has-referencing-records="showBackLinks = true"></BackLinkViewer>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<!-- Blank nodes -->
|
||||
<br />
|
||||
<span v-if="showBackLinks && !hideBackLinks"><br /></span>
|
||||
<v-btn
|
||||
no-gutters
|
||||
v-if="Object.keys(record.triples['BlankNode']).length > 0"
|
||||
|
|
@ -324,6 +334,7 @@ import MoreOrLessRecordsViewer from '@/components/MoreOrLessRecordsViewer.vue';
|
|||
import SpecialButton from '@/components/SpecialButton.vue'
|
||||
import { useCompConfig } from '@/composables/useCompConfig';
|
||||
import { useDisplay } from 'vuetify'
|
||||
import BackLinkViewer from './BackLinkViewer.vue';
|
||||
const { mobile } = useDisplay()
|
||||
// Define component properties
|
||||
const props = defineProps({
|
||||
|
|
@ -380,6 +391,14 @@ const fetchingRecords = ref(false);
|
|||
const canEditClass = ref(false);
|
||||
const showSpecialButtons = ref(false);
|
||||
const specialButtons = reactive({});
|
||||
const showBackLinks = ref(false);
|
||||
const firstUpdateDone = ref(false);
|
||||
const hideBackLinksConfig = componentConfig?.hideBackLinks;
|
||||
const hideBackLinks = ref(true);
|
||||
if (hideBackLinksConfig === false || Array.isArray(hideBackLinksConfig) &&
|
||||
!hideBackLinksConfig.includes(toCURIE(props.classIRI, allPrefixes))) {
|
||||
hideBackLinks.value = false
|
||||
}
|
||||
|
||||
const emit = defineEmits(['namedNodeSelected']);
|
||||
function selectNamedNode(recordClass, recordPID) {
|
||||
|
|
@ -398,6 +417,7 @@ onBeforeMount(async () => {
|
|||
fetchingRecords.value = true;
|
||||
await updateRecord(true);
|
||||
fetchingRecords.value = false;
|
||||
firstUpdateDone.value = true;
|
||||
let recordPIDprefix = toCURIE(props.quad.subject.value, allPrefixes, 'parts').prefix;
|
||||
if (configVarsMain['idResolvesExternally'].indexOf(recordPIDprefix) >= 0) {
|
||||
resolveExternally.value = true;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ const mainVarsToLoad = {
|
|||
NodeShapeViewer: {
|
||||
recordNumberStepSize: 5,
|
||||
textTruncateWidth: "85%",
|
||||
hideBackLinks: true,
|
||||
},
|
||||
URIEditor: {
|
||||
default: "curie",
|
||||
|
|
|
|||
|
|
@ -302,6 +302,56 @@ export function getSubjectQuad(subj, graph) {
|
|||
}
|
||||
}
|
||||
|
||||
export function getReferencingRecords(objVal, graph) {
|
||||
let referencingRecords = {};
|
||||
const firstLevelQuads = graph.getQuads(
|
||||
null,
|
||||
null,
|
||||
namedNode(objVal),
|
||||
null
|
||||
);
|
||||
for (const q of firstLevelQuads) {
|
||||
if (q.subject.termType === 'BlankNode') {
|
||||
var secondLevelQuads = graph.getQuads(
|
||||
null,
|
||||
null,
|
||||
q.subject,
|
||||
null
|
||||
);
|
||||
if (secondLevelQuads && secondLevelQuads.length) {
|
||||
if (!referencingRecords.hasOwnProperty(secondLevelQuads[0].predicate.value)) {
|
||||
referencingRecords[secondLevelQuads[0].predicate.value] = []
|
||||
}
|
||||
referencingRecords[secondLevelQuads[0].predicate.value].push({
|
||||
record_id: secondLevelQuads[0].subject.value
|
||||
})
|
||||
var sQ = getSubjectQuad(secondLevelQuads[0].subject, graph)
|
||||
if (sQ) {
|
||||
referencingRecords[secondLevelQuads[0].predicate.value].at(-1).class_iri = sQ.object.value
|
||||
referencingRecords[secondLevelQuads[0].predicate.value].at(-1).quad = sQ
|
||||
}
|
||||
if (secondLevelQuads.length > 1) {
|
||||
console.error("! secondLevelQuads has length > 1 !")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!referencingRecords.hasOwnProperty(q.predicate.value)) {
|
||||
referencingRecords[q.predicate.value] = []
|
||||
}
|
||||
referencingRecords[q.predicate.value].push({
|
||||
record_id: q.subject.value
|
||||
})
|
||||
var sQ = getSubjectQuad(q.subject, graph)
|
||||
if (sQ) {
|
||||
referencingRecords[q.predicate.value].at(-1).class_iri = sQ.object.value
|
||||
referencingRecords[q.predicate.value].at(-1).quad = sQ
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return referencingRecords
|
||||
}
|
||||
|
||||
export function objectsEqual(obj1, obj2) {
|
||||
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue