2023-11-09 23:08:35 +00:00
|
|
|
|
import { Credentials, DoorSaved, SiteConfigModel } from "@/lib/api";
|
2023-11-09 23:14:19 +00:00
|
|
|
|
import { Door } from "@/lib/door";
|
2023-11-04 15:58:31 +00:00
|
|
|
|
import { Advent22 } from "@/plugins/advent22";
|
2023-11-09 23:08:35 +00:00
|
|
|
|
import { RemovableRef, useLocalStorage } from "@vueuse/core";
|
2024-04-03 18:29:08 +00:00
|
|
|
|
import { AxiosBasicCredentials, AxiosError } from "axios";
|
|
|
|
|
|
import { toast } from "bulma-toast";
|
2023-11-01 23:58:09 +00:00
|
|
|
|
import { acceptHMRUpdate, defineStore } from "pinia";
|
|
|
|
|
|
|
2023-11-05 21:57:50 +00:00
|
|
|
|
declare global {
|
|
|
|
|
|
interface Navigator {
|
|
|
|
|
|
readonly msMaxTouchPoints: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-01 23:58:09 +00:00
|
|
|
|
|
2023-11-09 23:08:35 +00:00
|
|
|
|
type State = {
|
|
|
|
|
|
advent22: Advent22;
|
|
|
|
|
|
api_creds: RemovableRef<Credentials>;
|
2023-11-11 01:47:18 +00:00
|
|
|
|
is_initialized: boolean;
|
|
|
|
|
|
on_initialized: (() => void)[];
|
2023-11-09 23:08:35 +00:00
|
|
|
|
is_touch_device: boolean;
|
|
|
|
|
|
is_admin: boolean;
|
|
|
|
|
|
site_config: SiteConfigModel;
|
2023-11-11 01:44:13 +00:00
|
|
|
|
calendar_background_image: string | undefined;
|
2023-11-09 23:08:35 +00:00
|
|
|
|
calendar_aspect_ratio: number;
|
2023-11-09 23:14:19 +00:00
|
|
|
|
user_doors: Door[];
|
2023-11-09 23:08:35 +00:00
|
|
|
|
next_door_target: number | null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2023-11-01 23:58:09 +00:00
|
|
|
|
export const advent22Store = defineStore({
|
|
|
|
|
|
id: "advent22",
|
|
|
|
|
|
|
2023-11-09 23:08:35 +00:00
|
|
|
|
state: (): State => ({
|
|
|
|
|
|
advent22: new Advent22(),
|
|
|
|
|
|
api_creds: useLocalStorage("advent22/auth", ["", ""]),
|
2023-11-11 01:47:18 +00:00
|
|
|
|
is_initialized: false,
|
|
|
|
|
|
on_initialized: [],
|
2023-11-05 21:57:50 +00:00
|
|
|
|
is_touch_device:
|
|
|
|
|
|
window.matchMedia("(any-hover: none)").matches ||
|
|
|
|
|
|
"ontouchstart" in window ||
|
|
|
|
|
|
navigator.maxTouchPoints > 0 ||
|
|
|
|
|
|
navigator.msMaxTouchPoints > 0,
|
2023-11-03 14:40:44 +00:00
|
|
|
|
is_admin: false,
|
|
|
|
|
|
site_config: {
|
2023-11-04 16:01:58 +00:00
|
|
|
|
title: document.title,
|
|
|
|
|
|
subtitle: "",
|
2023-11-03 14:40:44 +00:00
|
|
|
|
content: "",
|
|
|
|
|
|
footer: "",
|
2023-11-09 23:08:35 +00:00
|
|
|
|
},
|
2023-11-11 01:44:13 +00:00
|
|
|
|
calendar_background_image: undefined,
|
2023-11-05 22:36:58 +00:00
|
|
|
|
calendar_aspect_ratio: 1,
|
2023-11-09 23:08:35 +00:00
|
|
|
|
user_doors: [],
|
|
|
|
|
|
next_door_target: null,
|
2023-11-03 14:40:44 +00:00
|
|
|
|
}),
|
2023-11-01 23:58:09 +00:00
|
|
|
|
|
2023-11-02 00:37:00 +00:00
|
|
|
|
getters: {
|
|
|
|
|
|
axios_creds: (state): AxiosBasicCredentials => {
|
|
|
|
|
|
const [username, password] = state.api_creds;
|
|
|
|
|
|
return { username: username, password: password };
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
2023-11-01 23:58:09 +00:00
|
|
|
|
|
|
|
|
|
|
actions: {
|
2023-11-09 23:08:35 +00:00
|
|
|
|
init(): void {
|
2023-11-24 11:57:33 +00:00
|
|
|
|
this.update()
|
|
|
|
|
|
.then(() => {
|
2023-11-11 01:47:18 +00:00
|
|
|
|
this.is_initialized = true;
|
|
|
|
|
|
for (const callback of this.on_initialized) callback();
|
2023-11-03 14:40:44 +00:00
|
|
|
|
})
|
2024-04-03 18:29:08 +00:00
|
|
|
|
.catch(this.alert_user_error);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
format_user_error([reason, endpoint]: [unknown, string]): string {
|
|
|
|
|
|
let msg =
|
|
|
|
|
|
"Unbekannter Fehler, bitte wiederholen! Besteht das Problem länger, bitte Admin benachrichtigen!";
|
|
|
|
|
|
let code = "U";
|
|
|
|
|
|
const result = () => `${msg} (Fehlercode: ${code}/${endpoint})`;
|
|
|
|
|
|
|
|
|
|
|
|
if (!(reason instanceof AxiosError)) return result();
|
|
|
|
|
|
|
|
|
|
|
|
switch (reason.code) {
|
|
|
|
|
|
case "ECONNABORTED":
|
|
|
|
|
|
// API unerreichbar
|
|
|
|
|
|
msg =
|
|
|
|
|
|
"API antwortet nicht, bitte später wiederholen! Besteht das Problem länger, bitte Admin benachrichtigen!";
|
|
|
|
|
|
code = "D";
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "ERR_NETWORK":
|
|
|
|
|
|
// Netzwerk nicht verbunden
|
|
|
|
|
|
msg = "Sieht aus, als sei deine Netzwerkverbindung gestört.";
|
|
|
|
|
|
code = "N";
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (reason.response === undefined) return result();
|
|
|
|
|
|
|
|
|
|
|
|
switch (reason.response.status) {
|
|
|
|
|
|
case 401:
|
|
|
|
|
|
// UNAUTHORIZED
|
|
|
|
|
|
msg = "Netter Versuch :)";
|
|
|
|
|
|
code = "A";
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 422:
|
|
|
|
|
|
// UNPROCESSABLE ENTITY
|
|
|
|
|
|
msg = "Funktion ist kaputt, bitte Admin benachrichtigen!";
|
|
|
|
|
|
code = "I";
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
// HTTP
|
|
|
|
|
|
code = `H${reason.response.status}`;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result();
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
alert_user_error(param: [unknown, string]): void {
|
|
|
|
|
|
toast({
|
|
|
|
|
|
message: this.format_user_error(param),
|
|
|
|
|
|
type: "is-danger",
|
|
|
|
|
|
});
|
2023-11-03 14:40:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
2023-11-24 11:57:33 +00:00
|
|
|
|
update(): Promise<void> {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
this.advent22
|
|
|
|
|
|
.api_get_blob("user/favicon")
|
|
|
|
|
|
.then((favicon_src) => {
|
|
|
|
|
|
const link: HTMLLinkElement =
|
|
|
|
|
|
document.querySelector("link[rel*='icon']") ||
|
|
|
|
|
|
document.createElement("link");
|
|
|
|
|
|
link.rel = "shortcut icon";
|
|
|
|
|
|
link.type = "image/x-icon";
|
|
|
|
|
|
link.href = favicon_src;
|
|
|
|
|
|
|
|
|
|
|
|
if (link.parentElement === null)
|
|
|
|
|
|
document.getElementsByTagName("head")[0].appendChild(link);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(() => {});
|
|
|
|
|
|
|
|
|
|
|
|
Promise.all([
|
|
|
|
|
|
this.update_is_admin(),
|
|
|
|
|
|
this.advent22.api_get<SiteConfigModel>("user/site_config"),
|
|
|
|
|
|
this.advent22.api_get_blob("user/background_image"),
|
|
|
|
|
|
this.advent22.api_get<DoorSaved[]>("user/doors"),
|
|
|
|
|
|
this.advent22.api_get<number | null>("user/next_door"),
|
|
|
|
|
|
])
|
|
|
|
|
|
.then(
|
|
|
|
|
|
([
|
|
|
|
|
|
is_admin,
|
|
|
|
|
|
site_config,
|
|
|
|
|
|
background_image,
|
|
|
|
|
|
user_doors,
|
|
|
|
|
|
next_door,
|
|
|
|
|
|
]) => {
|
|
|
|
|
|
is_admin; // discard value
|
|
|
|
|
|
|
|
|
|
|
|
document.title = site_config.title;
|
|
|
|
|
|
|
|
|
|
|
|
if (site_config.subtitle !== "")
|
|
|
|
|
|
document.title += " – " + site_config.subtitle;
|
|
|
|
|
|
|
|
|
|
|
|
this.site_config = site_config;
|
|
|
|
|
|
|
|
|
|
|
|
this.calendar_background_image = background_image;
|
|
|
|
|
|
|
|
|
|
|
|
this.user_doors.length = 0;
|
|
|
|
|
|
for (const door_saved of user_doors) {
|
|
|
|
|
|
this.user_doors.push(Door.load(door_saved));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (next_door !== null)
|
|
|
|
|
|
this.next_door_target = Date.now() + next_door;
|
|
|
|
|
|
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
.catch(reject);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2023-11-11 01:47:18 +00:00
|
|
|
|
when_initialized(callback: () => void): void {
|
|
|
|
|
|
if (this.is_initialized) {
|
|
|
|
|
|
callback();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.on_initialized.push(callback);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2023-11-09 18:19:48 +00:00
|
|
|
|
update_is_admin(): Promise<boolean> {
|
2023-11-09 23:08:35 +00:00
|
|
|
|
return new Promise((resolve, reject) => {
|
2023-11-04 15:58:31 +00:00
|
|
|
|
this.advent22
|
|
|
|
|
|
.api_get<boolean>("admin/is_admin")
|
2023-11-02 00:37:00 +00:00
|
|
|
|
.then((is_admin) => {
|
|
|
|
|
|
this.is_admin = is_admin;
|
|
|
|
|
|
resolve(is_admin);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(reject);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2023-11-09 18:19:48 +00:00
|
|
|
|
login(creds: Credentials): Promise<boolean> {
|
|
|
|
|
|
this.api_creds = creds;
|
|
|
|
|
|
return this.update_is_admin();
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2023-11-02 00:37:00 +00:00
|
|
|
|
logout(): Promise<boolean> {
|
2023-11-05 21:57:50 +00:00
|
|
|
|
return this.login(["", ""]);
|
2023-11-01 23:58:09 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
toggle_touch_device(): void {
|
|
|
|
|
|
this.is_touch_device = !this.is_touch_device;
|
|
|
|
|
|
},
|
2023-11-05 22:36:58 +00:00
|
|
|
|
|
|
|
|
|
|
set_calendar_aspect_ratio(rect: DOMRectReadOnly): void {
|
|
|
|
|
|
const result = rect.width / rect.height;
|
|
|
|
|
|
|
|
|
|
|
|
// filter suspicious results
|
|
|
|
|
|
if (result !== 0 && isFinite(result) && !isNaN(result))
|
|
|
|
|
|
this.calendar_aspect_ratio = result;
|
|
|
|
|
|
},
|
2023-11-01 23:58:09 +00:00
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (import.meta.webpackHot) {
|
|
|
|
|
|
import.meta.webpackHot.accept(
|
|
|
|
|
|
acceptHMRUpdate(advent22Store, import.meta.webpackHot),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|