-
-
Notifications
You must be signed in to change notification settings - Fork 19
feat(components): visualize api errors for steppers #1931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a6ec610
41b5df9
a271404
6d925b8
77e36a1
6641b65
ade8067
5de805e
63c1648
907ea53
9cf1423
29877bc
01281c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| <AppStep v-slot="attributes" :is-active="step === 'default'"> | ||
| <EventReportForm | ||
| ref="form" | ||
| v-model:error="error" | ||
| v-bind="attributes" | ||
| :account-id | ||
| :event | ||
|
|
@@ -27,6 +28,13 @@ | |
| }} | ||
| </div> | ||
| </AppStep> | ||
| <AppStep v-slot="attributes" :is-active="step === 'error'"> | ||
| <LayoutPageResult v-bind="attributes" type="error"> | ||
| <template #description> | ||
| {{ t('somethingWentWrong') }} | ||
| </template> | ||
| </LayoutPageResult> | ||
| </AppStep> | ||
| <template #title> | ||
| <AppStep v-slot="attributes" :is-active="step === 'default'"> | ||
| <span v-bind="attributes"> | ||
|
|
@@ -43,6 +51,11 @@ | |
| {{ t('titleBlockConfirmation') }} | ||
| </span> | ||
| </AppStep> | ||
| <AppStep v-slot="attributes" :is-active="step === 'error'"> | ||
| <span v-bind="attributes"> | ||
| {{ t('reportingFailed') }} | ||
| </span> | ||
| </AppStep> | ||
| </template> | ||
| <template #footer> | ||
| <AppStep v-slot="attributes" :is-active="step === 'default'"> | ||
|
|
@@ -89,6 +102,16 @@ | |
| </ButtonColored> | ||
| </DrawerClose> | ||
| </AppStep> | ||
| <AppStep v-slot="attributes" :is-active="step === 'error'"> | ||
| <ButtonColored | ||
| v-bind="attributes" | ||
| :aria-label="t('tryAgain')" | ||
| variant="primary" | ||
| @click="restart" | ||
| > | ||
| {{ t('tryAgain') }} | ||
| </ButtonColored> | ||
| </AppStep> | ||
| </template> | ||
| </AppDrawer> | ||
| </template> | ||
|
|
@@ -108,15 +131,17 @@ const { accountId, event } = defineProps<{ | |
| // template | ||
| const templateForm = useTemplateRef('form') | ||
|
|
||
| // stepper | ||
| const { error, restart, step } = useStepper< | ||
| 'reportConfirmation' | 'blockConfirmation' | 'error' | ||
| >({ initial: 'blockConfirmation' }) | ||
|
|
||
| // drawer | ||
| const isOpen = defineModel<boolean>() | ||
| const open = () => (isOpen.value = true) | ||
|
|
||
| // stepper | ||
dargmuesli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const { step } = useStepper<'reportConfirmation' | 'blockConfirmation'>() | ||
| const onAnimationEnd = (isOpen: boolean) => { | ||
| if (isOpen) return | ||
| step.value = 'default' | ||
| restart() | ||
| } | ||
|
|
||
| // block | ||
|
|
@@ -132,24 +157,16 @@ const blockOrganizer = async () => { | |
| createdBy: accountId, | ||
| }, | ||
| }) | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need to remove empty lines before |
||
| if (result.error) { | ||
| // TODO: confirm design | ||
| await showToast({ | ||
| icon: 'error', | ||
| text: apiErrorMessages.value.join('\n'), | ||
| title: t('globalError'), | ||
| }) | ||
| error.value = new Error( | ||
| apiErrorMessages.value.length > 0 | ||
| ? apiErrorMessages.value.join('\n') | ||
| : t('globalError'), | ||
| ) | ||
| return | ||
| } | ||
|
|
||
| if (!result.data) { | ||
| // TODO: confirm design | ||
| await showToast({ | ||
| icon: 'error', | ||
| text: t('globalErrorNoData'), | ||
| title: t('globalError'), | ||
| }) | ||
| error.value = new Error(t('globalError')) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not |
||
| return | ||
| } | ||
|
|
||
|
|
@@ -176,9 +193,12 @@ de: | |
| buttonReportSubmit: Meldung einreichen | ||
| contentBlockConfirmation: Der Benutzer {username} wurde blockiert. | ||
| contentReportConfirmation: Vielen Dank für die Meldung. Wir werden sie prüfen und dich über unsere Entscheidung benachrichtigen. Du kannst nun den Organisator {username} blockieren oder zur Event-Seite zurückkehren. | ||
| reportingFailed: Meldung fehlgeschlagen | ||
| somethingWentWrong: Etwas ist schief gelaufen. | ||
| titleBlockConfirmation: Benutzer blockiert | ||
| titleReport: Event melden | ||
| titleReportConfirmation: Meldung erhalten | ||
| tryAgain: Erneut versuchen | ||
| en: | ||
| buttonBlockConfirmation: Back to Dashboard | ||
| buttonReportCancel: Cancel | ||
|
|
@@ -187,7 +207,10 @@ en: | |
| buttonReportSubmit: Report | ||
| contentBlockConfirmation: The user {username} has been blocked. | ||
| contentReportConfirmation: Thank you for your report. We will review it and notify you about our decision. You can block the organizer {username} now or return to the event. | ||
| reportingFailed: Reporting Failed | ||
| somethingWentWrong: Something went wrong. | ||
| titleBlockConfirmation: User blocked | ||
| titleReport: Report event | ||
| titleReportConfirmation: Report received | ||
| tryAgain: Try Again | ||
| </i18n> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,13 +46,11 @@ const reasons = [ | |
| { label: t('drawerRadioOther'), value: 'other' }, | ||
| ] | ||
| const templateForm = useTemplateRef('form') | ||
| const modelError = defineModel<Error>('error') | ||
|
|
||
| // report | ||
| const createReportMutation = useCreateReportMutation() | ||
| const api = getApiData([createReportMutation]) | ||
| const apiErrorMessages = computed(() => | ||
| getCombinedErrorMessages(api.value.errors), | ||
| ) | ||
|
|
||
| // form | ||
| const submit = () => | ||
|
|
@@ -75,32 +73,33 @@ const onSubmit = handleSubmit(async (values) => { | |
| }, | ||
| }) | ||
|
|
||
| if (result.error) { | ||
| // TODO: confirm design | ||
| await showToast({ | ||
| icon: 'error', | ||
| text: apiErrorMessages.value.join('\n'), | ||
| title: t('globalError'), | ||
| }) | ||
| return | ||
| } | ||
| if (result.error) return | ||
|
|
||
| if (!result.data) { | ||
| // TODO: confirm design | ||
| await showToast({ | ||
| icon: 'error', | ||
| text: t('globalErrorNoData'), | ||
| title: t('globalError'), | ||
| }) | ||
| modelError.value = new Error(t('globalErrorNoData')) | ||
| return | ||
| } | ||
|
|
||
| emit('submitSuccess') | ||
| }) | ||
|
|
||
| defineExpose({ | ||
| submit, | ||
| }) | ||
|
|
||
| watch( | ||
| () => api.value.errors, | ||
| (current) => { | ||
| modelError.value = current?.length | ||
| ? // TODO: Use appropriate error codes here | ||
| new Error( | ||
| getCombinedErrorMessages(current, { | ||
| // postgres55000: t('postgres55000'), | ||
| // postgresP0002: t('postgresP0002'), | ||
|
Comment on lines
+93
to
+97
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about this TODO?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have the error code yet, I'll ask Svenn
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So by now the error codes should've gotten to you. What's the status? |
||
| })[0], | ||
| ) | ||
| : undefined | ||
| }, | ||
| ) | ||
| </script> | ||
|
|
||
| <i18n lang="yaml"> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| <template> | ||
| <AppForm | ||
| :class="classProps" | ||
| :errors="api.errors" | ||
| :form="v$" | ||
| :is-form-sent="isFormSent" | ||
| is-button-hidden | ||
|
|
@@ -35,10 +34,10 @@ const form = reactive({ | |
| emailAddress: ref<string>(), | ||
| }) | ||
| const isFormSent = ref(false) | ||
| const modelError = defineModel<Error>('error') | ||
|
|
||
| // api data | ||
| const passwordResetRequestMutation = useAccountPasswordResetRequestMutation() | ||
| const api = getApiData([passwordResetRequestMutation]) | ||
|
|
||
| // methods | ||
| const submit = async () => { | ||
|
|
@@ -48,9 +47,12 @@ const submit = async () => { | |
| emailAddress: form.emailAddress || '', | ||
| language: locale.value, | ||
| }) | ||
|
|
||
| if (result.error || !result.data) return | ||
|
|
||
| // Backend returns success even for invalid emails (security); only handle network errors | ||
| if (result.error || !result.data) { | ||
| modelError.value = new Error() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why an empty error here instead of adding a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is going to fail silently (security reasons) and their would be no error response from backend so I suppose we only need to take care of broken network connection. |
||
| return | ||
| } | ||
| modelError.value = undefined | ||
| emit('success') | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.