diff options
author | Zero~Informatique | 2019-12-28 04:52:30 +0100 |
---|---|---|
committer | Zero~Informatique | 2019-12-28 04:53:01 +0100 |
commit | a681accaa7617892bb7c53248aa9030a4eb47f50 (patch) | |
tree | 0d04aee1ef36ffaae1b0fac0a61ef7dad8d38e7c /viewer/src/components | |
parent | deaed8a6737edc6e28c08e9c6734dde6e37a4016 (diff) | |
download | ldgallery-a681accaa7617892bb7c53248aa9030a4eb47f50.tar.gz |
viewer: Tag propositions. Disabled directory indexation.
Note: The propositions are not based on the current search results, but on the searched tags, which doesn't seem to be the correct way. We'll probably have to move the search results to a store for global visibility.
Diffstat (limited to 'viewer/src/components')
-rw-r--r-- | viewer/src/components/LdProposition.vue | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/viewer/src/components/LdProposition.vue b/viewer/src/components/LdProposition.vue new file mode 100644 index 0000000..b23c14a --- /dev/null +++ b/viewer/src/components/LdProposition.vue | |||
@@ -0,0 +1,75 @@ | |||
1 | <template> | ||
2 | <div> | ||
3 | <div v-for="proposed in proposedTags" :key="proposed.rawTag" class="proposition"> | ||
4 | <fa-icon icon="minus" @click="add(Operation.SUBSTRACTION, proposed.rawTag)" /> | ||
5 | <span | ||
6 | @click="add(Operation.INTERSECTION, proposed.rawTag)" | ||
7 | >{{proposed.rawTag}} x{{proposed.count}}</span> | ||
8 | <fa-icon icon="plus" @click="add(Operation.ADDITION, proposed.rawTag)" /> | ||
9 | </div> | ||
10 | </div> | ||
11 | </template> | ||
12 | |||
13 | <script lang="ts"> | ||
14 | import { Component, Vue } from "vue-property-decorator"; | ||
15 | import { Operation } from "@/@types/tag/Operation"; | ||
16 | import Gallery from '../views/Gallery.vue'; | ||
17 | |||
18 | @Component | ||
19 | export default class LdTagInput extends Vue { | ||
20 | get Operation() { | ||
21 | return Operation; | ||
22 | } | ||
23 | |||
24 | get proposedTags() { | ||
25 | const currentTags = this.$uiStore.currentTags; | ||
26 | let propositions: { [index: string]: number } = {}; | ||
27 | if (currentTags.length > 0) { | ||
28 | // Tags count from current search | ||
29 | this.extractDistinctItems(currentTags) | ||
30 | .flatMap(item => item.tags) | ||
31 | .map(this.rightmost) | ||
32 | .filter(rawTag => !currentTags.find(currentTag => currentTag.tag === rawTag)) | ||
33 | .forEach(rawTag => (propositions[rawTag] = (propositions[rawTag] ?? 0) + 1)); | ||
34 | } else { | ||
35 | // Tags count from the whole gallery | ||
36 | Object.entries(this.$galleryStore.tags) | ||
37 | .forEach(entry => (propositions[entry[0]] = entry[1].items.length)); | ||
38 | } | ||
39 | |||
40 | return Object.entries(propositions) | ||
41 | .sort((a,b) => b[1] - a[1]) | ||
42 | .map(entry => ({rawTag: entry[0], count: entry[1]})); | ||
43 | } | ||
44 | |||
45 | extractDistinctItems(currentTags: Tag.Search[]): Gallery.Item[] { | ||
46 | return [...new Set(currentTags.flatMap(tag => tag.items))]; | ||
47 | } | ||
48 | |||
49 | rightmost(tag: Gallery.RawTag): Gallery.RawTag { | ||
50 | const dot = tag.lastIndexOf("."); | ||
51 | return dot <= 0 ? tag : tag.substr(dot + 1); | ||
52 | } | ||
53 | |||
54 | add(operation: Operation, rawTag: Gallery.RawTag) { | ||
55 | const node = this.$galleryStore.tags[rawTag]; | ||
56 | const search: Tag.Search = { ...node, operation, display: `${operation}${node.tag}` }; | ||
57 | this.$uiStore.currentTags.push(search); | ||
58 | this.$uiStore.mode = "search"; | ||
59 | } | ||
60 | } | ||
61 | </script> | ||
62 | |||
63 | <style lang="scss"> | ||
64 | .proposition { | ||
65 | display: flex; | ||
66 | justify-content: space-between; | ||
67 | align-items: center; | ||
68 | margin: 10px; | ||
69 | color: lightcyan; | ||
70 | cursor: pointer; | ||
71 | } | ||
72 | .proposition span { | ||
73 | padding: 0 10px; | ||
74 | } | ||
75 | </style> | ||