aboutsummaryrefslogtreecommitdiff
path: root/viewer/src/store
diff options
context:
space:
mode:
Diffstat (limited to 'viewer/src/store')
-rw-r--r--viewer/src/store/galleryStore.ts110
-rw-r--r--viewer/src/store/index.ts46
-rw-r--r--viewer/src/store/uiStore.ts56
3 files changed, 212 insertions, 0 deletions
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts
new file mode 100644
index 0000000..c4a039f
--- /dev/null
+++ b/viewer/src/store/galleryStore.ts
@@ -0,0 +1,110 @@
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.
15--
16-- You should have received a copy of the GNU Affero General Public License
17-- along with this program. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20import { createModule, mutation, action } from "vuex-class-component";
21
22const VuexModule = createModule({
23 namespaced: "galleryStore",
24 strict: true
25})
26
27export default class GalleryStore extends VuexModule {
28
29 galleryItemsRoot: Gallery.Item | null = null;
30 tags: Tag.Index = {};
31 currentPath: string = "/";
32
33 // ---
34
35 @mutation setGalleryItemsRoot(galleryItemsRoot: Gallery.Item) {
36 this.galleryItemsRoot = galleryItemsRoot;
37 }
38
39 @mutation private setTags(tags: Tag.Index) {
40 this.tags = tags;
41 }
42
43 @mutation setCurrentPath(currentPath: string) {
44 this.currentPath = currentPath;
45 }
46
47 get currentItemPath(): Gallery.Item[] {
48 const galleryItemsRoot = this.galleryItemsRoot;
49 if (galleryItemsRoot)
50 return GalleryStore.searchCurrentItemPath(galleryItemsRoot, this.currentPath);
51 return [];
52 }
53
54 get currentItem(): Gallery.Item | null {
55 const currentItemPath = this.currentItemPath;
56 return currentItemPath.length > 0 ? currentItemPath[currentItemPath.length - 1] : null;
57 }
58
59 // ---
60
61 // Fetches the gallery's JSON metadata
62 @action async fetchGalleryItems(url: string) {
63 fetch(url)
64 .then(response => response.json())
65 .then(this.setGalleryItemsRoot)
66 .then(this.indexTags);
67 }
68
69 // Indexes the gallery
70 @action async indexTags() {
71 let index = {};
72 if (this.galleryItemsRoot)
73 GalleryStore.pushTagsForItem(index, this.galleryItemsRoot);
74 console.log("Index: ", index);
75 this.setTags(index);
76 }
77
78 // ---
79
80 // Pushes all tags for a root item (and its children) to the index
81 private static pushTagsForItem(index: Tag.Index, item: Gallery.Item) {
82 console.log("IndexingTagsFor: ", item.path);
83 if (item.properties.type === "directory") {
84 item.properties.items.forEach(item => this.pushTagsForItem(index, item));
85 return; // Directories are not indexed
86 }
87 for (const tag of item.tags) {
88 const parts = tag.split('.');
89 let lastPart: string | null = null;
90 for (const part of parts) {
91 if (!index[part]) index[part] = { tag: part, items: [], children: {} };
92 if (!index[part].items.includes(item)) index[part].items.push(item);
93 if (lastPart) index[lastPart].children[part] = index[part];
94 lastPart = part;
95 }
96 }
97 }
98
99 // Searches for an item by path from a root item (navigation)
100 private static searchCurrentItemPath(item: Gallery.Item, path: string): Gallery.Item[] {
101 if (path === item.path) return [item];
102 if (item.properties.type === "directory" && path.startsWith(item.path)) {
103 const itemChain = item.properties.items
104 .map(item => this.searchCurrentItemPath(item, path))
105 .find(itemChain => itemChain.length > 0);
106 if (itemChain) return [item, ...itemChain];
107 }
108 return [];
109 }
110} \ No newline at end of file
diff --git a/viewer/src/store/index.ts b/viewer/src/store/index.ts
new file mode 100644
index 0000000..0277fa4
--- /dev/null
+++ b/viewer/src/store/index.ts
@@ -0,0 +1,46 @@
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.
15--
16-- You should have received a copy of the GNU Affero General Public License
17-- along with this program. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20import Vue from 'vue'
21import Vuex from 'vuex'
22import { extractVuexModule } from "vuex-class-component";
23import { createProxy } from "vuex-class-component";
24import UIStore from '@/store/uiStore';
25import GalleryStore from '@/store/galleryStore';
26
27Vue.use(Vuex)
28
29const store = new Vuex.Store({
30 modules: {
31 ...extractVuexModule(UIStore),
32 ...extractVuexModule(GalleryStore)
33 }
34});
35
36Vue.use((vue) => vue.prototype.$uiStore = createProxy(store, UIStore));
37Vue.use((vue) => vue.prototype.$galleryStore = createProxy(store, GalleryStore));
38
39declare module 'vue/types/vue' {
40 interface Vue {
41 $uiStore: UIStore,
42 $galleryStore: GalleryStore
43 }
44}
45
46export default store;
diff --git a/viewer/src/store/uiStore.ts b/viewer/src/store/uiStore.ts
new file mode 100644
index 0000000..6bcc538
--- /dev/null
+++ b/viewer/src/store/uiStore.ts
@@ -0,0 +1,56 @@
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.
15--
16-- You should have received a copy of the GNU Affero General Public License
17-- along with this program. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20import { createModule, mutation, action } from "vuex-class-component";
21
22const VuexModule = createModule({
23 namespaced: "uiStore",
24 strict: false
25})
26
27export default class UIStore extends VuexModule {
28
29 fullscreen: boolean = false;
30 mode: "navigation" | "search" = "navigation";
31 currentTags: Tag.Search[] = [];
32
33 // ---
34
35 get isModeSearch() {
36 return this.mode === "search";
37 }
38
39 get isModeNavigation() {
40 return this.mode === "navigation";
41 }
42
43 // ---
44
45 @mutation toggleFullscreen() {
46 this.fullscreen = !this.fullscreen;
47 }
48
49 @mutation setModeNavigation() {
50 this.mode = "navigation";
51 }
52
53 @mutation setModeSearch() {
54 this.mode = "search";
55 }
56}