From 6adebeda0df0f2dd3cace5b3668786b88745c66b Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Fri, 16 Oct 2026 10:03:49 -0400 Subject: [PATCH] refactor: system config endpoints (#32457) * refactor(web): tanstack query * refactor: use createQuery * fix: pnpm lockfile --- pnpm-lock.yaml | 18 ++++++ web/package.json | 1 + .../StorageTemplateSettings.svelte | 16 +++--- .../settings/SystemConfigButtonRow.svelte | 28 ++++----- .../managers/system-config-manager.svelte.ts | 57 ------------------- web/src/lib/queries/client.ts | 49 ++++++++++++++++ web/src/lib/queries/system-config.query.ts | 51 +++++++++++++++++ web/src/lib/services/system-config.service.ts | 34 ++--------- web/src/lib/stores/websocket.ts | 6 ++ web/src/routes/+layout.svelte | 52 +++++++++-------- web/src/routes/admin/+layout.ts | 2 - .../routes/admin/system-settings/+page.svelte | 7 ++- web/src/routes/admin/system-settings/+page.ts | 8 +-- .../admin/system-settings/AuthSettings.svelte | 10 +++- .../system-settings/BackupSettings.svelte | 10 +++- .../system-settings/FFmpegSettings.svelte | 11 ++-- .../system-settings/ImageSettings.svelte | 10 +++- .../IntegrityChecksSettings.svelte | 10 +++- .../admin/system-settings/JobSettings.svelte | 10 +++- .../system-settings/LibrarySettings.svelte | 10 +++- .../system-settings/LoggingSettings.svelte | 10 +++- .../MachineLearningSettings.svelte | 11 ++-- .../admin/system-settings/MapSettings.svelte | 10 +++- .../system-settings/MetadataSettings.svelte | 8 ++- .../NewVersionCheckSettings.svelte | 10 +++- .../NightlyTasksSettings.svelte | 10 +++- .../NotificationSettings.svelte | 13 +++-- .../system-settings/ServerSettings.svelte | 10 +++- .../system-settings/TemplateSettings.svelte | 7 ++- .../system-settings/ThemeSettings.svelte | 10 +++- .../system-settings/TrashSettings.svelte | 10 +++- .../admin/system-settings/UserSettings.svelte | 10 +++- web/src/routes/auth/onboarding/+page.svelte | 5 +- .../onboarding/OnboardingServerPrivacy.svelte | 15 +++-- 34 files changed, 335 insertions(+), 204 deletions(-) delete mode 100644 web/src/lib/managers/system-config-manager.svelte.ts create mode 100644 web/src/lib/queries/client.ts create mode 100644 web/src/lib/queries/system-config.query.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6fa9e75f..b3bc68d2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -822,6 +822,9 @@ importers: '@photo-sphere-viewer/video-plugin': specifier: ^5.14.0 version: 5.15.1(@photo-sphere-viewer/core@5.15.1) + '@tanstack/svelte-query': + specifier: ^6.3.2 + version: 6.3.2(svelte@5.57.2(@typescript-eslint/types@8.71.2)) '@types/geojson': specifier: ^7946.0.16 version: 7946.0.16 @@ -4699,6 +4702,14 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 + '@tanstack/query-core@5.104.2': + resolution: {integrity: sha512-/qbsxJK5c3Ve1aFIULWYNcT2jeRUAiD4HME6Eu2ZdpofHoVgAjpkQhLg5xHuOoBkTPQUJLfP7zOxy0qsBcqROA==} + + '@tanstack/svelte-query@6.3.2': + resolution: {integrity: sha512-bMPh3iyijRxqLlulDqJO80wm6mJughvVVTV4SZFMgTNSiA5AJJoOHJ3btQtYpeHgN0dMALhfo4R8chwB/9JA2Q==} + peerDependencies: + svelte: ^5.25.0 + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -17623,6 +17634,13 @@ snapshots: tailwindcss: 4.3.3 vite: 8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.102.0)(terser@5.49.0)(tsx@4.23.15)(yaml@2.9.1) + '@tanstack/query-core@5.104.2': {} + + '@tanstack/svelte-query@6.3.2(svelte@5.57.2(@typescript-eslint/types@8.71.2))': + dependencies: + '@tanstack/query-core': 5.104.2 + svelte: 5.57.2(@typescript-eslint/types@8.71.2) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.7 diff --git a/web/package.json b/web/package.json index 0d147c19e..a238f9ac3 100644 --- a/web/package.json +++ b/web/package.json @@ -36,6 +36,7 @@ "@photo-sphere-viewer/resolution-plugin": "^5.14.0", "@photo-sphere-viewer/settings-plugin": "^5.14.0", "@photo-sphere-viewer/video-plugin": "^5.14.0", + "@tanstack/svelte-query": "^6.3.2", "@types/geojson": "^7946.0.16", "@zoom-image/core": "^0.42.0", "@zoom-image/svelte": "^0.3.0", diff --git a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte index 999fa5537..eed418c39 100644 --- a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte +++ b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte @@ -6,11 +6,12 @@ import FormatMessage from '$lib/elements/FormatMessage.svelte'; import { authManager } from '$lib/managers/auth-manager.svelte'; import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte'; - import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; + import { createDefinedQuery, executeMutation } from '$lib/queries/client'; + import { getConfigQuery, updateConfigMutation } from '$lib/queries/system-config.query'; import StorageTemplateVariablesModal from '$lib/modals/StorageTemplateVariablesModal.svelte'; import { Route } from '$lib/route'; - import { handleSystemConfigSave } from '$lib/services/system-config.service'; import { getStorageTemplateOptions, type SystemConfigTemplateStorageOptionDto } from '@immich/sdk'; + import { cloneDeep } from 'lodash-es'; import { Code, Heading, IconButton, Link, modalManager, Text } from '@immich/ui'; import { mdiInformationOutline } from '@mdi/js'; import handlebar from 'handlebars'; @@ -39,8 +40,9 @@ type StorageTemplateOption = (typeof StorageTemplateOption)[keyof typeof StorageTemplateOption]; const disabled = $derived(featureFlagsManager.value.configFile); - const config = $derived(systemConfigManager.value); - let configToEdit = $state(systemConfigManager.cloneValue()); + const query = createDefinedQuery(getConfigQuery()); + const config = $derived(query.data); + let configToEdit = $state(cloneDeep(config)); // TODO remove once we support partial overwriting with database values if (preselectDate && !featureFlagsManager.value.configFile && !configToEdit.storageTemplate.enabled) { @@ -50,7 +52,7 @@ let templateOptions: SystemConfigTemplateStorageOptionDto | undefined = $state(); let selectedPreset = $state(''); - let customTemplate = $state(systemConfigManager.value.storageTemplate.template); + let customTemplate = $state(config.storageTemplate.template); const getTemplateOptions = async () => { templateOptions = await getStorageTemplateOptions(); @@ -151,9 +153,9 @@ } }); - onDestroy(async () => { + onDestroy(() => { if (saveOnClose) { - await handleSystemConfigSave({ storageTemplate: configToEdit.storageTemplate }); + void executeMutation(updateConfigMutation(), { storageTemplate: configToEdit.storageTemplate }); } }); diff --git a/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte b/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte index 3948b6bbc..fb40e600c 100644 --- a/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte +++ b/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte @@ -1,9 +1,10 @@ @@ -52,6 +52,8 @@
- +
diff --git a/web/src/lib/managers/system-config-manager.svelte.ts b/web/src/lib/managers/system-config-manager.svelte.ts deleted file mode 100644 index e002ea148..000000000 --- a/web/src/lib/managers/system-config-manager.svelte.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { getConfig, getConfigDefaults, type AdminConfigDto } from '@immich/sdk'; -import { cloneDeep } from 'lodash-es'; -import { eventManager } from '$lib/managers/event-manager.svelte'; - -class SystemConfigManager { - #value?: AdminConfigDto = $state(); - #defaultValue?: AdminConfigDto = $state(); - - constructor() { - eventManager.on({ - SystemConfigUpdate: (config) => (this.#value = config), - }); - } - - async init() { - await this.#loadConfig(); - await this.#loadDefault(); - } - - get value() { - if (!this.#value) { - throw new Error('Server config manager must be initialized first'); - } - - return this.#value; - } - - set value(config: AdminConfigDto) { - this.#value = config; - } - - get defaultValue() { - if (!this.#defaultValue) { - throw new Error('Server config manager must be initialized first'); - } - - return this.#defaultValue; - } - - cloneValue() { - return cloneDeep(this.value); - } - - cloneDefaultValue() { - return cloneDeep(this.defaultValue); - } - - async #loadConfig() { - this.#value = await getConfig(); - } - - async #loadDefault() { - this.#defaultValue = await getConfigDefaults(); - } -} - -export const systemConfigManager = new SystemConfigManager(); diff --git a/web/src/lib/queries/client.ts b/web/src/lib/queries/client.ts new file mode 100644 index 000000000..513f05476 --- /dev/null +++ b/web/src/lib/queries/client.ts @@ -0,0 +1,49 @@ +import { + createQuery, + QueryClient, + type CreateMutationOptions, + type DataTag, + type DefaultError, + type DefinedCreateQueryResult, + type NonUndefinedGuard, + type QueryKey, + type UndefinedInitialDataOptions, +} from '@tanstack/svelte-query'; +import { noop } from 'lodash-es'; +import { eventManager } from '$lib/managers/event-manager.svelte'; + +const createQueryClient = () => { + const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + + eventManager.on({ AuthLogout: () => client.clear() }); + + return client; +}; + +export const queryClient = createQueryClient(); + +export const createDefinedQuery = ( + options: UndefinedInitialDataOptions & { + queryKey: DataTag; + }, +): DefinedCreateQueryResult => { + const initialData = queryClient.getQueryData>( + options.queryKey, + ); + if (initialData === undefined) { + throw new Error(`${options.queryKey.join('/')} must be loaded first`); + } + + return createQuery(() => ({ ...options, initialData })); +}; + +export const executeMutation = ( + options: CreateMutationOptions, + variables: TVariables, +) => queryClient.getMutationCache().build(queryClient, options).execute(variables).catch(noop); diff --git a/web/src/lib/queries/system-config.query.ts b/web/src/lib/queries/system-config.query.ts new file mode 100644 index 000000000..fb7646570 --- /dev/null +++ b/web/src/lib/queries/system-config.query.ts @@ -0,0 +1,51 @@ +import { getConfig, getConfigDefaults, updateConfig, type AdminConfigDto } from '@immich/sdk'; +import { toastManager } from '@immich/ui'; +import { mutationOptions, queryOptions } from '@tanstack/svelte-query'; +import { isEqual } from 'lodash-es'; +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { queryClient } from '$lib/queries/client'; +import { handleError } from '$lib/utils/handle-error'; +import { getFormatter } from '$lib/utils/i18n'; + +export const getConfigQuery = () => + queryOptions({ + queryKey: ['system-config'], + queryFn: ({ signal }) => getConfig({ signal }), + staleTime: Infinity, + }); + +export const getConfigDefaultsQuery = () => + queryOptions({ + queryKey: ['system-config', 'defaults'], + queryFn: ({ signal }) => getConfigDefaults({ signal }), + staleTime: Infinity, + }); + +export const updateConfigMutation = () => + mutationOptions({ + mutationFn: async (update: Partial) => { + const config = await getConfig(); + const adminConfigDto = { ...config, ...update }; + + if (isEqual(config, adminConfigDto)) { + return; + } + + return updateConfig({ adminConfigDto }); + }, + onSuccess: async (config) => { + if (!config) { + return; + } + + queryClient.setQueryData(getConfigQuery().queryKey, config); + eventManager.emit('SystemConfigUpdate', config); + + const $t = await getFormatter(); + toastManager.primary($t('settings_saved')); + }, + onError: async (error) => { + const $t = await getFormatter(); + handleError(error, $t('errors.unable_to_save_settings')); + }, + }); diff --git a/web/src/lib/services/system-config.service.ts b/web/src/lib/services/system-config.service.ts index 6fa8bf0f1..568d59575 100644 --- a/web/src/lib/services/system-config.service.ts +++ b/web/src/lib/services/system-config.service.ts @@ -1,12 +1,10 @@ -import { getConfig, updateConfig, type ServerFeaturesDto, type AdminConfigDto } from '@immich/sdk'; -import { toastManager, type ActionItem } from '@immich/ui'; +import type { AdminConfigDto, ServerFeaturesDto } from '@immich/sdk'; +import type { ActionItem } from '@immich/ui'; import { mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js'; -import { isEqual } from 'lodash-es'; import type { MessageFormatter } from 'svelte-i18n'; -import { eventManager } from '$lib/managers/event-manager.svelte'; +import { executeMutation } from '$lib/queries/client'; +import { updateConfigMutation } from '$lib/queries/system-config.query'; import { copyToClipboard, downloadJson } from '$lib/utils'; -import { handleError } from '$lib/utils/handle-error'; -import { getFormatter } from '$lib/utils/i18n'; export const getSystemConfigActions = ( $t: MessageFormatter, @@ -44,26 +42,7 @@ export const getSystemConfigActions = ( return { CopyToClipboard, Download, Upload }; }; -export const handleSystemConfigSave = async (update: Partial) => { - const $t = await getFormatter(); - const config = await getConfig(); - const adminConfigDto = { ...config, ...update }; - - if (isEqual(config, adminConfigDto)) { - return; - } - - try { - const newConfig = await updateConfig({ adminConfigDto }); - - eventManager.emit('SystemConfigUpdate', newConfig); - toastManager.primary($t('settings_saved')); - } catch (error) { - handleError(error, $t('errors.unable_to_save_settings')); - } -}; - -export const handleUploadConfig = () => { +const handleUploadConfig = () => { const input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', '.json'); @@ -76,8 +55,7 @@ export const handleUploadConfig = () => { } const reader = async () => { const text = await file.text(); - const newConfig = JSON.parse(text); - await handleSystemConfigSave(newConfig); + await executeMutation(updateConfigMutation(), JSON.parse(text)); }; reader() .catch((error) => console.error('Error handling JSON config upload', error)) diff --git a/web/src/lib/stores/websocket.ts b/web/src/lib/stores/websocket.ts index 6c4ac1cfd..283038054 100644 --- a/web/src/lib/stores/websocket.ts +++ b/web/src/lib/stores/websocket.ts @@ -13,6 +13,8 @@ import { get, writable } from 'svelte/store'; import { page } from '$app/state'; import { authManager } from '$lib/managers/auth-manager.svelte'; import { eventManager } from '$lib/managers/event-manager.svelte'; +import { queryClient } from '$lib/queries/client'; +import { getConfigQuery } from '$lib/queries/system-config.query'; import { Route } from '$lib/route'; import { maintenanceStore } from '$lib/stores/maintenance.store'; import { notificationManager } from '$lib/stores/notification-manager.svelte'; @@ -68,6 +70,10 @@ websocket }) .on('disconnect', () => websocketStore.connected.set(false)) .on('on_server_version', (serverVersion) => websocketStore.serverVersion.set(serverVersion)) + .on( + 'on_config_update', + () => void queryClient.invalidateQueries({ queryKey: getConfigQuery().queryKey, exact: true }), + ) .on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode)) .on('MaintenanceStatusV1', (status) => { maintenanceStore.status.set(status); diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index f07b2774a..b72f581b7 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -12,6 +12,7 @@ import { eventManager } from '$lib/managers/event-manager.svelte'; import { serverConfigManager } from '$lib/managers/server-config-manager.svelte'; import ServerRestartingModal from '$lib/modals/ServerRestartingModal.svelte'; + import { queryClient } from '$lib/queries/client'; import { Route } from '$lib/route'; import { lang, locale } from '$lib/stores/preferences.store'; import { sidebarStore } from '$lib/stores/sidebar.svelte'; @@ -37,6 +38,7 @@ } from '@immich/ui'; import { En } from 'media-chrome/lang/en'; import { addTranslation } from 'media-chrome/utils/i18n'; + import { QueryClientProvider } from '@tanstack/svelte-query'; import { onMount, type Snippet } from 'svelte'; import { t } from 'svelte-i18n'; import { get } from 'svelte/store'; @@ -256,30 +258,32 @@ {/if} - - {#if page.data.error} - - {:else} - {@render children?.()} - {/if} + + + {#if page.data.error} + + {:else} + {@render children?.()} + {/if} - {#if showNavigationLoadingBar} - - {/if} + {#if showNavigationLoadingBar} + + {/if} - - - + + + - - + + + diff --git a/web/src/routes/admin/+layout.ts b/web/src/routes/admin/+layout.ts index 64356d82a..df213963e 100644 --- a/web/src/routes/admin/+layout.ts +++ b/web/src/routes/admin/+layout.ts @@ -1,8 +1,6 @@ -import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; import { authenticate } from '$lib/utils/auth'; import type { LayoutLoad } from './$types'; export const load = (async ({ url }) => { await authenticate(url, { admin: true }); - await systemConfigManager.init(); }) satisfies LayoutLoad; diff --git a/web/src/routes/admin/system-settings/+page.svelte b/web/src/routes/admin/system-settings/+page.svelte index fb0b14bf2..ab3b43ac4 100644 --- a/web/src/routes/admin/system-settings/+page.svelte +++ b/web/src/routes/admin/system-settings/+page.svelte @@ -21,7 +21,8 @@ import SettingAccordion from '$lib/components/shared-components/settings/SettingAccordion.svelte'; import SearchBar from '$lib/elements/SearchBar.svelte'; import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte'; - import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; + import { createDefinedQuery } from '$lib/queries/client'; + import { getConfigQuery } from '$lib/queries/system-config.query'; import { getSystemConfigActions } from '$lib/services/system-config.service'; import { Alert, CommandPaletteDefaultProvider, Container } from '@immich/ui'; import { @@ -56,6 +57,8 @@ const { data }: Props = $props(); + const config = createDefinedQuery(getConfigQuery()); + const settings: Array<{ component: Component; title: string; @@ -208,7 +211,7 @@ ); const { CopyToClipboard, Upload, Download } = $derived( - getSystemConfigActions($t, featureFlagsManager.value, systemConfigManager.value), + getSystemConfigActions($t, featureFlagsManager.value, config.data), ); diff --git a/web/src/routes/admin/system-settings/+page.ts b/web/src/routes/admin/system-settings/+page.ts index 38deb249c..32d7f4298 100644 --- a/web/src/routes/admin/system-settings/+page.ts +++ b/web/src/routes/admin/system-settings/+page.ts @@ -1,17 +1,15 @@ -import { getConfig, getConfigDefaults } from '@immich/sdk'; +import { queryClient } from '$lib/queries/client'; +import { getConfigDefaultsQuery, getConfigQuery } from '$lib/queries/system-config.query'; 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, { admin: true }); - const config = await getConfig(); - const defaultConfig = await getConfigDefaults(); + await Promise.all([queryClient.query(getConfigQuery()), queryClient.query(getConfigDefaultsQuery())]); const $t = await getFormatter(); return { - config, - defaultConfig, meta: { title: $t('admin.system_settings'), }, diff --git a/web/src/routes/admin/system-settings/AuthSettings.svelte b/web/src/routes/admin/system-settings/AuthSettings.svelte index 2ef24d517..7fd23dc79 100644 --- a/web/src/routes/admin/system-settings/AuthSettings.svelte +++ b/web/src/routes/admin/system-settings/AuthSettings.svelte @@ -6,19 +6,23 @@ import { SettingInputFieldType } from '$lib/constants'; import FormatMessage from '$lib/elements/FormatMessage.svelte'; import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte'; - import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; import AuthDisableLoginConfirmModal from '$lib/modals/AuthDisableLoginConfirmModal.svelte'; + import { createDefinedQuery } from '$lib/queries/client'; + import { getConfigQuery } from '$lib/queries/system-config.query'; import { handleError } from '$lib/utils/handle-error'; import { OAuthTokenEndpointAuthMethod, unlinkAllOAuthAccountsAdmin } from '@immich/sdk'; import { Button, Link, modalManager, Text, toastManager } from '@immich/ui'; import { mdiRestart } from '@mdi/js'; + import { cloneDeep } from 'lodash-es'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; import SettingSelect from './SettingSelect.svelte'; + const query = createDefinedQuery(getConfigQuery()); + const config = $derived(query.data); + const disabled = $derived(featureFlagsManager.value.configFile); - const config = $derived(systemConfigManager.value); - let configToEdit = $state(systemConfigManager.cloneValue()); + let configToEdit = $state(cloneDeep(config)); const handleToggleOverride = () => { // click runs before bind diff --git a/web/src/routes/admin/system-settings/BackupSettings.svelte b/web/src/routes/admin/system-settings/BackupSettings.svelte index 644be2e32..4e147794a 100644 --- a/web/src/routes/admin/system-settings/BackupSettings.svelte +++ b/web/src/routes/admin/system-settings/BackupSettings.svelte @@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/ImageSettings.svelte b/web/src/routes/admin/system-settings/ImageSettings.svelte index d7fd86e71..cbde1597e 100644 --- a/web/src/routes/admin/system-settings/ImageSettings.svelte +++ b/web/src/routes/admin/system-settings/ImageSettings.svelte @@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte b/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte index 0a1b5eb0b..0c01cbaed 100644 --- a/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte +++ b/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte @@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/JobSettings.svelte b/web/src/routes/admin/system-settings/JobSettings.svelte index b38c3c261..f0e319b2e 100644 --- a/web/src/routes/admin/system-settings/JobSettings.svelte +++ b/web/src/routes/admin/system-settings/JobSettings.svelte @@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/MachineLearningSettings.svelte b/web/src/routes/admin/system-settings/MachineLearningSettings.svelte index eb4362914..74d4856c8 100644 --- a/web/src/routes/admin/system-settings/MachineLearningSettings.svelte +++ b/web/src/routes/admin/system-settings/MachineLearningSettings.svelte @@ -1,4 +1,6 @@
diff --git a/web/src/routes/admin/system-settings/MapSettings.svelte b/web/src/routes/admin/system-settings/MapSettings.svelte index 07eb5292a..f987ee103 100644 --- a/web/src/routes/admin/system-settings/MapSettings.svelte +++ b/web/src/routes/admin/system-settings/MapSettings.svelte @@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/MetadataSettings.svelte b/web/src/routes/admin/system-settings/MetadataSettings.svelte index d49292694..825af6405 100644 --- a/web/src/routes/admin/system-settings/MetadataSettings.svelte +++ b/web/src/routes/admin/system-settings/MetadataSettings.svelte @@ -1,13 +1,17 @@
diff --git a/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte b/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte index 653448e06..45eb82bd5 100644 --- a/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte +++ b/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte @@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte b/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte index 88290a0f4..05a562ed8 100644 --- a/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte +++ b/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte @@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/NotificationSettings.svelte b/web/src/routes/admin/system-settings/NotificationSettings.svelte index 9de2a2d7d..cfe672ed4 100644 --- a/web/src/routes/admin/system-settings/NotificationSettings.svelte +++ b/web/src/routes/admin/system-settings/NotificationSettings.svelte @@ -1,4 +1,5 @@
diff --git a/web/src/routes/admin/system-settings/TemplateSettings.svelte b/web/src/routes/admin/system-settings/TemplateSettings.svelte index bcc9cc90c..33f9b4b14 100644 --- a/web/src/routes/admin/system-settings/TemplateSettings.svelte +++ b/web/src/routes/admin/system-settings/TemplateSettings.svelte @@ -2,7 +2,8 @@ import SettingAccordion from '$lib/components/shared-components/settings/SettingAccordion.svelte'; import SettingTextarea from './SettingTextarea.svelte'; import FormatMessage from '$lib/elements/FormatMessage.svelte'; - import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; + import { createDefinedQuery } from '$lib/queries/client'; + import { getConfigQuery } from '$lib/queries/system-config.query'; import EmailTemplatePreviewModal from '$lib/modals/EmailTemplatePreviewModal.svelte'; import { handleError } from '$lib/utils/handle-error'; import { type AdminConfigDto, type AdminConfigTemplateEmailsDto, getNotificationTemplateAdmin } from '@immich/sdk'; @@ -17,6 +18,8 @@ let { config = $bindable() }: Props = $props(); + const saved = createDefinedQuery(getConfigQuery()); + let loadingPreview = $state(false); const getTemplate = async (name: string, template: string) => { @@ -53,7 +56,7 @@ ]; const isEdited = (templateKey: keyof AdminConfigTemplateEmailsDto) => - config.templates.email[templateKey] !== systemConfigManager.value.templates.email[templateKey]; + config.templates.email[templateKey] !== saved.data.templates.email[templateKey]; const onsubmit = (event: Event) => { event.preventDefault(); diff --git a/web/src/routes/admin/system-settings/ThemeSettings.svelte b/web/src/routes/admin/system-settings/ThemeSettings.svelte index 7149825d0..90a8a04bc 100644 --- a/web/src/routes/admin/system-settings/ThemeSettings.svelte +++ b/web/src/routes/admin/system-settings/ThemeSettings.svelte @@ -1,14 +1,18 @@
diff --git a/web/src/routes/admin/system-settings/TrashSettings.svelte b/web/src/routes/admin/system-settings/TrashSettings.svelte index 6829d8487..e4734b005 100644 --- a/web/src/routes/admin/system-settings/TrashSettings.svelte +++ b/web/src/routes/admin/system-settings/TrashSettings.svelte @@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/UserSettings.svelte b/web/src/routes/admin/system-settings/UserSettings.svelte index 7ac33709a..f235ff1ed 100644 --- a/web/src/routes/admin/system-settings/UserSettings.svelte +++ b/web/src/routes/admin/system-settings/UserSettings.svelte @@ -1,16 +1,20 @@
diff --git a/web/src/routes/auth/onboarding/+page.svelte b/web/src/routes/auth/onboarding/+page.svelte index 65e5f95b7..f41280676 100644 --- a/web/src/routes/auth/onboarding/+page.svelte +++ b/web/src/routes/auth/onboarding/+page.svelte @@ -12,7 +12,8 @@ import OnboardingUserPrivacy from './OnboardingUserPrivacy.svelte'; import { authManager } from '$lib/managers/auth-manager.svelte'; import { serverConfigManager } from '$lib/managers/server-config-manager.svelte'; - import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; + import { queryClient } from '$lib/queries/client'; + import { getConfigQuery } from '$lib/queries/system-config.query'; import { Route } from '$lib/route'; import { OnboardingRole } from '$lib/types'; import { setUserOnboarding, updateAdminOnboarding } from '@immich/sdk'; @@ -155,7 +156,7 @@ onMount(async () => { if (userRole === OnboardingRole.SERVER) { - await systemConfigManager.init(); + await queryClient.query(getConfigQuery()); } }); diff --git a/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte b/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte index 3bae79b9a..0f10fdda1 100644 --- a/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte +++ b/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte @@ -1,14 +1,19 @@