diff options
Diffstat (limited to 'viewer/src/store/galleryStore.ts')
-rw-r--r-- | viewer/src/store/galleryStore.ts | 183 |
1 files changed, 83 insertions, 100 deletions
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts index 0cffdd9..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,106 +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 | 28 | ||
29 | export default class GalleryStore extends VuexModule { | 29 | function getUrlConfig() { |
30 | 30 | const search = window.location.search; | |
31 | config: Gallery.Config | null = null; | 31 | if (search.length > 1) return search.substring(1) + '.json'; |
32 | galleryIndex: Gallery.Index | null = null; | 32 | return 'config.json'; |
33 | tagsIndex: Tag.Index = {}; | 33 | } |
34 | tagsCategories: Tag.Category[] = []; | ||
35 | currentPath: string = "/"; | ||
36 | currentSearch: Tag.Search[] = []; | ||
37 | |||
38 | // --- | ||
39 | |||
40 | @mutation private setConfig(config: Gallery.Config) { | ||
41 | this.config = config; | ||
42 | } | ||
43 | |||
44 | @mutation setGalleryIndex(galleryIndex: Gallery.Index) { | ||
45 | this.galleryIndex = Object.freeze(galleryIndex); | ||
46 | } | ||
47 | |||
48 | @mutation private setTagsIndex(tagsIndex: Tag.Index) { | ||
49 | this.tagsIndex = Object.freeze(tagsIndex); | ||
50 | } | ||
51 | |||
52 | @mutation private setTagsCategories(tagsCategories: Tag.Category[]) { | ||
53 | this.tagsCategories = tagsCategories; | ||
54 | } | ||
55 | |||
56 | @mutation setCurrentPath(currentPath: string) { | ||
57 | this.currentPath = currentPath; | ||
58 | } | ||
59 | |||
60 | @mutation setCurrentSearch(currentSearch: Tag.Search[]) { | ||
61 | this.currentSearch = currentSearch; | ||
62 | } | ||
63 | |||
64 | // --- | ||
65 | |||
66 | get currentItemPath(): Gallery.Item[] { | ||
67 | const root = this.galleryIndex?.tree; | ||
68 | if (root) | ||
69 | return Navigation.searchCurrentItemPath(root, this.currentPath); | ||
70 | return []; | ||
71 | } | ||
72 | |||
73 | get currentItem(): Gallery.Item | null { | ||
74 | const path = this.currentItemPath; | ||
75 | return path.length > 0 ? path[path.length - 1] : null; | ||
76 | } | ||
77 | |||
78 | get galleryTitle(): string { | ||
79 | return this.galleryIndex?.properties.galleryTitle ?? "ldgallery"; | ||
80 | } | ||
81 | |||
82 | // --- | ||
83 | |||
84 | // Fetches the gallery's JSON config | ||
85 | @action async fetchConfig() { | ||
86 | return fetch(`${process.env.VUE_APP_DATA_URL}config.json`, { cache: "no-cache" }) | ||
87 | .then(response => response.json()) | ||
88 | .then(this.setConfig); | ||
89 | } | ||
90 | |||
91 | // Fetches the gallery's JSON metadata | ||
92 | @action async fetchGalleryItems() { | ||
93 | const root = this.config?.galleryRoot ?? ""; | ||
94 | return fetch(`${process.env.VUE_APP_DATA_URL}${root}index.json`, { cache: "no-cache" }) | ||
95 | .then(response => response.json()) | ||
96 | .then(this.setGalleryIndex) | ||
97 | .then(this.indexTags) | ||
98 | .then(this.indexTagCategories); | ||
99 | } | ||
100 | |||
101 | // Indexes the gallery | ||
102 | @action async indexTags() { | ||
103 | const root = this.galleryIndex?.tree ?? null; | ||
104 | const index = IndexFactory.generateTags(root); | ||
105 | this.setTagsIndex(index); | ||
106 | return index; | ||
107 | } | ||
108 | |||
109 | // Indexes the proposed categories | ||
110 | @action async indexTagCategories() { | ||
111 | const categories = IndexFactory.generateCategories(this.tagsIndex, this.galleryIndex?.properties.tagCategories); | ||
112 | this.setTagsCategories(categories); | ||
113 | return categories; | ||
114 | } | ||
115 | 34 | ||
116 | // Searches for tags | 35 | function responseToJson(response: Response) { |
117 | @action async search(filters: string[]) { | 36 | if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`); |
118 | const results = filters.flatMap(filter => IndexFactory.searchTags(this.tagsIndex, filter, true)); | 37 | return response.json(); |
119 | this.setCurrentSearch(results); | ||
120 | return results; | ||
121 | } | ||
122 | } | 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 | }); | ||