Skip to content

Commit

Permalink
ItemView: Add error handling (#36)
Browse files Browse the repository at this point in the history
Shows errors if scheme, top concepts, or concept data could not be loaded.
  • Loading branch information
stefandesu committed Jul 9, 2024
1 parent d152670 commit 0a262d3
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
8 changes: 8 additions & 0 deletions locale.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"conceptSearch": "Suche nach Konzept",
"license": "Lizenz",
"distributions": "Distributionen",
"error": "Fehler",
"schemeError": "Vokabular konnte nicht gefunden werden.",
"loadTopError": "@:error{':'} Oberkonzepte konnten nicht geladen werden.",
"loadConceptError": "Konzeptdetails konnten nicht geladen werden. Entweder existiert das Konzept nicht oder es gibt Probleme beim Zugriff auf das Backend.",
"searchInVocabulary": "in {voc} suchen"
},
"en": {
Expand All @@ -23,6 +27,10 @@
"conceptSearch": "Searching for concept",
"license": "License",
"distributions": "Distributions",
"error": "Error",
"schemeError": "Vocabulary could not be found.",
"loadTopError": "@:error{':'} Top concepts could not be loaded.",
"loadConceptError": "Concept details could not be loaded. Either the concept does not exist, or there are issues with the backend.",
"searchInVocabulary": "search in {voc}"
}
}
66 changes: 58 additions & 8 deletions src/client/views/ItemView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import config from "@/config.js"
import * as jskos from "jskos-tools"
import { AutoLink, LicenseInfo } from "jskos-vue"
import { schemes, registry, loadTop, loadNarrower, loadConcept, loadAncestors, saveConcept, formats } from "@/store.js"
import { computed, ref, watch } from "vue"
import { computed, ref, reactive, watch } from "vue"
import { useRoute, useRouter } from "vue-router"
import { utils } from "jskos-vue"
import MapView from "@/components/MapView.vue"
Expand All @@ -14,8 +14,15 @@ const router = useRouter()
const conceptTreeRef = ref(null)
const errors = reactive({
schemeError: false,
loadConceptError: false,
loadTopError: false,
})
const schemeUri = computed(() => route.params.voc.match(/^https?:\/\//) ? route.params.voc : `${config.namespace}${route.params.voc}/`)
const scheme = computed(() => {
return schemes.value?.find(s => jskos.compare(s, { uri: route.params.voc.match(/^https?:\/\//) ? route.params.voc : `${config.namespace}${route.params.voc}/` }))
return schemes.value?.find(s => jskos.compare(s, { uri: schemeUri.value }))
})
const uri = computed(() => scheme.value && (route.params.id && `${config.namespace}${route.params.voc}/${route.params.id}` || route.query.uri))
Expand All @@ -35,13 +42,21 @@ const hierarchyLoading = ref(true)
let topLoadingPromise = null
// Load top concepts when scheme is ready
watch(scheme, async () => {
watch([schemes, scheme], async () => {
errors.loadTopError = false
if (scheme.value && (!scheme.value?.topConcepts || scheme.value?.topConcepts?.includes(null))) {
topLoadingPromise = loadTop(scheme.value)
}
if (scheme.value) {
errors.schemeError = false
} else if (schemes.value?.length) {
console.error(`Scheme ${schemeUri.value} could not be found.`)
errors.schemeError = true
}
},{ immediate: true })
watch(uri, async (value, prevValue) => {
errors.loadConceptError = false
if (value && value !== prevValue) {
let shouldScroll = true
const openAndScroll = () => {
Expand Down Expand Up @@ -82,9 +97,23 @@ watch(uri, async (value, prevValue) => {
const tabsVueComponent = document.getElementsByClassName("jskos-vue-tabs")[0]?.__vueParentComponent
tabsVueComponent?.proxy?.activateTab(0)
// Wait for top concepts before doing anything else
topLoadingPromise && await topLoadingPromise
try {
topLoadingPromise && await topLoadingPromise
} catch (error) {
console.error(`Error loading top concepts for ${scheme.value?.uri}:`, error)
errors.loadTopError = true
}
// Load concept data
const loadedConcept = await loadConcept(value, scheme.value)
let loadedConcept
try {
loadedConcept = await loadConcept(value, scheme.value)
} catch (error) {
console.error(`Error loading concept ${value}:`, error)
errors.loadConceptError = true
conceptLoading.value = false
hierarchyLoading.value = false
return
}
// Abort if concept has changed in the meantime
if (value !== uri.value) {
return
Expand All @@ -111,9 +140,14 @@ const topConcepts = computed(() => {
<template>
<h2 id="schemeHeader">
<router-link :to="getRouterUrl({ scheme })">
<router-link
v-if="scheme && !errors.schemeError"
:to="getRouterUrl({ scheme })">
{{ jskos.prefLabel(scheme) }}
</router-link>
<span v-else>
{{ $t("error") }}: {{ schemeUri }}
</span>
<div
v-if="scheme?.license?.length"
id="licenseInfo">
Expand All @@ -128,7 +162,9 @@ const topConcepts = computed(() => {
:placeholder="jskos.notation(scheme) ? $t('searchInVocabulary', { voc: jskos.notation(scheme) }) : null"
@select="concept = { uri: $event.uri }" />
<!-- ConceptTree has to be on the top level in order for "scrollToUri" to work -->
<div id="conceptHierarchy">
<div
v-if="!errors.schemeError && !errors.loadTopError"
id="conceptHierarchy">
<concept-tree
v-if="topConcepts"
id="conceptTree"
Expand All @@ -143,14 +179,20 @@ const topConcepts = computed(() => {
</div>
</div>
<div
v-else
id="conceptHierarchy">
{{ errors.schemeError ? $t("schemeError") : $t("loadTopError") }}
</div>
<div
v-if="scheme"
id="conceptDetails">
<div
v-if="!scheme || conceptLoading"
class="loading">
<loading-indicator size="xl" />
</div>
<item-details
v-if="concept || scheme"
v-if="(concept || scheme) && !errors.loadConceptError"
id="itemDetails"
:item="concept || scheme"
:flat="true"
Expand Down Expand Up @@ -213,6 +255,14 @@ const topConcepts = computed(() => {
</ul>
</template>
</item-details>
<div
v-else
id="itemDetails">
<div class="jskos-vue-itemDetails-name">
{{ $t("error") }}: {{ uri }}
</div>
{{ $t("loadConceptError") }}
</div>
</div>
</template>
Expand Down

0 comments on commit 0a262d3

Please sign in to comment.