Skip to content

Commit

Permalink
First implementation of mismatch tagging (#667)
Browse files Browse the repository at this point in the history
Client implementation for gbv/jskos-server#194.
  • Loading branch information
stefandesu committed May 10, 2023
1 parent 6d113fc commit 4822f21
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 6 deletions.
6 changes: 4 additions & 2 deletions config/locale.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@
},
"annotationPopover": {
"addConfirmation": "Confirm",
"removeConfirmation": "Remove Confirmation"
"removeConfirmation": "Remove Confirmation",
"reason": "Reason"
},
"languages": {
"en": "English",
Expand Down Expand Up @@ -751,7 +752,8 @@
},
"annotationPopover": {
"addConfirmation": "Bestätigen",
"removeConfirmation": "Bestätigung entfernen"
"removeConfirmation": "Bestätigung entfernen",
"reason": "Grund"
},
"languages": {
"en": "Englisch",
Expand Down
78 changes: 76 additions & 2 deletions src/components/AnnotationList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@
}"
:link="$jskos.annotationCreatorUri(annotation)"
:text="$jskos.annotationCreatorName(annotation)" />
<span v-if="mismatchTagAllowedFor(annotation) && canEdit(annotation) && mismatchTagConcepts.length">
<br>{{ $t("annotationPopover.reason") }}:
<select
:value="mismatchTagFor(annotation)?.uri || null"
@change="changeMismatchTag(annotation, $event.target.value || null)">
<option
v-for="option in mismatchTagOptions"
:key="option.value"
:title="option.definition"
:value="option.value">{{ option.text }}</option>
</select>
</span>
<span v-else-if="mismatchTagFor(annotation)">
<br>{{ $t("annotationPopover.reason") }}: {{ mismatchTagLabel(mismatchTagFor(annotation)) }}
</span>
</div>
<div>
<font-awesome-icon
Expand All @@ -48,6 +63,7 @@ import DateString from "./DateString.vue"
// Import mixins
import auth from "@/mixins/auth.js"
import { getItem } from "@/items"
export default {
name: "AnnotationList",
Expand All @@ -63,6 +79,14 @@ export default {
default: null,
},
},
computed: {
mismatchTagConcepts() {
return getItem(this.provider?._config?.annotations?.mismatchTagVocabulary)?.topConcepts ?? []
},
mismatchTagOptions() {
return [{ value: null, text: "-" }].concat(this.mismatchTagConcepts.map(concept => ({ value: concept.uri, text: this.mismatchTagLabel(concept), definition: this.mismatchTagDefinition(concept) })))
},
},
methods: {
userOwnsAnnotation(annotation) {
return this.$jskos.annotationCreatorMatches(annotation, this.userUris)
Expand All @@ -75,6 +99,14 @@ export default {
crossUser: !this.userOwnsAnnotation(annotation),
})
},
canEdit(annotation) {
return !!this.provider?.isAuthorizedFor({
type: "annotations",
action: "update",
user: this.user,
crossUser: !this.userOwnsAnnotation(annotation),
})
},
async remove(index) {
if (!this.provider) {
return false
Expand Down Expand Up @@ -103,6 +135,43 @@ export default {
this.$emit("refresh-annotations", { annotations: this.annotations })
return success
},
mismatchTagAllowedFor(annotation) {
return annotation.motivation === "assessing" && annotation.bodyValue === "-1"
},
mismatchTagFor(annotation) {
if (!this.mismatchTagAllowedFor(annotation)) {
return null
}
const tag = annotation.body?.find(t => t.type === "SpecificResource" && t.purpose === "tagging" && t.value)
if (!tag) {
return null
}
return getItem({ uri: tag.value })
},
mismatchTagLabel(tag) {
return this.$jskos.prefLabel(getItem(tag), { language: this.$i18n.locale, fallbackToUri: false })
},
mismatchTagDefinition(tag) {
return this.$jskos.definition(getItem(tag), { language: this.$i18n.locale })
},
async changeMismatchTag(annotation, tag) {
const body = tag ? [{
type: "SpecificResource",
value: tag,
purpose: "tagging",
}] : null
try {
await this.provider.patchAnnotation({ annotation: { id: annotation.id, body } })
// TODO: Improve value refresh
if (body) {
annotation.body = body
} else {
delete annotation.body
}
} catch (error) {
this.$log.error(`Error updating mismatch tag for annotation ${annotation.id}:`, error)
}
},
},
}
</script>
Expand All @@ -121,13 +190,18 @@ export default {
flex: 1;
}
.annotationList > div > div:first-child {
flex: none;
padding-right: 10px;
}
.annotationList > div > div:last-child {
flex: none;
padding-left: 10px;
}
.annotationList > div > div:first-child, .annotationList > div > div:last-child {
flex: none;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
}
.annotationList > div:nth-child(odd) {
background-color: @color-background;
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/AnnotationPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,10 @@ export default {
return
}
// 2. Case: User has assessed and changes the value
promise = provider.patchAnnotation({ annotation: { id: ownAssessment.id, bodyValue: value } }).then(annotation => {
promise = provider.patchAnnotation({ annotation: { id: ownAssessment.id, bodyValue: value, body: null } }).then(annotation => {
if (annotation) {
ownAssessment.bodyValue = value
delete ownAssessment.body
this.alert(this.$t("alerts.annotationSaved"), null, "success")
this.$emit("refresh-annotations", { uri, annotations: mapping.annotations })
} else {
Expand Down
13 changes: 12 additions & 1 deletion src/components/MappingBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ import ConcordanceEditorModal from "./ConcordanceEditorModal.vue"
import ConcordanceDetail from "./ConcordanceDetail.vue"
import DateString from "./DateString.vue"
import _ from "lodash"
import { cdk } from "cocoda-sdk"
// Only use for cancel token generation!
import axios from "axios"
Expand All @@ -503,7 +504,7 @@ import dragandrop from "@/mixins/dragandrop.js"
import clickHandler from "@/mixins/click-handler.js"
import computed from "@/mixins/computed.js"
import pageVisibility from "@/mixins/page-visibility.js"
import { getItem, getItems, loadConcepts } from "@/items"
import { getItem, getItems, saveItem, loadConcepts, loadTop } from "@/items"
export default {
name: "MappingBrowser",
Expand Down Expand Up @@ -1150,6 +1151,16 @@ export default {
}
})
})
// Load mismatchTagVocabulary entries if necessary
this.mappingRegistries.map(registry => registry._config?.annotations?.mismatchTagVocabulary).filter(Boolean).forEach(scheme => {
const registry = cdk.registryForScheme(scheme)
if (!registry) {
this.$log.warn(`Could not find registry for mismatchTagVocabulary ${scheme.uri}. Feature is disabled.`)
return
}
scheme = saveItem(scheme)
loadTop(scheme, { registry })
})
},
beforeDestroy() {
// Stop any repeat managers
Expand Down

0 comments on commit 4822f21

Please sign in to comment.