From 7c2576b0cfb0a15b2a14f6f5ea96de16f0c23b44 Mon Sep 17 00:00:00 2001
From: Zero~Informatique
Date: Tue, 24 Dec 2019 02:22:56 +0100
Subject: viewer: Plugin for Optional chaining and Coalesce. Implemented tag
 operations (intersection, addition, substraction). Unified Tag.Search

---
 viewer/src/components/LdTagInput.vue | 48 ++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 8 deletions(-)

(limited to 'viewer/src/components/LdTagInput.vue')

diff --git a/viewer/src/components/LdTagInput.vue b/viewer/src/components/LdTagInput.vue
index 4121cd7..daca62d 100644
--- a/viewer/src/components/LdTagInput.vue
+++ b/viewer/src/components/LdTagInput.vue
@@ -6,11 +6,14 @@
     ellipsis
     attached
     :data="filteredTags"
-    field="tag"
+    field="display"
     type="is-black"
     icon="tag"
+    size="is-medium"
     class="panelTagInput"
     @typing="searchTags"
+    @add="onAdd"
+    @remove="onRemove"
   >
     <template slot-scope="props">{{displayOption(props.option)}}</template>
     <template slot="empty">{{$t('tagInput.nomatch')}}</template>
@@ -19,41 +22,70 @@
 
 <script lang="ts">
 import { Component, Vue } from "vue-property-decorator";
+import { Operation } from "@/@types/tag/Operation";
 
 @Component
 export default class LdTagInput extends Vue {
   filteredTags: Tag.Search[] = [];
 
+  onAdd(e: any) {
+    this.$uiStore.mode = "search";
+  }
+
+  onRemove() {
+    if (this.$uiStore.currentTags.length === 0) this.$uiStore.mode = "navigation";
+  }
+
   displayOption(option: Tag.Search): string {
-    return `${option.tag} (${option.items.length})`;
+    return `${option.display} (${option.items.length})`;
+  }
+
+  extractOperation(filter: string) {
+    const first = filter.slice(0, 1);
+    switch (first) {
+      case Operation.ADDITION:
+      case Operation.SUBSTRACTION:
+        return first;
+      default:
+        return Operation.INTERSECTION;
+    }
   }
 
   searchTags(filter: string) {
     const tags = this.$galleryStore.tags;
     let search: Tag.Search[] = [];
     if (tags && filter) {
+      const operation = this.extractOperation(filter);
+      if (operation !== Operation.INTERSECTION) filter = filter.slice(1);
       if (filter.includes(":")) {
         const filterParts = filter.split(":");
-        search = this.searchTagsFromFilterWithCategory(tags, filterParts[0], filterParts[1]);
+        search = this.searchTagsFromFilterWithCategory(tags, operation, filterParts[0], filterParts[1]);
       } else {
-        search = this.searchTagsFromFilter(tags, filter);
+        search = this.searchTagsFromFilter(tags, operation, filter);
       }
     }
     this.filteredTags = this.cleanupAndSort(search);
   }
 
-  searchTagsFromFilterWithCategory(tags: Tag.Index, category: string, disambiguation: string): Tag.NodeWithParent[] {
+  searchTagsFromFilterWithCategory(
+    tags: Tag.Index,
+    operation: Operation,
+    category: string,
+    disambiguation: string
+  ): Tag.Search[] {
     return Object.values(tags)
       .filter(node => node.tag.includes(category))
       .flatMap(node =>
         Object.values(node.children)
           .filter(child => child.tag.includes(disambiguation))
-          .map(child => ({ ...child, parent: node, tag: `${node.tag}:${child.tag}` }))
+          .map(child => ({ ...child, parent: node, operation, display: `${operation}${node.tag}:${child.tag}` }))
       );
   }
 
-  searchTagsFromFilter(tags: Tag.Index, filter: string): Tag.Node[] {
-    return Object.values(tags).filter(node => node.tag.includes(filter));
+  searchTagsFromFilter(tags: Tag.Index, operation: Operation, filter: string): Tag.Search[] {
+    return Object.values(tags)
+      .filter(node => node.tag.includes(filter))
+      .map(node => ({ ...node, operation, display: `${operation}${node.tag}` }));
   }
 
   cleanupAndSort(search: Tag.Search[]): Tag.Search[] {
-- 
cgit v1.2.3

