Skip to content

Commit 8ed8025

Browse files
Benoit NgoNgob
authored andcommitted
feat(error): Handling error globally as toasters
1 parent f470f2d commit 8ed8025

File tree

15 files changed

+214
-105
lines changed

15 files changed

+214
-105
lines changed

Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,19 @@ cs-check: sync-env ## cs-check
129129
phpstan: sync-env ## phpstan
130130
docker compose exec back composer -- run phpstan
131131

132-
.PHONY: frontlint
133-
frontlint: sync-env ## lint front (fix)
132+
be-yaml:
133+
docker compose exec back console -- bin/console lint:yaml config
134+
135+
.PHONY: fe-lint
136+
fe-lint: sync-env ## lint front (fix)
134137
docker compose exec front yarn lint --fix
135138

136139
.PHONY: frontcheck
137-
frontcheck: sync-env ## lint front (check)
140+
fe-check: sync-env ## lint front (check)
138141
docker compose exec front yarn lint
139142

140143
.PHONY: ci
141-
ci: cs-fix phpstan phpmd cs-check frontlint ## Run all CI tools
142-
144+
ci: cs-fix phpstan phpmd cs-check fe-lint ## Run all CI tools
143145

144146
.PHONY: drop-db-dev
145147
drop-db-dev: ## Drop database

apps/front/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"generate": "nuxt generate",
77
"preview": "nuxt preview",
88
"postinstall": "nuxt prepare",
9-
"lint": "eslint nuxt.config.ts --fix ; nuxi typecheck ; eslint ./src/"
9+
"lint": "eslint nuxt.config.ts --fix ; nuxi typecheck && eslint ./src/"
1010
},
1111
"devDependencies": {
1212
"@nuxt/eslint-config": "^0.1.1",
@@ -20,6 +20,8 @@
2020
"typescript": "^5.0.4",
2121
"vue-tsc": "^1.6.5"
2222
},
23+
24+
2325
"dependencies": {
2426
"@nuxtjs/i18n": "^8.0.0-rc.5",
2527
"@pinia/nuxt": "^0.4.11",

apps/front/src/app.vue

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
<template>
22
<div>
3-
<NuxtErrorBoundary @error="mHandleError">
4-
<NuxtLoadingIndicator
5-
color="linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,18,71,1) 60%, rgba(0,236,174,1) 100%)"
6-
/>
7-
<NuxtLayout v-if="!isMePending || isAuthenticated">
8-
<NuxtPage />
9-
</NuxtLayout>
10-
</NuxtErrorBoundary>
3+
<Toast />
4+
<NuxtLoadingIndicator
5+
color="linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,18,71,1) 60%, rgba(0,236,174,1) 100%)"
6+
/>
7+
<NuxtLayout v-if="!isMePending || isAuthenticated">
8+
<NuxtPage />
9+
</NuxtLayout>
1110
</div>
1211
</template>
1312
<script setup lang="ts">
@@ -19,9 +18,6 @@ const authStore = useAuthUser();
1918
2019
const route = useRoute();
2120
22-
const mHandleError = (e: unknown) => {
23-
logger.error("Primary error boundary", e);
24-
};
2521
const { isAuthenticated, isMePending, authUrl } = storeToRefs(authStore);
2622
// Doing this here instead than in the middleware allow reactivity on the auth user
2723
watchEffect(async () => {

apps/front/src/components/user/UserUpdateForm.vue

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
v-model:password-confirm="passwordConfirm"
1212
:is-password-confirmed="isPasswordConfirmed"
1313
/>
14-
{{ errorMessage }}
15-
{{ error }}
1614
<Button type="submit" :disabled="!isPasswordConfirmed">{{
1715
$t("components.user.updateForm.ok")
1816
}}</Button>
1917
</form>
18+
<div>
19+
{{ errorMessage }}
20+
{{ error }}
21+
</div>
2022
</template>
2123

2224
<script setup lang="ts">
@@ -45,19 +47,15 @@ const {
4547
securedPassword,
4648
} = useUser(data);
4749
const updateUser = async () => {
48-
try {
49-
await updateUserApi(
50-
data.value.id,
51-
{
52-
email: email.value,
53-
},
54-
securedPassword.value
55-
);
56-
userRefresh();
57-
await navigateTo("/users");
58-
} catch (e) {
59-
logger.error(e);
60-
}
50+
await updateUserApi(
51+
data.value.id,
52+
{
53+
email: email.value,
54+
},
55+
securedPassword.value
56+
);
57+
userRefresh();
58+
await navigateTo("/users");
6159
};
6260
</script>
6361

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
import { User } from "~/types/User";
22
import { DELETE } from "~/constants/http";
3+
import useBasicError from "~/composables/useBasicError";
34

45
export default function useDeleteUser() {
56
const { $appFetch } = useNuxtApp();
7+
8+
const { setError, resetError, errorMessage } = useBasicError();
69
return {
10+
errorMessage,
711
deleteUser: async (user: User) => {
8-
const response = await $appFetch("/users/" + user.id, {
9-
method: DELETE,
10-
});
11-
if (!response) {
12-
throw createError("Error while deleting user");
12+
try {
13+
resetError();
14+
const response = await $appFetch("/users/" + user.id, {
15+
method: DELETE,
16+
});
17+
if (!response) {
18+
throw createError("Error while deleting user");
19+
}
20+
return response;
21+
} catch (e: any) {
22+
await setError(e);
23+
throw e;
1324
}
14-
return response;
1525
},
1626
};
1727
}

apps/front/src/composables/useBasicError.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,26 @@ import { BasicError } from "~/types/BasicError";
44
export default function useBasicError() {
55
const error: Ref<BasicError | null> = ref(null);
66
const errorMessage = computed(() => {
7-
return (
8-
error.value?.detail || error.value?.message || error.value?.error || ""
9-
);
7+
// Dont display message on 500 (handled via toasters)
8+
if (
9+
error.value?.status &&
10+
(error.value.status > 500 || error.value.status === 403)
11+
) {
12+
return "";
13+
}
14+
if (error.value?.detail) {
15+
return error.value?.detail;
16+
}
17+
if (error.value?.message) {
18+
return Array.isArray(error.value.message)
19+
? error.value.message.join(".")
20+
: error.value.message;
21+
}
22+
23+
if (error.value?.title) {
24+
return error.value?.title;
25+
}
26+
return "";
1027
});
1128
const setError = async (e: any) => {
1229
error.value = e;

apps/front/src/locales/en.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,20 @@ export default {
5555
},
5656
},
5757
},
58+
plugins: {
59+
appFetch: {
60+
toasterUnauthorizedDetail: "Unauthorized",
61+
toasterUnauthorizedSummary: "Unauthorized",
62+
63+
toasterForbiddenDetail: "Forbidden",
64+
toasterForbiddenSummary: "Forbidden",
65+
66+
toasterCatchAllDetail: "Error",
67+
toasterCatchAllSummary: "Error",
68+
},
69+
error: {
70+
toasterCatchAllDetail: "Error",
71+
toasterCatchAllSummary: "Error",
72+
},
73+
}
5874
};

apps/front/src/locales/fr.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,20 @@ export default {
5555
},
5656
},
5757
},
58+
plugins: {
59+
appFetch: {
60+
toasterUnauthorizedDetail: "Vous n'êtes pas authentifié",
61+
toasterUnauthorizedSummary: "Erreur d'authentification",
62+
63+
toasterForbiddenDetail: "Vous n'êtes pas autorisé",
64+
toasterForbiddenSummary: "Erreur d'autorisation",
65+
66+
toasterCatchAllDetail: "Erreur",
67+
toasterCatchAllSummary: "Une erreur est survenue",
68+
},
69+
error: {
70+
toasterCatchAllDetail: "Erreur",
71+
toasterCatchAllSummary: "Une erreur est survenue",
72+
}
73+
}
5874
};

