Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant item selection/deselection #459

Merged
merged 16 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions examples/ahiqar-arabic-karshuni-with-variants-local.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html>
<head><title>TIDO</title>
<head>
<title>TIDO</title>

<meta charset="utf-8">
<meta name="description" content="">
<meta name="description" content="<%= htmlWebpackPlugin.options.productDescription %>">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1,maximum-scale=5,minimum-scale=1,width=device-width">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="dist/tido.css">
<meta name="viewport" content="initial-scale=1, maximum-scale=5, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
<style>
html, body {
margin: 0;
Expand All @@ -17,15 +17,17 @@
}
</style>
</head>
<body>
<noscript><strong>We're sorry but TIDO doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong></noscript>

<body>
<noscript>
<strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="dist/tido.js"></script>

<script type="module" src="/src/main.js"></script>
<script>
window.addEventListener('load', function () {
window.tido = new window.Tido({
window.addEventListener('load', function () {
window.tido = new window.Tido({
"collection": "http://localhost:8181/ahiqar/textapi/ahiqar/arabic-karshuni/collection.json",
"labels": {
"item": "Sheet",
Expand Down Expand Up @@ -114,19 +116,19 @@
"types": [
{
"name": "Person",
"icon": "biPersonFill"
"icon": "person"
},
{
"name": "Place",
"icon": "biGeoAltFill"
"icon": "marker"
},
{
"name": "Editorial Comment",
"icon": "biChatFill"
"icon": "chat"
},
{
"name": "Reference",
"icon": "biBoxArrowUpRight"
"icon": "externalLink"
}
]
}
Expand All @@ -141,7 +143,7 @@
"types": [
{
"name": "Motif",
"icon": "biPenFill"
"icon": "pen"
}
]
}
Expand All @@ -156,7 +158,7 @@
"types": [
{
"name": "Variant",
"icon": "biPenFill"
"icon": "pen"
}
]
}
Expand All @@ -171,7 +173,7 @@
}
}
});
});
</script>
});
</script>
</body>
</html>
116 changes: 111 additions & 5 deletions src/components/annotations/AnnotationVariantItem.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,129 @@
<template>
<div v-for="(variant, i) in annotation.body.value" :key="i" class="t-items-center t-flex">
<span v-if="variant.witness" v-html="variant.witness" class="t-mr-7"/>
<span v-else class="t-mr-7"> - </span>
<span v-html="variant.entry"/>
<div
v-for="(variant, i) in annotation.body.value"
:key="i"
class="t-items-center t-flex t-mb-1 t-relative"
:class="[
't-py-2 t-px-3 t-mb-1 t-rounded-md',
{ 'hover:t-bg-gray-200 dark:hover:t-bg-gray-600 t-cursor-pointer': !isActive(annotation) },
{ 't-bg-gray-300 dark:t-bg-gray-600 active': isVariantItemActive(variant.witness)}]"
:data-annotation-id="annotation.id"
@click="handleClick(variant.witness, i)"
>
<div
class="t-relative t-rounded-3xl t-box-border t-w-75 t-h-8 t-border-2 t-p-[2px]"
:style="{'border-color': getItemColorBasedOnIndex(i)}"
>
<span
v-if="variant.witness"
class="t-text-sm"
v-html="variant.witness"
/>
<span
v-else
class="t-text-sm"
> - </span>
</div>
<span
class="t-absolute t-right-[50%]"
v-html="variant.entry"
/>
</div>
</template>



<script setup lang="ts">
import { getItemColorBasedOnIndex } from '@/utils/color';
import { reactive, watch } from 'vue';
import * as AnnotationUtils from '@/utils/annotations';


export interface Props {
annotation: Annotation
annotation: Annotation,
isActive: (annotation: Annotation) => boolean,
toggle: (annotation: Annotation) => void,
}

const props = withDefaults(defineProps<Props>(), {
annotation: () => <Annotation>{},
isActive: () => true,
toggle: () => null,
})

let variantItemsSelection = reactive({})
let variantItemsColors = {}


