mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	refactor(web): centralize buttons (#2200)
This commit is contained in:
		
							parent
							
								
									767410959a
								
							
						
					
					
						commit
						ab5b92ae68
					
				@ -15,7 +15,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
:root {
 | 
					:root {
 | 
				
			||||||
	font-family: 'Work Sans', sans-serif;
 | 
						font-family: 'Work Sans', sans-serif;
 | 
				
			||||||
	/* --immich-icon-button-hover-color: #d3d3d3; */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
html {
 | 
					html {
 | 
				
			||||||
@ -64,22 +63,6 @@ input:focus-visible {
 | 
				
			|||||||
		@apply font-medium text-gray-500 dark:text-gray-300;
 | 
							@apply font-medium text-gray-500 dark:text-gray-300;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.immich-btn-primary {
 | 
					 | 
				
			||||||
		@apply bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray text-gray-100 border dark:border-immich-dark-gray rounded-xl py-2 px-4 transition-all duration-150 hover:bg-immich-primary dark:hover:bg-immich-dark-primary/90 hover:shadow-lg text-sm font-medium;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.immich-btn-primary-big {
 | 
					 | 
				
			||||||
		@apply inline-flex justify-center items-center bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray text-white enabled:dark:hover:bg-immich-dark-primary/80 enabled:hover:bg-immich-primary/75 disabled:cursor-not-allowed px-6 py-4 rounded-3xl shadow-md w-full font-semibold;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.immich-btn-secondary-big {
 | 
					 | 
				
			||||||
		@apply inline-flex justify-center items-center bg-gray-500 dark:bg-gray-200 text-white enabled:hover:bg-gray-500/75 enabled:dark:hover:bg-gray-200/80 dark:text-immich-dark-gray disabled:cursor-not-allowed px-6 py-4 rounded-3xl shadow-md w-full font-semibold;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.immich-text-button {
 | 
					 | 
				
			||||||
		@apply flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 p-2 rounded-lg font-medium;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* width */
 | 
						/* width */
 | 
				
			||||||
	.immich-scrollbar::-webkit-scrollbar {
 | 
						.immich-scrollbar::-webkit-scrollbar {
 | 
				
			||||||
		width: 8px;
 | 
							width: 8px;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { api, UserResponseDto } from '@api';
 | 
						import { api, UserResponseDto } from '@api';
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,11 +32,7 @@
 | 
				
			|||||||
		</p>
 | 
							</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="flex w-full px-4 gap-4 mt-8">
 | 
							<div class="flex w-full px-4 gap-4 mt-8">
 | 
				
			||||||
			<button
 | 
								<Button fullwidth color="red" on:click={deleteUser}>Confirm</Button>
 | 
				
			||||||
				on:click={deleteUser}
 | 
					 | 
				
			||||||
				class="flex-1 transition-colors bg-red-500 hover:bg-red-400 px-6 py-3 text-white rounded-full w-full font-medium"
 | 
					 | 
				
			||||||
				>Confirm
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { api, UserResponseDto } from '@api';
 | 
						import { api, UserResponseDto } from '@api';
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,11 +31,7 @@
 | 
				
			|||||||
		</p>
 | 
							</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="flex w-full px-4 gap-4 mt-8">
 | 
							<div class="flex w-full px-4 gap-4 mt-8">
 | 
				
			||||||
			<button
 | 
								<Button color="green" fullwidth on:click={restoreUser}>Confirm</Button>
 | 
				
			||||||
				on:click={restoreUser}
 | 
					 | 
				
			||||||
				class="flex-1 transition-colors bg-lime-600 hover:bg-lime-500 px-6 py-3 text-white rounded-full w-full font-medium"
 | 
					 | 
				
			||||||
				>Confirm
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
@ -19,17 +20,7 @@
 | 
				
			|||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="right">
 | 
						<div class="right">
 | 
				
			||||||
		<button
 | 
							<Button size="sm" color="gray" on:click={() => dispatch('reset')}>Reset</Button>
 | 
				
			||||||
			on:click={() => dispatch('reset')}
 | 
							<Button size="sm" on:click={() => dispatch('save')}>Save</Button>
 | 
				
			||||||
			class="text-sm bg-gray-500 dark:bg-gray-200 hover:bg-gray-500/75 dark:hover:bg-gray-200/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
			>Reset
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		<button
 | 
					 | 
				
			||||||
			type="submit"
 | 
					 | 
				
			||||||
			on:click={() => dispatch('save')}
 | 
					 | 
				
			||||||
			class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
			>Save
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
	import { AlbumResponseDto, api, ThumbnailFormat } from '@api';
 | 
						import { AlbumResponseDto, api, ThumbnailFormat } from '@api';
 | 
				
			||||||
	import { createEventDispatcher, onMount } from 'svelte';
 | 
						import { createEventDispatcher, onMount } from 'svelte';
 | 
				
			||||||
	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
						import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import noThumbnailUrl from '$lib/assets/no-thumbnail.png';
 | 
						import noThumbnailUrl from '$lib/assets/no-thumbnail.png';
 | 
				
			||||||
	import { locale } from '$lib/stores/preferences.store';
 | 
						import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
	import AssetSelection from './asset-selection.svelte';
 | 
						import AssetSelection from './asset-selection.svelte';
 | 
				
			||||||
	import UserSelectionModal from './user-selection-modal.svelte';
 | 
						import UserSelectionModal from './user-selection-modal.svelte';
 | 
				
			||||||
	import ShareInfoModal from './share-info-modal.svelte';
 | 
						import ShareInfoModal from './share-info-modal.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import Close from 'svelte-material-icons/Close.svelte';
 | 
						import Close from 'svelte-material-icons/Close.svelte';
 | 
				
			||||||
	import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
 | 
						import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
 | 
				
			||||||
	import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte';
 | 
						import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte';
 | 
				
			||||||
@ -42,6 +42,7 @@
 | 
				
			|||||||
	import { locale } from '$lib/stores/preferences.store';
 | 
						import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
	import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte';
 | 
						import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte';
 | 
				
			||||||
	import ImmichLogo from '../shared-components/immich-logo.svelte';
 | 
						import ImmichLogo from '../shared-components/immich-logo.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let album: AlbumResponseDto;
 | 
						export let album: AlbumResponseDto;
 | 
				
			||||||
	export let sharedLink: SharedLinkResponseDto | undefined = undefined;
 | 
						export let sharedLink: SharedLinkResponseDto | undefined = undefined;
 | 
				
			||||||
@ -469,12 +470,14 @@
 | 
				
			|||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				{#if isCreatingSharedAlbum && album.sharedUsers.length == 0}
 | 
									{#if isCreatingSharedAlbum && album.sharedUsers.length == 0}
 | 
				
			||||||
					<button
 | 
										<Button
 | 
				
			||||||
 | 
											size="sm"
 | 
				
			||||||
 | 
											rounded="lg"
 | 
				
			||||||
						disabled={album.assetCount == 0}
 | 
											disabled={album.assetCount == 0}
 | 
				
			||||||
						on:click={() => (isShowShareUserSelection = true)}
 | 
											on:click={() => (isShowShareUserSelection = true)}
 | 
				
			||||||
						class="immich-text-button border bg-immich-primary dark:bg-immich-dark-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed dark:text-immich-dark-bg dark:border-immich-dark-gray"
 | 
					 | 
				
			||||||
						><span class="px-2">Share</span></button
 | 
					 | 
				
			||||||
					>
 | 
										>
 | 
				
			||||||
 | 
											Share
 | 
				
			||||||
 | 
										</Button>
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
			</svelte:fragment>
 | 
								</svelte:fragment>
 | 
				
			||||||
		</ControlAppBar>
 | 
							</ControlAppBar>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
		selectedAssets
 | 
							selectedAssets
 | 
				
			||||||
	} from '$lib/stores/asset-interaction.store';
 | 
						} from '$lib/stores/asset-interaction.store';
 | 
				
			||||||
	import { locale } from '$lib/stores/preferences.store';
 | 
						import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,12 +64,14 @@
 | 
				
			|||||||
			>
 | 
								>
 | 
				
			||||||
				Select from computer
 | 
									Select from computer
 | 
				
			||||||
			</button>
 | 
								</button>
 | 
				
			||||||
			<button
 | 
								<Button
 | 
				
			||||||
 | 
									size="sm"
 | 
				
			||||||
 | 
									rounded="lg"
 | 
				
			||||||
				disabled={$selectedAssets.size === 0}
 | 
									disabled={$selectedAssets.size === 0}
 | 
				
			||||||
				on:click={addSelectedAssets}
 | 
									on:click={addSelectedAssets}
 | 
				
			||||||
				class="immich-text-button border bg-immich-primary dark:bg-immich-dark-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed dark:text-immich-dark-bg dark:border-immich-dark-gray"
 | 
					 | 
				
			||||||
				><span class="px-2">Done</span></button
 | 
					 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
 | 
									Done
 | 
				
			||||||
 | 
								</Button>
 | 
				
			||||||
		</svelte:fragment>
 | 
							</svelte:fragment>
 | 
				
			||||||
	</ControlAppBar>
 | 
						</ControlAppBar>
 | 
				
			||||||
	<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg">
 | 
						<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg">
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
	import BaseModal from '../shared-components/base-modal.svelte';
 | 
						import BaseModal from '../shared-components/base-modal.svelte';
 | 
				
			||||||
	import CircleAvatar from '../shared-components/circle-avatar.svelte';
 | 
						import CircleAvatar from '../shared-components/circle-avatar.svelte';
 | 
				
			||||||
	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
						import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
 | 
						import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
 | 
				
			||||||
	import MenuOption from '../shared-components/context-menu/menu-option.svelte';
 | 
						import MenuOption from '../shared-components/context-menu/menu-option.svelte';
 | 
				
			||||||
	import {
 | 
						import {
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@
 | 
				
			|||||||
	import { fly } from 'svelte/transition';
 | 
						import { fly } from 'svelte/transition';
 | 
				
			||||||
	import Thumbnail from '../assets/thumbnail/thumbnail.svelte';
 | 
						import Thumbnail from '../assets/thumbnail/thumbnail.svelte';
 | 
				
			||||||
	import ControlAppBar from '../shared-components/control-app-bar.svelte';
 | 
						import ControlAppBar from '../shared-components/control-app-bar.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let album: AlbumResponseDto;
 | 
						export let album: AlbumResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,12 +31,14 @@
 | 
				
			|||||||
		</svelte:fragment>
 | 
							</svelte:fragment>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<svelte:fragment slot="trailing">
 | 
							<svelte:fragment slot="trailing">
 | 
				
			||||||
			<button
 | 
								<Button
 | 
				
			||||||
 | 
									size="sm"
 | 
				
			||||||
 | 
									rounded="lg"
 | 
				
			||||||
				disabled={selectedThumbnail == undefined}
 | 
									disabled={selectedThumbnail == undefined}
 | 
				
			||||||
				on:click={() => dispatch('thumbnail-selected', { asset: selectedThumbnail })}
 | 
									on:click={() => dispatch('thumbnail-selected', { asset: selectedThumbnail })}
 | 
				
			||||||
				class="immich-text-button border bg-immich-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
				><span class="px-2">Done</span></button
 | 
					 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
 | 
									Done
 | 
				
			||||||
 | 
								</Button>
 | 
				
			||||||
		</svelte:fragment>
 | 
							</svelte:fragment>
 | 
				
			||||||
	</ControlAppBar>
 | 
						</ControlAppBar>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@
 | 
				
			|||||||
	import ShareCircle from 'svelte-material-icons/ShareCircle.svelte';
 | 
						import ShareCircle from 'svelte-material-icons/ShareCircle.svelte';
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
	import ImmichLogo from '../shared-components/immich-logo.svelte';
 | 
						import ImmichLogo from '../shared-components/immich-logo.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let album: AlbumResponseDto;
 | 
						export let album: AlbumResponseDto;
 | 
				
			||||||
	export let sharedUsersInAlbum: Set<UserResponseDto>;
 | 
						export let sharedUsersInAlbum: Set<UserResponseDto>;
 | 
				
			||||||
@ -117,11 +118,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		{#if selectedUsers.length > 0}
 | 
							{#if selectedUsers.length > 0}
 | 
				
			||||||
			<div class="flex place-content-end p-5 ">
 | 
								<div class="flex place-content-end p-5 ">
 | 
				
			||||||
				<button
 | 
									<Button size="sm" rounded="lg" on:click={() => dispatch('add-user', { selectedUsers })}>
 | 
				
			||||||
					on:click={() => dispatch('add-user', { selectedUsers })}
 | 
										Add
 | 
				
			||||||
					class="text-white bg-immich-primary px-4 py-2 rounded-lg text-sm font-bold transition-colors hover:bg-immich-primary/75"
 | 
									</Button>
 | 
				
			||||||
					>Add</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
	import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
 | 
						import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
 | 
				
			||||||
	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
						import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
 | 
				
			||||||
	import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
 | 
						import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
 | 
						import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
 | 
				
			||||||
	import MenuOption from '../shared-components/context-menu/menu-option.svelte';
 | 
						import MenuOption from '../shared-components/context-menu/menu-option.svelte';
 | 
				
			||||||
	import Star from 'svelte-material-icons/Star.svelte';
 | 
						import Star from 'svelte-material-icons/Star.svelte';
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										71
									
								
								web/src/lib/components/elements/buttons/button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								web/src/lib/components/elements/buttons/button.svelte
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					<script lang="ts" context="module">
 | 
				
			||||||
 | 
						export type Type = 'button' | 'submit' | 'reset';
 | 
				
			||||||
 | 
						export type Color =
 | 
				
			||||||
 | 
							| 'primary'
 | 
				
			||||||
 | 
							| 'secondary'
 | 
				
			||||||
 | 
							| 'transparent-primary'
 | 
				
			||||||
 | 
							| 'light-red'
 | 
				
			||||||
 | 
							| 'red'
 | 
				
			||||||
 | 
							| 'green'
 | 
				
			||||||
 | 
							| 'gray'
 | 
				
			||||||
 | 
							| 'transparent-gray'
 | 
				
			||||||
 | 
							| 'dark-gray';
 | 
				
			||||||
 | 
						export type Size = 'icon' | 'link' | 'sm' | 'base' | 'lg';
 | 
				
			||||||
 | 
						export type Rounded = 'lg' | '3xl' | 'full' | false;
 | 
				
			||||||
 | 
						export type Shadow = 'md' | false;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						export let type: Type = 'button';
 | 
				
			||||||
 | 
						export let color: Color = 'primary';
 | 
				
			||||||
 | 
						export let size: Size = 'base';
 | 
				
			||||||
 | 
						export let rounded: Rounded = '3xl';
 | 
				
			||||||
 | 
						export let shadow: Shadow = 'md';
 | 
				
			||||||
 | 
						export let disabled = false;
 | 
				
			||||||
 | 
						export let fullwidth = false;
 | 
				
			||||||
 | 
						export let border = false;
 | 
				
			||||||
 | 
						export let title: string | undefined = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const colorClasses: Record<Color, string> = {
 | 
				
			||||||
 | 
							primary:
 | 
				
			||||||
 | 
								'bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray enabled:dark:hover:bg-immich-dark-primary/80 enabled:hover:bg-immich-primary/90',
 | 
				
			||||||
 | 
							secondary:
 | 
				
			||||||
 | 
								'bg-gray-500 dark:bg-gray-200 text-white dark:text-immich-dark-gray enabled:hover:bg-gray-500/90 enabled:dark:hover:bg-gray-200/90',
 | 
				
			||||||
 | 
							'transparent-primary':
 | 
				
			||||||
 | 
								'text-gray-500 dark:text-immich-dark-primary enabled:hover:bg-gray-100 enabled:dark:hover:bg-gray-700',
 | 
				
			||||||
 | 
							'light-red': 'bg-[#F9DEDC] text-[#410E0B] enabled:hover:bg-red-50',
 | 
				
			||||||
 | 
							red: 'bg-red-500 text-white enabled:hover:bg-red-400',
 | 
				
			||||||
 | 
							green: 'bg-lime-600 text-white enabled:hover:bg-lime-500',
 | 
				
			||||||
 | 
							gray: 'bg-gray-500 dark:bg-gray-200 enabled:hover:bg-gray-500/75 enabled:dark:hover:bg-gray-200/80 text-white dark:text-immich-dark-gray',
 | 
				
			||||||
 | 
							'transparent-gray':
 | 
				
			||||||
 | 
								'dark:text-immich-dark-fg enabled:hover:bg-immich-primary/5 enabled:hover:text-gray-700 enabled:hover:dark:text-immich-dark-fg enabled:dark:hover:bg-immich-dark-primary/25 ',
 | 
				
			||||||
 | 
							'dark-gray':
 | 
				
			||||||
 | 
								'dark:border-immich-dark-gray dark:bg-gray-500 enabled:dark:hover:bg-immich-dark-primary/50 enabled:hover:bg-immich-primary/10 dark:text-white'
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const sizeClasses: Record<Size, string> = {
 | 
				
			||||||
 | 
							icon: 'p-2.5',
 | 
				
			||||||
 | 
							link: 'p-2 font-medium',
 | 
				
			||||||
 | 
							sm: 'px-4 py-2 text-sm font-medium',
 | 
				
			||||||
 | 
							base: 'px-6 py-3 font-medium',
 | 
				
			||||||
 | 
							lg: 'px-6 py-4 font-semibold'
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button
 | 
				
			||||||
 | 
						{type}
 | 
				
			||||||
 | 
						{disabled}
 | 
				
			||||||
 | 
						{title}
 | 
				
			||||||
 | 
						on:click
 | 
				
			||||||
 | 
						class="inline-flex justify-center items-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[
 | 
				
			||||||
 | 
							color
 | 
				
			||||||
 | 
						]} {sizeClasses[size]}"
 | 
				
			||||||
 | 
						class:rounded-lg={rounded === 'lg'}
 | 
				
			||||||
 | 
						class:rounded-3xl={rounded === '3xl'}
 | 
				
			||||||
 | 
						class:rounded-full={rounded === 'full'}
 | 
				
			||||||
 | 
						class:shadow-md={shadow === 'md'}
 | 
				
			||||||
 | 
						class:w-full={fullwidth}
 | 
				
			||||||
 | 
						class:border
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<slot />
 | 
				
			||||||
 | 
					</button>
 | 
				
			||||||
@ -1,7 +1,4 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * This is the circle icon component.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	import type Icon from 'svelte-material-icons/AbTesting.svelte';
 | 
						import type Icon from 'svelte-material-icons/AbTesting.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let logo: typeof Icon;
 | 
						export let logo: typeof Icon;
 | 
				
			||||||
@ -15,7 +12,7 @@
 | 
				
			|||||||
	{title}
 | 
						{title}
 | 
				
			||||||
	style:backgroundColor
 | 
						style:backgroundColor
 | 
				
			||||||
	style:--immich-icon-button-hover-color={hoverColor}
 | 
						style:--immich-icon-button-hover-color={hoverColor}
 | 
				
			||||||
	class={`immich-circle-icon-button dark:text-immich-dark-fg hover:dark:text-immich-dark-gray rounded-full p-3 flex place-items-center place-content-center transition-all`}
 | 
						class="immich-circle-icon-button dark:text-immich-dark-fg hover:dark:text-immich-dark-gray rounded-full p-3 flex place-items-center place-content-center transition-all"
 | 
				
			||||||
	on:click
 | 
						on:click
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<svelte:component this={logo} {size} />
 | 
						<svelte:component this={logo} {size} />
 | 
				
			||||||
							
								
								
									
										14
									
								
								web/src/lib/components/elements/buttons/icon-button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								web/src/lib/components/elements/buttons/icon-button.svelte
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					<script lang="ts" context="module">
 | 
				
			||||||
 | 
						export type Color = 'transparent-primary' | 'transparent-gray';
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import Button from './button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						export let color: Color = 'transparent-primary';
 | 
				
			||||||
 | 
						export let title: string | undefined = undefined;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<Button size="icon" {color} {title} shadow={false} rounded="full" on:click>
 | 
				
			||||||
 | 
						<slot />
 | 
				
			||||||
 | 
					</Button>
 | 
				
			||||||
							
								
								
									
										13
									
								
								web/src/lib/components/elements/buttons/link-button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/lib/components/elements/buttons/link-button.svelte
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					<script lang="ts" context="module">
 | 
				
			||||||
 | 
						export type Color = 'transparent-primary' | 'transparent-gray';
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import Button from './button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						export let color: Color = 'transparent-gray';
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<Button size="link" {color} shadow={false} rounded="lg" on:click>
 | 
				
			||||||
 | 
						<slot />
 | 
				
			||||||
 | 
					</Button>
 | 
				
			||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
	import { AppRoute } from '$lib/constants';
 | 
						import { AppRoute } from '$lib/constants';
 | 
				
			||||||
	import { api } from '@api';
 | 
						import { api } from '@api';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let error: string;
 | 
						let error: string;
 | 
				
			||||||
	let password = '';
 | 
						let password = '';
 | 
				
			||||||
@ -115,6 +116,6 @@
 | 
				
			|||||||
	{/if}
 | 
						{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="my-5 flex w-full">
 | 
						<div class="my-5 flex w-full">
 | 
				
			||||||
		<button type="submit" class="immich-btn-primary-big">Sign Up</button>
 | 
							<Button type="submit" size="lg" fullwidth>Sign up</Button>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
	import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
 | 
						import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
 | 
				
			||||||
	import FullScreenModal from '../shared-components/full-screen-modal.svelte';
 | 
						import FullScreenModal from '../shared-components/full-screen-modal.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let apiKey: Partial<APIKeyResponseDto>;
 | 
						export let apiKey: Partial<APIKeyResponseDto>;
 | 
				
			||||||
	export let title = 'API Key';
 | 
						export let title = 'API Key';
 | 
				
			||||||
@ -40,17 +41,8 @@
 | 
				
			|||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="flex w-full px-4 gap-4 mt-8">
 | 
								<div class="flex w-full px-4 gap-4 mt-8">
 | 
				
			||||||
				<button
 | 
									<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
 | 
				
			||||||
					type="button"
 | 
									<Button type="submit" fullwidth>{submitText}</Button>
 | 
				
			||||||
					on:click={() => handleCancel()}
 | 
					 | 
				
			||||||
					class="flex-1 transition-colors bg-gray-500 dark:bg-gray-200 hover:bg-gray-500/75 dark:hover:bg-gray-200/80 px-6 py-3 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium"
 | 
					 | 
				
			||||||
					>{cancelText}
 | 
					 | 
				
			||||||
				</button>
 | 
					 | 
				
			||||||
				<button
 | 
					 | 
				
			||||||
					type="submit"
 | 
					 | 
				
			||||||
					class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
					>{submitText}</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</form>
 | 
							</form>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@
 | 
				
			|||||||
		notificationController,
 | 
							notificationController,
 | 
				
			||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let secret = '';
 | 
						export let secret = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,16 +55,8 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="flex w-full px-4 gap-4 mt-8">
 | 
							<div class="flex w-full px-4 gap-4 mt-8">
 | 
				
			||||||
			<button
 | 
								<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button>
 | 
				
			||||||
				on:click={() => handleCopy()}
 | 
								<Button on:click={() => handleDone()} fullwidth>Done</Button>
 | 
				
			||||||
				class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
				>Copy to Clipboard</button
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
			<button
 | 
					 | 
				
			||||||
				on:click={() => handleDone()}
 | 
					 | 
				
			||||||
				class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
				>Done</button
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</FullScreenModal>
 | 
					</FullScreenModal>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { api, UserResponseDto } from '@api';
 | 
						import { api, UserResponseDto } from '@api';
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
	let error: string;
 | 
						let error: string;
 | 
				
			||||||
@ -78,6 +79,6 @@
 | 
				
			|||||||
		<p class="text-immich-primary text-sm">{success}</p>
 | 
							<p class="text-immich-primary text-sm">{success}</p>
 | 
				
			||||||
	{/if}
 | 
						{/if}
 | 
				
			||||||
	<div class="my-5 flex w-full">
 | 
						<div class="my-5 flex w-full">
 | 
				
			||||||
		<button type="submit" class="immich-btn-primary-big">Change Password</button>
 | 
							<Button type="submit" size="lg" fullwidth>Change password</Button>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
		notificationController,
 | 
							notificationController,
 | 
				
			||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let error: string;
 | 
						let error: string;
 | 
				
			||||||
	let success: string;
 | 
						let success: string;
 | 
				
			||||||
@ -140,13 +141,8 @@
 | 
				
			|||||||
		{#if success}
 | 
							{#if success}
 | 
				
			||||||
			<p class="text-immich-primary ml-4 text-sm">{success}</p>
 | 
								<p class="text-immich-primary ml-4 text-sm">{success}</p>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
		<div class="flex w-full">
 | 
							<div class="flex w-full p-4">
 | 
				
			||||||
			<button
 | 
								<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button>
 | 
				
			||||||
				type="submit"
 | 
					 | 
				
			||||||
				class="m-4 bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-6 py-3 text-white dark:text-immich-dark-gray rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
				disabled={isCreatingUser}
 | 
					 | 
				
			||||||
				>Create
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
		notificationController,
 | 
							notificationController,
 | 
				
			||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,16 +113,8 @@
 | 
				
			|||||||
			<p class="text-immich-primary ml-4 text-sm">{success}</p>
 | 
								<p class="text-immich-primary ml-4 text-sm">{success}</p>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
		<div class="flex w-full px-4 gap-4 mt-8">
 | 
							<div class="flex w-full px-4 gap-4 mt-8">
 | 
				
			||||||
			<button
 | 
								<Button color="light-red" fullwidth on:click={resetPassword}>Reset password</Button>
 | 
				
			||||||
				on:click={resetPassword}
 | 
								<Button type="submit" fullwidth>Confirm</Button>
 | 
				
			||||||
				class="flex-1 transition-colors bg-[#F9DEDC] hover:bg-red-50 text-[#410E0B] px-6 py-3 rounded-full w-full font-medium"
 | 
					 | 
				
			||||||
				>Reset password
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
			<button
 | 
					 | 
				
			||||||
				type="submit"
 | 
					 | 
				
			||||||
				class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
				>Confirm
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
	import { api, oauth, OAuthConfigResponseDto } from '@api';
 | 
						import { api, oauth, OAuthConfigResponseDto } from '@api';
 | 
				
			||||||
	import { createEventDispatcher, onMount } from 'svelte';
 | 
						import { createEventDispatcher, onMount } from 'svelte';
 | 
				
			||||||
	import { fade } from 'svelte/transition';
 | 
						import { fade } from 'svelte/transition';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let error: string;
 | 
						let error: string;
 | 
				
			||||||
	let email = '';
 | 
						let email = '';
 | 
				
			||||||
@ -110,22 +111,20 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="my-5 flex w-full">
 | 
							<div class="my-5 flex w-full">
 | 
				
			||||||
			<button
 | 
								<Button type="submit" size="lg" fullwidth disabled={loading || oauthLoading}>
 | 
				
			||||||
				type="submit"
 | 
					 | 
				
			||||||
				class="immich-btn-primary-big inline-flex items-center h-14"
 | 
					 | 
				
			||||||
				disabled={loading || oauthLoading}
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				{#if loading}
 | 
									{#if loading}
 | 
				
			||||||
					<LoadingSpinner />
 | 
										<span class="h-6">
 | 
				
			||||||
 | 
											<LoadingSpinner />
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
				{:else}
 | 
									{:else}
 | 
				
			||||||
					Login
 | 
										Login
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
			</button>
 | 
								</Button>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if authConfig.enabled}
 | 
					{#if !authConfig.enabled}
 | 
				
			||||||
	{#if authConfig.passwordLoginEnabled}
 | 
						{#if authConfig.passwordLoginEnabled}
 | 
				
			||||||
		<div class="inline-flex items-center justify-center w-full">
 | 
							<div class="inline-flex items-center justify-center w-full">
 | 
				
			||||||
			<hr class="w-3/4 h-px my-4 bg-gray-200 border-0 dark:bg-gray-600" />
 | 
								<hr class="w-3/4 h-px my-4 bg-gray-200 border-0 dark:bg-gray-600" />
 | 
				
			||||||
@ -141,19 +140,21 @@
 | 
				
			|||||||
			<p class="text-red-400" transition:fade>{oauthError}</p>
 | 
								<p class="text-red-400" transition:fade>{oauthError}</p>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
		<a href={authConfig.url} class="flex w-full">
 | 
							<a href={authConfig.url} class="flex w-full">
 | 
				
			||||||
			<button
 | 
								<Button
 | 
				
			||||||
				type="button"
 | 
									type="button"
 | 
				
			||||||
				disabled={loading || oauthLoading}
 | 
									disabled={loading || oauthLoading}
 | 
				
			||||||
				class={'inline-flex items-center h-14 ' + authConfig.passwordLoginEnabled
 | 
									size="lg"
 | 
				
			||||||
					? 'immich-btn-secondary-big'
 | 
									fullwidth
 | 
				
			||||||
					: 'immich-btn-primary-big'}
 | 
									color={authConfig.passwordLoginEnabled ? 'secondary' : 'primary'}
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
				{#if oauthLoading}
 | 
									{#if oauthLoading}
 | 
				
			||||||
					<LoadingSpinner />
 | 
										<span class="h-6">
 | 
				
			||||||
 | 
											<LoadingSpinner />
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
				{:else}
 | 
									{:else}
 | 
				
			||||||
					{authConfig.buttonText || 'Login with OAuth'}
 | 
										{authConfig.buttonText || 'Login with OAuth'}
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
			</button>
 | 
								</Button>
 | 
				
			||||||
		</a>
 | 
							</a>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
	import { api, AssetResponseDto, SharedLinkResponseDto } from '@api';
 | 
						import { api, AssetResponseDto, SharedLinkResponseDto } from '@api';
 | 
				
			||||||
	import ControlAppBar from '../shared-components/control-app-bar.svelte';
 | 
						import ControlAppBar from '../shared-components/control-app-bar.svelte';
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
 | 
						import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
 | 
				
			||||||
	import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte';
 | 
						import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte';
 | 
				
			||||||
	import { openFileUploadDialog } from '$lib/utils/file-uploader';
 | 
						import { openFileUploadDialog } from '$lib/utils/file-uploader';
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
	import Close from 'svelte-material-icons/Close.svelte';
 | 
						import Close from 'svelte-material-icons/Close.svelte';
 | 
				
			||||||
	import { createEventDispatcher, onMount, onDestroy } from 'svelte';
 | 
						import { createEventDispatcher, onMount, onDestroy } from 'svelte';
 | 
				
			||||||
	import { browser } from '$app/environment';
 | 
						import { browser } from '$app/environment';
 | 
				
			||||||
	import CircleIconButton from './circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import { clickOutside } from '$lib/utils/click-outside';
 | 
						import { clickOutside } from '$lib/utils/click-outside';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
	import FullScreenModal from './full-screen-modal.svelte';
 | 
						import FullScreenModal from './full-screen-modal.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let title = 'Confirm';
 | 
						export let title = 'Confirm';
 | 
				
			||||||
	export let prompt = 'Are you sure you want to do this?';
 | 
						export let prompt = 'Are you sure you want to do this?';
 | 
				
			||||||
@ -29,18 +30,8 @@
 | 
				
			|||||||
			</slot>
 | 
								</slot>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="flex w-full px-4 gap-4 mt-4">
 | 
								<div class="flex w-full px-4 gap-4 mt-4">
 | 
				
			||||||
				<button
 | 
									<Button fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
 | 
				
			||||||
					on:click={() => handleCancel()}
 | 
									<Button color="red" fullwidth on:click={() => handleConfirm()}>{confirmText}</Button>
 | 
				
			||||||
					class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					{cancelText}
 | 
					 | 
				
			||||||
				</button>
 | 
					 | 
				
			||||||
				<button
 | 
					 | 
				
			||||||
					on:click={() => handleConfirm()}
 | 
					 | 
				
			||||||
					class="flex-1 transition-colors bg-red-500 hover:bg-red-400 px-6 py-3 text-white rounded-full w-full font-medium"
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					{confirmText}
 | 
					 | 
				
			||||||
				</button>
 | 
					 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	import { createEventDispatcher, onDestroy, onMount } from 'svelte';
 | 
						import { createEventDispatcher, onDestroy, onMount } from 'svelte';
 | 
				
			||||||
	import Close from 'svelte-material-icons/Close.svelte';
 | 
						import Close from 'svelte-material-icons/Close.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import { fly } from 'svelte/transition';
 | 
						import { fly } from 'svelte/transition';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let showBackButton = true;
 | 
						export let showBackButton = true;
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@
 | 
				
			|||||||
		SettingInputFieldType
 | 
							SettingInputFieldType
 | 
				
			||||||
	} from '$lib/components/admin-page/settings/setting-input-field.svelte';
 | 
						} from '$lib/components/admin-page/settings/setting-input-field.svelte';
 | 
				
			||||||
	import { handleError } from '$lib/utils/handle-error';
 | 
						import { handleError } from '$lib/utils/handle-error';
 | 
				
			||||||
 | 
						import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let shareType: SharedLinkType;
 | 
						export let shareType: SharedLinkType;
 | 
				
			||||||
	export let sharedAssets: AssetResponseDto[] = [];
 | 
						export let sharedAssets: AssetResponseDto[] = [];
 | 
				
			||||||
@ -243,21 +244,11 @@
 | 
				
			|||||||
		{#if !isShowSharedLink}
 | 
							{#if !isShowSharedLink}
 | 
				
			||||||
			{#if editingLink}
 | 
								{#if editingLink}
 | 
				
			||||||
				<div class="flex justify-end">
 | 
									<div class="flex justify-end">
 | 
				
			||||||
					<button
 | 
										<Button size="sm" rounded="lg" on:click={handleEditLink}>Confirm</Button>
 | 
				
			||||||
						on:click={handleEditLink}
 | 
					 | 
				
			||||||
						class="text-white dark:text-black bg-immich-primary px-4 py-2 rounded-lg text-sm transition-colors hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:hover:bg-immich-dark-primary/75"
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
						Confirm
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			{:else}
 | 
								{:else}
 | 
				
			||||||
				<div class="flex justify-end">
 | 
									<div class="flex justify-end">
 | 
				
			||||||
					<button
 | 
										<Button size="sm" rounded="lg" on:click={handleCreateSharedLink}>Create link</Button>
 | 
				
			||||||
						on:click={handleCreateSharedLink}
 | 
					 | 
				
			||||||
						class="text-white dark:text-black bg-immich-primary px-4 py-2 rounded-lg text-sm transition-colors hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:hover:bg-immich-dark-primary/75"
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
						Create Link
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			{/if}
 | 
								{/if}
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
@ -266,11 +257,7 @@
 | 
				
			|||||||
			<div class="flex w-full gap-4">
 | 
								<div class="flex w-full gap-4">
 | 
				
			||||||
				<input class="immich-form-input w-full" bind:value={sharedLink} disabled />
 | 
									<input class="immich-form-input w-full" bind:value={sharedLink} disabled />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<button
 | 
									<Button on:click={() => handleCopy()}>Copy</Button>
 | 
				
			||||||
					on:click={() => handleCopy()}
 | 
					 | 
				
			||||||
					class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-2 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
					>Copy</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</section>
 | 
						</section>
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@
 | 
				
			|||||||
	import Cog from 'svelte-material-icons/Cog.svelte';
 | 
						import Cog from 'svelte-material-icons/Cog.svelte';
 | 
				
			||||||
	import Logout from 'svelte-material-icons/Logout.svelte';
 | 
						import Logout from 'svelte-material-icons/Logout.svelte';
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
 | 
						import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,16 +60,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p>
 | 
							<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class=" mt-4 flex place-items-center place-content-center">
 | 
							<div class="mt-4">
 | 
				
			||||||
			<button
 | 
								<Button
 | 
				
			||||||
				class="flex border rounded-3xl px-6 py-2 hover:bg-immich-primary/10 dark:border-immich-dark-gray dark:bg-gray-500 dark:hover:bg-immich-dark-primary/50 dark:text-white font-medium place-items-center place-content-center gap-2"
 | 
									color="dark-gray"
 | 
				
			||||||
 | 
									size="sm"
 | 
				
			||||||
 | 
									shadow={false}
 | 
				
			||||||
 | 
									border
 | 
				
			||||||
				on:click={() => {
 | 
									on:click={() => {
 | 
				
			||||||
					goto('/user-settings');
 | 
										goto('/user-settings');
 | 
				
			||||||
					dispatch('close');
 | 
										dispatch('close');
 | 
				
			||||||
				}}
 | 
									}}
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
				<span><Cog size="18" /></span>Account Settings</button
 | 
									<div class="flex gap-2 place-items-center place-content-center px-2">
 | 
				
			||||||
			>
 | 
										<Cog size="18" />
 | 
				
			||||||
 | 
										Account Settings
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</Button>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@
 | 
				
			|||||||
	import AccountInfoPanel from './account-info-panel.svelte';
 | 
						import AccountInfoPanel from './account-info-panel.svelte';
 | 
				
			||||||
	import ImmichLogo from '../immich-logo.svelte';
 | 
						import ImmichLogo from '../immich-logo.svelte';
 | 
				
			||||||
	import SearchBar from '../search-bar/search-bar.svelte';
 | 
						import SearchBar from '../search-bar/search-bar.svelte';
 | 
				
			||||||
 | 
						import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
	export let shouldShowUploadButton = true;
 | 
						export let shouldShowUploadButton = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -61,24 +62,27 @@
 | 
				
			|||||||
				<ThemeButton />
 | 
									<ThemeButton />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				{#if !$page.url.pathname.includes('/admin') && shouldShowUploadButton}
 | 
									{#if !$page.url.pathname.includes('/admin') && shouldShowUploadButton}
 | 
				
			||||||
					<button
 | 
										<div in:fly={{ x: 50, duration: 250 }}>
 | 
				
			||||||
						in:fly={{ x: 50, duration: 250 }}
 | 
											<LinkButton on:click={() => dispatch('uploadClicked')}>
 | 
				
			||||||
						on:click={() => dispatch('uploadClicked')}
 | 
												<div class="flex gap-2">
 | 
				
			||||||
						class="immich-text-button dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
 | 
													<TrayArrowUp size="20" />
 | 
				
			||||||
					>
 | 
													<span>Upload</span>
 | 
				
			||||||
						<TrayArrowUp size="20" />
 | 
												</div>
 | 
				
			||||||
						<span> Upload </span>
 | 
											</LinkButton>
 | 
				
			||||||
					</button>
 | 
										</div>
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				{#if user.isAdmin}
 | 
									{#if user.isAdmin}
 | 
				
			||||||
					<a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}>
 | 
										<a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}>
 | 
				
			||||||
						<button
 | 
											<LinkButton>
 | 
				
			||||||
							class={`flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5  dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg p-2 rounded-lg font-medium ${
 | 
												<span
 | 
				
			||||||
								$page.url.pathname.includes('/admin') &&
 | 
													class={$page.url.pathname.includes('/admin')
 | 
				
			||||||
								'text-immich-primary dark:immich-dark-primary underline'
 | 
														? 'text-immich-primary dark:text-immich-dark-primary underline'
 | 
				
			||||||
							}`}>Administration</button
 | 
														: ''}
 | 
				
			||||||
						>
 | 
												>
 | 
				
			||||||
 | 
													Administration
 | 
				
			||||||
 | 
												</span>
 | 
				
			||||||
 | 
											</LinkButton>
 | 
				
			||||||
					</a>
 | 
										</a>
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { browser } from '$app/environment';
 | 
						import { browser } from '$app/environment';
 | 
				
			||||||
	import { colorTheme } from '$lib/stores/preferences.store';
 | 
						import { colorTheme } from '$lib/stores/preferences.store';
 | 
				
			||||||
 | 
						import IconButton from '../elements/buttons/icon-button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const toggleTheme = () => {
 | 
						const toggleTheme = () => {
 | 
				
			||||||
		$colorTheme = $colorTheme === 'dark' ? 'light' : 'dark';
 | 
							$colorTheme = $colorTheme === 'dark' ? 'light' : 'dark';
 | 
				
			||||||
@ -17,11 +18,7 @@
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<button
 | 
					<IconButton on:click={toggleTheme} title="Toggle theme">
 | 
				
			||||||
	on:click={toggleTheme}
 | 
					 | 
				
			||||||
	type="button"
 | 
					 | 
				
			||||||
	class="text-gray-500 dark:text-immich-dark-primary hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none rounded-full p-2.5"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	{#if $colorTheme === 'light'}
 | 
						{#if $colorTheme === 'light'}
 | 
				
			||||||
		<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
 | 
							<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
			><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /></svg
 | 
								><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /></svg
 | 
				
			||||||
@ -35,4 +32,4 @@
 | 
				
			|||||||
			/></svg
 | 
								/></svg
 | 
				
			||||||
		>
 | 
							>
 | 
				
			||||||
	{/if}
 | 
						{/if}
 | 
				
			||||||
</button>
 | 
					</IconButton>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
	import { onMount } from 'svelte';
 | 
						import { onMount } from 'svelte';
 | 
				
			||||||
	import FullScreenModal from './full-screen-modal.svelte';
 | 
						import FullScreenModal from './full-screen-modal.svelte';
 | 
				
			||||||
	import type { ServerVersionReponseDto } from '@api';
 | 
						import type { ServerVersionReponseDto } from '@api';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let serverVersion: ServerVersionReponseDto;
 | 
						export let serverVersion: ServerVersionReponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,10 +73,7 @@
 | 
				
			|||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="text-right mt-8">
 | 
								<div class="text-right mt-8">
 | 
				
			||||||
				<button
 | 
									<Button fullwidth on:click={onAcknowledge}>Acknowledge</Button>
 | 
				
			||||||
					class="transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
					on:click={onAcknowledge}>Acknowledge</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</FullScreenModal>
 | 
						</FullScreenModal>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
	import ContentCopy from 'svelte-material-icons/ContentCopy.svelte';
 | 
						import ContentCopy from 'svelte-material-icons/ContentCopy.svelte';
 | 
				
			||||||
	import CircleEditOutline from 'svelte-material-icons/CircleEditOutline.svelte';
 | 
						import CircleEditOutline from 'svelte-material-icons/CircleEditOutline.svelte';
 | 
				
			||||||
	import * as luxon from 'luxon';
 | 
						import * as luxon from 'luxon';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
						import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@
 | 
				
			|||||||
	import SettingInputField, {
 | 
						import SettingInputField, {
 | 
				
			||||||
		SettingInputFieldType
 | 
							SettingInputFieldType
 | 
				
			||||||
	} from '../admin-page/settings/setting-input-field.svelte';
 | 
						} from '../admin-page/settings/setting-input-field.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let password = '';
 | 
						let password = '';
 | 
				
			||||||
	let newPassword = '';
 | 
						let newPassword = '';
 | 
				
			||||||
@ -64,13 +65,12 @@
 | 
				
			|||||||
				/>
 | 
									/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<div class="flex justify-end">
 | 
									<div class="flex justify-end">
 | 
				
			||||||
					<button
 | 
										<Button
 | 
				
			||||||
						type="submit"
 | 
											type="submit"
 | 
				
			||||||
 | 
											size="sm"
 | 
				
			||||||
						disabled={!(password && newPassword && newPassword === confirmPassword)}
 | 
											disabled={!(password && newPassword && newPassword === confirmPassword)}
 | 
				
			||||||
						on:click={() => handleChangePassword()}
 | 
											on:click={() => handleChangePassword()}>Save</Button
 | 
				
			||||||
						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
										>
 | 
				
			||||||
						>Save
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</form>
 | 
							</form>
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
		notificationController,
 | 
							notificationController,
 | 
				
			||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -67,17 +68,10 @@
 | 
				
			|||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			{:else if config.enabled}
 | 
								{:else if config.enabled}
 | 
				
			||||||
				{#if user.oauthId}
 | 
									{#if user.oauthId}
 | 
				
			||||||
					<button
 | 
										<Button size="sm" on:click={() => handleUnlink()}>Unlink Oauth</Button>
 | 
				
			||||||
						on:click={() => handleUnlink()}
 | 
					 | 
				
			||||||
						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
						>Unlink OAuth
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				{:else}
 | 
									{:else}
 | 
				
			||||||
					<a href={config.url}>
 | 
										<a href={config.url}>
 | 
				
			||||||
						<button
 | 
											<Button size="sm" on:click={() => handleUnlink()}>Link to OAuth</Button>
 | 
				
			||||||
							class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
							>Link to OAuth</button
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
					</a>
 | 
										</a>
 | 
				
			||||||
				{/if}
 | 
									{/if}
 | 
				
			||||||
			{/if}
 | 
								{/if}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@
 | 
				
			|||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
	import { locale } from '$lib/stores/preferences.store';
 | 
						import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let keys: APIKeyResponseDto[] = [];
 | 
						let keys: APIKeyResponseDto[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,11 +125,7 @@
 | 
				
			|||||||
<section class="my-4">
 | 
					<section class="my-4">
 | 
				
			||||||
	<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
 | 
						<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
 | 
				
			||||||
		<div class="flex justify-end mb-2">
 | 
							<div class="flex justify-end mb-2">
 | 
				
			||||||
			<button
 | 
								<Button size="sm" on:click={() => (newKey = { name: 'API Key' })}>New API Key</Button>
 | 
				
			||||||
				on:click={() => (newKey = { name: 'API Key' })}
 | 
					 | 
				
			||||||
				class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
				>New API Key
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{#if keys.length > 0}
 | 
							{#if keys.length > 0}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
	import SettingInputField, {
 | 
						import SettingInputField, {
 | 
				
			||||||
		SettingInputFieldType
 | 
							SettingInputFieldType
 | 
				
			||||||
	} from '../admin-page/settings/setting-input-field.svelte';
 | 
						} from '../admin-page/settings/setting-input-field.svelte';
 | 
				
			||||||
 | 
						import Button from '../elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let user: UserResponseDto;
 | 
						export let user: UserResponseDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,12 +66,7 @@
 | 
				
			|||||||
				/>
 | 
									/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<div class="flex justify-end">
 | 
									<div class="flex justify-end">
 | 
				
			||||||
					<button
 | 
										<Button type="submit" size="sm" on:click={() => handleSaveProfile()}>Save</Button>
 | 
				
			||||||
						type="submit"
 | 
					 | 
				
			||||||
						on:click={() => handleSaveProfile()}
 | 
					 | 
				
			||||||
						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
 | 
					 | 
				
			||||||
						>Save
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</form>
 | 
							</form>
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
	import { useAlbums } from './albums.bloc';
 | 
						import { useAlbums } from './albums.bloc';
 | 
				
			||||||
	import empty1Url from '$lib/assets/empty-1.svg';
 | 
						import empty1Url from '$lib/assets/empty-1.svg';
 | 
				
			||||||
	import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
						import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
				
			||||||
 | 
						import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let data: PageData;
 | 
						export let data: PageData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,15 +33,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<UserPageLayout user={data.user} title={data.meta.title}>
 | 
					<UserPageLayout user={data.user} title={data.meta.title}>
 | 
				
			||||||
	<div slot="buttons">
 | 
						<div slot="buttons">
 | 
				
			||||||
		<button
 | 
							<LinkButton on:click={handleCreateAlbum}>
 | 
				
			||||||
			on:click={handleCreateAlbum}
 | 
								<div class="flex place-items-center gap-2 text-sm">
 | 
				
			||||||
			class="immich-text-button text-sm dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<span>
 | 
					 | 
				
			||||||
				<PlusBoxOutline size="18" />
 | 
									<PlusBoxOutline size="18" />
 | 
				
			||||||
			</span>
 | 
									Create album
 | 
				
			||||||
			<p>Create album</p>
 | 
								</div>
 | 
				
			||||||
		</button>
 | 
							</LinkButton>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<!-- Album Card -->
 | 
						<!-- Album Card -->
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import CircleIconButton from '$lib/components/shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
 | 
						import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
 | 
				
			||||||
	import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte';
 | 
						import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte';
 | 
				
			||||||
	import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
 | 
						import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
	import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
 | 
						import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
 | 
				
			||||||
	import AlbumSelectionModal from '$lib/components/shared-components/album-selection-modal.svelte';
 | 
						import AlbumSelectionModal from '$lib/components/shared-components/album-selection-modal.svelte';
 | 
				
			||||||
	import CircleIconButton from '$lib/components/shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
	import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte';
 | 
						import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte';
 | 
				
			||||||
	import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
 | 
						import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
 | 
				
			||||||
	import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
 | 
						import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
	} from '$lib/components/shared-components/notification/notification';
 | 
						} from '$lib/components/shared-components/notification/notification';
 | 
				
			||||||
	import empty2Url from '$lib/assets/empty-2.svg';
 | 
						import empty2Url from '$lib/assets/empty-2.svg';
 | 
				
			||||||
	import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
						import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
				
			||||||
 | 
						import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let data: PageData;
 | 
						export let data: PageData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,25 +35,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<UserPageLayout user={data.user} title={data.meta.title}>
 | 
					<UserPageLayout user={data.user} title={data.meta.title}>
 | 
				
			||||||
	<div class="flex" slot="buttons">
 | 
						<div class="flex" slot="buttons">
 | 
				
			||||||
		<button
 | 
							<LinkButton on:click={createSharedAlbum}>
 | 
				
			||||||
			on:click={createSharedAlbum}
 | 
								<div class="flex place-items-center gap-1 text-sm">
 | 
				
			||||||
			class="flex place-items-center gap-1 text-sm hover:bg-immich-primary/5 p-2 rounded-lg font-medium hover:text-gray-700 dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<span>
 | 
					 | 
				
			||||||
				<PlusBoxOutline size="18" />
 | 
									<PlusBoxOutline size="18" />
 | 
				
			||||||
			</span>
 | 
									Create shared album
 | 
				
			||||||
			<p>Create shared album</p>
 | 
								</div>
 | 
				
			||||||
		</button>
 | 
							</LinkButton>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<button
 | 
							<LinkButton on:click={() => goto('/sharing/sharedlinks')}>
 | 
				
			||||||
			on:click={() => goto('/sharing/sharedlinks')}
 | 
								<div class="flex place-items-center gap-1 text-sm">
 | 
				
			||||||
			class="flex place-items-center gap-1 text-sm hover:bg-immich-primary/5 p-2 rounded-lg font-medium hover:text-gray-700 dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<span>
 | 
					 | 
				
			||||||
				<Link size="18" />
 | 
									<Link size="18" />
 | 
				
			||||||
			</span>
 | 
									Shared links
 | 
				
			||||||
			<p>Shared links</p>
 | 
								</div>
 | 
				
			||||||
		</button>
 | 
							</LinkButton>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<section>
 | 
						<section>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
 | 
						import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
	import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
 | 
						import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,10 +14,8 @@
 | 
				
			|||||||
		>
 | 
							>
 | 
				
			||||||
			Welcome to IMMICH Web
 | 
								Welcome to IMMICH Web
 | 
				
			||||||
		</h1>
 | 
							</h1>
 | 
				
			||||||
		<button
 | 
							<Button size="lg" rounded="lg" on:click={() => goto('/auth/register')}>
 | 
				
			||||||
			class="border px-4 py-4 rounded-md bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray dark:border-immich-dark-gray hover:bg-immich-primary/75 text-white font-bold w-[200px]"
 | 
								<span class="font-bold px-2">Getting Started</span>
 | 
				
			||||||
			on:click={() => goto('/auth/register')}
 | 
							</Button>
 | 
				
			||||||
			>Getting Started
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</section>
 | 
					</section>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
	import RestoreDialogue from '$lib/components/admin-page/restore-dialoge.svelte';
 | 
						import RestoreDialogue from '$lib/components/admin-page/restore-dialoge.svelte';
 | 
				
			||||||
	import { page } from '$app/stores';
 | 
						import { page } from '$app/stores';
 | 
				
			||||||
	import { locale } from '$lib/stores/preferences.store';
 | 
						import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
 | 
						import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let allUsers: UserResponseDto[] = [];
 | 
						let allUsers: UserResponseDto[] = [];
 | 
				
			||||||
	let shouldShowEditUserForm = false;
 | 
						let shouldShowEditUserForm = false;
 | 
				
			||||||
@ -151,12 +152,8 @@
 | 
				
			|||||||
					Please inform the user, and they will need to change the password at the next log-on.
 | 
										Please inform the user, and they will need to change the password at the next log-on.
 | 
				
			||||||
				</p>
 | 
									</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				<div class="flex w-full">
 | 
									<div class="flex w-full mt-6">
 | 
				
			||||||
					<button
 | 
										<Button fullwidth on:click={() => (shouldShowInfoPanel = false)}>Done</Button>
 | 
				
			||||||
						on:click={() => (shouldShowInfoPanel = false)}
 | 
					 | 
				
			||||||
						class="mt-6 bg-immich-primary hover:bg-immich-primary/75 px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
 | 
					 | 
				
			||||||
						>Done
 | 
					 | 
				
			||||||
					</button>
 | 
					 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</FullScreenModal>
 | 
							</FullScreenModal>
 | 
				
			||||||
@ -221,7 +218,5 @@
 | 
				
			|||||||
		</tbody>
 | 
							</tbody>
 | 
				
			||||||
	</table>
 | 
						</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<button on:click={() => (shouldShowCreateUserForm = true)} class="immich-btn-primary"
 | 
						<Button size="sm" on:click={() => (shouldShowCreateUserForm = true)}>Create user</Button>
 | 
				
			||||||
		>Create user</button
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
</section>
 | 
					</section>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user