apps/front/src/pages/users/index.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</div>
88
<div v-show="usersPending" v-t="{ path: 'pages.user.index.pending' }"></div>
99
<div v-show="error">{{ error }}}</div>
10+
{{ errorDelete }}
1011
<table v-if="users">
1112
<thead>
1213
<tr>
@@ -48,7 +49,7 @@ import useListUsers from "~/composables/api/user/useListUsers";
4849
import useDeleteUser from "~/composables/api/user/useDeleteUser";
4950
5051
const authStore = useAuthUser();
51-
const { deleteUser } = useDeleteUser();
52+
const { deleteUser, errorMessage: errorDelete } = useDeleteUser();
5253
5354
const {
5455
data: users,
@@ -63,6 +64,7 @@ const deleteUserClick = async (user: User) => {
6364
usersRefresh();
6465
} catch (e) {
6566
logger.error(e);
67+
throw e;
6668
}
6769
};
6870
</script>

apps/front/src/plugins/primevue.ts renamed to apps/front/src/plugins/01-primevue.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import TieredMenu from "primevue/tieredmenu";
44
import DataTable from "primevue/datatable";
55
import Column from "primevue/column";
66
import InputText from "primevue/inputtext";
7+
import Toast from "primevue/toast";
8+
import ToastService from "primevue/toastservice";
79

810
export default defineNuxtPlugin((nuxtApp) => {
911
nuxtApp.vueApp.use(PrimeVue, { ripple: true });
@@ -12,6 +14,7 @@ export default defineNuxtPlugin((nuxtApp) => {
1214
nuxtApp.vueApp.component("InputText", InputText);
1315
nuxtApp.vueApp.component("DataTable", DataTable);
1416
nuxtApp.vueApp.component("Column", Column);
15-
17+
nuxtApp.vueApp.use(ToastService);
18+
nuxtApp.vueApp.component("Toast", Toast);
1619
//other components that you need
1720
});

0 commit comments

Comments
 (0)