mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
fix(web): user settings styling (#25775)
This commit is contained in:
parent
1436e2a75f
commit
0273dcb0cf
13 changed files with 71 additions and 69 deletions
|
|
@ -5,7 +5,6 @@
|
||||||
import { changePinCode } from '@immich/sdk';
|
import { changePinCode } from '@immich/sdk';
|
||||||
import { Button, Heading, modalManager, Text, toastManager } from '@immich/ui';
|
import { Button, Heading, modalManager, Text, toastManager } from '@immich/ui';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { fade } from 'svelte/transition';
|
|
||||||
|
|
||||||
let currentPinCode = $state('');
|
let currentPinCode = $state('');
|
||||||
let newPinCode = $state('');
|
let newPinCode = $state('');
|
||||||
|
|
@ -38,27 +37,23 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="my-4">
|
<form autocomplete="off" onsubmit={handleSubmit}>
|
||||||
<div in:fade={{ duration: 200 }}>
|
<div class="flex flex-col gap-6 place-items-center place-content-center">
|
||||||
<form autocomplete="off" onsubmit={handleSubmit} class="mt-6">
|
<Heading>{$t('change_pin_code')}</Heading>
|
||||||
<div class="flex flex-col gap-6 place-items-center place-content-center">
|
<PinCodeInput label={$t('current_pin_code')} bind:value={currentPinCode} tabindexStart={1} pinLength={6} />
|
||||||
<Heading>{$t('change_pin_code')}</Heading>
|
<PinCodeInput label={$t('new_pin_code')} bind:value={newPinCode} tabindexStart={7} pinLength={6} />
|
||||||
<PinCodeInput label={$t('current_pin_code')} bind:value={currentPinCode} tabindexStart={1} pinLength={6} />
|
<PinCodeInput label={$t('confirm_new_pin_code')} bind:value={confirmPinCode} tabindexStart={13} pinLength={6} />
|
||||||
<PinCodeInput label={$t('new_pin_code')} bind:value={newPinCode} tabindexStart={7} pinLength={6} />
|
<button type="button" onclick={() => modalManager.show(PinCodeResetModal, {})}>
|
||||||
<PinCodeInput label={$t('confirm_new_pin_code')} bind:value={confirmPinCode} tabindexStart={13} pinLength={6} />
|
<Text color="muted" class="underline" size="small">{$t('forgot_pin_code_question')}</Text>
|
||||||
<button type="button" onclick={() => modalManager.show(PinCodeResetModal, {})}>
|
</button>
|
||||||
<Text color="muted" class="underline" size="small">{$t('forgot_pin_code_question')}</Text>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-end gap-2 mt-4">
|
|
||||||
<Button shape="round" color="secondary" type="button" size="small" onclick={resetForm}>
|
|
||||||
{$t('clear')}
|
|
||||||
</Button>
|
|
||||||
<Button shape="round" type="submit" size="small" loading={isLoading} disabled={!canSubmit}>
|
|
||||||
{$t('save')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
<div class="flex justify-end gap-2 mt-4">
|
||||||
|
<Button shape="round" color="secondary" type="button" size="small" onclick={resetForm}>
|
||||||
|
{$t('clear')}
|
||||||
|
</Button>
|
||||||
|
<Button shape="round" type="submit" size="small" loading={isLoading} disabled={!canSubmit}>
|
||||||
|
{$t('save')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<OnEvents {onUserPinCodeReset} />
|
<OnEvents {onUserPinCodeReset} />
|
||||||
|
|
||||||
<section>
|
<section class="my-4 sm:ms-8">
|
||||||
{#if hasPinCode}
|
{#if hasPinCode}
|
||||||
<div in:fade={{ duration: 200 }}>
|
<div in:fade={{ duration: 200 }}>
|
||||||
<PinCodeChangeForm />
|
<PinCodeChangeForm />
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<div class="ms-8 mt-4 flex flex-col gap-6">
|
<div class="sm:ms-8 flex flex-col gap-6">
|
||||||
<Field label={$t('theme_selection')} description={$t('theme_selection_description')}>
|
<Field label={$t('theme_selection')} description={$t('theme_selection_description')}>
|
||||||
<Switch checked={themeManager.theme.system} onCheckedChange={(checked) => themeManager.setSystem(checked)} />
|
<Switch checked={themeManager.theme.system} onCheckedChange={(checked) => themeManager.setSystem(checked)} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" {onsubmit}>
|
<form autocomplete="off" {onsubmit}>
|
||||||
<div class="ms-4 mt-4 flex flex-col gap-4">
|
<div class="sm:ms-8 flex flex-col gap-4">
|
||||||
<Field label={$t('password')} required>
|
<Field label={$t('password')} required>
|
||||||
<PasswordInput bind:value={password} autocomplete="current-password" />
|
<PasswordInput bind:value={password} autocomplete="current-password" />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import { deleteAllSessions, deleteSession, getSessions, type SessionResponseDto } from '@immich/sdk';
|
import { deleteAllSessions, deleteSession, getSessions, type SessionResponseDto } from '@immich/sdk';
|
||||||
import { Button, modalManager, Text, toastManager } from '@immich/ui';
|
import { Button, modalManager, Text, toastManager } from '@immich/ui';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
import DeviceCard from './device-card.svelte';
|
import DeviceCard from './device-card.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -50,33 +51,39 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
{#if currentSession}
|
<div in:fade={{ duration: 500 }}>
|
||||||
<div class="mb-6">
|
<div class="sm:ms-8 flex flex-col gap-4">
|
||||||
<Text class="mb-2" fontWeight="medium" size="tiny" color="primary">
|
{#if currentSession}
|
||||||
{$t('current_device')}
|
<div class="mb-6">
|
||||||
</Text>
|
<Text class="mb-2" fontWeight="medium" size="tiny" color="primary">
|
||||||
<DeviceCard session={currentSession} />
|
{$t('current_device')}
|
||||||
</div>
|
</Text>
|
||||||
{/if}
|
<DeviceCard session={currentSession} />
|
||||||
{#if otherSessions.length > 0}
|
</div>
|
||||||
<div class="mb-6">
|
{/if}
|
||||||
<Text class="mb-2" fontWeight="medium" size="tiny" color="primary">
|
{#if otherSessions.length > 0}
|
||||||
{$t('other_devices')}
|
<div class="mb-6">
|
||||||
</Text>
|
<Text class="mb-2" fontWeight="medium" size="tiny" color="primary">
|
||||||
{#each otherSessions as session, index (session.id)}
|
{$t('other_devices')}
|
||||||
<DeviceCard {session} onDelete={() => handleDelete(session)} />
|
</Text>
|
||||||
{#if index !== otherSessions.length - 1}
|
{#each otherSessions as session, index (session.id)}
|
||||||
<hr class="my-3" />
|
<DeviceCard {session} onDelete={() => handleDelete(session)} />
|
||||||
{/if}
|
{#if index !== otherSessions.length - 1}
|
||||||
{/each}
|
<hr class="my-3" />
|
||||||
</div>
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<Button shape="round" color="danger" size="small" onclick={handleDeleteAll}>{$t('log_out_all_devices')}</Button>
|
<Button shape="round" color="danger" size="small" onclick={handleDeleteAll}
|
||||||
|
>{$t('log_out_all_devices')}</Button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" {onsubmit}>
|
<form autocomplete="off" {onsubmit}>
|
||||||
<div class="ms-4 mt-4 flex flex-col gap-4">
|
<div class="sm:ms-8 flex flex-col gap-4">
|
||||||
<SettingInputField
|
<SettingInputField
|
||||||
inputType={SettingInputFieldType.NUMBER}
|
inputType={SettingInputFieldType.NUMBER}
|
||||||
label={$t('archive_size')}
|
label={$t('archive_size')}
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,9 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" {onsubmit}>
|
<form autocomplete="off" {onsubmit}>
|
||||||
<div class="ms-4 mt-4 flex flex-col">
|
<div class="sm:ms-4 md:ms-8 flex flex-col">
|
||||||
<SettingAccordion key="albums" title={$t('albums')} subtitle={$t('albums_feature_description')}>
|
<SettingAccordion key="albums" title={$t('albums')} subtitle={$t('albums_feature_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('albums_default_sort_order')} description={$t('albums_default_sort_order_description')}>
|
<Field label={$t('albums_default_sort_order')} description={$t('albums_default_sort_order_description')}>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="folders" title={$t('folders')} subtitle={$t('folders_feature_description')}>
|
<SettingAccordion key="folders" title={$t('folders')} subtitle={$t('folders_feature_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={foldersEnabled} />
|
<Switch bind:checked={foldersEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -97,7 +97,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="memories" title={$t('time_based_memories')} subtitle={$t('photos_from_previous_years')}>
|
<SettingAccordion key="memories" title={$t('time_based_memories')} subtitle={$t('photos_from_previous_years')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={memoriesEnabled} />
|
<Switch bind:checked={memoriesEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="people" title={$t('people')} subtitle={$t('people_feature_description')}>
|
<SettingAccordion key="people" title={$t('people')} subtitle={$t('people_feature_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={peopleEnabled} />
|
<Switch bind:checked={peopleEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="rating" title={$t('rating')} subtitle={$t('rating_description')}>
|
<SettingAccordion key="rating" title={$t('rating')} subtitle={$t('rating_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={ratingsEnabled} />
|
<Switch bind:checked={ratingsEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -131,7 +131,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="shared-links" title={$t('shared_links')} subtitle={$t('shared_links_description')}>
|
<SettingAccordion key="shared-links" title={$t('shared_links')} subtitle={$t('shared_links_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={sharedLinksEnabled} />
|
<Switch bind:checked={sharedLinksEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="tags" title={$t('tags')} subtitle={$t('tag_feature_description')}>
|
<SettingAccordion key="tags" title={$t('tags')} subtitle={$t('tag_feature_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('enable')}>
|
<Field label={$t('enable')}>
|
||||||
<Switch bind:checked={tagsEnabled} />
|
<Switch bind:checked={tagsEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -159,7 +159,7 @@
|
||||||
</SettingAccordion>
|
</SettingAccordion>
|
||||||
|
|
||||||
<SettingAccordion key="cast" title={$t('cast')} subtitle={$t('cast_description')}>
|
<SettingAccordion key="cast" title={$t('cast')} subtitle={$t('cast_description')}>
|
||||||
<div class="ms-4 mt-6 flex flex-col gap-4">
|
<div class="sm:ms-4 mt-4 flex flex-col gap-4">
|
||||||
<Field label={$t('gcast_enabled')} description={$t('gcast_enabled_description')}>
|
<Field label={$t('gcast_enabled')} description={$t('gcast_enabled_description')}>
|
||||||
<Switch bind:checked={gCastEnabled} />
|
<Switch bind:checked={gCastEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" {onsubmit}>
|
<form autocomplete="off" {onsubmit}>
|
||||||
<div class="ms-4 mt-4 flex flex-col gap-6">
|
<div class="sm:ms-8 flex flex-col gap-6">
|
||||||
<Field label={$t('enable')} description={$t('notification_toggle_setting_description')}>
|
<Field label={$t('enable')} description={$t('notification_toggle_setting_description')}>
|
||||||
<Switch bind:checked={emailNotificationsEnabled} />
|
<Switch bind:checked={emailNotificationsEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<div class="flex justify-end">
|
<div class="sm:ms-8 flex justify-end">
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<div class="flex place-content-center place-items-center">
|
<div class="flex place-content-center place-items-center">
|
||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<OnEvents {onApiKeyCreate} {onApiKeyUpdate} {onApiKeyDelete} />
|
<OnEvents {onApiKeyCreate} {onApiKeyUpdate} {onApiKeyDelete} />
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
|
<div class="sm:ms-8 flex flex-col gap-2" in:fade={{ duration: 500 }}>
|
||||||
<div class="mb-2 flex justify-end">
|
<div class="mb-2 flex justify-end">
|
||||||
<Button leadingIcon={Create.icon} shape="round" size="small" onclick={() => Create.onAction(Create)}>
|
<Button leadingIcon={Create.icon} shape="round" size="small" onclick={() => Create.onAction(Create)}>
|
||||||
{Create.title}
|
{Create.title}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" onsubmit={preventDefault(bubble('submit'))}>
|
<form autocomplete="off" onsubmit={preventDefault(bubble('submit'))}>
|
||||||
<div class="ms-4 mt-4 flex flex-col gap-4">
|
<div class="sm:ms-8 flex flex-col gap-4">
|
||||||
<Field label={$t('user_id')} disabled>
|
<Field label={$t('user_id')} disabled>
|
||||||
<Input bind:value={editedUser.id} />
|
<Input bind:value={editedUser.id} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div class="sm:ms-8" in:fade={{ duration: 500 }}>
|
||||||
{#if $isPurchased}
|
{#if $isPurchased}
|
||||||
<!-- BADGE TOGGLE -->
|
<!-- BADGE TOGGLE -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<section class="my-6 w-full">
|
<section class="my-4 w-full">
|
||||||
<Heading size="tiny">{$t('photos_and_videos')}</Heading>
|
<Heading size="tiny">{$t('photos_and_videos')}</Heading>
|
||||||
<Table striped spacing="small" class="mt-4" size="small">
|
<Table striped spacing="small" class="mt-4" size="small">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue