From a681accaa7617892bb7c53248aa9030a4eb47f50 Mon Sep 17 00:00:00 2001
From: Zero~Informatique
Date: Sat, 28 Dec 2019 04:52:30 +0100
Subject: 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.

---
 viewer/src/components/LdProposition.vue | 75 +++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 viewer/src/components/LdProposition.vue

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

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 @@
+<template>
+  <div>
+    <div v-for="proposed in proposedTags" :key="proposed.rawTag" class="proposition">
+      <fa-icon icon="minus" @click="add(Operation.SUBSTRACTION, proposed.rawTag)" />
+      <span
+        @click="add(Operation.INTERSECTION, proposed.rawTag)"
+      >{{proposed.rawTag}}&nbsp;x{{proposed.count}}</span>
+      <fa-icon icon="plus" @click="add(Operation.ADDITION, proposed.rawTag)" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { Component, Vue } from "vue-property-decorator";
+import { Operation } from "@/@types/tag/Operation";
+import Gallery from '../views/Gallery.vue';
+
+@Component
+export default class LdTagInput extends Vue {
+  get Operation() {
+    return Operation;
+  }
+
+  get proposedTags() {
+    const currentTags = this.$uiStore.currentTags;
+    let propositions: { [index: string]: number } = {};
+    if (currentTags.length > 0) {
+      // Tags count from current search
+      this.extractDistinctItems(currentTags)
+        .flatMap(item => item.tags)
+        .map(this.rightmost)
+        .filter(rawTag => !currentTags.find(currentTag => currentTag.tag === rawTag))
+        .forEach(rawTag => (propositions[rawTag] = (propositions[rawTag] ?? 0) + 1));
+    } else {
+      // Tags count from the whole gallery
+      Object.entries(this.$galleryStore.tags)
+        .forEach(entry => (propositions[entry[0]] = entry[1].items.length));
+    }
+    
+    return Object.entries(propositions)
+      .sort((a,b) => b[1] - a[1])
+      .map(entry => ({rawTag: entry[0], count: entry[1]}));
+  }
+
+  extractDistinctItems(currentTags: Tag.Search[]): Gallery.Item[] {
+    return [...new Set(currentTags.flatMap(tag => tag.items))];
+  }
+
+  rightmost(tag: Gallery.RawTag): Gallery.RawTag {
+    const dot = tag.lastIndexOf(".");
+    return dot <= 0 ? tag : tag.substr(dot + 1);
+  }
+
+  add(operation: Operation, rawTag: Gallery.RawTag) {
+    const node = this.$galleryStore.tags[rawTag];
+    const search: Tag.Search = { ...node, operation, display: `${operation}${node.tag}` };
+    this.$uiStore.currentTags.push(search);
+    this.$uiStore.mode = "search";
+  }
+}
+</script>
+
+<style lang="scss">
+.proposition {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin: 10px;
+  color: lightcyan;
+  cursor: pointer;
+}
+.proposition span {
+  padding: 0 10px;
+}
+</style>
-- 
cgit v1.2.3

