User Error Formatting

This commit is contained in:
Jörn-Michael Miehe 2023-09-13 15:24:25 +00:00
parent c4b1c180e0
commit 421f7d185c
4 changed files with 122 additions and 70 deletions

View file

@ -48,9 +48,15 @@ export default class extends Vue {
this.modal_visible = false; this.modal_visible = false;
this.$advent22.set_api_auth(username, password); this.$advent22.set_api_auth(username, password);
this.$advent22.api_get<boolean>("admin/is_admin").then((is_admin) => { this.$advent22
.api_get<boolean>("admin/is_admin")
.then((is_admin) => {
this.$emit("update:modelValue", is_admin); this.$emit("update:modelValue", is_admin);
this.is_busy = false; this.is_busy = false;
})
.catch((error) => {
alert(this.$advent22.format_user_error(error));
this.is_busy = false;
}); });
} }

View file

@ -83,8 +83,9 @@ export default class extends Vue {
public loading_doors = false; public loading_doors = false;
public saving_doors = false; public saving_doors = false;
private load_doors(): Promise<void | DoorsSaved> { private load_doors(): Promise<DoorsSaved> {
return this.$advent22 return new Promise<DoorsSaved>((resolve, reject) => {
this.$advent22
.api_get<DoorsSaved>("admin/doors") .api_get<DoorsSaved>("admin/doors")
.then((data) => { .then((data) => {
this.doors.length = 0; this.doors.length = 0;
@ -94,35 +95,46 @@ export default class extends Vue {
} }
this.is_loaded = true; this.is_loaded = true;
resolve(data);
}) })
.catch(([reason, endpoint]) => alert(`Fehler: ${reason} in ${endpoint}`)); .catch(([reason, endpoint]) => {
alert(`Fehler: ${reason} in ${endpoint}`);
reject();
});
});
} }
private save_doors(): Promise<void> { private save_doors(): Promise<void> {
return new Promise<void>((resolve, reject) => {
const data: DoorsSaved = []; const data: DoorsSaved = [];
for (const door of this.doors) { for (const door of this.doors) {
data.push(door.save()); data.push(door.save());
} }
return this.$advent22 this.$advent22
.api_put("admin/doors", data) .api_put("admin/doors", data)
.catch((reason) => alert(`Fehler: ${reason} in admin/doors`)); .then(resolve)
.catch(([reason, endpoint]) => {
alert(`Fehler: ${reason} in ${endpoint}`);
reject();
});
});
} }
public on_open(): void { public on_open(): void {
this.is_loaded = false; this.is_loaded = false;
this.load_doors(); this.load_doors().catch(() => {});
} }
public on_download() { public on_download() {
if (confirm("Aktuelle Änderungen verwerfen und Status vom Server laden?")) { if (confirm("Aktuelle Änderungen verwerfen und Status vom Server laden?")) {
this.loading_doors = true; this.loading_doors = true;
this.load_doors().then(() => { this.load_doors()
alert("Erfolgeich!"); .then(() => alert("Erfolgeich!"))
this.loading_doors = false; .catch(() => {})
}); .finally(() => (this.loading_doors = false));
} }
} }
@ -137,12 +149,14 @@ export default class extends Vue {
if (confirm("Aktuelle Änderungen an den Server schicken?")) { if (confirm("Aktuelle Änderungen an den Server schicken?")) {
this.saving_doors = true; this.saving_doors = true;
this.save_doors().then(() => { this.save_doors()
this.load_doors().then(() => { .then(() => {
alert("Erfolgeich!"); this.load_doors()
this.saving_doors = false; .then(() => alert("Erfolgeich!"))
}); .catch(() => {})
}); .finally(() => (this.saving_doors = false));
})
.catch(() => (this.saving_doors = false));
} }
} }
} }

View file

@ -4,7 +4,6 @@
<script lang="ts"> <script lang="ts">
import { Door } from "@/lib/door"; import { Door } from "@/lib/door";
import { AxiosError } from "axios";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import SVGRect from "./SVGRect.vue"; import SVGRect from "./SVGRect.vue";
@ -27,25 +26,8 @@ export default class extends Vue {
this.$advent22 this.$advent22
.api_get_blob(`user/image_${this.door.day}`) .api_get_blob(`user/image_${this.door.day}`)
.then((data) => this.$emit("doorSuccess", this.door.day, data)) .then((data) => this.$emit("doorSuccess", this.door.day, data))
.catch(([reason]) => { .catch((error) => {
let msg = "Unbekannter Fehler, bitte wiederholen!"; this.$emit("doorFailure", this.$advent22.format_user_error(error));
if (reason instanceof AxiosError) {
if (reason.code === "ECONNABORTED") {
// API unerreichbar
msg = "API antwortet nicht, bitte später wiederholen!";
} else if (reason.response !== undefined) {
if (reason.response.status === 401) {
// 401 UNAUTHORIZED
msg = "Netter Versuch :)";
} else if (reason.response.status === 422) {
// 422 UNPROCESSABLE ENTITY
msg = "Türchen ist kaputt, bitte Admin benachrichtigen!";
}
}
}
this.$emit("doorFailure", msg);
}); });
} }
} }

View file

@ -1,4 +1,4 @@
import axios, { AxiosInstance, ResponseType } from "axios"; import axios, { AxiosError, AxiosInstance, ResponseType } from "axios";
import { App, Plugin } from "vue"; import { App, Plugin } from "vue";
export class Advent22 { export class Advent22 {
@ -28,6 +28,55 @@ export class Advent22 {
return `Türchen ${day}`; return `Türchen ${day}`;
} }
public format_user_error([reason, endpoint]: unknown[]): 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();
}
public set_api_auth(username: string, password: string) { public set_api_auth(username: string, password: string) {
this.api_auth = { username: username, password: password }; this.api_auth = { username: username, password: password };
} }
@ -78,8 +127,7 @@ export class Advent22 {
public api_get_blob(endpoint: string): Promise<string> { public api_get_blob(endpoint: string): Promise<string> {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
this._api_get<Blob>(endpoint, "blob") this._api_get<Blob>(endpoint, "blob").then((data: Blob) => {
.then((data: Blob) => {
const reader = new FileReader(); const reader = new FileReader();
reader.readAsDataURL(data); reader.readAsDataURL(data);
reader.onloadend = () => { reader.onloadend = () => {
@ -89,8 +137,7 @@ export class Advent22 {
reject(["failed data url", endpoint]); reject(["failed data url", endpoint]);
} }
}; };
}) });
.catch(reject);
}); });
} }
@ -99,12 +146,15 @@ export class Advent22 {
auth: this.api_auth, auth: this.api_auth,
}; };
return new Promise<void>((resolve, reject) => return new Promise<void>((resolve, reject) => {
this.axios this.axios
.put(this.api_url(endpoint), data, req_config) .put(this.api_url(endpoint), data, req_config)
.then(() => resolve()) .then(() => resolve())
.catch(reject), .catch((reason) => {
); console.error(`Failed to query ${endpoint}: ${reason}`);
reject([reason, endpoint]);
});
});
} }
} }