Add centralized error handler for sync Vue app
This commit is contained in:
parent
da90401b2d
commit
01f35b603e
3 changed files with 83 additions and 1 deletions
|
|
@ -1,14 +1,50 @@
|
||||||
|
<style>
|
||||||
|
.global-error-toast {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: #c00;
|
||||||
|
color: white;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 9999;
|
||||||
|
max-width: 400px;
|
||||||
|
animation: slideIn 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
transform: translateX(400px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<div v-if="error" class="global-error-toast">
|
||||||
|
{{ error.message }}
|
||||||
|
<button @click="errorClear">x</button>
|
||||||
|
</div>
|
||||||
<router-view />
|
<router-view />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import { apiClient } from "@/client";
|
import { apiClient } from "@/client";
|
||||||
import router from "@/route/config";
|
import router from "@/route/config";
|
||||||
|
import { useErrorHandler } from "@/composable/error-handler";
|
||||||
|
|
||||||
import { SSEManager, type SSEMessageResource } from "@/SSEManager";
|
import { SSEManager, type SSEMessageResource } from "@/SSEManager";
|
||||||
|
|
||||||
|
const { error, errorClear } = useErrorHandler();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
SSEManager.connect("/api/events");
|
SSEManager.connect("/api/events");
|
||||||
SSEManager.subscribe((msg: SSEMessageResource) => {
|
SSEManager.subscribe((msg: SSEMessageResource) => {
|
||||||
|
|
|
||||||
29
ts/composable/error-handler.ts
Normal file
29
ts/composable/error-handler.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
interface ErrorState {
|
||||||
|
hasError: boolean;
|
||||||
|
message: string;
|
||||||
|
timestamp: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalError = ref<ErrorState | null>(null);
|
||||||
|
|
||||||
|
export function useErrorHandler() {
|
||||||
|
const setError = (error: Error) => {
|
||||||
|
globalError.value = {
|
||||||
|
hasError: true,
|
||||||
|
message: error.message,
|
||||||
|
timestamp: new Date(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorClear = () => {
|
||||||
|
globalError.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
error: globalError,
|
||||||
|
setError,
|
||||||
|
errorClear,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import App from "@/AppSync.vue";
|
||||||
import * as config from "@/config";
|
import * as config from "@/config";
|
||||||
import router from "@/route/config";
|
import router from "@/route/config";
|
||||||
import * as sentry from "@/sentry";
|
import * as sentry from "@/sentry";
|
||||||
|
import { useErrorHandler } from "@/composable/error-handler";
|
||||||
|
|
||||||
import "maplibre-gl/dist/maplibre-gl.css";
|
import "maplibre-gl/dist/maplibre-gl.css";
|
||||||
|
|
||||||
|
|
@ -18,8 +19,24 @@ import "@/gen/custom-icons.scss";
|
||||||
import * as bootstrap from "bootstrap";
|
import * as bootstrap from "bootstrap";
|
||||||
window.bootstrap = bootstrap;
|
window.bootstrap = bootstrap;
|
||||||
|
|
||||||
|
const { setError } = useErrorHandler();
|
||||||
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
app.config.errorHandler = (err, instance, info) => {
|
||||||
|
// err: the error object
|
||||||
|
// instance: the component instance where error occurred
|
||||||
|
// info: Vue-specific error info, e.g., lifecycle hook
|
||||||
|
|
||||||
|
console.error("Global error:", err);
|
||||||
|
console.error("Error info:", info);
|
||||||
|
console.error("Error instance:", instance);
|
||||||
|
|
||||||
|
// You could dispatch to a store, send to error tracking service, etc.
|
||||||
|
// For example, trigger a global error state
|
||||||
|
setError(err);
|
||||||
|
};
|
||||||
|
|
||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
sentry.Init(app, pinia).then(() => {
|
sentry.Init(app, pinia).then(() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue