From c393f9846aa0dc351315482d53e309e230503d38 Mon Sep 17 00:00:00 2001
From: Valentin Rigal <rigal@teklia.com>
Date: Wed, 20 Dec 2023 14:38:45 +0000
Subject: [PATCH] Allow to select a child without a zone

---
 src/components/Element/PanelHeader.vue        | 21 +++++++++++++++++--
 src/components/Image/InteractiveImage.vue     |  2 +-
 src/components/Image/Tools.vue                |  3 ++-
 .../Navigation/ChildrenTree/TreeItem.vue      |  8 ++-----
 src/store/annotation.js                       |  4 ----
 src/views/Element.vue                         |  3 ++-
 6 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/src/components/Element/PanelHeader.vue b/src/components/Element/PanelHeader.vue
index 93608a151..757b69a4b 100644
--- a/src/components/Element/PanelHeader.vue
+++ b/src/components/Element/PanelHeader.vue
@@ -54,6 +54,13 @@
       <span v-else-if="element.creator">Created by <strong>{{ element.creator }}</strong></span>
       <ConfidenceTag v-if="Number.isFinite(element.confidence)" :value="element.confidence" />
     </p>
+    <!-- Display a message at the top of the panel when a selected children has no zone -->
+    <div
+      v-if="!element.zone?.polygon && !isFolder && element.id !== mainElementId"
+      class="notification is-info my-2 p-3"
+    >
+      This element has no zone.
+    </div>
     <Modal v-model="deleteModal" :title="'Delete ' + typeName(element.type) + ' ' + element.name">
       <p>
         Are you sure you want to delete the {{ typeName(element.type) }}
@@ -124,9 +131,19 @@ export default {
     element () {
       return this.elements[this.elementId]
     },
+    isFolder () {
+      return this.getType(this.element.type).folder
+    },
     isAnnotable () {
-      const isFolder = this.getType(this.element.type).folder
-      return this.element?.zone !== null && !isFolder && this.corpus && this.canWrite(this.corpus)
+      const mainElement = this.elements[this.mainElementId]
+      if (!mainElement) return false
+      const mainFolder = this.getType(mainElement.type).folder
+      return (
+        mainElement.image !== null &&
+        !mainFolder &&
+        this.corpus &&
+        this.canWrite(this.corpus)
+      )
     },
     corpusId () {
       return this.element?.corpus?.id ?? null
diff --git a/src/components/Image/InteractiveImage.vue b/src/components/Image/InteractiveImage.vue
index 1183ee6dc..522928e84 100644
--- a/src/components/Image/InteractiveImage.vue
+++ b/src/components/Image/InteractiveImage.vue
@@ -44,7 +44,7 @@
             fill="transparent"
           />
           <!-- Display the currently edited element using lines and circles -->
-          <g v-if="selectedElement" v-on:mouseover="setHoveredId(selectedElement.id)" v-on:mouseleave="setHoveredId(null)">
+          <g v-if="selectedElement && selectedElement.zone !== null" v-on:mouseover="setHoveredId(selectedElement.id)" v-on:mouseleave="setHoveredId(null)">
             <!-- A polyline for the background color, allowing to drag the element around. -->
             <polyline
               :points="svgPolygon(selectedElement.zone.polygon)"
diff --git a/src/components/Image/Tools.vue b/src/components/Image/Tools.vue
index 07db57efa..d2b64711b 100644
--- a/src/components/Image/Tools.vue
+++ b/src/components/Image/Tools.vue
@@ -5,8 +5,9 @@
         <a
           class="button"
           :class="{ 'is-primary is-outlined': tool === 'select' }"
-          title="Select and move an existing child"
           v-on:click="changeTool('select')"
+          :disabled="selectedElement.zone === null || undefined"
+          :title="selectedElement.zone === null ? 'This element has no polygon' : 'Select and move the selected element'"
         >
           <span class="icon">
             <i class="icon-hand-pointer"></i>
diff --git a/src/components/Navigation/ChildrenTree/TreeItem.vue b/src/components/Navigation/ChildrenTree/TreeItem.vue
index ebf094be8..da1595b55 100644
--- a/src/components/Navigation/ChildrenTree/TreeItem.vue
+++ b/src/components/Navigation/ChildrenTree/TreeItem.vue
@@ -225,11 +225,6 @@ export default {
     },
     interactiveSelect (element) {
       if (!this.interactive) return
-      if (!this.element.zone || !this.element.zone.polygon) {
-        this.notify({ type: 'info', text: 'This element has no zone.' })
-        this.selectElement(null)
-        return
-      }
       if (this.annotationEnabled && this.annotationTool !== 'select') {
         // In edition mode, set current tool to selection
         this.setAnnotationTool('select')
@@ -242,10 +237,11 @@ export default {
       ) {
         this.selectElement(null)
       } else {
+        const eltPolygon = element?.zone?.polygon || null
         this.selectElement({
           id: element.id,
           name: element.name,
-          zone: { polygon: [...element.zone.polygon] }
+          zone: eltPolygon && { polygon: [...eltPolygon] }
         })
         if (this.$route.query.highlight !== element.id) {
           const query = { ...clone(this.$route.query) }
diff --git a/src/store/annotation.js b/src/store/annotation.js
index c44f0dbe4..18c8d0180 100644
--- a/src/store/annotation.js
+++ b/src/store/annotation.js
@@ -205,10 +205,6 @@ export const mutations = {
   },
 
   selectElement (state, object) {
-    // Edited element may have a polygon if defined
-    if (object !== null && (!object.zone || !object.zone.polygon)) {
-      throw new Error('Edited element must be null or have a defined zone.')
-    }
     state.selectedElement = object
   },
 
diff --git a/src/views/Element.vue b/src/views/Element.vue
index ebbb9d2ab..52939067f 100644
--- a/src/views/Element.vue
+++ b/src/views/Element.vue
@@ -235,10 +235,11 @@ export default {
       if (!this.parents[this.highlight]) await this.$store.dispatch('elements/getParentsBulk', { id: this.highlight, corpus: this.corpus })
       if (!this.parents[this.highlight] || !this.parents[this.highlight].includes(this.element.id)) return
       if (!this.elements[this.highlight]) await this.$store.dispatch('elements/get', { id: this.highlight })
+      const eltPolygon = this.elements[this.highlight]?.zone?.polygon || []
       this.selectElement({
         id: this.highlight,
         name: this.elements[this.highlight].name,
-        zone: { polygon: [...this.elements[this.highlight].zone.polygon] }
+        zone: { polygon: [...eltPolygon] }
       })
     },
     isNeighbor (id) {
-- 
GitLab