watch(() => props.annotation, () => {
props.annotation.body.value.forEach((variantItem) => {
const witness = variantItem.witness
variantItemsSelection[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

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]

const selector = props.annotation.target[0].selector.value
if (variantItemsSelection[witness] === true) {
AnnotationUtils.addWitness(selector, witness, variantItemsColors)
}
else {
AnnotationUtils.removeWitness(selector, witness)
}
}

function isAtLeastOneVariantItemClicked() {
let isClicked = false
Object.keys(variantItemsSelection).forEach((witness) => {
if (variantItemsSelection[witness] === true) isClicked = true
})
return isClicked
}

function isOnlyThisVariantActive(witness) {
let isOnlyThisVariantClicked = true
Object.keys(variantItemsSelection).forEach((wit) => {
if (variantItemsSelection[wit] === true && wit!== witness) isOnlyThisVariantClicked = false
})
return isOnlyThisVariantClicked
}

function isVariantItemActive(witness): boolean{
return variantItemsSelection[witness] === true
}


function getVariantItemsSelected(): string[] {
let variantItemsSelected: string[] = []
Object.keys(variantItemsSelection).forEach((wit) => {
if (variantItemsSelection[wit] === true) variantItemsSelected.push(wit)
})

return variantItemsSelected

}



</script>


Expand Down
48 changes: 30 additions & 18 deletions src/components/annotations/AnnotationsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,40 @@
<div
v-for="annotation in configuredAnnotations"
:key="annotation.id"
:data-annotation-id="annotation.id"
class="item"
:class="[
't-py-2 t-px-3 t-mb-1 t-rounded-md',
{ 'hover:t-bg-gray-200 dark:hover:t-bg-gray-600 t-cursor-pointer': !isText(annotation) && !isActive(annotation) },
{ 't-bg-gray-300 dark:t-bg-gray-600 active': isActive(annotation) }
]"
@click="isText(annotation) ? ()=>{} : toggle(annotation)"
>

<div v-if="!isVariant(annotation)" class="t-flex t-items-center t-space-x-2">
<AnnotationIcon
<div
v-if="!isVariant(annotation)"
class="t-flex t-items-center t-space-x-2 item"
:class="[
't-py-2 t-px-3 t-mb-1 t-rounded-md',
{ 'hover:t-bg-gray-200 dark:hover:t-bg-gray-600 t-cursor-pointer': !isText(annotation) && !isActive(annotation) },
{ 't-bg-gray-300 dark:t-bg-gray-600 active': isActive(annotation) }]"
:data-annotation-id="annotation.id"
@click="isText(annotation) ? ()=>{} : toggle(annotation)"
>
<AnnotationIcon
v-if="!isText(annotation)"
:name="getIconName(annotation.body['x-content-type'])"
/>
<span v-html="annotation.body.value"/>
</div>
/>
<span v-html="annotation.body.value" />
</div>

<div v-else>
<AnnotationVariantItem :annotation="annotation" />
</div>
<div v-else>
<AnnotationVariantItem
:annotation="annotation"
:is-active="isActive"
:toggle="toggle"
/>
</div>

<!-- eslint-disable -- https://eslint.vuejs.org/rules/no-v-html.html -->
<!-- eslint-disable -- https://eslint.vuejs.org/rules/no-v-html.html -->


</div>
</div>
</template>


<script setup lang="ts">
import { computed } from 'vue';
import AnnotationIcon from '@/components/annotations/AnnotationIcon.vue';
Expand Down Expand Up @@ -68,6 +73,7 @@ function isActive(annotation: Annotation): boolean {
function isText(annotation: Annotation): boolean {
return annotationTypesMapping.value[annotation.body['x-content-type']] === 'text';
}

function getIconName(typeName: string): string {
return props.types.find(({ name }) => name === typeName)?.icon || 'pencil';
}
Expand All @@ -76,10 +82,16 @@ function isVariant(annotation) {
return annotation.body['x-content-type'] === 'Variant';
}

function isVariantsTabOpened() {
return props.configuredAnnotations[0].body['x-content-type'] === 'Variant';
}

</script>



<style lang="scss" scoped>



</style>
6 changes: 6 additions & 0 deletions src/components/panels/Panel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ import PanelImageAction from '@/components/panels/actions/PanelImageAction.vue';
import LoadingSpinner from '@/components/LoadingSpinner.vue';
import MessageBox from '@/components/MessageBox.vue';
import { findComponent } from '@/utils/panels';
import * as AnnotationUtils from '@/utils/annotations'


// NOTE: Using `setup()` rather than the recommended `<script setup>`
// to avoid issues with asset loading.
Expand Down Expand Up @@ -366,6 +368,10 @@ export default {

function onViewChange(index) {
activeTabIndex.value = index;
if (index !==2) {
AnnotationUtils.removeChipsFromOtherViews()
}

emit('active-view', activeTabIndex.value);
}

Expand Down
Loading