Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): store accordion state in search params #6435

Merged
merged 4 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
/>

<SettingAccordion
key="hardware-acceleration"
title="Hardware Acceleration"
subtitle="Experimental; much faster, but will have lower quality at the same bitrate"
>
Expand Down Expand Up @@ -296,7 +297,11 @@
</div>
</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">
<SettingInputField
inputType={SettingInputFieldType.NUMBER}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@

<div>
<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>
<div class="ml-4 mt-4 flex flex-col gap-4">
<SettingSwitch
Expand Down Expand Up @@ -70,7 +75,12 @@
</form>
</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>
<div class="ml-4 mt-4 flex flex-col gap-4">
<SettingSwitch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@
/>
</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">
<SettingSwitch
title="ENABLED"
Expand All @@ -69,7 +73,11 @@
</div>
</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">
<SettingSwitch
title="ENABLED"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault>
<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">
<SettingSwitch
title="ENABLED"
Expand Down Expand Up @@ -51,7 +51,7 @@
</div></SettingAccordion
>

<SettingAccordion title="Reverse Geocoding Settings">
<SettingAccordion key="reverse-geocoding" title="Reverse Geocoding Settings">
<svelte:fragment slot="subtitle">
<p class="text-sm dark:text-immich-dark-fg">
Manage <a
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
<script lang="ts">
import { page } from '$app/stores';
import { QueryParameter } from '$lib/constants';
import { hasParamValue, updateParamList } from '$lib/utils';
import { slide } from 'svelte/transition';

export let title: string;
export let subtitle = '';

export let key: string;
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>

<div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700">
Expand Down
21 changes: 11 additions & 10 deletions web/src/lib/components/user-settings-page/user-settings-list.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,33 @@
}
</script>

<SettingAccordion title="Appearance" subtitle="Manage your Immich appearance">
<SettingAccordion key="appearance" title="Appearance" subtitle="Manage your Immich appearance">
<AppearanceSettings />
</SettingAccordion>

<SettingAccordion title="Account" subtitle="Manage your account">
<SettingAccordion key="account" title="Account" subtitle="Manage your account">
<UserProfileSettings user={$user} />
</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 />
</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 />
</SettingAccordion>

<SettingAccordion title="Libraries" subtitle="Manage your asset libraries">
<SettingAccordion key="libraries" title="Libraries" subtitle="Manage your asset libraries">
<LibraryList />
</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} />
</SettingAccordion>

{#if $featureFlags.loaded && $featureFlags.oauth}
<SettingAccordion
key="oauth"
title="OAuth"
subtitle="Manage your OAuth connection"
isOpen={oauthOpen ||
Expand All @@ -62,18 +63,18 @@
</SettingAccordion>
{/if}

<SettingAccordion title="Password" subtitle="Change your password">
<SettingAccordion key="password" title="Password" subtitle="Change your password">
<ChangePasswordSettings />
</SettingAccordion>

<SettingAccordion title="Sharing" subtitle="Manage sharing with partners">
<SettingAccordion key="sharing" title="Sharing" subtitle="Manage sharing with partners">
<PartnerSettings user={$user} />
</SettingAccordion>

<SettingAccordion title="Sidebar" subtitle="Manage sidebar settings">
<SettingAccordion key="sidebar" title="Sidebar" subtitle="Manage sidebar settings">
<SidebarSettings />
</SettingAccordion>

<SettingAccordion title="Trash" subtitle="Manage trash settings">
<SettingAccordion key="trash" title="Trash" subtitle="Manage trash settings">
<TrashSettings />
</SettingAccordion>
5 changes: 3 additions & 2 deletions web/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ export const dateFormats = {
export enum QueryParameter {
ACTION = 'action',
ASSET_INDEX = 'assetIndex',
SMART_SEARCH = 'smartSearch',
IS_OPEN = 'isOpen',
MEMORY_INDEX = 'memoryIndex',
ONBOARDING_STEP = 'step',
OPEN_SETTING = 'openSetting',
QUERY = 'query',
PREVIOUS_ROUTE = 'previousRoute',
QUERY = 'query',
SEARCHED_PEOPLE = 'searchedPeople',
SEARCH_TERM = 'q',
SMART_SEARCH = 'smartSearch',
}

export enum OpenSettingQueryParameterValue {
Expand Down
33 changes: 33 additions & 0 deletions web/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -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 });
};
59 changes: 39 additions & 20 deletions web/src/routes/admin/system-settings/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script lang="ts">
import { page } from '$app/stores';
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 MachineLearningSettings from '$lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte';
Expand All @@ -17,7 +16,7 @@
import { downloadManager } from '$lib/stores/download';
import { featureFlags } from '$lib/stores/server-config.store';
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 type { PageData } from './$types';
import NewVersionCheckSettings from '$lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte';
Expand All @@ -30,7 +29,22 @@
export let data: PageData;

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 blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
Expand All @@ -41,90 +55,95 @@
setTimeout(() => downloadManager.clear(downloadKey), 5000);
};

