diff options
Diffstat (limited to 'viewer/src/store')
-rw-r--r-- | viewer/src/store/galleryStore.ts | 199 | ||||
-rw-r--r-- | viewer/src/store/index.ts | 47 | ||||
-rw-r--r-- | viewer/src/store/uiStore.ts | 82 |
3 files changed, 127 insertions, 201 deletions
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts index 5d599aa..7ee660a 100644 --- a/viewer/src/store/galleryStore.ts +++ b/viewer/src/store/galleryStore.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* ldgallery - A static generator which turns a collection of tagged | 1 | /* ldgallery - A static generator which turns a collection of tagged |
2 | -- pictures into a searchable web gallery. | 2 | -- pictures into a searchable web gallery. |
3 | -- | 3 | -- |
4 | -- Copyright (C) 2019-2020 Guillaume FOUET | 4 | -- Copyright (C) 2019-2022 Guillaume FOUET |
5 | -- | 5 | -- |
6 | -- This program is free software: you can redistribute it and/or modify | 6 | -- This program is free software: you can redistribute it and/or modify |
7 | -- it under the terms of the GNU Affero General Public License as | 7 | -- it under the terms of the GNU Affero General Public License as |
@@ -17,122 +17,89 @@ | |||
17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. | 17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | import { createModule, mutation, action } from "vuex-class-component"; | 20 | import { Config, Index, Item } from '@/@types/gallery'; |
21 | import IndexFactory from "@/services/indexfactory"; | 21 | import { TagCategory, TagIndex, TagSearch } from '@/@types/tag'; |
22 | import Navigation from "@/services/navigation"; | 22 | import { useIndexFactory } from '@/services/indexFactory'; |
23 | import { useNavigation } from '@/services/navigation'; | ||
24 | import { defineStore } from 'pinia'; | ||
23 | 25 | ||
24 | const VuexModule = createModule({ | 26 | const navigation = useNavigation(); |
25 | namespaced: "galleryStore", | 27 | const indexFactory = useIndexFactory(); |
26 | strict: true, | ||
27 | }); | ||
28 | |||
29 | export default class GalleryStore extends VuexModule { | ||
30 | config: Gallery.Config | null = null; | ||
31 | galleryIndex: Gallery.Index | null = null; | ||
32 | tagsIndex: Tag.Index = {}; | ||
33 | tagsCategories: Tag.Category[] = []; | ||
34 | currentPath: string | null = null; | ||
35 | currentSearch: Tag.Search[] = []; | ||
36 | |||
37 | // --- | ||
38 | |||
39 | @mutation private setConfig(config: Gallery.Config) { | ||
40 | this.config = config; | ||
41 | } | ||
42 | |||
43 | @mutation setGalleryIndex(galleryIndex: Gallery.Index) { | ||
44 | this.galleryIndex = Object.freeze(galleryIndex); | ||
45 | } | ||
46 | |||
47 | @mutation private setTagsIndex(tagsIndex: Tag.Index) { | ||
48 | this.tagsIndex = Object.freeze(tagsIndex); | ||
49 | } | ||
50 | |||
51 | @mutation private setTagsCategories(tagsCategories: Tag.Category[]) { | ||
52 | this.tagsCategories = tagsCategories; | ||
53 | } | ||
54 | |||
55 | @mutation setCurrentPath(currentPath: string) { | ||
56 | this.currentPath = currentPath; | ||
57 | } | ||
58 | |||
59 | @mutation setCurrentSearch(currentSearch: Tag.Search[]) { | ||
60 | this.currentSearch = currentSearch; | ||
61 | } | ||
62 | |||
63 | // --- | ||
64 | |||
65 | get currentItemPath(): Gallery.Item[] { | ||
66 | const root = this.galleryIndex?.tree; | ||
67 | if (root && this.currentPath) return Navigation.searchCurrentItemPath(root, this.currentPath); | ||
68 | return []; | ||
69 | } | ||
70 | |||
71 | get currentItem(): Gallery.Item | null { | ||
72 | const path = this.currentItemPath; | ||
73 | return path.length > 0 ? path[path.length - 1] : null; | ||
74 | } | ||
75 | 28 | ||
76 | get galleryTitle(): string { | 29 | function getUrlConfig() { |
77 | return this.galleryIndex?.properties.galleryTitle ?? "ldgallery"; | 30 | const search = window.location.search; |
78 | } | 31 | if (search.length > 1) return search.substring(1) + '.json'; |
79 | 32 | return 'config.json'; | |
80 | get resourceRoot(): string { | 33 | } |
81 | return process.env.VUE_APP_DATA_URL + this.config!.galleryRoot; | ||
82 | } | ||
83 | |||
84 | // --- | ||
85 | |||
86 | // Fetches the gallery's JSON config | ||
87 | @action async fetchConfig() { | ||
88 | await fetch(`${process.env.VUE_APP_DATA_URL}${GalleryStore.getUrlConfig()}`, { cache: "no-cache" }) | ||
89 | .then(GalleryStore.responseToJson) | ||
90 | .then(this.setConfig); | ||
91 | return this.config!; | ||
92 | } | ||
93 | |||
94 | // Fetches the gallery's JSON metadata | ||
95 | @action async fetchGalleryItems() { | ||
96 | const root = this.config?.galleryRoot ?? ""; | ||
97 | const index = this.config?.galleryIndex ?? "index.json"; | ||
98 | await fetch(`${process.env.VUE_APP_DATA_URL}${root}${index}`, { cache: "no-cache" }) | ||
99 | .then(GalleryStore.responseToJson) | ||
100 | .then(this.setGalleryIndex) | ||
101 | .then(this.indexTags) | ||
102 | .then(this.indexTagCategories); | ||
103 | return this.galleryIndex!; | ||
104 | } | ||
105 | |||
106 | // Indexes the gallery | ||
107 | @action async indexTags() { | ||
108 | const root = this.galleryIndex?.tree ?? null; | ||
109 | const index = IndexFactory.generateTags(root); | ||
110 | this.setTagsIndex(index); | ||
111 | return index; | ||
112 | } | ||
113 | |||
114 | // Indexes the proposed categories | ||
115 | @action async indexTagCategories() { | ||
116 | const categories = IndexFactory.generateCategories(this.tagsIndex, this.galleryIndex?.properties.tagCategories); | ||
117 | this.setTagsCategories(categories); | ||
118 | return categories; | ||
119 | } | ||
120 | |||
121 | // Searches for tags | ||
122 | @action async search(filters: string[]) { | ||
123 | const results = filters.flatMap(filter => IndexFactory.searchTags(this.tagsIndex, filter, true)); | ||
124 | this.setCurrentSearch(results); | ||
125 | return results; | ||
126 | } | ||
127 | |||
128 | private static getUrlConfig() { | ||
129 | let search = window.location.search; | ||
130 | if (search.length > 1) return search.substr(1) + ".json"; | ||
131 | return "config.json"; | ||
132 | } | ||
133 | 34 | ||
134 | private static responseToJson(response: Response) { | 35 | function responseToJson(response: Response) { |
135 | if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`); | 36 | if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`); |
136 | return response.json(); | 37 | return response.json(); |
137 | } | ||
138 | } | 38 | } |
39 | |||
40 | export const useGalleryStore = defineStore('gallery', { | ||
41 | state: () => ({ | ||
42 | config: null as Config | null, | ||
43 | galleryIndex: null as Index | null, | ||
44 | tagsIndex: {} as TagIndex, | ||
45 | tagsCategories: [] as TagCategory[], | ||
46 | currentPath: null as string | null, | ||
47 | currentSearch: [] as TagSearch[], | ||
48 | }), | ||
49 | getters: { | ||
50 | currentItemPath(): Item[] { | ||
51 | const root = this.galleryIndex?.tree; | ||
52 | if (root && this.currentPath) return navigation.searchCurrentItemPath(root, this.currentPath); | ||
53 | return []; | ||
54 | }, | ||
55 | currentItem(): Item | null { | ||
56 | const path = this.currentItemPath; | ||
57 | return path.length > 0 ? path[path.length - 1] : null; | ||
58 | }, | ||
59 | galleryTitle(): string { | ||
60 | return this.galleryIndex?.properties.galleryTitle ?? 'ldgallery'; | ||
61 | }, | ||
62 | resourceRoot(): string { | ||
63 | return process.env.VUE_APP_DATA_URL + (this.config?.galleryRoot ?? ''); | ||
64 | }, | ||
65 | }, | ||
66 | actions: { | ||
67 | // Fetches the gallery's JSON config | ||
68 | async fetchConfig() { | ||
69 | await fetch(`${process.env.VUE_APP_DATA_URL}${getUrlConfig()}`, { cache: 'no-cache' }) | ||
70 | .then(responseToJson) | ||
71 | .then(v => (this.config = v)); | ||
72 | return this.config as Config; | ||
73 | }, | ||
74 | // Fetches the gallery's JSON metadata | ||
75 | async fetchGalleryItems() { | ||
76 | const root = this.config?.galleryRoot ?? ''; | ||
77 | const index = this.config?.galleryIndex ?? 'index.json'; | ||
78 | await fetch(`${process.env.VUE_APP_DATA_URL}${root}${index}`, { cache: 'no-cache' }) | ||
79 | .then(responseToJson) | ||
80 | .then(v => (this.galleryIndex = v)) | ||
81 | .then(this.indexTags) | ||
82 | .then(this.indexTagCategories); | ||
83 | return this.galleryIndex; | ||
84 | }, | ||
85 | // Indexes the gallery | ||
86 | async indexTags() { | ||
87 | const root = this.galleryIndex?.tree ?? null; | ||
88 | const index = indexFactory.generateTags(root); | ||
89 | this.tagsIndex = index; | ||
90 | return index; | ||
91 | }, | ||
92 | // Indexes the proposed categories | ||
93 | async indexTagCategories() { | ||
94 | const categories = indexFactory.generateCategories(this.tagsIndex, this.galleryIndex?.properties.tagCategories); | ||
95 | this.tagsCategories = categories; | ||
96 | return categories; | ||
97 | }, | ||
98 | // Searches for tags | ||
99 | async search(filters: string[]) { | ||
100 | const results = filters.flatMap(filter => indexFactory.searchTags(this.tagsIndex, filter, true)); | ||
101 | this.currentSearch = results; | ||
102 | return results; | ||
103 | }, | ||
104 | }, | ||
105 | }); | ||
diff --git a/viewer/src/store/index.ts b/viewer/src/store/index.ts deleted file mode 100644 index f86d66b..0000000 --- a/viewer/src/store/index.ts +++ /dev/null | |||
@@ -1,47 +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 | -- | ||
6 | -- This program is free software: you can redistribute it and/or modify | ||
7 | -- it under the terms of the GNU Affero General Public License as | ||
8 | -- published by the Free Software Foundation, either version 3 of the | ||
9 | -- License, or (at your option) any later version. | ||
10 | -- | ||
11 | -- This program is distributed in the hope that it will be useful, | ||
12 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | -- GNU Affero General Public License for more details. |