From 06c4d9299bb684805051355555fa89f0d440d194 Mon Sep 17 00:00:00 2001
From: Zero~Informatique
Date: Sun, 22 Dec 2019 11:26:53 +0100
Subject: viewer: Implemented tag category and disambiguation filtering

---
 viewer/src/components/LdTagInput.vue | 52 +++++++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 10 deletions(-)

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

diff --git a/viewer/src/components/LdTagInput.vue b/viewer/src/components/LdTagInput.vue
index 4edc1ce..4121cd7 100644
--- a/viewer/src/components/LdTagInput.vue
+++ b/viewer/src/components/LdTagInput.vue
@@ -3,14 +3,16 @@
     v-model="$uiStore.currentTags"
     :placeholder="$t('tagInput.placeholder')"
     autocomplete
+    ellipsis
+    attached
     :data="filteredTags"
     field="tag"
     type="is-black"
-    size="is-large"
+    icon="tag"
     class="panelTagInput"
-    @typing="getFilteredTags"
+    @typing="searchTags"
   >
-    <template slot-scope="props">{{props.option.tag}} ({{props.option.items.length}})</template>
+    <template slot-scope="props">{{displayOption(props.option)}}</template>
     <template slot="empty">{{$t('tagInput.nomatch')}}</template>
   </b-taginput>
 </template>
@@ -20,15 +22,45 @@ import { Component, Vue } from "vue-property-decorator";
 
 @Component
 export default class LdTagInput extends Vue {
-  filteredTags: Tag.Node[] = [];
+  filteredTags: Tag.Search[] = [];
 
-  getFilteredTags(filter: string) {
+  displayOption(option: Tag.Search): string {
+    return `${option.tag} (${option.items.length})`;
+  }
+
+  searchTags(filter: string) {
     const tags = this.$galleryStore.tags;
-    if (tags && filter)
-      this.filteredTags = Object.values(tags)
-        .filter(node => node.tag.includes(filter))
-        .sort((a, b) => b.items.length - a.items.length);
-    else this.filteredTags = [];
+    let search: Tag.Search[] = [];
+    if (tags && filter) {
+      if (filter.includes(":")) {
+        const filterParts = filter.split(":");
+        search = this.searchTagsFromFilterWithCategory(tags, filterParts[0], filterParts[1]);
+      } else {
+        search = this.searchTagsFromFilter(tags, filter);
+      }
+    }
+    this.filteredTags = this.cleanupAndSort(search);
+  }
+
+  searchTagsFromFilterWithCategory(tags: Tag.Index, category: string, disambiguation: string): Tag.NodeWithParent[] {
+    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}` }))
+      );
+  }
+
+  searchTagsFromFilter(tags: Tag.Index, filter: string): Tag.Node[] {
+    return Object.values(tags).filter(node => node.tag.includes(filter));
+  }
+
+  cleanupAndSort(search: Tag.Search[]): Tag.Search[] {
+    const currentTags = this.$uiStore.currentTags;
+    return search
+      .filter(node => !currentTags.find(currentTag => currentTag.tag === node.tag))
+      .sort((a, b) => b.items.length - a.items.length);
   }
 }
 </script>
-- 
cgit v1.2.3

