diff --git a/web/src/app.d.ts b/web/src/app.d.ts index 13619596b2..46398aad3c 100644 --- a/web/src/app.d.ts +++ b/web/src/app.d.ts @@ -8,6 +8,12 @@ declare namespace App { } // interface Platform {} + + interface Error { + message: string; + stack?: string; + code?: string; + } } // Source: https://stackoverflow.com/questions/63814432/typescript-typing-of-non-standard-window-event-in-svelte diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index f061284480..0ed93b7b9e 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -1,5 +1,15 @@ -import type { Handle } from '@sveltejs/kit'; +import type { Handle, HandleServerError } from '@sveltejs/kit'; +import { AxiosError } from 'axios'; export const handle: Handle = async ({ event, resolve }) => { return await resolve(event); }; + +export const handleError: HandleServerError = async ({ error }) => { + const httpError = error as AxiosError; + return { + message: httpError?.message || 'Hmm, not sure about that. Check the logs or open a ticket?', + stack: httpError?.stack, + code: httpError.code || '500' + }; +}; diff --git a/web/src/lib/components/forms/login-form.svelte b/web/src/lib/components/forms/login-form.svelte index 07ebf88c76..33ba0598a8 100644 --- a/web/src/lib/components/forms/login-form.svelte +++ b/web/src/lib/components/forms/login-form.svelte @@ -2,6 +2,7 @@ import { goto } from '$app/navigation'; import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte'; import { loginPageMessage } from '$lib/constants'; + import { handleError } from '$lib/utils/handle-error'; import { api, oauth, OAuthConfigResponseDto } from '@api'; import { createEventDispatcher, onMount } from 'svelte'; @@ -9,7 +10,7 @@ let email = ''; let password = ''; let oauthError: string; - let oauthConfig: OAuthConfigResponseDto = { enabled: false, passwordLoginEnabled: false }; + let authConfig: OAuthConfigResponseDto = { enabled: false, passwordLoginEnabled: false }; let loading = true; const dispatch = createEventDispatcher(); @@ -30,17 +31,18 @@ try { const { data } = await oauth.getConfig(window.location); - oauthConfig = data; + authConfig = data; - const { enabled, url, autoLaunch } = oauthConfig; + const { enabled, url, autoLaunch } = authConfig; if (enabled && url && autoLaunch && !oauth.isAutoLaunchDisabled(window.location)) { await goto('/auth/login?autoLaunch=0', { replaceState: true }); await goto(url); return; } - } catch (e) { - console.error('Error [login-form] [oauth.generateConfig]', e); + } catch (error) { + authConfig.passwordLoginEnabled = true; + handleError(error, 'Unable to connect!'); } loading = false; @@ -92,7 +94,7 @@ {:else} - {#if oauthConfig.passwordLoginEnabled} + {#if authConfig.passwordLoginEnabled}
@@ -133,26 +135,26 @@ {/if} - {#if oauthConfig.enabled} + {#if authConfig.enabled}
- {#if oauthConfig.passwordLoginEnabled} + {#if authConfig.passwordLoginEnabled}
{/if} {#if oauthError}

{oauthError}

{/if} - + {authConfig.buttonText || 'Login with OAuth'}
{/if} - {#if !oauthConfig.enabled && !oauthConfig.passwordLoginEnabled} + {#if !authConfig.enabled && !authConfig.passwordLoginEnabled}

Login has been disabled.

{/if} {/if} diff --git a/web/src/lib/components/shared-components/notification/notification-card.svelte b/web/src/lib/components/shared-components/notification/notification-card.svelte index fdf843e72c..91d713aa26 100644 --- a/web/src/lib/components/shared-components/notification/notification-card.svelte +++ b/web/src/lib/components/shared-components/notification/notification-card.svelte @@ -90,5 +90,7 @@
-

{@html notificationInfo.message}

+

+ {@html notificationInfo.message} +

diff --git a/web/src/lib/utils/handle-error.ts b/web/src/lib/utils/handle-error.ts index 786719759b..77c1d6b2f1 100644 --- a/web/src/lib/utils/handle-error.ts +++ b/web/src/lib/utils/handle-error.ts @@ -6,8 +6,14 @@ import { export function handleError(error: unknown, message: string) { console.error(`[handleError]: ${message}`, error); + + let serverMessage = (error as ApiError)?.response?.data?.message; + if (serverMessage) { + serverMessage = `${String(serverMessage).slice(0, 50)}\n(Immich Server Error)`; + } + notificationController.show({ - message: (error as ApiError)?.response?.data?.message || message, + message: serverMessage || message, type: NotificationType.Error }); } diff --git a/web/src/routes/+error.svelte b/web/src/routes/+error.svelte index 902d3218f8..d0b25f87e5 100644 --- a/web/src/routes/+error.svelte +++ b/web/src/routes/+error.svelte @@ -1,29 +1,122 @@ -
-
- Error code {$page.status} -
- - {$page.error?.message} - -
-
-

Verbose

-
{JSON.stringify($page.error)}
+
+
+ +
- - +
+
- +
+
+

+ 🚨 Error - Something went wrong +

+
+ +
+
+ +
+ +
+
+

{$page.error?.message} - {$page.error?.code}

+ {#if $page.error?.stack} + +
{$page.error?.stack || 'No stack'}
+ {/if} +
+
+ +
+ + +
+
+
diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 2965b59cf2..c9c1300a2d 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -78,7 +78,7 @@ - {$page.data.meta?.title} - Immich + {$page.data.meta?.title || 'Web'} - Immich {#if $page.data.meta}