diff --git a/src/components/annotations/AnnotationVariantItem.vue b/src/components/annotations/AnnotationVariantItem.vue
index 5288e8e1..24894b7f 100644
--- a/src/components/annotations/AnnotationVariantItem.vue
+++ b/src/components/annotations/AnnotationVariantItem.vue
@@ -12,7 +12,7 @@
>
import { getItemColorBasedOnIndex } from '@/utils/color';
-import { reactive, watch } from 'vue';
+import { reactive, watch, computed } from 'vue';
+import { useAnnotationsStore } from '@/stores/annotations';
import * as AnnotationUtils from '@/utils/annotations';
+const annotationStore = useAnnotationsStore();
+const activeAnnotSelectVariantItems = computed(() => annotationStore.activeAnnotSelectVariantItems);
+const variantItemsColors = computed(() => annotationStore.variantItemsColors)
+
export interface Props {
annotation: Annotation,
isActive: (annotation: Annotation) => boolean,
@@ -51,47 +56,91 @@ const props = withDefaults(defineProps(), {
toggle: () => null,
})
-let variantItemsSelection = reactive({})
-let variantItemsColors = {}
-
+let initialVariantItemsSelection = {}
+
watch(() => props.annotation, () => {
+
props.annotation.body.value.forEach((variantItem) => {
const witness = variantItem.witness
- variantItemsSelection[witness] = false
+ initialVariantItemsSelection[witness] = false
})
})
-
-
+
function handleClick(witness: string, i: number) {
// if at least one variant item is selected, then we don't toggle this annotation
// for each variant item: we should save a state of selected or not, so that to show the icon or not...
- const witnessColor = getItemColorBasedOnIndex(i)
- if (witness in variantItemsColors === false) variantItemsColors[witness] = witnessColor
+
+ // get the number of keys in the variantItemsColors - if the witness is not in the variantItemsColors then we request the next color - which has index the same as this count
+
+
+ const witnessColor = getWitnessColor(witness)
+ if (witness in variantItemsColors.value === false) {
+ updateVariantItemsColors(witness, witnessColor)
+ }
+
+ const variantItemsSelection = pickVariantItemsSelection()
if (!isAtLeastOneVariantItemClicked()) {
// for the first variant item of each variant object
props.toggle(props.annotation)
-
}
+
if ((isOnlyThisVariantActive(witness)) && (isVariantItemActive(witness))) {
// when we have only one variant item of a certain variant object selected and then we deselect it -> remove the blue highlight from the text
props.toggle(props.annotation)
}
+
// update the state of 'false' or 'true' whether this variant item is selected or not
- variantItemsSelection[witness] = !variantItemsSelection[witness]
+ variantItemsSelection[witness] = !variantItemsSelection[witness]
+ annotationStore.updateActiveAnnotSelectVariantItems(props.annotation.id, [props.annotation, variantItemsSelection])
const selector = props.annotation.target[0].selector.value
- if (variantItemsSelection[witness] === true) {
- AnnotationUtils.addWitness(selector, witness, variantItemsColors)
+ if (variantItemsSelection[witness] === true) { // to change
+ AnnotationUtils.addWitness(selector, witness, variantItemsColors.value)
}
else {
AnnotationUtils.removeWitness(selector, witness)
}
}
+
+function updateVariantItemsColors(witness: string, witnessColor: string) {
+ variantItemsColors.value[witness] = witnessColor
+ annotationStore.setVariantItemsColors(variantItemsColors.value)
+}
+
+
+function allocateWitnessColorInVariantItem(witness: string): string {
+ const witnessColor = getWitnessColor(witness)
+ if (witness in variantItemsColors.value === false) {
+ updateVariantItemsColors(witness, witnessColor)
+ }
+ return witnessColor
+}
+
+function getWitnessColor(witness): string {
+
+ let indexColor;
+ if (Object.keys(variantItemsColors.value).length === 0){
+ // the first variant item to be selected
+ return getItemColorBasedOnIndex(0)
+ }
+ else if ((witness in variantItemsColors.value) === false) {
+ // this variant item was not yet selected, but there are already at least one selected
+ indexColor = Object.keys(variantItemsColors.value).length
+ return getItemColorBasedOnIndex(indexColor)
+ }
+
+ // if the variant item with this witness was already selected somewhere in the annotation
+ return variantItemsColors.value[witness]
+}
+
+
function isAtLeastOneVariantItemClicked() {
+ const variantItemsSelection = pickVariantItemsSelection()
+
let isClicked = false
Object.keys(variantItemsSelection).forEach((witness) => {
if (variantItemsSelection[witness] === true) isClicked = true
@@ -99,7 +148,10 @@ function isAtLeastOneVariantItemClicked() {
return isClicked
}
+
function isOnlyThisVariantActive(witness) {
+ const variantItemsSelection = pickVariantItemsSelection()
+
let isOnlyThisVariantClicked = true
Object.keys(variantItemsSelection).forEach((wit) => {
if (variantItemsSelection[wit] === true && wit!== witness) isOnlyThisVariantClicked = false
@@ -107,19 +159,41 @@ function isOnlyThisVariantActive(witness) {
return isOnlyThisVariantClicked
}
-function isVariantItemActive(witness): boolean{
- return variantItemsSelection[witness] === true
-}
+function pickVariantItemsSelection() {
+ // we use this function in order to distinguish the state of variant items selection, before clicking on a certain variant item: either
+ // a) no variant item is selected - initial state, variantItemsSelection copies the value of initialVariantItemsSelection (every variant item has false value)
+ // b) the variant item belongs to an active annotation - use the store computed property : 'activeAnnotSelectVariantItems'
+ // if we have active annotation - we use the value of 'activeAnnotSelectVariantItems' property in the annotation store
+ // else: we use the initial variant items selection - all false values
+ let variantItemsSelection;
+
+ if (Object.keys(activeAnnotSelectVariantItems.value).length > 0) {
+ if((props.annotation.id in activeAnnotSelectVariantItems.value) === false) {
+ variantItemsSelection = { ...initialVariantItemsSelection };
+ }
+ else {
+ variantItemsSelection = activeAnnotSelectVariantItems.value[props.annotation.id][1]
+ }
+ }
+ else {
+ variantItemsSelection = { ...initialVariantItemsSelection };
+ }
+ return variantItemsSelection
+}
-function getVariantItemsSelected(): string[] {
- let variantItemsSelected: string[] = []
- Object.keys(variantItemsSelection).forEach((wit) => {
- if (variantItemsSelection[wit] === true) variantItemsSelected.push(wit)
- })
+function isVariantItemActive(witness): boolean{
- return variantItemsSelected
+ if(Object.keys(activeAnnotSelectVariantItems.value).length > 0) {
+ if( (props.annotation.id in activeAnnotSelectVariantItems.value) === false) {
+ return false
+ }
+ else {
+ return activeAnnotSelectVariantItems.value[props.annotation.id][1][witness]
+ }
+ }
+ return false
}
diff --git a/src/stores/annotations.ts b/src/stores/annotations.ts
index 8a026748..bc99abf9 100644
--- a/src/stores/annotations.ts
+++ b/src/stores/annotations.ts
@@ -13,7 +13,9 @@ import { useConfigStore} from '@/stores/config';
export const useAnnotationsStore = defineStore('annotations', () => {
const activeTab = ref('')
- const activeAnnotations = ref({} as ActiveAnnotation)
+ const activeAnnotations = ref({})
+ const activeAnnotSelectVariantItems = ref({})
+ const variantItemsColors = ref({})
const annotations = ref(null)
const filteredAnnotations = ref([])
const isLoading = ref(false);
@@ -39,6 +41,18 @@ export const useAnnotationsStore = defineStore('annotations', () => {
filteredAnnotations.value = payload
}
+ function setVariantItemsColors(payload) {
+ variantItemsColors.value = payload
+ }
+
+ function setActiveAnnotSelectVariantItems(payload) {
+ activeAnnotSelectVariantItems.value = payload
+ }
+
+ function updateActiveAnnotSelectVariantItems(id, payload) {
+ activeAnnotSelectVariantItems.value[id] = payload
+ }
+
const addActiveAnnotation = (id: string) => {
const annotationStore = useAnnotationsStore()
const configStore = useConfigStore()
@@ -120,9 +134,13 @@ export const useAnnotationsStore = defineStore('annotations', () => {
const removeActiveAnnotation = (id) => {
const annotationStore = useAnnotationsStore()
const removeAnnotation = activeAnnotations.value[id];
+
if (!removeAnnotation) {
return;
}
+
+ // If removed active annotation is variant - then set all the variant items selection to false for this annotation
+
const activeAnnotationsList = { ...activeAnnotations.value };
@@ -268,11 +286,28 @@ export const useAnnotationsStore = defineStore('annotations', () => {
// We need to check here if the right annotations panel tab is active
// a.k.a. it exists in the current filteredAnnotations
const annotation = filteredAnnotations.value.find((filtered) => filtered.id === id);
+ const selector = annotation.target[0].selector.value
if (annotation) {
if (targetIsSelected) {
removeActiveAnnotation(id)
+ if (AnnotationUtils.isVariant(annotation)) {
+ // we need to know which witnesses belong to this annotation AND are selected - so that we can remove the witnesses chips from the text
+ const witnessesHtml = AnnotationUtils.getWitnessesHtmlEl(selector)
+ const witnessesList = AnnotationUtils.getWitnessesList(witnessesHtml)
+ // remove the 'witnesses chips' which are selected
+ AnnotationUtils.removeWitnessesChipsWhenDeselectText(witnessesList, selector)
+ delete activeAnnotSelectVariantItems.value[annotation.id]
+ }
} else {
addActiveAnnotation(id)
+ if(AnnotationUtils.isVariant(annotation)) {
+ // if annotation is variant - additionally set the variant items selection to true
+ const variantItemsSelect = AnnotationUtils.initVariantItemsSelection(annotation, true)
+
+ activeAnnotSelectVariantItems.value[annotation.id] = [activeAnnotations.value[annotation.id], variantItemsSelect]
+ // add all the 'witnesses chips' for this annotation variant
+ AnnotationUtils.addWitnessesChipsWhenSelectText(variantItemsSelect, selector, variantItemsColors.value)
+ }
}
}
});
@@ -321,10 +356,10 @@ export const useAnnotationsStore = defineStore('annotations', () => {
}
return {
- activeTab, activeAnnotations, annotations, filteredAnnotations, isLoading, // states
+ activeTab, activeAnnotations, activeAnnotSelectVariantItems, annotations, filteredAnnotations, isLoading, variantItemsColors, // states
isAllAnnotationSelected, isNoAnnotationSelected, // computed
- setActiveAnnotations, setAnnotations, updateAnnotationLoading, setFilteredAnnotations, // functions
- addActiveAnnotation, selectFilteredAnnotations, addHighlightAttributesToText,
+ setActiveAnnotations, setAnnotations, updateAnnotationLoading, setFilteredAnnotations, setActiveAnnotSelectVariantItems, setVariantItemsColors, // functions
+ addActiveAnnotation, selectFilteredAnnotations, addHighlightAttributesToText, updateActiveAnnotSelectVariantItems,
annotationLoaded, removeActiveAnnotation, resetAnnotations, initAnnotations,
addHighlightHoverListeners, addHighlightClickListeners, getNearestParentAnnotation,
selectAll, selectNone, discoverParentAnnotationIds, discoverChildAnnotationIds
diff --git a/src/utils/annotations.js b/src/utils/annotations.js
index 0c6a2845..67c9064b 100644
--- a/src/utils/annotations.js
+++ b/src/utils/annotations.js
@@ -2,6 +2,7 @@ import * as Utils from '@/utils/index';
import { getIcon } from '@/utils/icons';
import { i18n } from '@/i18n';
+
// utility functions that we can use as generic way for perform tranformation on annotations.
export function addHighlightToElements(selector, root, annotationId) {
@@ -239,6 +240,7 @@ export function addWitness(selector, witness, variantItemsColors) {
const parentEl = targetHtmlEl.parentElement
const indexOfTarget = [].slice.call(parentEl.children).indexOf(targetHtmlEl)
+
const witHtml = createCurrWitHtml(witness, variantItemsColors[witness])
if(!parentEl.children[indexOfTarget-1].classList.contains("witnesses")) {
@@ -287,7 +289,7 @@ export function removeWitness(selector, witness) {
witHtml[0].remove()
}
-function getWitnessesHtmlEl(selector) {
+export function getWitnessesHtmlEl(selector) {
// selector represents the target text of a certain variant item
// we aim to get the html element which contains the 'witnesses chips' related to the target.
// this html element which contains the 'witnesses chips' is located before the target element
@@ -299,6 +301,50 @@ function getWitnessesHtmlEl(selector) {
return witnessesHtmlEl
}
+export function getWitnessesList(witnessesHtml) {
+ // returns the list of witnesses() which are already selected
+ let witnessesList= []
+ Array.from(witnessesHtml.children).forEach((witnessHtml) => {
+ witnessesList.push(witnessHtml.innerHTML)
+ })
+ return witnessesList
+}
+
+export function unselectVariantItems(variantItemsSelection) {
+ let newVariantItemsSelection = {}
+ Object.keys(variantItemsSelection).forEach((wit) => {
+ newVariantItemsSelection[wit] = false
+ })
+ return newVariantItemsSelection
+}
+
+export function addWitnessesChipsWhenSelectText(variantItemsSelection, selector, variantItemsColors) {
+ // variantItemsSelection: JSON object of 'witness name': 'true'
+ // this function aims to add all witnesses on the highlighted text when we click on the text
+
+ Object.keys(variantItemsSelection).forEach((witness) => {
+ addWitness(selector, witness, variantItemsColors)
+ })
+}
+
+export function removeWitnessesChipsWhenDeselectText(witnessesList, selector) {
+ witnessesList.forEach((witness) => {
+ removeWitness(selector, witness)
+ })
+}
+
+export function isVariant(annotation) {
+ return annotation.body['x-content-type'] === 'Variant';
+}
+
+export function initVariantItemsSelection(annotation, value) {
+ // initialize with the boolean of 'value' variable
+ let variantItemsSelection = {}
+ annotation.body.value.forEach((variantItem) => {
+ variantItemsSelection[variantItem.witness] = value
+ } )
+ return variantItemsSelection
+}
export function getAnnotationListElement(id, container) {
return [...container.querySelectorAll('.q-item')].find((annotationItem) => {