🚧 ui: re-scaffolding

- fix lint errors
This commit is contained in:
Jörn-Michael Miehe 2026-02-21 23:48:18 +00:00
parent d816460efa
commit b1c65f4d4a
12 changed files with 49 additions and 63 deletions

View file

@ -1,21 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"experimentalDecorators": true,
"lib": ["es2020", "dom", "dom.iterable", "es2022.object", "es2023.array"],
// "moduleResolution": "node",
// "sourceMap": true,
"baseUrl": ".",
"types": ["webpack-env", "mocha", "chai"],
"paths": {
"@/*": ["src/*"]
}
},
"include": [
"src/**/*.vue",
"src/**/*.ts",
// "src/**/*.tsx",
"tests/**/*.ts"
// "tests/**/*.tsx",
]
}

View file

@ -1,11 +0,0 @@
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import App from "../App.vue";
describe("App", () => {
it("mounts renders properly", () => {
const wrapper = mount(App);
expect(wrapper.text()).toContain("You did it!");
});
});

View file

@ -8,7 +8,7 @@
<h3>Zuordnung Buchstaben</h3>
<div class="tags are-medium">
<template v-for="(data, day) in day_data" :key="`part-${day}`">
<template v-for="[day, data] in day_data" :key="`part-${day}`">
<span v-if="data.part === ''" class="tag is-warning">
{{ day }}
</span>
@ -21,7 +21,7 @@
<h3>Zuordnung Bilder</h3>
<div class="tags are-medium">
<span
v-for="(data, day) in day_data"
v-for="[day, data] in day_data"
:key="`image-${day}`"
:class="'tag is-' + (data.part === '' ? 'warning' : 'primary')"
>
@ -32,7 +32,7 @@
<h3>Alle Türchen</h3>
<div class="tags are-medium">
<BulmaButton
v-for="(data, day) in day_data"
v-for="[day, data] in day_data"
:key="`btn-${day}`"
:class="'tag is-' + (data.part === '' ? 'warning' : 'info')"
:icon="['fas', 'fa-door-open']"
@ -48,14 +48,19 @@
<script setup lang="ts">
import { API } from "@/lib/api";
import { name_door, objForEach } from "@/lib/helpers";
import type { ImageData, NumStrDict } from "@/lib/model";
import type { ImageData } from "@/lib/model";
import { ref } from "vue";
import MultiModal, { type HMultiModal } from "../MultiModal.vue";
import BulmaButton from "../bulma/Button.vue";
import BulmaDrawer from "../bulma/Drawer.vue";
const day_data = ref<Record<number, { part: string; image_name: string }>>({});
interface DayData {
part: string;
image_name: string;
}
const day_data = ref<Map<number, DayData>>(new Map());
let modal: HMultiModal | undefined;
@ -65,24 +70,31 @@ function on_modal_handle(handle: HMultiModal): void {
async function on_open(): Promise<void> {
const [day_parts, day_image_names] = await Promise.all([
API.request<NumStrDict>("admin/day_parts"),
API.request<NumStrDict>("admin/day_image_names"),
API.request<Record<number, string>>("admin/day_parts"),
API.request<Record<number, string>>("admin/day_image_names"),
]);
const _ensure_day_in_data = (day: number) => {
if (!(day in day_data.value)) {
day_data.value[day] = { part: "", image_name: "" };
const _get_data = (day: number) => {
let result = day_data.value.get(day);
if (result === undefined) {
result = { part: "", image_name: "" };
day_data.value.set(day, result);
}
return result;
};
// for (const [day, part] of day_parts.entries()) {
// _get_data(day).part = part;
// }
objForEach(day_parts, (day, part) => {
_ensure_day_in_data(day);
day_data.value[day].part = part;
_get_data(day).part = part;
});
objForEach(day_image_names, (day, image_name) => {
_ensure_day_in_data(day);
day_data.value[day].image_name = image_name;
_get_data(day).image_name = image_name;
});
}

View file

@ -232,7 +232,7 @@ const admin_config_model = ref<AdminConfigModel>({
});
const doors = ref<DoorSaved[]>([]);
const creds = ref<Record<string, Credentials>>({
const creds = ref({
dav: {
username: "",
password: "",

View file

@ -13,14 +13,19 @@
<figure class="image is-unselectable">
<img :src="unwrap_loading(store.background_image).data_url" />
<ThouCanvas>
<PreviewDoor v-for="(_, index) in model" :key="`door-${index}`" v-model="model[index]" />
<PreviewDoor
v-for="(door, index) in model"
:key="`door-${index}`"
:model-value="door"
@update:model-value="updateAt(index, door)"
/>
</ThouCanvas>
</figure>
</div>
</template>
<script setup lang="ts">
import { type VueLike, unwrap_loading } from "@/lib/helpers";
import { unwrap_loading, type VueLike } from "@/lib/helpers";
import { Door } from "@/lib/rects/door";
import { advent22Store } from "@/lib/store";
@ -28,5 +33,12 @@ import ThouCanvas from "../calendar/ThouCanvas.vue";
import PreviewDoor from "./PreviewDoor.vue";
const model = defineModel<VueLike<Door>[]>({ required: true });
function updateAt(i: number, val: VueLike<Door>) {
const copy = [...model.value];
copy[i] = val;
model.value = copy;
}
const store = advent22Store();
</script>

View file

@ -18,12 +18,8 @@ interface Params {
export class API {
private static get api_baseurl(): string {
// in production mode, return "proto://hostname/api"
if (process.env.NODE_ENV === "production") {
if (import.meta.env.PROD) {
return `${window.location.protocol}//${window.location.host}/api`;
} else if (process.env.NODE_ENV !== "development") {
// not in prouction or development mode
// eslint-disable-next-line no-console
console.warn("Unexpected NODE_ENV value: ", process.env.NODE_ENV);
}
// in development mode, return "proto://hostname:8000/api"
@ -84,7 +80,6 @@ export class API {
const response = await this.axios.request<T>(this.get_axios_config(p));
return response.data;
} catch (reason) {
// eslint-disable-next-line no-console
console.error(`Failed to query ${p.endpoint}: ${reason}`);
throw new APIError(reason, p.endpoint);
}

View file

@ -39,7 +39,6 @@ export function handle_error(error: unknown): void {
if (error instanceof APIError) {
error.alert();
} else {
// eslint-disable-next-line no-console
console.error(error);
}
}

View file

@ -45,10 +45,6 @@ export interface SiteConfigModel {
footer: string;
}
export interface NumStrDict {
[key: number]: string;
}
export interface DoorSaved {
day: number;
x1: number;

View file

@ -62,7 +62,7 @@ export const advent22Store = defineStore("advent22", {
if (link.parentElement === null)
document.getElementsByTagName("head")[0]!.appendChild(link);
} catch {}
} catch { }
try {
const [is_admin, site_config, background_image, user_doors, next_door] = await Promise.all([

View file

@ -5,6 +5,8 @@
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"lib": ["es2020", "dom", "dom.iterable", "es2022.object", "es2023.array"],
"paths": {
"@/*": ["./src/*"]
}

View file

@ -5,7 +5,6 @@
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
"lib": [],
"types": ["node", "jsdom"]
}
}

View file

@ -1,7 +1,7 @@
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
import vueDevTools from "vite-plugin-vue-devtools";
// https://vite.dev/config/
@ -12,4 +12,7 @@ export default defineConfig({
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
build: {
sourcemap: true,
},
});