diff options
author | Zéro~Informatique | 2022-07-26 08:44:34 +0200 |
---|---|---|
committer | pacien | 2022-09-03 01:30:42 +0200 |
commit | 00510820a2794efcadbc83f7f8b54318fe198ecb (patch) | |
tree | a894d99c22a601197869c7a6928d40bb4ae2c392 /viewer/src/store | |
parent | 88aa098c07e067f9f737fbeba1f52a9bd5042e53 (diff) | |
download | ldgallery-00510820a2794efcadbc83f7f8b54318fe198ecb.tar.gz |
viewer: migrate to vue 3, general refactoring and cleanup
Non-exhaustive list of fixes and improvements done at the same time:
- html default background to grey (avoids white flash during init)
- unified links behavior
- added more theme variables
- removed the flex-expand transition (it wasn't working) and replaced it
with a slide
- fixed LdLoading not centered on the content
- title on removable tags
- fixed an issue with encoded URI from vue-router
- unified Item resource URLs
- removed the iframe for PlainTextViewer (it wasn't working properly)
and replaced it with a pre
- fixed clear and search buttons tabindex
- fixed the information panel bumping up during the fade animation of
tag's dropdown
- fixed some focus outlines not appearing correctly
- moved CSS variables to the :root context
- Code cleaning
GitHub: closes #217
GitHub: closes #300
GitHub: closes #297
GitHub: closes #105
GitHub: closes #267
GitHub: closes #275
GitHub: closes #228
GitHub: closes #215
GitHub: closes #112
Diffstat (limited to 'viewer/src/store')
-rw-r--r-- | viewer/src/store/galleryStore.ts | 201 | ||||
-rw-r--r-- | viewer/src/store/index.ts | 46 | ||||
-rw-r--r-- | viewer/src/store/uiStore.ts | 116 |
3 files changed, 129 insertions, 234 deletions
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts index e2adf18..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,124 +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 { Config, Index, Item } from "@/@types/gallery"; | 20 | import { Config, Index, Item } from '@/@types/gallery'; |
21 | import { TagCategory, TagIndex, TagSearch } from "@/@types/tag"; | 21 | import { TagCategory, TagIndex, TagSearch } from '@/@types/tag'; |
22 | import IndexFactory from "@/services/indexfactory"; | 22 | import { useIndexFactory } from '@/services/indexFactory'; |
23 | import Navigation from "@/services/navigation"; | 23 | import { useNavigation } from '@/services/navigation'; |
24 | import { action, createModule, mutation } from "vuex-class-component"; | 24 | import { defineStore } from 'pinia'; |
25 | 25 | ||
26 | const VuexModule = createModule({ | 26 | const navigation = useNavigation(); |
27 | namespaced: "galleryStore", | 27 | const indexFactory = useIndexFactory(); |
28 | strict: true, | ||
29 | }); | ||
30 | |||
31 | export default class GalleryStore extends VuexModule { | ||
32 | config: Config | null = null; | ||
33 | galleryIndex: Index | null = null; | ||
34 | tagsIndex: TagIndex = {}; | ||
35 | tagsCategories: TagCategory[] = []; | ||
36 | currentPath: string | null = null; | ||
37 | currentSearch: TagSearch[] = []; | ||
38 | |||
39 | // --- | ||
40 | |||
41 | @mutation private setConfig(config: Config) { | ||
42 | this.config = config; | ||
43 | } | ||
44 | |||
45 | @mutation setGalleryIndex(galleryIndex: Index) { | ||
46 | this.galleryIndex = Object.freeze(galleryIndex); | ||
47 | } | ||
48 | |||
49 | @mutation private setTagsIndex(tagsIndex: TagIndex) { | ||
50 | this.tagsIndex = Object.freeze(tagsIndex); | ||
51 | } | ||
52 | |||
53 | @mutation private setTagsCategories(tagsCategories: TagCategory[]) { | ||
54 | this.tagsCategories = tagsCategories; | ||
55 | } | ||
56 | |||
57 | @mutation setCurrentPath(currentPath: string) { | ||
58 | this.currentPath = currentPath; | ||
59 | } | ||
60 | |||
61 | @mutation setCurrentSearch(currentSearch: TagSearch[]) { | ||
62 | this.currentSearch = currentSearch; | ||
63 | } | ||
64 | |||
65 | // --- | ||
66 | |||
67 | get currentItemPath(): Item[] { | ||
68 | const root = this.galleryIndex?.tree; | ||
69 | if (root && this.currentPath) return Navigation.searchCurrentItemPath(root, this.currentPath); | ||
70 | return []; | ||
71 | } | ||
72 | |||
73 | get currentItem(): Item | null { | ||
74 | const path = this.currentItemPath; | ||
75 | return path.length > 0 ? path[path.length - 1] : null; | ||
76 | } | ||
77 | 28 | ||
78 | get galleryTitle(): string { | 29 | function getUrlConfig() { |
79 | return this.galleryIndex?.properties.galleryTitle ?? "ldgallery"; | 30 | const search = window.location.search; |
80 | } | 31 | if (search.length > 1) return search.substring(1) + '.json'; |
81 | 32 | return 'config.json'; | |
82 | get resourceRoot(): string { | 33 | } |
83 | return process.env.VUE_APP_DATA_URL + this.config!.galleryRoot; | ||
84 | } | ||
85 | |||
86 | // --- | ||
87 | |||
88 | // Fetches the gallery's JSON config | ||
89 | @action async fetchConfig() { | ||
90 | await fetch(`${process.env.VUE_APP_DATA_URL}${GalleryStore.getUrlConfig()}`, { cache: "no-cache" }) | ||
91 | .then(GalleryStore.responseToJson) | ||
92 | .then(this.setConfig); | ||
93 | return this.config!; | ||
94 | } | ||
95 | |||
96 | // Fetches the gallery's JSON metadata | ||
97 | @action async fetchGalleryItems() { | ||
98 | const root = this.config?.galleryRoot ?? ""; | ||
99 | const index = this.config?.galleryIndex ?? "index.json"; | ||
100 | await fetch(`${process.env.VUE_APP_DATA_URL}${root}${index}`, { cache: "no-cache" }) | ||
101 | .then(GalleryStore.responseToJson) | ||
102 | .then(this.setGalleryIndex) | ||
103 | .then(this.indexTags) | ||
104 | .then(this.indexTagCategories); | ||
105 | return this.galleryIndex!; | ||
106 | } | ||
107 | |||
108 | // Indexes the gallery | ||
109 | @action async indexTags() { | ||
110 | const root = this.galleryIndex?.tree ?? null; | ||
111 | const index = IndexFactory.generateTags(root); | ||
112 | this.setTagsIndex(index); | ||
113 | return index; | ||
114 | } | ||
115 | |||
116 | // Indexes the proposed categories | ||
117 | @action async indexTagCategories() { | ||
118 | const categories = IndexFactory.generateCategories(this.tagsIndex, this.galleryIndex?.properties.tagCategories); | ||
119 | this.setTagsCategories(categories); | ||
120 | return categories; | ||
121 | } | ||
122 | |||
123 | // Searches for tags | ||
124 | @action async search(filters: string[]) { | ||
125 | const results = filters.flatMap(filter => IndexFactory.searchTags(this.tagsIndex, filter, true)); | ||
126 | this.setCurrentSearch(results); | ||
127 | return results; | ||
128 | } | ||
129 | |||
130 | private static getUrlConfig() { | ||
131 | const search = window.location.search; | ||
132 | if (search.length > 1) return search.substr(1) + ".json"; | ||
133 | return "config.json"; | ||
134 | } | ||
135 | 34 | ||
136 | private static responseToJson(response: Response) { | 35 | function responseToJson(response: Response) { |
137 | if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`); | 36 | if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`); |
138 | return response.json(); | 37 | return response.json(); |
139 | } | ||
140 | } | 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 1f49589..0000000 --- a/viewer/src/store/index.ts +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* ldgallery - A static generator which turns a collection of tagged |