mirror of
https://github.com/immich-app/immich.git
synced 2025-01-27 22:22:45 +01:00
feat(web): store accordion state in search params (#6435)
* keep admin settings accordion state in search params * refactor: sync implementation * fix: avoid mutating svelte's internal search params * add query parameter to enum --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
parent
6e7865519a
commit
a9e6657a37
9 changed files with 132 additions and 41 deletions
web/src
lib
components
admin-page/settings
user-settings-page
routes/admin/system-settings
|
@ -235,6 +235,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingAccordion
|
<SettingAccordion
|
||||||
|
key="hardware-acceleration"
|
||||||
title="Hardware Acceleration"
|
title="Hardware Acceleration"
|
||||||
subtitle="Experimental; much faster, but will have lower quality at the same bitrate"
|
subtitle="Experimental; much faster, but will have lower quality at the same bitrate"
|
||||||
>
|
>
|
||||||
|
@ -296,7 +297,11 @@
|
||||||
</div>
|
</div>
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Advanced" subtitle="Options most users should not need to change">
|
<SettingAccordion
|
||||||
|
key="advanced-options"
|
||||||
|
title="Advanced"
|
||||||
|
subtitle="Options most users should not need to change"
|
||||||
|
>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingInputField
|
<SettingInputField
|
||||||
inputType={SettingInputFieldType.NUMBER}
|
inputType={SettingInputFieldType.NUMBER}
|
||||||
|
|
|
@ -26,7 +26,12 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<SettingAccordion title="Library watching (EXPERIMENTAL)" subtitle="Automatically watch for changed files" isOpen>
|
<SettingAccordion
|
||||||
|
key="library-watching"
|
||||||
|
title="Library watching (EXPERIMENTAL)"
|
||||||
|
subtitle="Automatically watch for changed files"
|
||||||
|
isOpen
|
||||||
|
>
|
||||||
<form autocomplete="off" on:submit|preventDefault>
|
<form autocomplete="off" on:submit|preventDefault>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
|
@ -70,7 +75,12 @@
|
||||||
</form>
|
</form>
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Periodic Scanning" subtitle="Configure periodic library scanning" isOpen>
|
<SettingAccordion
|
||||||
|
key="library-scanning"
|
||||||
|
title="Periodic Scanning"
|
||||||
|
subtitle="Configure periodic library scanning"
|
||||||
|
isOpen
|
||||||
|
>
|
||||||
<form autocomplete="off" on:submit|preventDefault>
|
<form autocomplete="off" on:submit|preventDefault>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
|
|
|
@ -42,7 +42,11 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SettingAccordion title="Smart Search" subtitle="Search for images semantically using CLIP embeddings">
|
<SettingAccordion
|
||||||
|
key="smart-search"
|
||||||
|
title="Smart Search"
|
||||||
|
subtitle="Search for images semantically using CLIP embeddings"
|
||||||
|
>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title="ENABLED"
|
title="ENABLED"
|
||||||
|
@ -69,7 +73,11 @@
|
||||||
</div>
|
</div>
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Facial Recognition" subtitle="Detect, recognize and group faces in images">
|
<SettingAccordion
|
||||||
|
key="facial-recognition"
|
||||||
|
title="Facial Recognition"
|
||||||
|
subtitle="Detect, recognize and group faces in images"
|
||||||
|
>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title="ENABLED"
|
title="ENABLED"
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" on:submit|preventDefault>
|
<form autocomplete="off" on:submit|preventDefault>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<SettingAccordion title="Map Settings" subtitle="Manage map settings">
|
<SettingAccordion key="map" title="Map Settings" subtitle="Manage map settings">
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title="ENABLED"
|
title="ENABLED"
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
</div></SettingAccordion
|
</div></SettingAccordion
|
||||||
>
|
>
|
||||||
|
|
||||||
<SettingAccordion title="Reverse Geocoding Settings">
|
<SettingAccordion key="reverse-geocoding" title="Reverse Geocoding Settings">
|
||||||
<svelte:fragment slot="subtitle">
|
<svelte:fragment slot="subtitle">
|
||||||
<p class="text-sm dark:text-immich-dark-fg">
|
<p class="text-sm dark:text-immich-dark-fg">
|
||||||
Manage <a
|
Manage <a
|
||||||
|
|
|
@ -1,10 +1,24 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { QueryParameter } from '$lib/constants';
|
||||||
|
import { hasParamValue, updateParamList } from '$lib/utils';
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
export let title: string;
|
export let title: string;
|
||||||
export let subtitle = '';
|
export let subtitle = '';
|
||||||
|
export let key: string;
|
||||||
export let isOpen = false;
|
export let isOpen = false;
|
||||||
const toggle = () => (isOpen = !isOpen);
|
|
||||||
|
const syncFromUrl = () => (isOpen = hasParamValue(QueryParameter.IS_OPEN, key));
|
||||||
|
const syncToUrl = (isOpen: boolean) => updateParamList({ param: QueryParameter.IS_OPEN, value: key, add: isOpen });
|
||||||
|
|
||||||
|
isOpen ? syncToUrl(true) : syncFromUrl();
|
||||||
|
$: $page.url && syncFromUrl();
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
isOpen = !isOpen;
|
||||||
|
syncToUrl(isOpen);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700">
|
<div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700">
|
||||||
|
|
|
@ -27,32 +27,33 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SettingAccordion title="Appearance" subtitle="Manage your Immich appearance">
|
<SettingAccordion key="appearance" title="Appearance" subtitle="Manage your Immich appearance">
|
||||||
<AppearanceSettings />
|
<AppearanceSettings />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Account" subtitle="Manage your account">
|
<SettingAccordion key="account" title="Account" subtitle="Manage your account">
|
||||||
<UserProfileSettings user={$user} />
|
<UserProfileSettings user={$user} />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="API Keys" subtitle="Manage your API keys">
|
<SettingAccordion key="api-keys" title="API Keys" subtitle="Manage your API keys">
|
||||||
<UserAPIKeyList bind:keys />
|
<UserAPIKeyList bind:keys />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Authorized Devices" subtitle="Manage your logged-in devices">
|
<SettingAccordion key="authorized-devices" title="Authorized Devices" subtitle="Manage your logged-in devices">
|
||||||
<DeviceList bind:devices />
|
<DeviceList bind:devices />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Libraries" subtitle="Manage your asset libraries">
|
<SettingAccordion key="libraries" title="Libraries" subtitle="Manage your asset libraries">
|
||||||
<LibraryList />
|
<LibraryList />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Memories" subtitle="Manage what you see in your memories.">
|
<SettingAccordion key="memories" title="Memories" subtitle="Manage what you see in your memories.">
|
||||||
<MemoriesSettings user={$user} />
|
<MemoriesSettings user={$user} />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
{#if $featureFlags.loaded && $featureFlags.oauth}
|
{#if $featureFlags.loaded && $featureFlags.oauth}
|
||||||
<SettingAccordion
|
<SettingAccordion
|
||||||
|
key="oauth"
|
||||||
title="OAuth"
|
title="OAuth"
|
||||||
subtitle="Manage your OAuth connection"
|
subtitle="Manage your OAuth connection"
|
||||||
isOpen={oauthOpen ||
|
isOpen={oauthOpen ||
|
||||||
|
@ -62,18 +63,18 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<SettingAccordion title="Password" subtitle="Change your password">
|
<SettingAccordion key="password" title="Password" subtitle="Change your password">
|
||||||
<ChangePasswordSettings />
|
<ChangePasswordSettings />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Sharing" subtitle="Manage sharing with partners">
|
<SettingAccordion key="sharing" title="Sharing" subtitle="Manage sharing with partners">
|
||||||
<PartnerSettings user={$user} />
|
<PartnerSettings user={$user} />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Sidebar" subtitle="Manage sidebar settings">
|
<SettingAccordion key="sidebar" title="Sidebar" subtitle="Manage sidebar settings">
|
||||||
<SidebarSettings />
|
<SidebarSettings />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion title="Trash" subtitle="Manage trash settings">
|
<SettingAccordion key="trash" title="Trash" subtitle="Manage trash settings">
|
||||||
<TrashSettings />
|
<TrashSettings />
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
|
@ -63,14 +63,15 @@ export const dateFormats = {
|
||||||
export enum QueryParameter {
|
export enum QueryParameter {
|
||||||
ACTION = 'action',
|
ACTION = 'action',
|
||||||
ASSET_INDEX = 'assetIndex',
|
ASSET_INDEX = 'assetIndex',
|
||||||
SMART_SEARCH = 'smartSearch',
|
IS_OPEN = 'isOpen',
|
||||||
MEMORY_INDEX = 'memoryIndex',
|
MEMORY_INDEX = 'memoryIndex',
|
||||||
ONBOARDING_STEP = 'step',
|
ONBOARDING_STEP = 'step',
|
||||||
OPEN_SETTING = 'openSetting',
|
OPEN_SETTING = 'openSetting',
|
||||||
QUERY = 'query',
|
|
||||||
PREVIOUS_ROUTE = 'previousRoute',
|
PREVIOUS_ROUTE = 'previousRoute',
|
||||||
|
QUERY = 'query',
|
||||||
SEARCHED_PEOPLE = 'searchedPeople',
|
SEARCHED_PEOPLE = 'searchedPeople',
|
||||||
SEARCH_TERM = 'q',
|
SEARCH_TERM = 'q',
|
||||||
|
SMART_SEARCH = 'smartSearch',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OpenSettingQueryParameterValue {
|
export enum OpenSettingQueryParameterValue {
|
||||||
|
|
33
web/src/lib/utils.ts
Normal file
33
web/src/lib/utils.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
|
interface UpdateParamAction {
|
||||||
|
param: string;
|
||||||
|
value: string;
|
||||||
|
add: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getParamValues = (param: string) =>
|
||||||
|
new Set((get(page).url.searchParams.get(param) || '').split(' ').filter((x) => x !== ''));
|
||||||
|
|
||||||
|
export const hasParamValue = (param: string, value: string) => getParamValues(param).has(value);
|
||||||
|
|
||||||
|
export const updateParamList = async ({ param, value, add }: UpdateParamAction) => {
|
||||||
|
const values = getParamValues(param);
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
values.add(value);
|
||||||
|
} else {
|
||||||
|
values.delete(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(get(page).url.searchParams);
|
||||||
|
searchParams.set(param, [...values.values()].join(' '));
|
||||||
|
|
||||||
|
if (values.size === 0) {
|
||||||
|
searchParams.delete(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
await goto(`?${searchParams.toString()}`, { replaceState: true, noScroll: true, keepFocus: true });
|
||||||
|
};
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
|
||||||
import FFmpegSettings from '$lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte';
|
import FFmpegSettings from '$lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte';
|
||||||
import JobSettings from '$lib/components/admin-page/settings/job-settings/job-settings.svelte';
|
import JobSettings from '$lib/components/admin-page/settings/job-settings/job-settings.svelte';
|
||||||
import MachineLearningSettings from '$lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte';
|
import MachineLearningSettings from '$lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte';
|
||||||
|
@ -17,7 +16,7 @@
|
||||||
import { downloadManager } from '$lib/stores/download';
|
import { downloadManager } from '$lib/stores/download';
|
||||||
import { featureFlags } from '$lib/stores/server-config.store';
|
import { featureFlags } from '$lib/stores/server-config.store';
|
||||||
import { downloadBlob } from '$lib/utils/asset-utils';
|
import { downloadBlob } from '$lib/utils/asset-utils';
|
||||||
import { type SystemConfigDto, copyToClipboard } from '@api';
|
import { copyToClipboard } from '@api';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import NewVersionCheckSettings from '$lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte';
|
import NewVersionCheckSettings from '$lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte';
|
||||||
|
@ -29,7 +28,22 @@
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
let config = data.configs;
|
let config = data.configs;
|
||||||
let openSettings = ($page.url.searchParams.get('open')?.split(',') || []) as Array<keyof SystemConfigDto>;
|
|
||||||
|
type Settings =
|
||||||
|
| typeof JobSettings
|
||||||
|
| typeof LibrarySettings
|
||||||
|
| typeof LoggingSettings
|
||||||
|
| typeof MachineLearningSettings
|
||||||
|
| typeof MapSettings
|
||||||
|
| typeof OAuthSettings
|
||||||
|
| typeof PasswordLoginSettings
|
||||||
|
| typeof ServerSettings
|
||||||
|
| typeof StorageTemplateSettings
|
||||||
|
| typeof ThemeSettings
|
||||||
|
| typeof ThumbnailSettings
|
||||||
|
| typeof TrashSettings
|
||||||
|
| typeof NewVersionCheckSettings
|
||||||
|
| typeof FFmpegSettings;
|
||||||
|
|
||||||
const downloadConfig = () => {
|
const downloadConfig = () => {
|
||||||
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
|
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
|
||||||
|
@ -40,90 +54,95 @@
|
||||||
setTimeout(() => downloadManager.clear(downloadKey), 5000);
|
setTimeout(() => downloadManager.clear(downloadKey), 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const settings = [
|
const settings: Array<{
|
||||||
|
item: Settings;
|
||||||
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
key: string;
|
||||||
|
}> = [
|
||||||
{
|
{
|
||||||
item: JobSettings,
|
item: JobSettings,
|
||||||
title: 'Job Settings',
|
title: 'Job Settings',
|
||||||
subtitle: 'Manage job concurrency',
|
subtitle: 'Manage job concurrency',
|
||||||
isOpen: openSettings.includes('job'),
|
key: 'job',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: LibrarySettings,
|
item: LibrarySettings,
|
||||||
title: 'Library',
|
title: 'Library',
|
||||||
subtitle: 'Manage library settings',
|
subtitle: 'Manage library settings',
|
||||||
isOpen: openSettings.includes('library'),
|
key: 'library',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: LoggingSettings,
|
item: LoggingSettings,
|
||||||
title: 'Logging',
|
title: 'Logging',
|
||||||
subtitle: 'Manage log settings',
|
subtitle: 'Manage log settings',
|
||||||
isOpen: openSettings.includes('logging'),
|
key: 'logging',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: MachineLearningSettings,
|
item: MachineLearningSettings,
|
||||||
title: 'Machine Learning Settings',
|
title: 'Machine Learning Settings',
|
||||||
subtitle: 'Manage machine learning features and settings',
|
subtitle: 'Manage machine learning features and settings',
|
||||||
isOpen: openSettings.includes('machineLearning'),
|
key: 'machine-learning',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: MapSettings,
|
item: MapSettings,
|
||||||
title: 'Map & GPS Settings',
|
title: 'Map & GPS Settings',
|
||||||
subtitle: 'Manage map related features and setting',
|
subtitle: 'Manage map related features and setting',
|
||||||
isOpen: openSettings.some((key) => ['map', 'reverseGeocoding'].includes(key)),
|
key: 'location',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: OAuthSettings,
|
item: OAuthSettings,
|
||||||
title: 'OAuth Authentication',
|
title: 'OAuth Authentication',
|
||||||
subtitle: 'Manage the login with OAuth settings',
|
subtitle: 'Manage the login with OAuth settings',
|
||||||
isOpen: openSettings.includes('oauth'),
|
key: 'oauth',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: PasswordLoginSettings,
|
item: PasswordLoginSettings,
|
||||||
title: 'Password Authentication',
|
title: 'Password Authentication',
|
||||||
subtitle: 'Manage the login with password settings',
|
subtitle: 'Manage the login with password settings',
|
||||||
isOpen: openSettings.includes('passwordLogin'),
|
key: 'password',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: ServerSettings,
|
item: ServerSettings,
|
||||||
title: 'Server Settings',
|
title: 'Server Settings',
|
||||||
subtitle: 'Manage server settings',
|
subtitle: 'Manage server settings',
|
||||||
isOpen: openSettings.includes('server'),
|
key: 'server',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: StorageTemplateSettings,
|
item: StorageTemplateSettings,
|
||||||
title: 'Storage Template',
|
title: 'Storage Template',
|
||||||
subtitle: 'Manage the folder structure and file name of the upload asset',
|
subtitle: 'Manage the folder structure and file name of the upload asset',
|
||||||
isOpen: openSettings.includes('storageTemplate'),
|
key: 'storage-template',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: ThemeSettings,
|
item: ThemeSettings,
|
||||||
title: 'Theme Settings',
|
title: 'Theme Settings',
|
||||||
subtitle: 'Manage customization of the Immich web interface',
|
subtitle: 'Manage customization of the Immich web interface',
|
||||||
isOpen: openSettings.includes('theme'),
|
key: 'theme',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: ThumbnailSettings,
|
item: ThumbnailSettings,
|
||||||
title: 'Thumbnail Settings',
|
title: 'Thumbnail Settings',
|
||||||
subtitle: 'Manage the resolution of thumbnail sizes',
|
subtitle: 'Manage the resolution of thumbnail sizes',
|
||||||
isOpen: openSettings.includes('thumbnail'),
|
key: 'thumbnail',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: TrashSettings,
|
item: TrashSettings,
|
||||||
title: 'Trash Settings',
|
title: 'Trash Settings',
|
||||||
subtitle: 'Manage trash settings',
|
subtitle: 'Manage trash settings',
|
||||||
isOpen: openSettings.includes('trash'),
|
key: 'trash',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: NewVersionCheckSettings,
|
item: NewVersionCheckSettings,
|
||||||
title: 'Version Check',
|
title: 'Version Check',
|
||||||
subtitle: 'Enable/disable the new version notification',
|
subtitle: 'Enable/disable the new version notification',
|
||||||
isOpen: openSettings.includes('newVersionCheck'),
|
key: 'version-check',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: FFmpegSettings,
|
item: FFmpegSettings,
|
||||||
title: 'Video Transcoding Settings',
|
title: 'Video Transcoding Settings',
|
||||||
subtitle: 'Manage the resolution and encoding information of the video files',
|
subtitle: 'Manage the resolution and encoding information of the video files',
|
||||||
isOpen: openSettings.includes('ffmpeg'),
|
key: 'video-transcoding',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
@ -157,8 +176,8 @@
|
||||||
<AdminSettings bind:config let:handleReset let:handleSave let:savedConfig let:defaultConfig>
|
<AdminSettings bind:config let:handleReset let:handleSave let:savedConfig let:defaultConfig>
|
||||||
<section id="setting-content" class="flex place-content-center sm:mx-4">
|
<section id="setting-content" class="flex place-content-center sm:mx-4">
|
||||||
<section class="w-full pb-28 sm:w-5/6 md:w-[850px]">
|
<section class="w-full pb-28 sm:w-5/6 md:w-[850px]">
|
||||||
{#each settings as { item, title, subtitle, isOpen }}
|
{#each settings as { item, title, subtitle, key }}
|
||||||
<SettingAccordion {title} {subtitle} {isOpen}>
|
<SettingAccordion {title} {subtitle} {key}>
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={item}
|
this={item}
|
||||||
on:save={({ detail }) => handleSave(detail)}
|
on:save={({ detail }) => handleSave(detail)}
|
||||||
|
|
Loading…
Reference in a new issue