aboutsummaryrefslogtreecommitdiff
path: root/viewer/src
diff options
context:
space:
mode:
Diffstat (limited to 'viewer/src')
-rw-r--r--viewer/src/@types/gallery.d.ts3
-rw-r--r--viewer/src/@types/tag.d.ts6
-rw-r--r--viewer/src/assets/scss/global.scss4
-rw-r--r--viewer/src/assets/scss/theme.scss4
-rw-r--r--viewer/src/components/LdProposition.vue52
-rw-r--r--viewer/src/components/LdTagInput.vue9
-rw-r--r--viewer/src/locales/en.json5
-rw-r--r--viewer/src/services/indexfactory.ts30
-rw-r--r--viewer/src/store/galleryStore.ts15
-rw-r--r--viewer/src/views/PanelLeft.vue24
10 files changed, 117 insertions, 35 deletions
diff --git a/viewer/src/@types/gallery.d.ts b/viewer/src/@types/gallery.d.ts
index 4fa544f..de1c0dd 100644
--- a/viewer/src/@types/gallery.d.ts
+++ b/viewer/src/@types/gallery.d.ts
@@ -23,7 +23,8 @@ declare namespace Gallery {
23 } 23 }
24 24
25 interface GalleryProperties { 25 interface GalleryProperties {
26 galleryTitle: string 26 galleryTitle: string,
27 tagCategories: RawTag[]
27 } 28 }
28 interface Index { 29 interface Index {
29 properties: GalleryProperties, 30 properties: GalleryProperties,
diff --git a/viewer/src/@types/tag.d.ts b/viewer/src/@types/tag.d.ts
index a390c80..229c418 100644
--- a/viewer/src/@types/tag.d.ts
+++ b/viewer/src/@types/tag.d.ts
@@ -21,6 +21,7 @@ declare namespace Tag {
21 interface Node { 21 interface Node {
22 tag: Gallery.RawTag; 22 tag: Gallery.RawTag;
23 tagfiltered: Gallery.RawTag; 23 tagfiltered: Gallery.RawTag;
24 rootPart: boolean;
24 items: Gallery.Item[]; 25 items: Gallery.Item[];
25 children: Index; 26 children: Index;
26 } 27 }
@@ -31,4 +32,9 @@ declare namespace Tag {
31 } 32 }
32 type SearchByOperation = { [index: string]: Tag.Search[] }; 33 type SearchByOperation = { [index: string]: Tag.Search[] };
33 type Index = { [index: string]: Node }; 34 type Index = { [index: string]: Node };
35
36 interface Category {
37 tag: string;
38 index: Index;
39 }
34} 40}
diff --git a/viewer/src/assets/scss/global.scss b/viewer/src/assets/scss/global.scss
index bd7a7e7..9e61b8b 100644
--- a/viewer/src/assets/scss/global.scss
+++ b/viewer/src/assets/scss/global.scss
@@ -85,8 +85,8 @@ button svg + span {
85 overflow: auto; 85 overflow: auto;
86} 86}
87.scrollbar::-webkit-scrollbar { 87.scrollbar::-webkit-scrollbar {
88 width: 10px; 88 width: $scrollbar-width;
89 height: 10px; 89 height: $scrollbar-width;
90} 90}
91.scrollbar::-webkit-scrollbar-corner { 91.scrollbar::-webkit-scrollbar-corner {
92 background-color: transparent; 92 background-color: transparent;
diff --git a/viewer/src/assets/scss/theme.scss b/viewer/src/assets/scss/theme.scss
index 0028688..9e9cdc8 100644
--- a/viewer/src/assets/scss/theme.scss
+++ b/viewer/src/assets/scss/theme.scss
@@ -42,6 +42,8 @@ $radius: 0;
42$loading-background: $palette-800; 42$loading-background: $palette-800;
43$title-color: $palette-200; 43$title-color: $palette-200;
44$title-size: $size-5; 44$title-size: $size-5;
45$subtitle-color: $palette-200;
46$subtitle-size: $size-5;
45$tag-background-color: $palette-800; 47$tag-background-color: $palette-800;
46$button-color: $palette-100; 48$button-color: $palette-100;
47$button-active-color: $palette-100; 49$button-active-color: $palette-100;
@@ -62,11 +64,13 @@ $panel-left-txtcolor: $primary;
62$command-buttons-bgcolor: $palette-700; 64$command-buttons-bgcolor: $palette-700;
63$content-bgcolor: $palette-900; 65$content-bgcolor: $palette-900;
64$scrollbar-color: $palette-300; 66$scrollbar-color: $palette-300;
67$scrollbar-width: 10px;
65$loader-color: $palette-800; 68$loader-color: $palette-800;
66$input-tag-delete-background-color: $palette-700; 69$input-tag-delete-background-color: $palette-700;
67$breadcrumb-margins: 12px; 70$breadcrumb-margins: 12px;
68$breadcrumb-overflow-mask-size: $breadcrumb-margins + 60px; 71$breadcrumb-overflow-mask-size: $breadcrumb-margins + 60px;
69$thumbnail-other-size: $body-line-height * 9em; 72$thumbnail-other-size: $body-line-height * 9em;
73$proposed-category-bgcolor: $palette-700;
70 74
71// Layout 75// Layout
72 76
diff --git a/viewer/src/components/LdProposition.vue b/viewer/src/components/LdProposition.vue
index 3357777..c69a7c3 100644
--- a/viewer/src/components/LdProposition.vue
+++ b/viewer/src/components/LdProposition.vue
@@ -19,8 +19,9 @@
19--> 19-->
20 20
21<template> 21<template>
22 <div> 22 <div class="proposition">
23 <div v-for="proposed in proposedTags" :key="proposed.rawTag" class="proposition"> 23 <h2 v-if="showCategory && proposedTags.length" class="subtitle category">{{title}}</h2>
24 <div v-for="proposed in proposedTags" :key="proposed.rawTag">
24 <a 25 <a
25 class="operation-btns link" 26 class="operation-btns link"
26 :title="$t('tag-propositions.substraction')" 27 :title="$t('tag-propositions.substraction')"
@@ -54,6 +55,8 @@ import { Operation } from "@/@types/Operation";
54 55
55@Component 56@Component
56export default class LdProposition extends Vue { 57export default class LdProposition extends Vue {
58 @Prop() readonly category?: Tag.Node;
59 @Prop({ type: Boolean, required: true }) readonly showCategory!: boolean;
57 @Prop({ type: Array, required: true }) readonly currentTags!: string[]; 60 @Prop({ type: Array, required: true }) readonly currentTags!: string[];
58 @Prop({ required: true }) readonly tagsIndex!: Tag.Index; 61 @Prop({ required: true }) readonly tagsIndex!: Tag.Index;
59 @PropSync("searchFilters", { type: Array, required: true }) model!: Tag.Search[]; 62 @PropSync("searchFilters", { type: Array, required: true }) model!: Tag.Search[];
@@ -69,13 +72,14 @@ export default class LdProposition extends Vue {
69 this.extractDistinctItems(this.model) 72 this.extractDistinctItems(this.model)
70 .flatMap(item => item.tags) 73 .flatMap(item => item.tags)
71 .map(this.rightmost) 74 .map(this.rightmost)
72 .filter(rawTag => !this.model.find(search => search.tag === rawTag)) 75 .filter(rawTag => this.tagsIndex[rawTag] && !this.model.find(search => search.tag === rawTag))
73 .forEach(rawTag => (propositions[rawTag] = (propositions[rawTag] ?? 0) + 1)); 76 .forEach(rawTag => (propositions[rawTag] = (propositions[rawTag] ?? 0) + 1));
74 } else { 77 } else {
75 // Tags count from the current directory 78 // Tags count from the current directory
76 this.currentTags 79 this.currentTags
77 .flatMap(tag => tag.split(":")) 80 .flatMap(tag => tag.split(":"))
78 .map(tag => this.tagsIndex[tag]) 81 .map(tag => this.tagsIndex[tag])
82 .filter(Boolean)
79 .forEach(tagindex => (propositions[tagindex.tag] = tagindex.items.length)); 83 .forEach(tagindex => (propositions[tagindex.tag] = tagindex.items.length));
80 } 84 }
81 85
@@ -84,6 +88,10 @@ export default class LdProposition extends Vue {
84 .map(entry => ({ rawTag: entry[0], count: entry[1] })); 88 .map(entry => ({ rawTag: entry[0], count: entry[1] }));
85 } 89 }
86 90
91 get title() {
92 return this.category?.tag ?? this.$t("panelLeft.propositions.other");
93 }
94
87 extractDistinctItems(currentTags: Tag.Search[]): Gallery.Item[] { 95 extractDistinctItems(currentTags: Tag.Search[]): Gallery.Item[] {
88 return [...new Set(currentTags.flatMap(tag => tag.items))]; 96 return [...new Set(currentTags.flatMap(tag => tag.items))];
89 } 97 }
@@ -95,8 +103,8 @@ export default class LdProposition extends Vue {
95 103
96 add(operation: Operation, rawTag: Gallery.RawTag) { 104 add(operation: Operation, rawTag: Gallery.RawTag) {
97 const node = this.tagsIndex[rawTag]; 105 const node = this.tagsIndex[rawTag];
98 const search: Tag.Search = { ...node, operation, display: `${operation}${node.tag}` }; 106 const display = this.category ? `${operation}${this.category.tag}:${node.tag}` : `${operation}${node.tag}`;
99 this.model.push(search); 107 this.model.push({ ...node, parent: this.category, operation, display });
100 } 108 }
101} 109}
102</script> 110</script>
@@ -105,19 +113,29 @@ export default class LdProposition extends Vue {
105@import "@/assets/scss/theme.scss"; 113@import "@/assets/scss/theme.scss";
106 114
107.proposition { 115.proposition {
108 display: flex; 116 .subtitle {
109 align-items: center; 117 background-color: $proposed-category-bgcolor;
110 padding-right: 7px; 118 width: 100%;
111 .operation-tag { 119 padding: 0 0 6px 0;
112 text-overflow: ellipsis; 120 margin: 0;
113 white-space: nowrap; 121 text-align: center;
114 overflow: hidden; 122 font-variant: small-caps;
115 flex-grow: 1;
116 cursor: pointer;
117 } 123 }
118 .operation-btns { 124 > div {
119 padding: 2px 7px; 125 display: flex;
120 cursor: pointer; 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 }
121 } 139 }
122} 140}
123</style> 141</style>
diff --git a/viewer/src/components/LdTagInput.vue b/viewer/src/components/LdTagInput.vue
index b1b9e3e..6b6e749 100644
--- a/viewer/src/components/LdTagInput.vue
+++ b/viewer/src/components/LdTagInput.vue
@@ -57,10 +57,17 @@ export default class LdTagInput extends Vue {
57 return `${option.display} (${option.items.length})`; 57 return `${option.display} (${option.items.length})`;
58 } 58 }
59 59
60 filterAlreadyPresent(newSearch: Tag.Search) {
61 return !this.model.find(
62 currentSearch =>
63 currentSearch.tag === newSearch.tag && (!currentSearch.parent || currentSearch.parent === newSearch.parent)
64 );
65 }