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(-)
(limited to 'viewer/src')
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"
>
- {{props.option.tag}} ({{props.option.items.length}})
+ {{displayOption(props.option)}}
{{$t('tagInput.nomatch')}}
@@ -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