mirror of https://github.com/immich-app/immich.git
refactor: server config and feature flags managers (#23894)
parent
f11bfb9581
commit
1200bfad13
@ -1,78 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { retrieveServerConfig } from '$lib/stores/system-config-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getConfig, getConfigDefaults, updateConfig, type SystemConfigDto } from '@immich/sdk';
|
||||
import { toastManager } from '@immich/ui';
|
||||
import { cloneDeep, isEqual } from 'lodash-es';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { SettingsResetOptions } from './admin-settings';
|
||||
|
||||
interface Props {
|
||||
config: SystemConfigDto;
|
||||
children: import('svelte').Snippet<[{ savedConfig: SystemConfigDto; defaultConfig: SystemConfigDto }]>;
|
||||
}
|
||||
|
||||
let { config = $bindable(), children }: Props = $props();
|
||||
|
||||
let savedConfig: SystemConfigDto | undefined = $state();
|
||||
let defaultConfig: SystemConfigDto | undefined = $state();
|
||||
|
||||
export const handleReset = async (options: SettingsResetOptions) => {
|
||||
await (options.default ? resetToDefault(options.configKeys) : reset(options.configKeys));
|
||||
};
|
||||
|
||||
export const handleSave = async (update: Partial<SystemConfigDto>) => {
|
||||
let systemConfigDto = {
|
||||
...savedConfig,
|
||||
...update,
|
||||
} as SystemConfigDto;
|
||||
|
||||
if (isEqual(systemConfigDto, savedConfig)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newConfig = await updateConfig({
|
||||
systemConfigDto,
|
||||
});
|
||||
|
||||
config = cloneDeep(newConfig);
|
||||
savedConfig = cloneDeep(newConfig);
|
||||
toastManager.success($t('settings_saved'));
|
||||
|
||||
await retrieveServerConfig();
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_save_settings'));
|
||||
}
|
||||
};
|
||||
|
||||
const reset = async (configKeys: Array<keyof SystemConfigDto>) => {
|
||||
const resetConfig = await getConfig();
|
||||
|
||||
for (const key of configKeys) {
|
||||
config = { ...config, [key]: resetConfig[key] };
|
||||
}
|
||||
|
||||
toastManager.info($t('admin.reset_settings_to_recent_saved'));
|
||||
};
|
||||
|
||||
const resetToDefault = (configKeys: Array<keyof SystemConfigDto>) => {
|
||||
if (!defaultConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of configKeys) {
|
||||
config = { ...config, [key]: defaultConfig[key] };
|
||||
}
|
||||
|
||||
toastManager.info($t('admin.reset_settings_to_default'));
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
[savedConfig, defaultConfig] = await Promise.all([getConfig(), getConfigDefaults()]);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if savedConfig && defaultConfig}
|
||||
{@render children({ savedConfig, defaultConfig })}
|
||||
{/if}
|
||||
@ -1,4 +0,0 @@
|
||||
import type { ResetOptions } from '$lib/utils/dipatch';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
|
||||
export type SettingsResetOptions = ResetOptions & { configKeys: Array<keyof SystemConfigDto> };
|
||||
@ -0,0 +1,28 @@
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { getServerFeatures, type ServerFeaturesDto } from '@immich/sdk';
|
||||
|
||||
class FeatureFlagsManager {
|
||||
#value?: ServerFeaturesDto = $state();
|
||||
|
||||
constructor() {
|
||||
eventManager.on('SystemConfigUpdate', () => void this.#loadFeatureFlags());
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.#loadFeatureFlags();
|
||||
}
|
||||
|
||||
get value() {
|
||||
if (!this.#value) {
|
||||
throw new Error('Feature flags manager must be initialized first');
|
||||
}
|
||||
|
||||
return this.#value;
|
||||
}
|
||||
|
||||
async #loadFeatureFlags() {
|
||||
this.#value = await getServerFeatures();
|
||||
}
|
||||
}
|
||||
|
||||
export const featureFlagsManager = new FeatureFlagsManager();
|
||||
@ -0,0 +1,28 @@
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { getServerConfig, type ServerConfigDto } from '@immich/sdk';
|
||||
|
||||
class ServerConfigManager {
|
||||
#value?: ServerConfigDto = $state();
|
||||
|
||||
constructor() {
|
||||
eventManager.on('SystemConfigUpdate', () => void this.loadServerConfig());
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.loadServerConfig();
|
||||
}
|
||||
|
||||
get value() {
|
||||
if (!this.#value) {
|
||||
throw new Error('Server config manager must be initialized first');
|
||||
}
|
||||
|
||||
return this.#value;
|
||||
}
|
||||
|
||||
async loadServerConfig() {
|
||||
this.#value = await getServerConfig();
|
||||
}
|
||||
}
|
||||
|
||||
export const serverConfigManager = new ServerConfigManager();
|
||||
@ -0,0 +1,55 @@
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { getConfig, getConfigDefaults, type SystemConfigDto } from '@immich/sdk';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
class SystemConfigManager {
|
||||
#value?: SystemConfigDto = $state();
|
||||
#defaultValue?: SystemConfigDto = $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: SystemConfigDto) {
|
||||
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();
|
||||
@ -1,108 +0,0 @@
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import {
|
||||
getConfig,
|
||||
getConfigDefaults,
|
||||
getServerConfig,
|
||||
getServerFeatures,
|
||||
type ServerConfigDto,
|
||||
type ServerFeaturesDto,
|
||||
type SystemConfigDto,
|
||||
} from '@immich/sdk';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export type FeatureFlags = ServerFeaturesDto & { loaded: boolean };
|
||||
|
||||
export const featureFlags = writable<FeatureFlags>({
|
||||
loaded: false,
|
||||
smartSearch: true,
|
||||
duplicateDetection: false,
|
||||
facialRecognition: true,
|
||||
importFaces: false,
|
||||
sidecar: true,
|
||||
map: true,
|
||||
reverseGeocoding: true,
|
||||
search: true,
|
||||
oauth: false,
|
||||
oauthAutoLaunch: false,
|
||||
passwordLogin: true,
|
||||
configFile: false,
|
||||
trash: true,
|
||||
email: false,
|
||||
ocr: true,
|
||||
});
|
||||
|
||||
export type ServerConfig = ServerConfigDto & { loaded: boolean };
|
||||
|
||||
export const serverConfig = writable<ServerConfig>({
|
||||
loaded: false,
|
||||
oauthButtonText: '',
|
||||
loginPageMessage: '',
|
||||
trashDays: 30,
|
||||
userDeleteDelay: 7,
|
||||
isInitialized: false,
|
||||
isOnboarded: false,
|
||||
externalDomain: '',
|
||||
mapDarkStyleUrl: '',
|
||||
mapLightStyleUrl: '',
|
||||
publicUsers: true,
|
||||
});
|
||||
|
||||
class SystemConfigManager {
|
||||
#value?: SystemConfigDto = $state();
|
||||
#defaultValue?: SystemConfigDto = $state();
|
||||
|
||||
constructor() {
|
||||
eventManager.on('SystemConfigUpdate', (config) => (this.#value = config));
|
||||
}
|
||||
|
||||
get value() {
|
||||
if (!this.#value) {
|
||||
throw new Error('System config dto must be initialized first');
|
||||
}
|
||||
|
||||
return this.#value;
|
||||
}
|
||||
|
||||
set value(config: SystemConfigDto) {
|
||||
this.#value = config;
|
||||
}
|
||||
|
||||
get defaultValue() {
|
||||
if (!this.#defaultValue) {
|
||||
throw new Error('System config dto must be initialized first');
|
||||
}
|
||||
|
||||
return this.#defaultValue;
|
||||
}
|
||||
|
||||
cloneValue() {
|
||||
return cloneDeep(this.value);
|
||||
}
|
||||
|
||||
cloneDefaultValue() {
|
||||
return cloneDeep(this.defaultValue);
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.#loadConfig();
|
||||
await this.#loadDefault();
|
||||
}
|
||||
|
||||
async #loadConfig() {
|
||||
this.#value = await getConfig();
|
||||
}
|
||||
|
||||
async #loadDefault() {
|
||||
this.#defaultValue = await getConfigDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
export const retrieveServerConfig = async () => {
|
||||
const [flags, config] = await Promise.all([getServerFeatures(), getServerConfig()]);
|
||||
|
||||
featureFlags.update(() => ({ ...flags, loaded: true }));
|
||||
serverConfig.update(() => ({ ...config, loaded: true }));
|
||||
};
|
||||
|
||||
export const systemConfigManager = new SystemConfigManager();
|
||||
Loading…
Reference in New Issue