WIP: major refactoring
This commit is contained in:
parent
55081b24d8
commit
15b957791f
7 changed files with 79 additions and 99 deletions
|
@ -2,33 +2,34 @@ module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
|
|
||||||
env: {
|
env: {
|
||||||
node: true
|
node: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
'extends': [
|
extends: [
|
||||||
'plugin:vue/vue3-essential',
|
"plugin:vue/vue3-essential",
|
||||||
'eslint:recommended',
|
"eslint:recommended",
|
||||||
'@vue/typescript/recommended'
|
"@vue/typescript/recommended",
|
||||||
],
|
],
|
||||||
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: 2020
|
ecmaVersion: 2020,
|
||||||
},
|
},
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
"no-empty": "off",
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
|
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
},
|
},
|
||||||
|
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
'**/__tests__/*.{j,t}s?(x)',
|
"**/__tests__/*.{j,t}s?(x)",
|
||||||
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
"**/tests/unit/**/*.spec.{j,t}s?(x)",
|
||||||
],
|
],
|
||||||
env: {
|
env: {
|
||||||
mocha: true
|
mocha: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<div class="image is-unselectable">
|
<div class="image is-unselectable">
|
||||||
<img :src="store.calendar_background_image" />
|
<img :src="store.background_image" />
|
||||||
<ThouCanvas>
|
<ThouCanvas>
|
||||||
<CalendarDoor
|
<CalendarDoor
|
||||||
v-for="(door, index) in doors"
|
v-for="(door, index) in doors"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<figure class="image is-unselectable">
|
<figure class="image is-unselectable">
|
||||||
<img :src="store.calendar_background_image" />
|
<img :src="store.background_image" />
|
||||||
<ThouCanvas>
|
<ThouCanvas>
|
||||||
<PreviewDoor
|
<PreviewDoor
|
||||||
v-for="(door, index) in doors"
|
v-for="(door, index) in doors"
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<figure class="image is-unselectable">
|
<figure class="image is-unselectable">
|
||||||
<img :src="store.calendar_background_image" />
|
<img :src="store.background_image" />
|
||||||
<DoorCanvas :doors="doors" />
|
<DoorCanvas :doors="doors" />
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { APIError } from "./api_error";
|
||||||
|
|
||||||
export function objForEach<T>(
|
export function objForEach<T>(
|
||||||
obj: T,
|
obj: T,
|
||||||
f: (k: keyof T, v: T[keyof T]) => void,
|
f: (k: keyof T, v: T[keyof T]) => void,
|
||||||
|
@ -8,3 +10,20 @@ export function objForEach<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Loading<T> = T | "loading" | "error";
|
||||||
|
|
||||||
|
export function loading_success<T>(o: Loading<T>): o is T {
|
||||||
|
if (o === "loading") return false;
|
||||||
|
if (o === "error") return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handle_error(error: unknown) {
|
||||||
|
if (error instanceof APIError) {
|
||||||
|
error.alert();
|
||||||
|
} else {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ export interface DoorSaved {
|
||||||
export interface ImageData {
|
export interface ImageData {
|
||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
aspect_ratio: number;
|
|
||||||
data_url: string;
|
data_url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { acceptHMRUpdate, defineStore } from "pinia";
|
import { acceptHMRUpdate, defineStore } from "pinia";
|
||||||
import { API } from "./api";
|
import { API } from "./api";
|
||||||
import { Credentials, DoorSaved, SiteConfigModel } from "./model";
|
import { Loading, loading_success } from "./helpers";
|
||||||
|
import { Credentials, DoorSaved, ImageData, SiteConfigModel } from "./model";
|
||||||
import { Door } from "./rects/door";
|
import { Door } from "./rects/door";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -13,9 +14,8 @@ type State = {
|
||||||
on_initialized: (() => void)[];
|
on_initialized: (() => void)[];
|
||||||
is_touch_device: boolean;
|
is_touch_device: boolean;
|
||||||
is_admin: boolean;
|
is_admin: boolean;
|
||||||
site_config: SiteConfigModel;
|
site_config: Loading<SiteConfigModel>;
|
||||||
calendar_background_image: string | undefined;
|
background_image: Loading<ImageData>;
|
||||||
calendar_aspect_ratio: number;
|
|
||||||
user_doors: Door[];
|
user_doors: Door[];
|
||||||
next_door_target: number | null;
|
next_door_target: number | null;
|
||||||
};
|
};
|
||||||
|
@ -31,14 +31,8 @@ export const advent22Store = defineStore({
|
||||||
navigator.maxTouchPoints > 0 ||
|
navigator.maxTouchPoints > 0 ||
|
||||||
navigator.msMaxTouchPoints > 0,
|
navigator.msMaxTouchPoints > 0,
|
||||||
is_admin: false,
|
is_admin: false,
|
||||||
site_config: {
|
site_config: "loading",
|
||||||
title: document.title,
|
background_image: "loading",
|
||||||
subtitle: "",
|
|
||||||
content: "",
|
|
||||||
footer: "",
|
|
||||||
},
|
|
||||||
calendar_background_image: undefined,
|
|
||||||
calendar_aspect_ratio: 1,
|
|
||||||
user_doors: [],
|
user_doors: [],
|
||||||
next_door_target: null,
|
next_door_target: null,
|
||||||
}),
|
}),
|
||||||
|
@ -48,83 +42,58 @@ export const advent22Store = defineStore({
|
||||||
this.update().then(() => this.on_initialized.forEach((fn) => fn()));
|
this.update().then(() => this.on_initialized.forEach((fn) => fn()));
|
||||||
},
|
},
|
||||||
|
|
||||||
update(): Promise<void> {
|
async update(): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
try {
|
||||||
API.request("user/favicon");
|
const favicon = await API.request<ImageData>("user/favicon");
|
||||||
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)
|
const link: HTMLLinkElement =
|
||||||
document.getElementsByTagName("head")[0].appendChild(link);
|
document.querySelector("link[rel*='icon']") ||
|
||||||
})
|
document.createElement("link");
|
||||||
.catch(() => {});
|
link.rel = "shortcut icon";
|
||||||
|
link.type = "image/x-icon";
|
||||||
|
link.href = favicon.data_url;
|
||||||
|
|
||||||
Promise.all([
|
if (link.parentElement === null)
|
||||||
|
document.getElementsByTagName("head")[0].appendChild(link);
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const [is_admin, site_config, background_image, user_doors, next_door] =
|
||||||
|
await Promise.all([
|
||||||
this.update_is_admin(),
|
this.update_is_admin(),
|
||||||
this.advent22.api_get<SiteConfigModel>("user/site_config"),
|
API.request<SiteConfigModel>("user/site_config"),
|
||||||
this.advent22.api_get_blob("user/background_image"),
|
API.request<ImageData>("user/background_image"),
|
||||||
this.advent22.api_get<DoorSaved[]>("user/doors"),
|
API.request<DoorSaved[]>("user/doors"),
|
||||||
this.advent22.api_get<number | null>("user/next_door"),
|
API.request<number | null>("user/next_door"),
|
||||||
])
|
]);
|
||||||
.then(
|
is_admin; // discard value
|
||||||
([
|
|
||||||
is_admin,
|
|
||||||
site_config,
|
|
||||||
background_image,
|
|
||||||
user_doors,
|
|
||||||
next_door,
|
|
||||||
]) => {
|
|
||||||
is_admin; // discard value
|
|
||||||
|
|
||||||
document.title = site_config.title;
|
document.title = site_config.title;
|
||||||
|
|
||||||
if (site_config.subtitle !== "")
|
if (site_config.subtitle !== "")
|
||||||
document.title += " – " + site_config.subtitle;
|
document.title += " – " + site_config.subtitle;
|
||||||
|
|
||||||
this.site_config = site_config;
|
this.site_config = site_config;
|
||||||
|
this.background_image = background_image;
|
||||||
|
|
||||||
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));
|
||||||
|
}
|
||||||
|
|
||||||
this.user_doors.length = 0;
|
if (next_door !== null) this.next_door_target = Date.now() + next_door;
|
||||||
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);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
when_initialized(callback: () => void): void {
|
when_initialized(callback: () => void): void {
|
||||||
if (this.is_initialized) {
|
if (loading_success(this.site_config)) {
|
||||||
callback();
|
callback();
|
||||||
} else {
|
} else {
|
||||||
this.on_initialized.push(callback);
|
this.on_initialized.push(callback);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
update_is_admin(): Promise<boolean> {
|
async update_is_admin(): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
this.is_admin = await API.request<boolean>("admin/is_admin");
|
||||||
this.advent22
|
return this.is_admin;
|
||||||
.api_get<boolean>("admin/is_admin")
|
|
||||||
.then((is_admin) => {
|
|
||||||
this.is_admin = is_admin;
|
|
||||||
resolve(is_admin);
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
login(creds: Credentials): Promise<boolean> {
|
login(creds: Credentials): Promise<boolean> {
|
||||||
|
@ -139,14 +108,6 @@ export const advent22Store = defineStore({
|
||||||
toggle_touch_device(): void {
|
toggle_touch_device(): void {
|
||||||
this.is_touch_device = !this.is_touch_device;
|
this.is_touch_device = !this.is_touch_device;
|
||||||
},
|
},
|
||||||
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue