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/@types/tag/index.d.ts | 4 +++ viewer/src/components/LdTagInput.vue | 52 +++++++++++++++++++++++++++++------- viewer/src/plugins/fontawesome.ts | 4 +-- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/viewer/src/@types/tag/index.d.ts b/viewer/src/@types/tag/index.d.ts index 6a027d4..30bbebb 100644 --- a/viewer/src/@types/tag/index.d.ts +++ b/viewer/src/@types/tag/index.d.ts @@ -4,5 +4,9 @@ declare namespace Tag { items: Gallery.Item[]; children: Index; } + interface NodeWithParent extends Node { + parent: Node; + } + type Search = Node | NodeWithParent; type Index = { [index: string]: Node }; } \ No newline at end of file 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" > - + @@ -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); } } diff --git a/viewer/src/plugins/fontawesome.ts b/viewer/src/plugins/fontawesome.ts index 3af77b6..e129c57 100644 --- a/viewer/src/plugins/fontawesome.ts +++ b/viewer/src/plugins/fontawesome.ts @@ -1,9 +1,9 @@ import Vue from "vue"; import { library } from "@fortawesome/fontawesome-svg-core"; -import { faExpandArrowsAlt, faFolder, faSearch } from "@fortawesome/free-solid-svg-icons"; +import { faExpandArrowsAlt, faFolder, faSearch, faTag } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; -library.add(faExpandArrowsAlt, faFolder, faSearch); +library.add(faExpandArrowsAlt, faFolder, faSearch, faTag); Vue.component("fa-icon", FontAwesomeIcon); -- cgit v1.2.3