const settings = [
const settings: Array<{
item: Settings;
title: string;
subtitle: string;
key: string;
}> = [
{
item: JobSettings,
title: 'Job Settings',
subtitle: 'Manage job concurrency',
isOpen: openSettings.includes('job'),
key: 'job',
},
{
item: LibrarySettings,
title: 'Library',
subtitle: 'Manage library settings',
isOpen: openSettings.includes('library'),
key: 'library',
},
{
item: LoggingSettings,
title: 'Logging',
subtitle: 'Manage log settings',
isOpen: openSettings.includes('logging'),
key: 'logging',
},
{
item: MachineLearningSettings,
title: 'Machine Learning Settings',
subtitle: 'Manage machine learning features and settings',
isOpen: openSettings.includes('machineLearning'),
key: 'machine-learning',
},
{
item: MapSettings,
title: 'Map & GPS Settings',
subtitle: 'Manage map related features and setting',
isOpen: openSettings.some((key) => ['map', 'reverseGeocoding'].includes(key)),
key: 'location',
},
{
item: OAuthSettings,
title: 'OAuth Authentication',
subtitle: 'Manage the login with OAuth settings',
isOpen: openSettings.includes('oauth'),
key: 'oauth',
},
{
item: PasswordLoginSettings,
title: 'Password Authentication',
subtitle: 'Manage the login with password settings',
isOpen: openSettings.includes('passwordLogin'),
key: 'password',
},
{
item: ServerSettings,
title: 'Server Settings',
subtitle: 'Manage server settings',
isOpen: openSettings.includes('server'),
key: 'server',
},
{
item: StorageTemplateSettings,
title: 'Storage Template',
subtitle: 'Manage the folder structure and file name of the upload asset',
isOpen: openSettings.includes('storageTemplate'),
key: 'storage-template',
},
{
item: ThemeSettings,
title: 'Theme Settings',
subtitle: 'Manage customization of the Immich web interface',
isOpen: openSettings.includes('theme'),
key: 'theme',
},
{
item: ThumbnailSettings,
title: 'Thumbnail Settings',
subtitle: 'Manage the resolution of thumbnail sizes',
isOpen: openSettings.includes('thumbnail'),
key: 'thumbnail',
},
{
item: TrashSettings,
title: 'Trash Settings',
subtitle: 'Manage trash settings',
isOpen: openSettings.includes('trash'),
key: 'trash',
},
{
item: NewVersionCheckSettings,
title: 'Version Check',
subtitle: 'Enable/disable the new version notification',
isOpen: openSettings.includes('newVersionCheck'),
key: 'version-check',
},
{
item: FFmpegSettings,
title: 'Video Transcoding Settings',
subtitle: 'Manage the resolution and encoding information of the video files',
isOpen: openSettings.includes('ffmpeg'),
key: 'video-transcoding',
},
];
</script>
Expand Down Expand Up @@ -158,8 +177,8 @@
<AdminSettings bind:config let:handleReset let:handleSave let:savedConfig let:defaultConfig>
<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]">
{#each settings as { item, title, subtitle, isOpen }}
<SettingAccordion {title} {subtitle} {isOpen}>
{#each settings as { item, title, subtitle, key }}
<SettingAccordion {title} {subtitle} {key}>
<svelte:component
this={item}
on:save={({ detail }) => handleSave(detail)}
Expand Down