diff --git a/web/src/lib/components/user-settings-page/user-settings-list.svelte b/web/src/lib/components/user-settings-page/user-settings-list.svelte
index e3392ac077..66eae1280b 100644
--- a/web/src/lib/components/user-settings-page/user-settings-list.svelte
+++ b/web/src/lib/components/user-settings-page/user-settings-list.svelte
@@ -10,7 +10,7 @@
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import { user } from '$lib/stores/user.store';
import { oauth } from '$lib/utils';
- import { type ApiKeyResponseDto, type SessionResponseDto } from '@immich/sdk';
+ import { getApiKeys, type ApiKeyResponseDto, type SessionResponseDto } from '@immich/sdk';
import {
mdiAccountGroupOutline,
mdiAccountOutline,
@@ -36,13 +36,19 @@
import PartnerSettings from './partner-settings.svelte';
import UserAPIKeyList from './user-api-key-list.svelte';
import UserProfileSettings from './user-profile-settings.svelte';
+ import { onMount } from 'svelte';
interface Props {
- keys?: ApiKeyResponseDto[];
sessions?: SessionResponseDto[];
}
- let { keys = $bindable([]), sessions = $bindable([]) }: Props = $props();
+ let { sessions = $bindable([]) }: Props = $props();
+
+ let keys: ApiKeyResponseDto[] = $state([]);
+
+ onMount(async () => {
+ keys = await getApiKeys();
+ })
let oauthOpen =
oauth.isCallback(globalThis.location) ||
diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts
index 389ebbefab..059d6ffb65 100644
--- a/web/src/lib/constants.ts
+++ b/web/src/lib/constants.ts
@@ -62,6 +62,7 @@ export enum SessionStorageKey {
// TODO split into user settings vs system settings
export enum OpenQueryParam {
+ API_KEYS = 'api-keys',
OAUTH = 'oauth',
JOB = 'job',
STORAGE_TEMPLATE = 'storage-template',
diff --git a/web/src/lib/route.ts b/web/src/lib/route.ts
index 5a59ec704c..42ab1e22cc 100644
--- a/web/src/lib/route.ts
+++ b/web/src/lib/route.ts
@@ -116,6 +116,7 @@ export const Route = {
// settings
userSettings: (params?: { isOpen?: OpenQueryParam }) => '/user-settings' + asQueryString(params),
+ newApiKey: (params?: { permissions?: string }) => '/user-settings/new-api-key' + asQueryString(params),
// system
systemSettings: (params?: { isOpen?: OpenQueryParam }) => '/admin/system-settings' + asQueryString(params),
diff --git a/web/src/lib/services/api-key.service.ts b/web/src/lib/services/api-key.service.ts
index dec333c0bc..d5890907c8 100644
--- a/web/src/lib/services/api-key.service.ts
+++ b/web/src/lib/services/api-key.service.ts
@@ -1,6 +1,7 @@
+import { goto } from '$app/navigation';
import { eventManager } from '$lib/managers/event-manager.svelte';
-import ApiKeyCreateModal from '$lib/modals/ApiKeyCreateModal.svelte';
import ApiKeyUpdateModal from '$lib/modals/ApiKeyUpdateModal.svelte';
+import { Route } from '$lib/route';
import { handleError } from '$lib/utils/handle-error';
import { getFormatter } from '$lib/utils/i18n';
import {
@@ -19,7 +20,7 @@ export const getApiKeysActions = ($t: MessageFormatter) => {
const Create: ActionItem = {
title: $t('new_api_key'),
icon: mdiPlus,
- onAction: () => modalManager.show(ApiKeyCreateModal, {}),
+ onAction: () => goto(Route.newApiKey()),
};
return { Create };
diff --git a/web/src/routes/(user)/user-settings/+layout.svelte b/web/src/routes/(user)/user-settings/+layout.svelte
new file mode 100644
index 0000000000..096047a885
--- /dev/null
+++ b/web/src/routes/(user)/user-settings/+layout.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ {@render children?.()}
+
+
diff --git a/web/src/routes/(user)/user-settings/+page.ts b/web/src/routes/(user)/user-settings/+layout.ts
similarity index 79%
rename from web/src/routes/(user)/user-settings/+page.ts
rename to web/src/routes/(user)/user-settings/+layout.ts
index bf36eeefb5..5731277f9d 100644
--- a/web/src/routes/(user)/user-settings/+page.ts
+++ b/web/src/routes/(user)/user-settings/+layout.ts
@@ -1,17 +1,15 @@
import { authenticate } from '$lib/utils/auth';
import { getFormatter } from '$lib/utils/i18n';
-import { getApiKeys, getSessions } from '@immich/sdk';
+import { getSessions } from '@immich/sdk';
import type { PageLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url);
- const keys = await getApiKeys();
const sessions = await getSessions();
const $t = await getFormatter();
return {
- keys,
sessions,
meta: {
title: $t('settings'),
diff --git a/web/src/routes/(user)/user-settings/+page.svelte b/web/src/routes/(user)/user-settings/+page.svelte
index bf4f5b00f1..e69de29bb2 100644
--- a/web/src/routes/(user)/user-settings/+page.svelte
+++ b/web/src/routes/(user)/user-settings/+page.svelte
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
diff --git a/web/src/routes/(user)/user-settings/new-api-key/+page.svelte b/web/src/routes/(user)/user-settings/new-api-key/+page.svelte
new file mode 100644
index 0000000000..cb8766ce2d
--- /dev/null
+++ b/web/src/routes/(user)/user-settings/new-api-key/+page.svelte
@@ -0,0 +1,55 @@
+
+
+{#if !secret}
+
+
+
+
+
+
+
+
+{:else}
+
+{/if}
diff --git a/web/src/routes/(user)/user-settings/new-api-key/+page.ts b/web/src/routes/(user)/user-settings/new-api-key/+page.ts
new file mode 100644
index 0000000000..7d9569bbe0
--- /dev/null
+++ b/web/src/routes/(user)/user-settings/new-api-key/+page.ts
@@ -0,0 +1,14 @@
+import { authenticate } from '$lib/utils/auth';
+import { getFormatter } from '$lib/utils/i18n';
+import type { PageLoad } from './$types';
+
+export const load = (async ({ url }) => {
+ await authenticate(url);
+ const $t = await getFormatter();
+
+ return {
+ meta: {
+ title: $t('settings'),
+ },
+ };
+}) satisfies PageLoad;