aboutsummaryrefslogtreecommitdiff
path: root/viewer/src/components/LdProposition.vue
diff options
context:
space:
mode:
Diffstat (limited to 'viewer/src/components/LdProposition.vue')
-rw-r--r--viewer/src/components/LdProposition.vue141
1 files changed, 0 insertions, 141 deletions
diff --git a/viewer/src/components/LdProposition.vue b/viewer/src/components/LdProposition.vue
deleted file mode 100644
index fe3af07..0000000
--- a/viewer/src/components/LdProposition.vue
+++ /dev/null
@@ -1,141 +0,0 @@
1<!-- ldgallery - A static generator which turns a collection of tagged
2-- pictures into a searchable web gallery.
3--
4-- Copyright (C) 2019-2020 Guillaume FOUET
5-- 2020 Pacien TRAN-GIRARD
6--
7-- This program is free software: you can redistribute it and/or modify
8-- it under the terms of the GNU Affero General Public License as
9-- published by the Free Software Foundation, either version 3 of the
10-- License, or (at your option) any later version.
11--
12-- This program is distributed in the hope that it will be useful,
13-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15-- GNU Affero General Public License for more details.
16--
17-- You should have received a copy of the GNU Affero General Public License
18-- along with this program. If not, see <https://www.gnu.org/licenses/>.
19-->
20
21<template>
22 <div class="proposition">
23 <h2 v-if="showCategory && proposedTags.length" class="subtitle category">{{title}}</h2>
24 <div v-for="proposed in proposedTags" :key="proposed.rawTag">
25 <a
26 class="operation-btns link"
27 :title="$t('tag-propositions.substraction')"
28 @click="add(Operation.SUBSTRACTION, proposed.rawTag)"
29 >
30 <fa-icon icon="minus" alt="[-]" />
31 </a>
32
33 <a
34 class="operation-btns link"
35 :title="$t('tag-propositions.addition')"
36 @click="add(Operation.ADDITION, proposed.rawTag)"
37 >
38 <fa-icon icon="plus" alt="[+]" />
39 </a>
40
41 <a
42 class="operation-tag link"
43 :title="$t('tag-propositions.intersection')"
44 @click="add(Operation.INTERSECTION, proposed.rawTag)"
45 >{{proposed.rawTag}}</a>
46
47 <div class="disabled" :title="$t('tag-propositions.item-count')">{{proposed.count}}</div>
48 </div>
49 </div>
50</template>
51
52<script lang="ts">
53import { Component, Vue, Prop, PropSync } from "vue-property-decorator";
54import { Operation } from "@/@types/Operation";
55
56@Component
57export default class LdProposition extends Vue {
58 @Prop() readonly category?: Tag.Node;
59 @Prop({ type: Boolean, required: true }) readonly showCategory!: boolean;
60 @Prop({ type: Array, required: true }) readonly currentTags!: string[];
61 @Prop({ required: true }) readonly tagsIndex!: Tag.Index;
62 @PropSync("searchFilters", { type: Array, required: true }) model!: Tag.Search[];
63
64 get Operation() {
65 return Operation;
66 }
67
68 get proposedTags() {
69 let propositions: { [index: string]: number } = {};
70 if (this.model.length > 0) {
71 // Tags count from current search
72 this.extractDistinctItems(this.model)
73 .flatMap(item => item.tags)
74 .map(this.rightmost)
75 .filter(rawTag => this.tagsIndex[rawTag] && !this.model.find(search => search.tag === rawTag))
76 .forEach(rawTag => (propositions[rawTag] = (propositions[rawTag] ?? 0) + 1));
77 } else {
78 // Tags count from the current directory
79 this.currentTags
80 .flatMap(tag => tag.split(":"))
81 .map(tag => this.tagsIndex[tag])
82 .filter(Boolean)
83 .forEach(tagindex => (propositions[tagindex.tag] = tagindex.items.length));
84 }
85
86 return Object.entries(propositions)
87 .sort((a, b) => b[1] - a[1])
88 .map(entry => ({ rawTag: entry[0], count: entry[1] }));
89 }
90
91 get title() {
92 return this.category?.tag ?? this.$t("panelLeft.propositions.other");
93 }
94
95 extractDistinctItems(currentTags: Tag.Search[]): Gallery.Item[] {
96 return [...new Set(currentTags.flatMap(tag => tag.items))];
97 }
98
99 rightmost(tag: Gallery.RawTag): Gallery.RawTag {
100 const dot = tag.lastIndexOf(":");
101 return dot <= 0 ? tag : tag.substr(dot + 1);
102 }
103
104 add(operation: Operation, rawTag: Gallery.RawTag) {
105 const node = this.tagsIndex[rawTag];
106 const display = this.category ? `${operation}${this.category.tag}:${node.tag}` : `${operation}${node.tag}`;
107 this.model.push({ ...node, parent: this.category, operation, display });
108 }
109}
110</script>
111
112<style lang="scss">
113@import "~@/assets/scss/theme.scss";
114
115.proposition {
116 .subtitle {
117 background-color: $proposed-category-bgcolor;
118 width: 100%;
119 padding: 0 0 6px 0;
120 margin: 0;
121 text-align: center;
122 font-variant: small-caps;
123 }
124 > div {
125 display: flex;
126 align-items: center;
127 padding-right: 7px;
128 .operation-tag {
129 text-overflow: ellipsis;
130 white-space: nowrap;
131 overflow: hidden;
132 flex-grow: 1;
133 cursor: pointer;
134 }
135 .operation-btns {
136 padding: 2px 7px;
137 cursor: pointer;
138 }
139 }
140}
141</style>