mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor: admin settings (#23843)
This commit is contained in:
@@ -3,7 +3,7 @@ import { AppRoute } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
import { serverConfig } from '$lib/stores/system-config-manager.svelte';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getFormatter } from '$lib/utils/i18n';
|
||||
@@ -91,7 +91,6 @@ export const handleUpdateSharedLink = async (sharedLink: SharedLinkResponseDto,
|
||||
const response = await updateSharedLink({ id: sharedLink.id, sharedLinkEditDto: dto });
|
||||
|
||||
eventManager.emit('SharedLinkUpdate', { album: sharedLink.album, ...response });
|
||||
|
||||
toastManager.success($t('saved'));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import { downloadManager } from '$lib/managers/download-manager.svelte';
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { type FeatureFlags } from '$lib/stores/system-config-manager.svelte';
|
||||
import type { ActionItem } from '$lib/types';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
import { downloadBlob } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getFormatter } from '$lib/utils/i18n';
|
||||
import { getConfig, updateConfig, type SystemConfigDto } from '@immich/sdk';
|
||||
import { toastManager } from '@immich/ui';
|
||||
import { mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import type { MessageFormatter } from 'svelte-i18n';
|
||||
|
||||
export const getSystemConfigActions = ($t: MessageFormatter, $featureFlags: FeatureFlags, config: SystemConfigDto) => {
|
||||
const CopyToClipboard: ActionItem = {
|
||||
title: $t('copy_to_clipboard'),
|
||||
icon: mdiContentCopy,
|
||||
onSelect: () => void handleCopyToClipboard(config),
|
||||
};
|
||||
|
||||
const Download: ActionItem = {
|
||||
title: $t('export_as_json'),
|
||||
icon: mdiDownload,
|
||||
onSelect: () => handleDownloadConfig(config),
|
||||
};
|
||||
|
||||
const Upload: ActionItem = {
|
||||
title: $t('import_from_json'),
|
||||
icon: mdiUpload,
|
||||
$if: () => !$featureFlags.configFile,
|
||||
onSelect: () => handleUploadConfig(),
|
||||
};
|
||||
|
||||
return { CopyToClipboard, Download, Upload };
|
||||
};
|
||||
|
||||
export const handleSystemConfigSave = async (update: Partial<SystemConfigDto>) => {
|
||||
const $t = await getFormatter();
|
||||
const config = await getConfig();
|
||||
const systemConfigDto = { ...config, ...update };
|
||||
|
||||
if (isEqual(config, systemConfigDto)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newConfig = await updateConfig({ systemConfigDto });
|
||||
|
||||
eventManager.emit('SystemConfigUpdate', newConfig);
|
||||
toastManager.success($t('settings_saved'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_save_settings'));
|
||||
}
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/16167581/sort-object-properties-and-json-stringify/43636793#43636793
|
||||
const jsonReplacer = (_key: string, value: unknown) =>
|
||||
value instanceof Object && !Array.isArray(value)
|
||||
? Object.keys(value)
|
||||
.sort()
|
||||
// eslint-disable-next-line unicorn/no-array-reduce
|
||||
.reduce((sorted: { [key: string]: unknown }, key) => {
|
||||
sorted[key] = (value as { [key: string]: unknown })[key];
|
||||
return sorted;
|
||||
}, {})
|
||||
: value;
|
||||
|
||||
export const handleCopyToClipboard = async (config: SystemConfigDto) => {
|
||||
await copyToClipboard(JSON.stringify(config, jsonReplacer, 2));
|
||||
};
|
||||
|
||||
export const handleDownloadConfig = (config: SystemConfigDto) => {
|
||||
const blob = new Blob([JSON.stringify(config, jsonReplacer, 2)], { type: 'application/json' });
|
||||
const downloadKey = 'immich-config.json';
|
||||
downloadManager.add(downloadKey, blob.size);
|
||||
downloadManager.update(downloadKey, blob.size);
|
||||
downloadBlob(blob, downloadKey);
|
||||
setTimeout(() => downloadManager.clear(downloadKey), 5000);
|
||||
};
|
||||
|
||||
export const handleUploadConfig = () => {
|
||||
const input = globalThis.document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('accept', 'json');
|
||||
input.setAttribute('style', 'display: none');
|
||||
|
||||
input.addEventListener('change', ({ target }) => {
|
||||
const file = (target as HTMLInputElement).files?.[0];
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
const reader = async () => {
|
||||
const text = await file.text();
|
||||
const newConfig = JSON.parse(text);
|
||||
await handleSystemConfigSave(newConfig);
|
||||
};
|
||||
reader().catch((error) => console.error('Error handling JSON config upload', error));
|
||||
globalThis.document.append(input);
|
||||
});
|
||||
input.remove();
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import UserCreateModal from '$lib/modals/UserCreateModal.svelte';
|
||||
import UserDeleteConfirmModal from '$lib/modals/UserDeleteConfirmModal.svelte';
|
||||
import UserEditModal from '$lib/modals/UserEditModal.svelte';
|
||||
import UserRestoreConfirmModal from '$lib/modals/UserRestoreConfirmModal.svelte';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
import { serverConfig } from '$lib/stores/system-config-manager.svelte';
|
||||
import { user as authUser } from '$lib/stores/user.store';
|
||||
import type { ActionItem } from '$lib/types';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
|
||||
Reference in New Issue
Block a user