aboutsummaryrefslogtreecommitdiff
path: root/viewer/src
diff options
context:
space:
mode:
authorZero~Informatique2019-12-28 04:52:30 +0100
committerZero~Informatique2019-12-28 04:53:01 +0100
commita681accaa7617892bb7c53248aa9030a4eb47f50 (patch)
tree0d04aee1ef36ffaae1b0fac0a61ef7dad8d38e7c /viewer/src
parentdeaed8a6737edc6e28c08e9c6734dde6e37a4016 (diff)
downloadldgallery-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')
-rw-r--r--viewer/src/@types/gallery/index.d.ts3
-rw-r--r--viewer/src/@types/tag/index.d.ts2
-rw-r--r--viewer/src/components/LdProposition.vue75
-rw-r--r--viewer/src/locales/en.json3
-rw-r--r--viewer/src/plugins/fontawesome.ts6
-rw-r--r--viewer/src/store/galleryStore.ts6
-rw-r--r--viewer/src/views/PanelLeft.vue2
7 files changed, 91 insertions, 6 deletions
diff --git a/viewer/src/@types/gallery/index.d.ts b/viewer/src/@types/gallery/index.d.ts
index b47c812..310c865 100644
--- a/viewer/src/@types/gallery/index.d.ts
+++ b/viewer/src/@types/gallery/index.d.ts
@@ -9,7 +9,7 @@ declare namespace Gallery {
9 title: string, 9 title: string,
10 date: string, 10 date: string,
11 description: string, 11 description: string,
12 tags: string[], 12 tags: RawTag[],
13 path: string, 13 path: string,
14 thumbnail: { 14 thumbnail: {
15 path: string, 15 path: string,
@@ -28,4 +28,5 @@ declare namespace Gallery {
28 type: "directory", 28 type: "directory",
29 items: Item[] 29 items: Item[]
30 } 30 }
31 type RawTag = string;
31} \ No newline at end of file 32} \ No newline at end of file
diff --git a/viewer/src/@types/tag/index.d.ts b/viewer/src/@types/tag/index.d.ts
index 6a0c605..181f47a 100644
--- a/viewer/src/@types/tag/index.d.ts
+++ b/viewer/src/@types/tag/index.d.ts
@@ -1,6 +1,6 @@
1declare namespace Tag { 1declare namespace Tag {
2 interface Node { 2 interface Node {
3 tag: string; 3 tag: Gallery.RawTag;
4 items: Gallery.Item[]; 4 items: Gallery.Item[];
5 children: Index; 5 children: Index;
6 } 6 }
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}}&nbsp;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">
14import { Component, Vue } from "vue-property-decorator";
15import { Operation } from "@/@types/tag/Operation";
16import Gallery from '../views/Gallery.vue';
17
18@Component
19export 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>
diff --git a/viewer/src/locales/en.json b/viewer/src/locales/en.json
index d885872..4c9f5d4 100644
--- a/viewer/src/locales/en.json
+++ b/viewer/src/locales/en.json
@@ -5,5 +5,6 @@
5 "panelLeft.mode": "Mode", 5 "panelLeft.mode": "Mode",
6 "mode.navigation": "Navigation", 6 "mode.navigation": "Navigation",
7 "mode.search": "Search", 7 "mode.search": "Search",
8 "search.no-results": "No results" 8 "search.no-results": "No results",
9 "panelLeft.propositions": "Proposed tags"
9} \ No newline at end of file 10} \ No newline at end of file
diff --git a/viewer/src/plugins/fontawesome.ts b/viewer/src/plugins/fontawesome.ts
index ba31c9e..7308afe 100644
--- a/viewer/src/plugins/fontawesome.ts
+++ b/viewer/src/plugins/fontawesome.ts
@@ -6,7 +6,9 @@ import {
6 faExpandArrowsAlt, 6 faExpandArrowsAlt,
7 faFolder, 7 faFolder,
8 faSearch, 8 faSearch,
9 faTag 9 faTag,
10 faPlus,
11 faMinus,
10} from "@fortawesome/free-solid-svg-icons"; 12} from "@fortawesome/free-solid-svg-icons";
11 13
12library.add( 14library.add(
@@ -14,6 +16,8 @@ library.add(
14 faFolder, 16 faFolder,
15 faSearch, 17 faSearch,
16 faTag, 18 faTag,
19 faPlus,
20 faMinus,
17); 21);
18 22
19Vue.component("fa-icon", FontAwesomeIcon); 23Vue.component("fa-icon", FontAwesomeIcon);
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts
index 8a611ea..179fbe2 100644
--- a/viewer/src/store/galleryStore.ts
+++ b/viewer/src/store/galleryStore.ts
@@ -44,6 +44,10 @@ export default class GalleryStore extends VuexModule {
44 // Pushes all tags for a root item (and its children) to the index 44 // Pushes all tags for a root item (and its children) to the index
45 private static pushTagsForItem(index: Tag.Index, item: Gallery.Item) { 45 private static pushTagsForItem(index: Tag.Index, item: Gallery.Item) {
46 console.log("IndexingTagsFor: ", item.path); 46 console.log("IndexingTagsFor: ", item.path);
47 if (item.properties.type === "directory") {
48 item.properties.items.forEach(item => this.pushTagsForItem(index, item));
49 return; // Directories are not indexed
50 }
47 for (const tag of item.tags) { 51 for (const tag of item.tags) {
48 const parts = tag.split('.'); 52 const parts = tag.split('.');
49 let lastPart: string | null = null; 53 let lastPart: string | null = null;
@@ -54,8 +58,6 @@ export default class GalleryStore extends VuexModule {
54 lastPart = part; 58 lastPart = part;
55 } 59 }
56 } 60 }
57 if (item.properties.type === "directory")
58 item.properties.items.forEach(item => this.pushTagsForItem(index, item));
59 } 61 }
60 62
61 // Searches for an item by path from a root item (navigation) 63 // Searches for an item by path from a root item (navigation)
diff --git a/viewer/src/views/PanelLeft.vue b/viewer/src/views/PanelLeft.vue
index c187ce6..df1fe54 100644
--- a/viewer/src/views/PanelLeft.vue
+++ b/viewer/src/views/PanelLeft.vue
@@ -4,6 +4,8 @@
4 <ld-mode-radio /> 4 <ld-mode-radio />
5 <h1>{{$t('panelLeft.filters')}}</h1> 5 <h1>{{$t('panelLeft.filters')}}</h1>
6 <ld-tag-input /> 6 <ld-tag-input />
7 <h1>{{$t('panelLeft.propositions')}}</h1>
8 <ld-proposition />
7 </div> 9 </div>
8</template> 10</template>
9 11