mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 09:59:00 -07:00
chore(web): sort tailwindcss class automatically (#3330)
This commit is contained in:
parent
f28fc8fa5c
commit
7316ad5a72
82
web/package-lock.json
generated
82
web/package-lock.json
generated
@ -53,6 +53,7 @@
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^2.8.4",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"prettier-plugin-tailwindcss": "^0.4.1",
|
||||
"svelte": "^4.0.5",
|
||||
"svelte-check": "^3.4.3",
|
||||
"svelte-jester": "^2.3.2",
|
||||
@ -10146,6 +10147,80 @@
|
||||
"svelte": "^3.2.0 || ^4.0.0-next.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz",
|
||||
"integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ianvs/prettier-plugin-sort-imports": "*",
|
||||
"@prettier/plugin-pug": "*",
|
||||
"@shopify/prettier-plugin-liquid": "*",
|
||||
"@shufo/prettier-plugin-blade": "*",
|
||||
"@trivago/prettier-plugin-sort-imports": "*",
|
||||
"prettier": "^2.2 || ^3.0",
|
||||
"prettier-plugin-astro": "*",
|
||||
"prettier-plugin-css-order": "*",
|
||||
"prettier-plugin-import-sort": "*",
|
||||
"prettier-plugin-jsdoc": "*",
|
||||
"prettier-plugin-marko": "*",
|
||||
"prettier-plugin-organize-attributes": "*",
|
||||
"prettier-plugin-organize-imports": "*",
|
||||
"prettier-plugin-style-order": "*",
|
||||
"prettier-plugin-svelte": "*",
|
||||
"prettier-plugin-twig-melody": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ianvs/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"@prettier/plugin-pug": {
|
||||
"optional": true
|
||||
},
|
||||
"@shopify/prettier-plugin-liquid": {
|
||||
"optional": true
|
||||
},
|
||||
"@shufo/prettier-plugin-blade": {
|
||||
"optional": true
|
||||
},
|
||||
"@trivago/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-astro": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-css-order": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-import-sort": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-jsdoc": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-marko": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-attributes": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-style-order": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-svelte": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-twig-melody": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-format": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
|
||||
@ -19248,6 +19323,13 @@
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"prettier-plugin-tailwindcss": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz",
|
||||
"integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
|
||||
|
@ -48,6 +48,7 @@
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^2.8.4",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"prettier-plugin-tailwindcss": "^0.4.1",
|
||||
"svelte": "^4.0.5",
|
||||
"svelte-check": "^3.4.3",
|
||||
"svelte-jester": "^2.3.2",
|
||||
|
@ -56,7 +56,7 @@ input:focus-visible {
|
||||
|
||||
@layer utilities {
|
||||
.immich-form-input {
|
||||
@apply bg-slate-200 p-4 rounded-xl focus:border-immich-primary text-sm dark:bg-gray-600 dark:text-immich-dark-fg disabled:bg-gray-400 dark:disabled:bg-gray-800 disabled:cursor-not-allowed disabled:text-gray-200;
|
||||
@apply rounded-xl bg-slate-200 p-4 text-sm focus:border-immich-primary disabled:cursor-not-allowed disabled:bg-gray-400 disabled:text-gray-200 dark:bg-gray-600 dark:text-immich-dark-fg dark:disabled:bg-gray-800;
|
||||
}
|
||||
|
||||
.immich-form-label {
|
||||
|
@ -12,7 +12,7 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="h-full w-full py-2 flex gap-2 flex-col place-items-center place-content-center px-8 text-gray-600 transition-colors hover:bg-immich-primary hover:text-white dark:text-gray-200 dark:hover:bg-immich-dark-primary text-xs dark:hover:text-black {colorClasses[
|
||||
class="flex h-full w-full flex-col place-content-center place-items-center gap-2 px-8 py-2 text-xs text-gray-600 transition-colors hover:bg-immich-primary hover:text-white dark:text-gray-200 dark:hover:bg-immich-dark-primary dark:hover:text-black {colorClasses[
|
||||
color
|
||||
]}"
|
||||
on:click
|
||||
|
@ -11,6 +11,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="w-full text-center text-sm p-2 {colorClasses[color]}">
|
||||
<div class="w-full p-2 text-center text-sm {colorClasses[color]}">
|
||||
<slot />
|
||||
</div>
|
||||
|
@ -34,9 +34,9 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex sm:flex-row flex-col bg-gray-100 dark:bg-immich-dark-gray rounded-2xl sm:rounded-[35px] overflow-hidden"
|
||||
class="flex flex-col overflow-hidden rounded-2xl bg-gray-100 dark:bg-immich-dark-gray sm:flex-row sm:rounded-[35px]"
|
||||
>
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex w-full flex-col">
|
||||
{#if queueStatus.isPaused}
|
||||
<JobTileStatus color="warning">Paused</JobTileStatus>
|
||||
{:else if queueStatus.isActive}
|
||||
@ -44,8 +44,8 @@
|
||||
{/if}
|
||||
<div class="flex flex-col gap-2 p-5 sm:p-7 md:p-9">
|
||||
<div class="flex items-center gap-4 text-xl font-semibold text-immich-primary dark:text-immich-dark-primary">
|
||||
<span class="flex gap-2 items-center">
|
||||
<svelte:component this={icon} size="1.25em" class="shrink-0 hidden sm:block" />
|
||||
<span class="flex items-center gap-2">
|
||||
<svelte:component this={icon} size="1.25em" class="hidden shrink-0 sm:block" />
|
||||
{title.toUpperCase()}
|
||||
</span>
|
||||
<div class="flex gap-2">
|
||||
@ -63,7 +63,7 @@
|
||||
</div>
|
||||
|
||||
{#if subtitle}
|
||||
<div class="text-sm dark:text-white whitespace-pre-line">{subtitle}</div>
|
||||
<div class="whitespace-pre-line text-sm dark:text-white">{subtitle}</div>
|
||||
{/if}
|
||||
|
||||
{#if slots?.description}
|
||||
@ -72,9 +72,9 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex w-full max-w-md mt-2 flex-col sm:flex-row">
|
||||
<div class="mt-2 flex w-full max-w-md flex-col sm:flex-row">
|
||||
<div
|
||||
class="{commonClasses} bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray rounded-t-lg sm:rounded-l-lg sm:rounded-r-none"
|
||||
class="{commonClasses} rounded-t-lg bg-immich-primary text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray sm:rounded-l-lg sm:rounded-r-none"
|
||||
>
|
||||
<p>Active</p>
|
||||
<p class="text-2xl">
|
||||
@ -83,7 +83,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="{commonClasses} bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray rounded-b-lg sm:rounded-r-lg sm:rounded-l-none flex-row-reverse"
|
||||
class="{commonClasses} flex-row-reverse rounded-b-lg bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray sm:rounded-l-none sm:rounded-r-lg"
|
||||
>
|
||||
<p class="text-2xl">
|
||||
{waitingCount.toLocaleString($locale)}
|
||||
@ -93,7 +93,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex sm:flex-col flex-row sm:w-32 w-full overflow-hidden">
|
||||
<div class="flex w-full flex-row overflow-hidden sm:w-32 sm:flex-col">
|
||||
{#if !isIdle}
|
||||
{#if waitingCount > 0}
|
||||
<JobTileButton color="gray" on:click={() => dispatch('command', { command: JobCommand.Empty, force: false })}>
|
||||
|
@ -29,20 +29,20 @@
|
||||
<div>
|
||||
<p class="text-sm dark:text-immich-dark-fg">TOTAL USAGE</p>
|
||||
|
||||
<div class="mt-5 justify-between lg:flex hidden">
|
||||
<div class="mt-5 hidden justify-between lg:flex">
|
||||
<StatsCard logo={CameraIris} title="PHOTOS" value={stats.photos} />
|
||||
<StatsCard logo={PlayCircle} title="VIDEOS" value={stats.videos} />
|
||||
<StatsCard logo={Memory} title="STORAGE" value={statsUsage} unit={statsUsageUnit} />
|
||||
</div>
|
||||
<div class="mt-5 lg:hidden flex">
|
||||
<div class="bg-immich-gray dark:bg-immich-dark-gray rounded-3xl p-5 flex flex-col justify-between">
|
||||
<div class="mt-5 flex lg:hidden">
|
||||
<div class="flex flex-col justify-between rounded-3xl bg-immich-gray p-5 dark:bg-immich-dark-gray">
|
||||
<div class="flex flex-wrap gap-x-12">
|
||||
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
|
||||
<CameraIris size="25" />
|
||||
<p>PHOTOS</p>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono font-semibold text-2xl">
|
||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.photos)}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{stats.photos}</span
|
||||
>
|
||||
@ -54,7 +54,7 @@
|
||||
<p>VIDEOS</p>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono font-semibold text-2xl">
|
||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.videos)}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{stats.videos}</span
|
||||
>
|
||||
@ -66,11 +66,11 @@
|
||||
<p>STORAGE</p>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono font-semibold text-2xl flex">
|
||||
<div class="relative flex text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(statsUsage)}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{statsUsage}</span
|
||||
>
|
||||
<span class="text-center my-auto ml-2 text-base font-light text-gray-400">{statsUsageUnit}</span>
|
||||
<span class="my-auto ml-2 text-center text-base font-light text-gray-400">{statsUsageUnit}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -79,28 +79,28 @@
|
||||
|
||||
<div>
|
||||
<p class="text-sm dark:text-immich-dark-fg">USER USAGE DETAIL</p>
|
||||
<table class="text-left w-full mt-5">
|
||||
<table class="mt-5 w-full text-left">
|
||||
<thead
|
||||
class="border rounded-md mb-4 bg-gray-50 dark:bg-immich-dark-gray dark:border-immich-dark-gray flex text-immich-primary dark:text-immich-dark-primary w-full h-12"
|
||||
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary"
|
||||
>
|
||||
<tr class="flex w-full place-items-center">
|
||||
<th class="text-center w-1/4 font-medium text-sm">User</th>
|
||||
<th class="text-center w-1/4 font-medium text-sm">Photos</th>
|
||||
<th class="text-center w-1/4 font-medium text-sm">Videos</th>
|
||||
<th class="text-center w-1/4 font-medium text-sm">Size</th>
|
||||
<th class="w-1/4 text-center text-sm font-medium">User</th>
|
||||
<th class="w-1/4 text-center text-sm font-medium">Photos</th>
|
||||
<th class="w-1/4 text-center text-sm font-medium">Videos</th>
|
||||
<th class="w-1/4 text-center text-sm font-medium">Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="overflow-y-auto rounded-md w-full max-h-[320px] block border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
class="block max-h-[320px] w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
{#each stats.usageByUser as user (user.userId)}
|
||||
<tr
|
||||
class="text-center flex place-items-center w-full h-[50px] even:bg-immich-bg even:dark:bg-immich-dark-gray/50 odd:bg-immich-gray odd:dark:bg-immich-dark-gray/75"
|
||||
class="flex h-[50px] w-full place-items-center text-center odd:bg-immich-gray even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50"
|
||||
>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.userFirstName} {user.userLastName}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.photos.toLocaleString($locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.videos.toLocaleString($locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{asByteUnitString(user.usage, $locale)}</td>
|
||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.userFirstName} {user.userLastName}</td>
|
||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.photos.toLocaleString($locale)}</td>
|
||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.videos.toLocaleString($locale)}</td>
|
||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{asByteUnitString(user.usage, $locale)}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
|
@ -15,13 +15,13 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="w-[250px] h-[140px] bg-immich-gray dark:bg-immich-dark-gray rounded-3xl p-5 flex flex-col justify-between">
|
||||
<div class="flex h-[140px] w-[250px] flex-col justify-between rounded-3xl bg-immich-gray p-5 dark:bg-immich-dark-gray">
|
||||
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
|
||||
<svelte:component this={logo} size="40" />
|
||||
<p>{title}</p>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono font-semibold text-2xl">
|
||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{value}</span
|
||||
>
|
||||
|
@ -79,7 +79,7 @@
|
||||
{#await getConfigs() then}
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
<div class="flex flex-col gap-4 ml-4 mt-4">
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="CONSTANT RATE FACTOR (-crf)"
|
||||
|
@ -75,7 +75,7 @@
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
{#each jobNames as jobName}
|
||||
<div class="flex flex-col gap-4 ml-4 mt-4">
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="{api.getJobName(jobName)} Concurrency"
|
||||
|
@ -107,7 +107,7 @@
|
||||
<div class="mt-2">
|
||||
{#await getConfigs() then}
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault class="flex flex-col mx-4 gap-4 py-4">
|
||||
<form autocomplete="off" on:submit|preventDefault class="mx-4 flex flex-col gap-4 py-4">
|
||||
<p class="text-sm dark:text-immich-dark-fg">
|
||||
For more details about this feature, refer to the <a
|
||||
href="http://immich.app/docs/administration/oauth#mobile-redirect-uri"
|
||||
|
@ -96,7 +96,7 @@
|
||||
{#await getConfigs() then}
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
<div class="flex flex-col gap-4 ml-4 mt-4">
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<div class="ml-4">
|
||||
<SettingSwitch
|
||||
title="ENABLED"
|
||||
|
@ -7,8 +7,8 @@
|
||||
const toggle = () => (isOpen = !isOpen);
|
||||
</script>
|
||||
|
||||
<div class="border-b-[1px] border-gray-200 dark:border-gray-700 py-4">
|
||||
<div class="flex justify-between place-items-center">
|
||||
<div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700">
|
||||
<div class="flex place-items-center justify-between">
|
||||
<div>
|
||||
<h2 class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
@ -20,7 +20,7 @@
|
||||
<button
|
||||
on:click={toggle}
|
||||
aria-expanded={isOpen}
|
||||
class="immich-circle-icon-button hover:bg-immich-primary/10 dark:text-immich-dark-fg hover:dark:bg-immich-dark-primary/20 rounded-full p-3 flex place-items-center place-content-center transition-all"
|
||||
class="immich-circle-icon-button flex place-content-center place-items-center rounded-full p-3 transition-all hover:bg-immich-primary/10 dark:text-immich-dark-fg hover:dark:bg-immich-dark-primary/20"
|
||||
>
|
||||
<svg
|
||||
style="tran"
|
||||
|
@ -7,12 +7,12 @@
|
||||
export let showResetToDefault = true;
|
||||
</script>
|
||||
|
||||
<div class="flex justify-between gap-2 mt-8">
|
||||
<div class="mt-8 flex justify-between gap-2">
|
||||
<div class="left">
|
||||
{#if showResetToDefault}
|
||||
<button
|
||||
on:click={() => dispatch('reset-to-default')}
|
||||
class="text-sm dark:text-immich-dark-primary hover:dark:text-immich-dark-primary/75 text-immich-primary hover:text-immich-primary/75 font-medium bg-none"
|
||||
class="bg-none text-sm font-medium text-immich-primary hover:text-immich-primary/75 dark:text-immich-dark-primary hover:dark:text-immich-dark-primary/75"
|
||||
>
|
||||
Reset to default
|
||||
</button>
|
||||
|
@ -28,7 +28,7 @@
|
||||
</script>
|
||||
|
||||
<div class="w-full">
|
||||
<div class={`flex place-items-center gap-1 h-[26px]`}>
|
||||
<div class={`flex h-[26px] place-items-center gap-1`}>
|
||||
<label class={`immich-form-label text-sm`} for={label}>{label}</label>
|
||||
{#if required}
|
||||
<div class="text-red-400">*</div>
|
||||
@ -37,7 +37,7 @@
|
||||
{#if isEdited}
|
||||
<div
|
||||
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
|
||||
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]"
|
||||
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
|
||||
>
|
||||
Unsaved change
|
||||
</div>
|
||||
@ -45,13 +45,13 @@
|
||||
</div>
|
||||
|
||||
{#if desc}
|
||||
<p class="immich-form-label text-xs pb-2" id="{label}-desc">
|
||||
<p class="immich-form-label pb-2 text-xs" id="{label}-desc">
|
||||
{desc}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<input
|
||||
class="immich-form-input pb-2 w-full"
|
||||
class="immich-form-input w-full pb-2"
|
||||
aria-describedby={desc ? `${label}-desc` : undefined}
|
||||
aria-labelledby="{label}-label"
|
||||
id={label}
|
||||
|
@ -15,13 +15,13 @@
|
||||
</script>
|
||||
|
||||
<div class="w-full">
|
||||
<div class={`flex place-items-center gap-1 h-[26px]`}>
|
||||
<div class={`flex h-[26px] place-items-center gap-1`}>
|
||||
<label class={`immich-form-label text-sm`} for="{name}-select">{label}</label>
|
||||
|
||||
{#if isEdited}
|
||||
<div
|
||||
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
|
||||
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]"
|
||||
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
|
||||
>
|
||||
Unsaved change
|
||||
</div>
|
||||
@ -29,13 +29,13 @@
|
||||
</div>
|
||||
|
||||
{#if desc}
|
||||
<p class="immich-form-label text-xs pb-2" id="{name}-desc">
|
||||
<p class="immich-form-label pb-2 text-xs" id="{name}-desc">
|
||||
{desc}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<select
|
||||
class="immich-form-input pb-2 w-full"
|
||||
class="immich-form-input w-full pb-2"
|
||||
aria-describedby={desc ? `${name}-desc` : undefined}
|
||||
{name}
|
||||
id="{name}-select"
|
||||
|
@ -9,16 +9,16 @@
|
||||
export let isEdited = false;
|
||||
</script>
|
||||
|
||||
<div class="flex justify-between place-items-center">
|
||||
<div class="flex place-items-center justify-between">
|
||||
<div>
|
||||
<div class="flex place-items-center gap-1 h-[26px]">
|
||||
<div class="flex h-[26px] place-items-center gap-1">
|
||||
<label class="immich-form-label text-sm" for={title}>
|
||||
{title}
|
||||
</label>
|
||||
{#if isEdited}
|
||||
<div
|
||||
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
|
||||
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]"
|
||||
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
|
||||
>
|
||||
Unsaved change
|
||||
</div>
|
||||
@ -28,8 +28,8 @@
|
||||
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
|
||||
</div>
|
||||
|
||||
<label class="relative inline-block flex-none w-[36px] h-[10px]">
|
||||
<input class="opacity-0 w-0 h-0 disabled::cursor-not-allowed" type="checkbox" bind:checked on:click {disabled} />
|
||||
<label class="relative inline-block h-[10px] w-[36px] flex-none">
|
||||
<input class="disabled::cursor-not-allowed h-0 w-0 opacity-0" type="checkbox" bind:checked on:click {disabled} />
|
||||
|
||||
{#if disabled}
|
||||
<span class="slider-disable" />
|
||||
|
@ -133,7 +133,7 @@
|
||||
<section class="dark:text-immich-dark-fg">
|
||||
{#await getConfigs() then}
|
||||
<div id="directory-path-builder" class="m-4">
|
||||
<h3 class="font-medium text-immich-primary dark:text-immich-dark-primary text-base">Variables</h3>
|
||||
<h3 class="text-base font-medium text-immich-primary dark:text-immich-dark-primary">Variables</h3>
|
||||
|
||||
<section class="support-date">
|
||||
{#await getSupportDateTimeFormat()}
|
||||
@ -150,9 +150,9 @@
|
||||
</section>
|
||||
|
||||
<div class="mt-4 flex flex-col">
|
||||
<h3 class="font-medium text-immich-primary dark:text-immich-dark-primary text-base">Template</h3>
|
||||
<h3 class="text-base font-medium text-immich-primary dark:text-immich-dark-primary">Template</h3>
|
||||
|
||||
<div class="text-xs my-2">
|
||||
<div class="my-2 text-xs">
|
||||
<h4>PREVIEW</h4>
|
||||
</div>
|
||||
|
||||
@ -167,17 +167,17 @@
|
||||
<code>{user.storageLabel || user.id}</code> is the user's Storage Label
|
||||
</p>
|
||||
|
||||
<p class="text-xs p-4 bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg py-2 rounded-lg mt-2">
|
||||
<p class="mt-2 rounded-lg bg-gray-200 p-4 py-2 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
|
||||
<span class="text-immich-fg/25 dark:text-immich-dark-fg/50"
|
||||
>UPLOAD_LOCATION/{user.storageLabel || user.id}</span
|
||||
>/{parsedTemplate()}.jpg
|
||||
</p>
|
||||
|
||||
<form autocomplete="off" class="flex flex-col" on:submit|preventDefault>
|
||||
<div class="flex flex-col my-2">
|
||||
<div class="my-2 flex flex-col">
|
||||
<label class="text-xs" for="presets">PRESET</label>
|
||||
<select
|
||||
class="text-sm bg-slate-200 p-2 rounded-lg mt-2 dark:bg-gray-600 hover:cursor-pointer"
|
||||
class="mt-2 rounded-lg bg-slate-200 p-2 text-sm hover:cursor-pointer dark:bg-gray-600"
|
||||
name="presets"
|
||||
id="preset-select"
|
||||
bind:value={selectedPreset}
|
||||
@ -202,7 +202,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="migration-info" class="text-sm mt-4">
|
||||
<div id="migration-info" class="mt-4 text-sm">
|
||||
<p>
|
||||
Template changes will only apply to new assets. To retroactively apply the template to previously uploaded
|
||||
assets, run the <a href="/admin/jobs-status" class="text-immich-primary dark:text-immich-dark-primary"
|
||||
|
@ -9,18 +9,18 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="text-xs mt-2">
|
||||
<div class="mt-2 text-xs">
|
||||
<h4>DATE & TIME</h4>
|
||||
</div>
|
||||
|
||||
<div class="text-xs bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg p-4 mt-2 rounded-lg">
|
||||
<div class="mt-2 rounded-lg bg-gray-200 p-4 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
|
||||
<div class="mb-2 text-gray-600 dark:text-immich-dark-fg">
|
||||
<p>Asset's creation timestamp is used for the datetime information</p>
|
||||
<p>Sample time 2022-09-04T20:03:05.250</p>
|
||||
</div>
|
||||
<div class="flex gap-[50px]">
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">YEAR</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">YEAR</p>
|
||||
<ul>
|
||||
{#each options.yearOptions as yearFormat}
|
||||
<li>{'{{'}{yearFormat}{'}}'} - {getLuxonExample(yearFormat)}</li>
|
||||
@ -29,7 +29,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">MONTH</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">MONTH</p>
|
||||
<ul>
|
||||
{#each options.monthOptions as monthFormat}
|
||||
<li>{'{{'}{monthFormat}{'}}'} - {getLuxonExample(monthFormat)}</li>
|
||||
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">DAY</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">DAY</p>
|
||||
<ul>
|
||||
{#each options.dayOptions as dayFormat}
|
||||
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
|
||||
@ -47,7 +47,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">HOUR</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">HOUR</p>
|
||||
<ul>
|
||||
{#each options.hourOptions as dayFormat}
|
||||
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
|
||||
@ -56,7 +56,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">MINUTE</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">MINUTE</p>
|
||||
<ul>
|
||||
{#each options.minuteOptions as dayFormat}
|
||||
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
|
||||
@ -65,7 +65,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">SECOND</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">SECOND</p>
|
||||
<ul>
|
||||
{#each options.secondOptions as dayFormat}
|
||||
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
|
||||
|
@ -1,25 +1,25 @@
|
||||
<div class="text-xs mt-4">
|
||||
<div class="mt-4 text-xs">
|
||||
<h4>OTHER VARIABLES</h4>
|
||||
</div>
|
||||
|
||||
<div class="text-xs bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg p-4 mt-2 rounded-lg">
|
||||
<div class="mt-2 rounded-lg bg-gray-200 p-4 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
|
||||
<div class="flex gap-[50px]">
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE NAME</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE NAME</p>
|
||||
<ul>
|
||||
<li>{`{{filename}}`}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE EXTENSION</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE EXTENSION</p>
|
||||
<ul>
|
||||
<li>{`{{ext}}`}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE TYPE</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE TYPE</p>
|
||||
<ul>
|
||||
<li>{`{{filetype}}`} - VID or IMG</li>
|
||||
<li>{`{{filetypefull}}`} - VIDEO or IMAGE</li>
|
||||
|
@ -60,7 +60,7 @@
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="group hover:cursor-pointer mt-4 border-[3px] border-transparent dark:hover:border-immich-dark-primary/75 hover:border-immich-primary/75 rounded-3xl p-5 relative"
|
||||
class="group relative mt-4 rounded-3xl border-[3px] border-transparent p-5 hover:cursor-pointer hover:border-immich-primary/75 dark:hover:border-immich-dark-primary/75"
|
||||
on:click={() => dispatchClick('click', album)}
|
||||
on:keydown={() => dispatchClick('click', album)}
|
||||
data-testid="album-card"
|
||||
@ -69,7 +69,7 @@
|
||||
{#if showContextMenu}
|
||||
<div
|
||||
id={`icon-${album.id}`}
|
||||
class="absolute top-6 right-6 z-10"
|
||||
class="absolute right-6 top-6 z-10"
|
||||
on:click|stopPropagation|preventDefault={showAlbumContextMenu}
|
||||
data-testid="context-button-parent"
|
||||
>
|
||||
@ -79,16 +79,16 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class={`aspect-square relative`}>
|
||||
<div class={`relative aspect-square`}>
|
||||
<img
|
||||
src={imageData}
|
||||
alt={album.id}
|
||||
class={`object-cover h-full w-full transition-all z-0 rounded-3xl duration-300 hover:shadow-lg`}
|
||||
class={`z-0 h-full w-full rounded-3xl object-cover transition-all duration-300 hover:shadow-lg`}
|
||||
data-testid="album-image"
|
||||
draggable="false"
|
||||
/>
|
||||
<div
|
||||
class="w-full h-full absolute top-0 rounded-3xl {isSharingView
|
||||
class="absolute top-0 h-full w-full rounded-3xl {isSharingView
|
||||
? 'group-hover:bg-yellow-800/25'
|
||||
: 'group-hover:bg-indigo-800/25'} "
|
||||
/>
|
||||
@ -96,14 +96,14 @@
|
||||
|
||||
<div class="mt-4">
|
||||
<p
|
||||
class="text-xl font-semibold dark:text-immich-dark-primary text-immich-primary w-full truncate"
|
||||
class="w-full truncate text-xl font-semibold text-immich-primary dark:text-immich-dark-primary"
|
||||
data-testid="album-name"
|
||||
title={album.albumName}
|
||||
>
|
||||
{album.albumName}
|
||||
</p>
|
||||
|
||||
<span class="text-sm flex gap-2 dark:text-immich-dark-fg" data-testid="album-details">
|
||||
<span class="flex gap-2 text-sm dark:text-immich-dark-fg" data-testid="album-details">
|
||||
{#if showItemCount}
|
||||
<p>
|
||||
{album.assetCount.toLocaleString($locale)}
|
||||
|
@ -298,7 +298,7 @@
|
||||
{#if isPublicShared && !isOwned}
|
||||
<a
|
||||
data-sveltekit-preload-data="hover"
|
||||
class="flex gap-2 place-items-center hover:cursor-pointer ml-6"
|
||||
class="ml-6 flex place-items-center gap-2 hover:cursor-pointer"
|
||||
href="https://immich.app"
|
||||
>
|
||||
<ImmichLogo height={30} width={30} />
|
||||
@ -377,7 +377,7 @@
|
||||
</ControlAppBar>
|
||||
{/if}
|
||||
|
||||
<section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40">
|
||||
<section class="my-[160px] flex flex-col px-6 sm:px-12 md:px-24 lg:px-40">
|
||||
<input
|
||||
on:keydown={(e) => {
|
||||
if (e.key == 'Enter') {
|
||||
@ -387,9 +387,9 @@
|
||||
}}
|
||||
on:focus={() => (isEditingTitle = true)}
|
||||
on:blur={() => (isEditingTitle = false)}
|
||||
class={`transition-all text-6xl text-immich-primary dark:text-immich-dark-primary w-[99%] border-b-2 border-transparent outline-none ${
|
||||
class={`w-[99%] border-b-2 border-transparent text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary ${
|
||||
isOwned ? 'hover:border-gray-400' : 'hover:border-transparent'
|
||||
} focus:outline-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary bg-immich-bg dark:bg-immich-dark-bg dark:focus:bg-immich-dark-gray`}
|
||||
} bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray`}
|
||||
type="text"
|
||||
bind:value={album.albumName}
|
||||
disabled={!isOwned}
|
||||
@ -397,14 +397,14 @@
|
||||
/>
|
||||
|
||||
{#if album.assetCount > 0}
|
||||
<span class="flex gap-2 my-4 text-sm text-gray-500 font-medium" data-testid="album-details">
|
||||
<span class="my-4 flex gap-2 text-sm font-medium text-gray-500" data-testid="album-details">
|
||||
<p class="">{getDateRange()}</p>
|
||||
<p>·</p>
|
||||
<p>{album.assetCount} items</p>
|
||||
</span>
|
||||
{/if}
|
||||
{#if album.shared}
|
||||
<div class="flex my-6 gap-x-1">
|
||||
<div class="my-6 flex gap-x-1">
|
||||
{#each album.sharedUsers as user (user.id)}
|
||||
<button on:click={() => (isShowShareInfoModal = true)}>
|
||||
<UserAvatar {user} size="md" autoColor />
|
||||
@ -415,7 +415,7 @@
|
||||
style:display={isOwned ? 'block' : 'none'}
|
||||
on:click={() => (isShowShareUserSelection = true)}
|
||||
title="Add more users"
|
||||
class="h-12 w-12 border bg-white transition-colors hover:bg-gray-300 text-3xl flex place-items-center place-content-center rounded-full"
|
||||
class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-white text-3xl transition-colors hover:bg-gray-300"
|
||||
>+</button
|
||||
>
|
||||
</div>
|
||||
@ -430,7 +430,7 @@
|
||||
<p class="text-xs dark:text-immich-dark-fg">ADD PHOTOS</p>
|
||||
<button
|
||||
on:click={() => (isShowAssetSelection = true)}
|
||||
class="w-full py-8 border bg-immich-bg dark:bg-immich-dark-gray text-immich-fg dark:text-immich-dark-fg dark:hover:text-immich-dark-primary rounded-md mt-5 flex place-items-center gap-6 px-8 transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none"
|
||||
class="mt-5 flex w-full place-items-center gap-6 rounded-md border bg-immich-bg px-8 py-8 text-immich-fg transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none dark:bg-immich-dark-gray dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
|
||||
>
|
||||
<span class="text-text-immich-primary dark:text-immich-dark-primary"><Plus size="24" /> </span>
|
||||
<span class="text-lg">Select photos</span>
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
||||
>
|
||||
<ControlAppBar
|
||||
on:close-button-click={() => {
|
||||
@ -56,14 +56,14 @@
|
||||
<svelte:fragment slot="trailing">
|
||||
<button
|
||||
on:click={handleSelectFromComputerClicked}
|
||||
class="text-immich-primary dark:text-immich-dark-primary text-sm hover:bg-immich-primary/10 dark:hover:bg-immich-dark-primary/25 transition-all px-6 py-2 rounded-lg font-medium"
|
||||
class="rounded-lg px-6 py-2 text-sm font-medium text-immich-primary transition-all hover:bg-immich-primary/10 dark:text-immich-dark-primary dark:hover:bg-immich-dark-primary/25"
|
||||
>
|
||||
Select from computer
|
||||
</button>
|
||||
<Button size="sm" rounded="lg" disabled={$selectedAssets.size === 0} on:click={addSelectedAssets}>Done</Button>
|
||||
</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg">
|
||||
<section class="grid h-screen bg-immich-bg pl-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
||||
<AssetGrid isAlbumSelectionMode={true} />
|
||||
</section>
|
||||
</section>
|
||||
|
@ -73,19 +73,19 @@
|
||||
{#if !selectedRemoveUser}
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Options</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
|
||||
<section class="max-h-[400px] overflow-y-auto immich-scrollbar pb-4">
|
||||
<section class="immich-scrollbar max-h-[400px] overflow-y-auto pb-4">
|
||||
{#each album.sharedUsers as user}
|
||||
<div
|
||||
class="flex gap-4 p-5 place-items-center justify-between w-full transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
class="flex w-full place-items-center justify-between gap-4 p-5 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div class="flex gap-4 place-items-center">
|
||||
<div class="flex place-items-center gap-4">
|
||||
<UserAvatar {user} size="md" autoColor />
|
||||
<p class="font-medium text-sm">{user.firstName} {user.lastName}</p>
|
||||
<p class="text-sm font-medium">{user.firstName} {user.lastName}</p>
|
||||
</div>
|
||||
|
||||
<div id={`icon-${user.id}`} class="flex place-items-center">
|
||||
@ -108,7 +108,7 @@
|
||||
{:else if user.id == currentUser?.id}
|
||||
<button
|
||||
on:click={() => (selectedRemoveUser = user)}
|
||||
class="text-sm text-immich-primary dark:text-immich-dark-primary font-medium transition-colors hover:text-immich-primary/75"
|
||||
class="text-sm font-medium text-immich-primary transition-colors hover:text-immich-primary/75 dark:text-immich-dark-primary"
|
||||
>Leave</button
|
||||
>
|
||||
{/if}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full py-[160px] bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg py-[160px] dark:bg-immich-dark-bg"
|
||||
>
|
||||
<ControlAppBar on:close-button-click={() => dispatch('close')}>
|
||||
<svelte:fragment slot="leading">
|
||||
@ -42,7 +42,7 @@
|
||||
</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
|
||||
<section class="flex flex-wrap gap-14 px-20 overflow-y-auto">
|
||||
<section class="flex flex-wrap gap-14 overflow-y-auto px-20">
|
||||
<!-- Image grid -->
|
||||
<div class="flex flex-wrap gap-[2px]">
|
||||
{#each album.assets as asset}
|
||||
|
@ -55,22 +55,22 @@
|
||||
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<ImmichLogo width={24} />
|
||||
<p class="font-medium">Invite to album</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
|
||||
<div class="max-h-[300px] overflow-y-auto immich-scrollbar">
|
||||
<div class="immich-scrollbar max-h-[300px] overflow-y-auto">
|
||||
{#if selectedUsers.length > 0}
|
||||
<div class="flex gap-4 py-2 px-5 overflow-x-auto place-items-center mb-2">
|
||||
<div class="mb-2 flex place-items-center gap-4 overflow-x-auto px-5 py-2">
|
||||
<p class="font-medium">To</p>
|
||||
|
||||
{#each selectedUsers as user}
|
||||
{#key user.id}
|
||||
<button
|
||||
on:click={() => deselectUser(user)}
|
||||
class="flex gap-1 place-items-center border border-gray-400 rounded-full p-1 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
|
||||
class="flex place-items-center gap-1 rounded-full border border-gray-400 p-1 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
>
|
||||
<UserAvatar {user} size="sm" autoColor />
|
||||
<p class="text-xs font-medium">{user.firstName} {user.lastName}</p>
|
||||
@ -81,17 +81,17 @@
|
||||
{/if}
|
||||
|
||||
{#if users.length > 0}
|
||||
<p class="text-xs font-medium px-5">SUGGESTIONS</p>
|
||||
<p class="px-5 text-xs font-medium">SUGGESTIONS</p>
|
||||
|
||||
<div class="my-4">
|
||||
{#each users as user}
|
||||
<button
|
||||
on:click={() => selectUser(user)}
|
||||
class="w-full flex place-items-center gap-4 py-4 px-5 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all"
|
||||
class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
>
|
||||
{#if selectedUsers.includes(user)}
|
||||
<span
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-bg rounded-full w-12 h-12 border flex place-items-center place-content-center text-3xl dark:border-immich-dark-gray"
|
||||
class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg"
|
||||
>✓</span
|
||||
>
|
||||
{:else}
|
||||
@ -111,7 +111,7 @@
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="text-sm p-5">
|
||||
<p class="p-5 text-sm">
|
||||
Looks like you have shared this album with all users or you don't have any user to share with.
|
||||
</p>
|
||||
{/if}
|
||||
@ -124,9 +124,9 @@
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div id="shared-buttons" class="flex my-4 justify-around place-items-center place-content-center">
|
||||
<div id="shared-buttons" class="my-4 flex place-content-center place-items-center justify-around">
|
||||
<button
|
||||
class="flex flex-col gap-2 place-items-center place-content-center hover:cursor-pointer"
|
||||
class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"
|
||||
on:click={onSharedLinkClick}
|
||||
>
|
||||
<Link size={24} />
|
||||
@ -135,7 +135,7 @@
|
||||
|
||||
{#if sharedLinks.length}
|
||||
<button
|
||||
class="flex flex-col gap-2 place-items-center place-content-center hover:cursor-pointer"
|
||||
class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"
|
||||
on:click={() => goto(AppRoute.SHARED_LINKS)}
|
||||
>
|
||||
<ShareCircle size={24} />
|
||||
|
@ -25,20 +25,20 @@
|
||||
|
||||
<button
|
||||
on:click={() => dispatcher('album')}
|
||||
class="w-full flex gap-4 px-6 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
|
||||
class="flex w-full gap-4 px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div class="h-12 w-12 rounded-xl bg-slate-300">
|
||||
{#if album.albumThumbnailAssetId}
|
||||
<img
|
||||
src={api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)}
|
||||
alt={album.albumName}
|
||||
class={`object-cover h-full w-full transition-all z-0 rounded-xl duration-300 hover:shadow-lg`}
|
||||
class={`z-0 h-full w-full rounded-xl object-cover transition-all duration-300 hover:shadow-lg`}
|
||||
data-testid="album-image"
|
||||
draggable="false"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="h-12 flex flex-col items-start justify-center">
|
||||
<div class="flex h-12 flex-col items-start justify-center">
|
||||
<span>{albumNameArray[0]}<b>{albumNameArray[1]}</b>{albumNameArray[2]}</span>
|
||||
<span class="flex gap-1 text-sm">
|
||||
{#if variant === 'simple'}
|
||||
|
@ -46,12 +46,12 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="h-16 flex justify-between place-items-center px-3 transition-transform duration-200 z-[1001] bg-gradient-to-b from-black/40"
|
||||
class="z-[1001] flex h-16 place-items-center justify-between bg-gradient-to-b from-black/40 px-3 transition-transform duration-200"
|
||||
>
|
||||
<div class="text-white">
|
||||
<CircleIconButton isOpacity={true} logo={ArrowLeft} on:click={() => dispatch('goBack')} />
|
||||
</div>
|
||||
<div class="text-white flex gap-2 justify-end w-[calc(100%-3rem)] overflow-hidden">
|
||||
<div class="flex w-[calc(100%-3rem)] justify-end gap-2 overflow-hidden text-white">
|
||||
{#if showMotionPlayButton}
|
||||
{#if isMotionPhotoPlaying}
|
||||
<CircleIconButton
|
||||
|
@ -245,9 +245,9 @@
|
||||
|
||||
<section
|
||||
id="immich-asset-viewer"
|
||||
class="fixed h-screen w-screen left-0 top-0 overflow-y-hidden bg-black z-[1001] grid grid-rows-[64px_1fr] grid-cols-4"
|
||||
class="fixed left-0 top-0 z-[1001] grid h-screen w-screen grid-cols-4 grid-rows-[64px_1fr] overflow-y-hidden bg-black"
|
||||
>
|
||||
<div class="col-start-1 col-span-4 row-start-1 row-span-1 z-[1000] transition-transform">
|
||||
<div class="z-[1000] col-span-4 col-start-1 row-span-1 row-start-1 transition-transform">
|
||||
<AssetViewerNavBar
|
||||
{asset}
|
||||
isMotionPhotoPlaying={shouldPlayMotionPhoto}
|
||||
@ -270,17 +270,17 @@
|
||||
</div>
|
||||
|
||||
{#if showNavigation}
|
||||
<div class="row-start-2 row-span-1 col-start-1 column-span-1 justify-self-start mb-[60px] z-[999]">
|
||||
<div class="column-span-1 z-[999] col-start-1 row-span-1 row-start-2 mb-[60px] justify-self-start">
|
||||
<NavigationArea on:click={navigateAssetBackward}><ChevronLeft size="36" /></NavigationArea>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="row-start-1 row-span-full col-start-1 col-span-4">
|
||||
<div class="col-span-4 col-start-1 row-span-full row-start-1">
|
||||
{#key asset.id}
|
||||
{#if !asset.resized}
|
||||
<div class="h-full w-full flex justify-center">
|
||||
<div class="flex h-full w-full justify-center">
|
||||
<div
|
||||
class="h-full bg-gray-100 dark:bg-immich-dark-gray flex items-center justify-center aspect-square px-auto"
|
||||
class="px-auto flex aspect-square h-full items-center justify-center bg-gray-100 dark:bg-immich-dark-gray"
|
||||
>
|
||||
<ImageBrokenVariant size="25%" />
|
||||
</div>
|
||||
@ -303,7 +303,7 @@
|
||||
</div>
|
||||
|
||||
{#if showNavigation}
|
||||
<div class="row-start-2 row-span-1 col-start-4 col-span-1 justify-self-end mb-[60px] z-[999]">
|
||||
<div class="z-[999] col-span-1 col-start-4 row-span-1 row-start-2 mb-[60px] justify-self-end">
|
||||
<NavigationArea on:click={navigateAssetForward}><ChevronRight size="36" /></NavigationArea>
|
||||
</div>
|
||||
{/if}
|
||||
@ -312,7 +312,7 @@
|
||||
<div
|
||||
transition:fly={{ duration: 150 }}
|
||||
id="detail-panel"
|
||||
class="bg-immich-bg w-[360px] z-[1002] row-span-full transition-all overflow-y-auto dark:bg-immich-dark-bg dark:border-l dark:border-l-immich-dark-gray"
|
||||
class="z-[1002] row-span-full w-[360px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg"
|
||||
translate="yes"
|
||||
>
|
||||
<DetailPanel
|
||||
|
@ -80,20 +80,20 @@
|
||||
<section class="p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg">
|
||||
<div class="flex place-items-center gap-2">
|
||||
<button
|
||||
class="rounded-full p-3 flex place-items-center place-content-center hover:bg-gray-200 transition-colors dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||
on:click={() => dispatch('close')}
|
||||
>
|
||||
<Close size="24" />
|
||||
</button>
|
||||
|
||||
<p class="text-immich-fg dark:text-immich-dark-fg text-lg">Info</p>
|
||||
<p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
|
||||
</div>
|
||||
|
||||
<section class="mx-4 mt-10">
|
||||
<textarea
|
||||
bind:this={textarea}
|
||||
class="max-h-[500px]
|
||||
text-base text-black bg-transparent dark:text-white border-b focus:border-b-2 border-gray-500 w-full focus:border-immich-primary dark:focus:border-immich-dark-primary transition-all resize-none overflow-hidden outline-none disabled:border-none"
|
||||
w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
|
||||
placeholder={$page?.data?.user?.id !== asset.ownerId ? '' : 'Add a description'}
|
||||
style:display={$page?.data?.user?.id !== asset.ownerId && textarea?.value == '' ? 'none' : 'block'}
|
||||
on:focusin={handleFocusIn}
|
||||
@ -108,7 +108,7 @@
|
||||
<section class="px-4 py-4 text-sm">
|
||||
<h2>PEOPLE</h2>
|
||||
|
||||
<div class="flex flex-wrap gap-2 mt-4">
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
{#each people as person (person.id)}
|
||||
<a href="/people/{person.id}" class="w-[90px]" on:click={() => dispatch('close-viewer')}>
|
||||
<ImageThumbnail
|
||||
@ -120,7 +120,7 @@
|
||||
heightStyle="90px"
|
||||
thumbhash={null}
|
||||
/>
|
||||
<p class="font-medium mt-1 truncate">{person.name}</p>
|
||||
<p class="mt-1 truncate font-medium">{person.name}</p>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
@ -178,7 +178,7 @@
|
||||
<p class="break-all">
|
||||
{getAssetFilename(asset)}
|
||||
</p>
|
||||
<div class="flex text-sm gap-2">
|
||||
<div class="flex gap-2 text-sm">
|
||||
{#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth}
|
||||
{#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)}
|
||||
<p>
|
||||
@ -200,7 +200,7 @@
|
||||
|
||||
<div>
|
||||
<p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p>
|
||||
<div class="flex text-sm gap-2">
|
||||
<div class="flex gap-2 text-sm">
|
||||
<p>{`ƒ/${asset.exifInfo.fNumber.toLocaleString($locale)}` || ''}</p>
|
||||
|
||||
{#if asset.exifInfo.exposureTime}
|
||||
@ -227,10 +227,10 @@
|
||||
|
||||
<div>
|
||||
<p>{asset.exifInfo.city}</p>
|
||||
<div class="flex text-sm gap-2">
|
||||
<div class="flex gap-2 text-sm">
|
||||
<p>{asset.exifInfo.state}</p>
|
||||
</div>
|
||||
<div class="flex text-sm gap-2">
|
||||
<div class="flex gap-2 text-sm">
|
||||
<p>{asset.exifInfo.country}</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -258,7 +258,7 @@
|
||||
<section class="p-2 dark:text-immich-dark-fg">
|
||||
<div class="px-4 py-4">
|
||||
{#if albums.length > 0}
|
||||
<p class="text-sm pb-4">APPEARS IN</p>
|
||||
<p class="pb-4 text-sm">APPEARS IN</p>
|
||||
{/if}
|
||||
{#each albums as album}
|
||||
<a data-sveltekit-preload-data="hover" href={`/albums/${album.id}`}>
|
||||
@ -271,14 +271,14 @@
|
||||
<div>
|
||||
<img
|
||||
alt={album.albumName}
|
||||
class="w-[50px] h-[50px] object-cover rounded"
|
||||
class="h-[50px] w-[50px] rounded object-cover"
|
||||
src={album.albumThumbnailAssetId &&
|
||||
api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
|
||||
draggable="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-auto mb-auto">
|
||||
<div class="mb-auto mt-auto">
|
||||
<p class="dark:text-immich-dark-primary">{album.albumName}</p>
|
||||
<div class="flex gap-2 text-sm">
|
||||
<p>{album.assetCount} items</p>
|
||||
|
@ -15,25 +15,25 @@
|
||||
{#if $isDownloading}
|
||||
<div
|
||||
transition:fly={{ x: -100, duration: 350 }}
|
||||
class="w-[315px] max-h-[270px] bg-immich-bg border rounded-2xl shadow-sm absolute bottom-10 left-2 p-4 z-[10000] text-sm"
|
||||
class="absolute bottom-10 left-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border bg-immich-bg p-4 text-sm shadow-sm"
|
||||
>
|
||||
<p class="text-gray-500 text-xs mb-2">DOWNLOADING</p>
|
||||
<div class="max-h-[200px] my-2 overflow-y-auto mb-2 flex flex-col text-sm">
|
||||
<p class="mb-2 text-xs text-gray-500">DOWNLOADING</p>
|
||||
<div class="my-2 mb-2 flex max-h-[200px] flex-col overflow-y-auto text-sm">
|
||||
{#each Object.keys($downloadAssets) as downloadKey (downloadKey)}
|
||||
{@const download = $downloadAssets[downloadKey]}
|
||||
<div class="mb-2 flex place-items-center" transition:slide>
|
||||
<div class="w-full pr-10">
|
||||
<div class="font-medium text-xs flex gap-2 place-items-center justify-between">
|
||||
<div class="flex place-items-center justify-between gap-2 text-xs font-medium">
|
||||
<p class="truncate">■ {downloadKey}</p>
|
||||
{#if download.total}
|
||||
<p class="whitespace-nowrap">{asByteUnitString(download.total, $locale)}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex place-items-center gap-2">
|
||||
<div class="w-full bg-gray-200 rounded-full h-[7px] dark:bg-gray-700">
|
||||
<div class="bg-immich-primary h-[7px] rounded-full" style={`width: ${download.percentage}%`} />
|
||||
<div class="h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||
<div class="h-[7px] rounded-full bg-immich-primary" style={`width: ${download.percentage}%`} />
|
||||
</div>
|
||||
<p class="whitespace-nowrap min-w-[4em] text-right">
|
||||
<p class="min-w-[4em] whitespace-nowrap text-right">
|
||||
<span class="text-immich-primary">{download.percentage}%</span>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -2,8 +2,8 @@
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="group h-full flex place-items-center" on:click on:keydown>
|
||||
<button class="rounded-full p-3 transition text-gray-500 mx-4 group-hover:text-white group-hover:bg-gray-500">
|
||||
<div class="group flex h-full place-items-center" on:click on:keydown>
|
||||
<button class="mx-4 rounded-full p-3 text-gray-500 transition group-hover:bg-gray-500 group-hover:text-white">
|
||||
<slot />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -103,7 +103,7 @@
|
||||
<div
|
||||
bind:this={element}
|
||||
transition:fade={{ duration: 150 }}
|
||||
class="flex place-items-center place-content-center h-full select-none"
|
||||
class="flex h-full select-none place-content-center place-items-center"
|
||||
>
|
||||
{#await loadAssetData()}
|
||||
<LoadingSpinner />
|
||||
@ -113,7 +113,7 @@
|
||||
transition:fade={{ duration: 150 }}
|
||||
src={assetData}
|
||||
alt={asset.id}
|
||||
class="object-contain h-full w-full"
|
||||
class="h-full w-full object-contain"
|
||||
draggable="false"
|
||||
/>
|
||||
</div>
|
||||
|
@ -22,7 +22,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div transition:fade={{ duration: 150 }} class="flex place-items-center place-content-center h-full select-none">
|
||||
<div transition:fade={{ duration: 150 }} class="flex h-full select-none place-content-center place-items-center">
|
||||
<video
|
||||
controls
|
||||
class="h-full object-contain"
|
||||
@ -35,7 +35,7 @@
|
||||
</video>
|
||||
|
||||
{#if isVideoLoading}
|
||||
<div class="absolute flex place-items-center place-content-center">
|
||||
<div class="absolute flex place-content-center place-items-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -33,7 +33,7 @@
|
||||
on:image-load|once={() => (complete = true)}
|
||||
/>
|
||||
{#if hidden}
|
||||
<div class="absolute top-1/2 left-1/2 transform translate-x-[-50%] translate-y-[-50%]">
|
||||
<div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
|
||||
<EyeOffOutline size="2em" />
|
||||
</div>
|
||||
{/if}
|
||||
@ -44,7 +44,7 @@
|
||||
style:height={heightStyle}
|
||||
src={thumbHashToDataURL(Buffer.from(thumbhash, 'base64'))}
|
||||
alt={altText}
|
||||
class="absolute object-cover top-0"
|
||||
class="absolute top-0 object-cover"
|
||||
class:rounded-lg={curve}
|
||||
class:shadow-lg={shadow}
|
||||
class:rounded-full={circle}
|
||||
|
@ -69,7 +69,7 @@
|
||||
<div
|
||||
style:width="{width}px"
|
||||
style:height="{height}px"
|
||||
class="relative group overflow-hidden {disabled
|
||||
class="group relative overflow-hidden {disabled
|
||||
? 'bg-gray-300'
|
||||
: 'bg-immich-primary/20 dark:bg-immich-dark-primary/20'}"
|
||||
class:cursor-not-allowed={disabled}
|
||||
@ -80,7 +80,7 @@
|
||||
on:keydown={thumbnailKeyDownHandler}
|
||||
>
|
||||
{#if intersecting}
|
||||
<div class="absolute w-full h-full z-20">
|
||||
<div class="absolute z-20 h-full w-full">
|
||||
<!-- Select asset button -->
|
||||
{#if !readonly && (mouseOver || selected || selectionCandidate)}
|
||||
<button
|
||||
@ -103,12 +103,12 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="h-full w-full bg-gray-100 dark:bg-immich-dark-gray absolute select-none transition-transform"
|
||||
class="absolute h-full w-full select-none bg-gray-100 transition-transform dark:bg-immich-dark-gray"
|
||||
class:scale-[0.85]={selected}
|
||||
>
|
||||
<!-- Gradient overlay on hover -->
|
||||
<div
|
||||
class="absolute w-full h-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 group-hover:opacity-100 transition-opacity z-10"
|
||||
class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100"
|
||||
/>
|
||||
|
||||
<!-- Favorite asset star -->
|
||||
@ -133,13 +133,13 @@
|
||||
thumbhash={asset.thumbhash}
|
||||
/>
|
||||
{:else}
|
||||
<div class="w-full h-full p-4 flex items-center justify-center">
|
||||
<div class="flex h-full w-full items-center justify-center p-4">
|
||||
<ImageBrokenVariant size="48" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if asset.type === AssetTypeEnum.Video}
|
||||
<div class="absolute w-full h-full top-0">
|
||||
<div class="absolute top-0 h-full w-full">
|
||||
<VideoThumbnail
|
||||
url={api.getAssetFileUrl(asset.id, false, true, publicSharedKey)}
|
||||
enablePlayback={mouseOver}
|
||||
@ -149,7 +149,7 @@
|
||||
{/if}
|
||||
|
||||
{#if asset.type === AssetTypeEnum.Image && asset.livePhotoVideoId}
|
||||
<div class="absolute w-full h-full top-0">
|
||||
<div class="absolute top-0 h-full w-full">
|
||||
<VideoThumbnail
|
||||
url={api.getAssetFileUrl(asset.livePhotoVideoId, false, true, publicSharedKey)}
|
||||
pauseIcon={MotionPauseOutline}
|
||||
@ -162,7 +162,7 @@
|
||||
</div>
|
||||
{#if selectionCandidate}
|
||||
<div
|
||||
class="absolute w-full h-full top-0 bg-immich-primary opacity-40"
|
||||
class="absolute top-0 h-full w-full bg-immich-primary opacity-40"
|
||||
in:fade={{ duration: 100 }}
|
||||
out:fade={{ duration: 100 }}
|
||||
/>
|
||||
|
@ -29,7 +29,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="absolute right-0 top-0 text-white text-xs font-medium flex gap-1 place-items-center z-20">
|
||||
<div class="absolute right-0 top-0 z-20 flex place-items-center gap-1 text-xs font-medium text-white">
|
||||
{#if showTime}
|
||||
<span class="pt-2">
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')}
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<span
|
||||
class="pt-2 pr-2"
|
||||
class="pr-2 pt-2"
|
||||
on:mouseenter={() => {
|
||||
if (playbackOnIconHover) {
|
||||
enablePlayback = true;
|
||||
@ -67,7 +67,7 @@
|
||||
{#if enablePlayback}
|
||||
<video
|
||||
bind:this={player}
|
||||
class="w-full h-full object-cover"
|
||||
class="h-full w-full object-cover"
|
||||
muted
|
||||
autoplay
|
||||
src={url}
|
||||
|
@ -14,7 +14,7 @@
|
||||
</script>
|
||||
|
||||
<span
|
||||
class="inline-block h-min whitespace-nowrap px-4 pt-[0.55em] pb-[0.55em] text-center align-baseline text-xs leading-none {colorClasses[
|
||||
class="inline-block h-min whitespace-nowrap px-4 pb-[0.55em] pt-[0.55em] text-center align-baseline text-xs leading-none {colorClasses[
|
||||
color
|
||||
]}"
|
||||
class:rounded-md={rounded === true}
|
||||
|
@ -59,7 +59,7 @@
|
||||
{disabled}
|
||||
{title}
|
||||
on:click
|
||||
class="inline-flex justify-center items-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[
|
||||
class="inline-flex items-center justify-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[
|
||||
color
|
||||
]} {sizeClasses[size]}"
|
||||
class:rounded-lg={rounded === 'lg'}
|
||||
|
@ -16,7 +16,7 @@
|
||||
style:background-color={backgroundColor}
|
||||
style:--immich-icon-button-hover-color={hoverColor}
|
||||
class:dark:text-immich-dark-fg={!forceDark}
|
||||
class="rounded-full p-3 flex place-items-center place-content-center transition-all
|
||||
class="flex place-content-center place-items-center rounded-full p-3 transition-all
|
||||
{isOpacity ? 'hover:bg-immich-bg/30' : 'immich-circle-icon-button hover:dark:text-immich-dark-gray'}
|
||||
{forceDark && 'hover:text-black'}
|
||||
{hideMobile && 'hidden sm:flex'}"
|
||||
|
@ -33,18 +33,18 @@
|
||||
{#if showMenu}
|
||||
<div
|
||||
transition:fly={{ y: -30, x: 30, duration: 200 }}
|
||||
class="absolute top-5 right-0 min-w-[250px] bg-gray-100 dark:bg-gray-700 rounded-2xl py-4 shadow-lg dark:text-white text-black z-50 text-md flex flex-col"
|
||||
class="text-md absolute right-0 top-5 z-50 flex min-w-[250px] flex-col rounded-2xl bg-gray-100 py-4 text-black shadow-lg dark:bg-gray-700 dark:text-white"
|
||||
>
|
||||
{#each options as option, index (option)}
|
||||
<button
|
||||
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-4 transition-all grid grid-cols-[20px,1fr] place-items-center gap-2"
|
||||
class="grid grid-cols-[20px,1fr] place-items-center gap-2 p-4 transition-all hover:bg-gray-300 dark:hover:bg-gray-800"
|
||||
on:click={() => handleSelectOption(index)}
|
||||
>
|
||||
{#if value == option}
|
||||
<div class="text-immich-primary dark:text-immich-dark-primary font-medium">
|
||||
<div class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
<Check size="18" />
|
||||
</div>
|
||||
<p class="justify-self-start text-immich-primary dark:text-immich-dark-primary font-medium">
|
||||
<p class="justify-self-start font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{option}
|
||||
</p>
|
||||
{:else}
|
||||
|
@ -15,7 +15,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex place-items-center max-w-lg rounded-lg border dark:border-transparent p-2 bg-gray-100 dark:bg-gray-700"
|
||||
class="flex max-w-lg place-items-center rounded-lg border bg-gray-100 p-2 dark:border-transparent dark:bg-gray-700"
|
||||
use:clickOutside
|
||||
on:outclick={() => dispatch('cancel')}
|
||||
>
|
||||
@ -28,14 +28,14 @@
|
||||
heightStyle="2rem"
|
||||
/>
|
||||
<form
|
||||
class="ml-4 flex justify-between w-full gap-16"
|
||||
class="ml-4 flex w-full justify-between gap-16"
|
||||
autocomplete="off"
|
||||
on:submit|preventDefault={() => dispatch('change', name)}
|
||||
>
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
class="gap-2 w-full bg-gray-100 dark:bg-gray-700 dark:text-white"
|
||||
class="w-full gap-2 bg-gray-100 dark:bg-gray-700 dark:text-white"
|
||||
type="text"
|
||||
placeholder="New name or nickname"
|
||||
bind:value={name}
|
||||
|
@ -25,12 +25,12 @@
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
||||
>
|
||||
<ControlAppBar on:close-button-click={onClose}>
|
||||
<svelte:fragment slot="leading">Select feature photo</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
<section class="pt-[100px] pl-[70px] bg-immich-bg dark:bg-immich-dark-bg">
|
||||
<section class="bg-immich-bg pl-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
||||
<AssetSelectionViewer {assets} on:select={handleSelectedAsset} />
|
||||
</section>
|
||||
</section>
|
||||
|
@ -18,14 +18,14 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="relative transition-all rounded-lg"
|
||||
class="relative rounded-lg transition-all"
|
||||
on:click={handleOnClicked}
|
||||
disabled={!selectable}
|
||||
style:width={thumbnailSize ? thumbnailSize + 'px' : '100%'}
|
||||
style:height={thumbnailSize ? thumbnailSize + 'px' : '100%'}
|
||||
>
|
||||
<div
|
||||
class="filter w-full h-full brightness-90 border-2"
|
||||
class="h-full w-full border-2 brightness-90 filter"
|
||||
class:rounded-full={circle}
|
||||
class:rounded-lg={!circle}
|
||||
class:border-transparent={!border}
|
||||
@ -42,7 +42,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-primary/30 opacity-0"
|
||||
class="absolute left-0 top-0 h-full w-full bg-immich-primary/30 opacity-0"
|
||||
class:hover:opacity-100={selectable}
|
||||
class:rounded-full={circle}
|
||||
class:rounded-lg={!circle}
|
||||
@ -50,7 +50,7 @@
|
||||
|
||||
{#if selected}
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full bg-blue-500/80"
|
||||
class="absolute left-0 top-0 h-full w-full bg-blue-500/80"
|
||||
class:rounded-full={circle}
|
||||
class:rounded-lg={!circle}
|
||||
/>
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
{#if person.name}
|
||||
<span
|
||||
class="absolute bottom-2 left-0 w-full text-center font-medium text-white text-ellipsis w-100 px-1 hover:cursor-pointer backdrop-blur-[1px]"
|
||||
class="w-100 absolute bottom-2 left-0 w-full text-ellipsis px-1 text-center font-medium text-white backdrop-blur-[1px] hover:cursor-pointer"
|
||||
>
|
||||
{person.name}
|
||||
</span>
|
||||
|
@ -75,7 +75,7 @@
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
||||
>
|
||||
<ControlAppBar on:close-button-click={onClose}>
|
||||
<svelte:fragment slot="leading">
|
||||
@ -99,12 +99,12 @@
|
||||
>
|
||||
</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
<section class="pt-[100px] px-[70px] bg-immich-bg dark:bg-immich-dark-bg">
|
||||
<section class="bg-immich-bg px-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
||||
<section id="merge-face-selector relative">
|
||||
<div class="place-items-center place-content-center mb-10 h-[200px]">
|
||||
<p class="uppercase mb-4 dark:text-white text-center">Choose matching faces to merge</p>
|
||||
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
||||
<p class="mb-4 text-center uppercase dark:text-white">Choose matching faces to merge</p>
|
||||
|
||||
<div class="grid grid-flow-col-dense place-items-center place-content-center gap-4">
|
||||
<div class="grid grid-flow-col-dense place-content-center place-items-center gap-4">
|
||||
{#each selectedPeople as person (person.id)}
|
||||
<div animate:flip={{ duration: 250, easing: quintOut }}>
|
||||
<FaceThumbnail border circle {person} selectable thumbnailSize={120} on:click={() => onSelect(person)} />
|
||||
@ -118,10 +118,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="p-10 overflow-y-auto rounded-3xl bg-gray-200 dark:bg-immich-dark-gray"
|
||||
class="overflow-y-auto rounded-3xl bg-gray-200 p-10 dark:bg-immich-dark-gray"
|
||||
style:max-height={screenHeight - 200 - 200 + 'px'}
|
||||
>
|
||||
<div class="grid grid-col-2 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10 gap-8">
|
||||
<div class="grid-col-2 grid gap-8 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10">
|
||||
{#each unselectedPeople as person (person.id)}
|
||||
<FaceThumbnail {person} on:click={() => onSelect(person)} circle border selectable />
|
||||
{/each}
|
||||
|
@ -11,19 +11,19 @@
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
||||
>
|
||||
<div
|
||||
class="absolute border-b dark:border-immich-dark-gray flex justify-between place-items-center dark:text-immich-dark-fg w-full h-16"
|
||||
class="absolute flex h-16 w-full place-items-center justify-between border-b dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div class="flex items-center justify-between p-8 w-full">
|
||||
<div class="flex w-full items-center justify-between p-8">
|
||||
<div class="flex items-center">
|
||||
<CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} />
|
||||
<p class="ml-4">Show & hide faces</p>
|
||||
</div>
|
||||
<IconButton on:click={() => dispatch('doneClick')}>Done</IconButton>
|
||||
</div>
|
||||
<div class="absolute top-16 h-[calc(100%-theme(spacing.16))] w-full immich-scrollbar p-4 pb-8">
|
||||
<div class="immich-scrollbar absolute top-16 h-[calc(100%-theme(spacing.16))] w-full p-4 pb-8">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -50,7 +50,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={registerAdmin} method="post" class="flex flex-col gap-5 mt-5">
|
||||
<form on:submit|preventDefault={registerAdmin} method="post" class="mt-5 flex flex-col gap-5">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="email">Admin Email</label>
|
||||
<input class="immich-form-input" id="email" name="email" type="email" autocomplete="email" required />
|
||||
|
@ -17,13 +17,13 @@
|
||||
|
||||
<FullScreenModal on:clickOutside={() => handleCancel()}>
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg"
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
>
|
||||
<KeyVariant size="4em" />
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
|
||||
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
</h1>
|
||||
</div>
|
||||
@ -34,7 +34,7 @@
|
||||
<input class="immich-form-input" id="name" name="name" type="text" bind:value={apiKey.name} />
|
||||
</div>
|
||||
|
||||
<div class="flex w-full px-4 gap-4 mt-8">
|
||||
<div class="mt-8 flex w-full gap-4 px-4">
|
||||
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
|
||||
<Button type="submit" fullwidth>{submitText}</Button>
|
||||
</div>
|
||||
|
@ -31,13 +31,13 @@
|
||||
|
||||
<FullScreenModal>
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg"
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
>
|
||||
<KeyVariant size="4em" />
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">API Key</h1>
|
||||
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">API Key</h1>
|
||||
|
||||
<p class="text-sm dark:text-immich-dark-fg">
|
||||
This value will only be shown once. Please be sure to copy it before closing the window.
|
||||
@ -49,7 +49,7 @@
|
||||
<textarea class="immich-form-input" id="secret" name="secret" readonly={true} value={secret} />
|
||||
</div>
|
||||
|
||||
<div class="flex w-full px-4 gap-4 mt-8">
|
||||
<div class="mt-8 flex w-full gap-4 px-4">
|
||||
{#if canCopyImagesToClipboard}
|
||||
<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button>
|
||||
{/if}
|
||||
|
@ -46,7 +46,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={changePassword} method="post" class="flex flex-col gap-5 mt-5">
|
||||
<form on:submit|preventDefault={changePassword} method="post" class="mt-5 flex flex-col gap-5">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="password">New Password</label>
|
||||
<input
|
||||
@ -74,11 +74,11 @@
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<p class="text-red-400 text-sm">{error}</p>
|
||||
<p class="text-sm text-red-400">{error}</p>
|
||||
{/if}
|
||||
|
||||
{#if success}
|
||||
<p class="text-immich-primary text-sm">{success}</p>
|
||||
<p class="text-sm text-immich-primary">{success}</p>
|
||||
{/if}
|
||||
<div class="my-5 flex w-full">
|
||||
<Button type="submit" size="lg" fullwidth>Change password</Button>
|
||||
|
@ -78,12 +78,12 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg"
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div class="flex flex-col place-items-center place-content-center gap-4 px-4">
|
||||
<div class="flex flex-col place-content-center place-items-center gap-4 px-4">
|
||||
<ImmichLogo class="text-center" height="100" width="100" />
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Create new user</h1>
|
||||
<p class="text-sm border rounded-md p-4 font-mono text-gray-600 dark:border-immich-dark-bg dark:text-gray-300">
|
||||
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Create new user</h1>
|
||||
<p class="rounded-md border p-4 font-mono text-sm text-gray-600 dark:border-immich-dark-bg dark:text-gray-300">
|
||||
Please provide your user with the password, they will have to change it on their first sign in.
|
||||
</p>
|
||||
</div>
|
||||
@ -122,11 +122,11 @@
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<p class="text-red-400 ml-4 text-sm">{error}</p>
|
||||
<p class="ml-4 text-sm text-red-400">{error}</p>
|
||||
{/if}
|
||||
|
||||
{#if success}
|
||||
<p class="text-immich-primary ml-4 text-sm">{success}</p>
|
||||
<p class="ml-4 text-sm text-immich-primary">{success}</p>
|
||||
{/if}
|
||||
<div class="flex w-full p-4">
|
||||
<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button>
|
||||
|
@ -67,13 +67,13 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg"
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
>
|
||||
<AccountEditOutline size="4em" />
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Edit user</h1>
|
||||
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Edit user</h1>
|
||||
</div>
|
||||
|
||||
<form on:submit|preventDefault={editUser} autocomplete="off">
|
||||
@ -134,13 +134,13 @@
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<p class="text-red-400 ml-4 text-sm">{error}</p>
|
||||
<p class="ml-4 text-sm text-red-400">{error}</p>
|
||||
{/if}
|
||||
|
||||
{#if success}
|
||||
<p class="text-immich-primary ml-4 text-sm">{success}</p>
|
||||
<p class="ml-4 text-sm text-immich-primary">{success}</p>
|
||||
{/if}
|
||||
<div class="flex w-full px-4 gap-4 mt-8">
|
||||
<div class="mt-8 flex w-full gap-4 px-4">
|
||||
{#if canResetPassword}
|
||||
<Button color="light-red" fullwidth on:click={() => (isShowResetPasswordConfirmation = true)}
|
||||
>Reset password</Button
|
||||
|
@ -79,7 +79,7 @@
|
||||
</script>
|
||||
|
||||
{#if authConfig.passwordLoginEnabled}
|
||||
<form on:submit|preventDefault={login} class="flex flex-col gap-5 mt-5">
|
||||
<form on:submit|preventDefault={login} class="mt-5 flex flex-col gap-5">
|
||||
{#if errorMessage}
|
||||
<p class="text-red-400" transition:fade>
|
||||
{errorMessage}
|
||||
@ -128,10 +128,10 @@
|
||||
|
||||
{#if authConfig.enabled}
|
||||
{#if authConfig.passwordLoginEnabled}
|
||||
<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" />
|
||||
<div class="inline-flex w-full items-center justify-center">
|
||||
<hr class="my-4 h-px w-3/4 border-0 bg-gray-200 dark:bg-gray-600" />
|
||||
<span
|
||||
class="absolute px-3 font-medium text-gray-900 -translate-x-1/2 left-1/2 dark:text-white bg-white dark:bg-immich-dark-gray"
|
||||
class="absolute left-1/2 -translate-x-1/2 bg-white px-3 font-medium text-gray-900 dark:bg-immich-dark-gray dark:text-white"
|
||||
>
|
||||
or
|
||||
</span>
|
||||
@ -162,5 +162,5 @@
|
||||
{/if}
|
||||
|
||||
{#if !authConfig.enabled && !authConfig.passwordLoginEnabled}
|
||||
<p class="text-center dark:text-immich-dark-fg p-4">Login has been disabled.</p>
|
||||
<p class="p-4 text-center dark:text-immich-dark-fg">Login has been disabled.</p>
|
||||
{/if}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<slot name="header" />
|
||||
</header>
|
||||
<main
|
||||
class="grid md:grid-cols-[theme(spacing.64)_auto] grid-cols-[theme(spacing.18)_auto] relative pt-[var(--navbar-height)] h-screen overflow-hidden bg-immich-bg dark:bg-immich-dark-bg"
|
||||
class="relative grid h-screen grid-cols-[theme(spacing.18)_auto] overflow-hidden bg-immich-bg pt-[var(--navbar-height)] dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
|
||||
>
|
||||
<slot name="sidebar">
|
||||
<SideBar />
|
||||
@ -26,13 +26,13 @@
|
||||
{#if title}
|
||||
<section class="relative">
|
||||
<div
|
||||
class="absolute border-b dark:border-immich-dark-gray flex justify-between place-items-center dark:text-immich-dark-fg w-full p-4 h-16"
|
||||
class="absolute flex h-16 w-full place-items-center justify-between border-b p-4 dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<p class="font-medium">{title}</p>
|
||||
<slot name="buttons" />
|
||||
</div>
|
||||
|
||||
<div class="absolute overflow-y-auto top-16 h-[calc(100%-theme(spacing.16))] w-full immich-scrollbar p-4 pb-8">
|
||||
<div class="immich-scrollbar absolute top-16 h-[calc(100%-theme(spacing.16))] w-full overflow-y-auto p-4 pb-8">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
|
@ -20,9 +20,9 @@
|
||||
|
||||
<FullScreenModal on:clickOutside={() => dispatch('close')}>
|
||||
<div
|
||||
class="flex flex-col gap-8 border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-8 shadow-sm w-96 max-w-lg rounded-3xl"
|
||||
class="flex w-96 max-w-lg flex-col gap-8 rounded-3xl border bg-white p-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||
>
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium self-center">Map Settings</h1>
|
||||
<h1 class="self-center text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Map Settings</h1>
|
||||
|
||||
<form
|
||||
on:submit|preventDefault={() => dispatch('save', settings)}
|
||||
@ -32,8 +32,8 @@
|
||||
<SettingSwitch title="Only favorites" bind:checked={settings.onlyFavorites} />
|
||||
{#if customDateRange}
|
||||
<div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4">
|
||||
<div class="flex justify-between items-center gap-8">
|
||||
<label class="immich-form-label text-sm shrink-0" for="date-after">Date after</label>
|
||||
<div class="flex items-center justify-between gap-8">
|
||||
<label class="immich-form-label shrink-0 text-sm" for="date-after">Date after</label>
|
||||
<input
|
||||
class="immich-form-input w-40"
|
||||
type="date"
|
||||
@ -42,8 +42,8 @@
|
||||
bind:value={settings.dateAfter}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-between items-center gap-8">
|
||||
<label class="immich-form-label text-sm shrink-0" for="date-before">Date before</label>
|
||||
<div class="flex items-center justify-between gap-8">
|
||||
<label class="immich-form-label shrink-0 text-sm" for="date-before">Date before</label>
|
||||
<input class="immich-form-input w-40" type="date" id="date-before" bind:value={settings.dateBefore} />
|
||||
</div>
|
||||
<div class="flex justify-center text-xs">
|
||||
@ -104,7 +104,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex w-full gap-4 mt-4">
|
||||
<div class="mt-4 flex w-full gap-4">
|
||||
<Button color="gray" size="sm" fullwidth on:click={() => dispatch('close')}>Cancel</Button>
|
||||
<Button type="submit" size="sm" fullwidth>Save</Button>
|
||||
</div>
|
||||
|
@ -111,12 +111,12 @@
|
||||
</svelte:fragment>
|
||||
|
||||
{#if !galleryInView}
|
||||
<div class="flex place-items-center place-content-center overflow-hidden gap-2">
|
||||
<div class="flex place-content-center place-items-center gap-2 overflow-hidden">
|
||||
<CircleIconButton logo={paused ? Play : Pause} forceDark on:click={() => (paused = !paused)} />
|
||||
|
||||
{#each currentMemory.assets as _, i}
|
||||
<button class="relative w-full py-2" on:click={() => goto(`?memory=${memoryIndex}&asset=${i}`)}>
|
||||
<span class="absolute left-0 w-full h-[2px] bg-gray-500" />
|
||||
<span class="absolute left-0 h-[2px] w-full bg-gray-500" />
|
||||
{#await resetPromise}
|
||||
<span class="absolute left-0 h-[2px] bg-white" style:width={`${i < assetIndex ? 100 : 0}%`} />
|
||||
{:then}
|
||||
@ -139,7 +139,7 @@
|
||||
|
||||
{#if galleryInView}
|
||||
<div
|
||||
class="sticky top-20 flex place-content-center place-items-center z-30 transition-opacity"
|
||||
class="sticky top-20 z-30 flex place-content-center place-items-center transition-opacity"
|
||||
class:opacity-0={!galleryInView}
|
||||
class:opacity-100={galleryInView}
|
||||
>
|
||||
@ -149,28 +149,28 @@
|
||||
</div>
|
||||
{/if}
|
||||
<!-- Viewer -->
|
||||
<section class="pt-20 overflow-hidden">
|
||||
<section class="overflow-hidden pt-20">
|
||||
<div
|
||||
class="flex w-[300%] h-[calc(100vh_-_180px)] items-center justify-center box-border ml-[-100%] gap-10 overflow-hidden"
|
||||
class="ml-[-100%] box-border flex h-[calc(100vh_-_180px)] w-[300%] items-center justify-center gap-10 overflow-hidden"
|
||||
>
|
||||
<!-- PREVIOUS MEMORY -->
|
||||
<div
|
||||
class="rounded-2xl w-[20vw] h-1/2"
|
||||
class="h-1/2 w-[20vw] rounded-2xl"
|
||||
class:opacity-25={previousMemory}
|
||||
class:opacity-0={!previousMemory}
|
||||
class:hover:opacity-70={previousMemory}
|
||||
>
|
||||
<button class="rounded-2xl h-full w-full relative" disabled={!previousMemory} on:click={toPreviousMemory}>
|
||||
<button class="relative h-full w-full rounded-2xl" disabled={!previousMemory} on:click={toPreviousMemory}>
|
||||
<img
|
||||
class="rounded-2xl h-full w-full object-cover"
|
||||
class="h-full w-full rounded-2xl object-cover"
|
||||
src={previousMemory ? api.getAssetThumbnailUrl(previousMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
|
||||
{#if previousMemory}
|
||||
<div class="absolute right-4 bottom-4 text-white text-left">
|
||||
<p class="font-semibold text-xs text-gray-200">PREVIOUS</p>
|
||||
<div class="absolute bottom-4 right-4 text-left text-white">
|
||||
<p class="text-xs font-semibold text-gray-200">PREVIOUS</p>
|
||||
<p class="text-xl">{previousMemory.title}</p>
|
||||
</div>
|
||||
{/if}
|
||||
@ -179,19 +179,19 @@
|
||||
|
||||
<!-- CURRENT MEMORY -->
|
||||
<div
|
||||
class="main-view rounded-2xl h-full relative w-[70vw] bg-black flex place-items-center place-content-center"
|
||||
class="main-view relative flex h-full w-[70vw] place-content-center place-items-center rounded-2xl bg-black"
|
||||
>
|
||||
<div class="bg-black w-full h-full rounded-2xl">
|
||||
<div class="h-full w-full rounded-2xl bg-black">
|
||||
<!-- CONTROL BUTTONS -->
|
||||
<div class="absolute h-full flex justify-between w-full">
|
||||
<div class="flex h-full flex-col place-content-center place-items-center ml-4">
|
||||
<div class="absolute flex h-full w-full justify-between">
|
||||
<div class="ml-4 flex h-full flex-col place-content-center place-items-center">
|
||||
<div class="inline-block">
|
||||
{#if canGoBack}
|
||||
<CircleIconButton logo={ChevronLeft} backgroundColor="#202123" on:click={toPrevious} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-full flex-col place-content-center place-items-center mr-4">
|
||||
<div class="mr-4 flex h-full flex-col place-content-center place-items-center">
|
||||
<div class="inline-block">
|
||||
{#if canGoForward}
|
||||
<CircleIconButton logo={ChevronRight} backgroundColor="#202123" on:click={toNext} />
|
||||
@ -203,14 +203,14 @@
|
||||
{#key currentAsset.id}
|
||||
<img
|
||||
transition:fade
|
||||
class="rounded-2xl w-full h-full object-contain transition-all"
|
||||
class="h-full w-full rounded-2xl object-contain transition-all"
|
||||
src={api.getAssetThumbnailUrl(currentAsset.id, 'JPEG')}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
{/key}
|
||||
|
||||
<div class="absolute top-4 left-8 text-white text-sm font-medium">
|
||||
<div class="absolute left-8 top-4 text-sm font-medium text-white">
|
||||
<p>
|
||||
{DateTime.fromISO(currentMemory.assets[0].fileCreatedAt).toLocaleString(DateTime.DATE_FULL)}
|
||||
</p>
|
||||
@ -224,22 +224,22 @@
|
||||
|
||||
<!-- NEXT MEMORY -->
|
||||
<div
|
||||
class="rounded-xl w-[20vw] h-1/2"
|
||||
class="h-1/2 w-[20vw] rounded-xl"
|
||||
class:opacity-25={nextMemory}
|
||||
class:opacity-0={!nextMemory}
|
||||
class:hover:opacity-70={nextMemory}
|
||||
>
|
||||
<button class="rounded-2xl h-full w-full relative" on:click={toNextMemory} disabled={!nextMemory}>
|
||||
<button class="relative h-full w-full rounded-2xl" on:click={toNextMemory} disabled={!nextMemory}>
|
||||
<img
|
||||
class="rounded-2xl h-full w-full object-cover"
|
||||
class="h-full w-full rounded-2xl object-cover"
|
||||
src={nextMemory ? api.getAssetThumbnailUrl(nextMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
|
||||
{#if nextMemory}
|
||||
<div class="absolute left-4 bottom-4 text-white text-left">
|
||||
<p class="font-semibold text-xs text-gray-200">UP NEXT</p>
|
||||
<div class="absolute bottom-4 left-4 text-left text-white">
|
||||
<p class="text-xs font-semibold text-gray-200">UP NEXT</p>
|
||||
<p class="text-xl">{nextMemory.title}</p>
|
||||
</div>
|
||||
{/if}
|
||||
@ -252,7 +252,7 @@
|
||||
|
||||
<section class="bg-immich-dark-gray pl-4">
|
||||
<div
|
||||
class="sticky flex place-content-center place-items-center mb-10 mt-4 transition-all"
|
||||
class="sticky mb-10 mt-4 flex place-content-center place-items-center transition-all"
|
||||
class:opacity-0={galleryInView}
|
||||
class:opacity-100={!galleryInView}
|
||||
>
|
||||
|
@ -155,7 +155,7 @@
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="flex flex-col mt-5"
|
||||
class="mt-5 flex flex-col"
|
||||
on:mouseenter={() => {
|
||||
isMouseOverGroup = true;
|
||||
assetMouseEventHandler(dateGroupTitle, null);
|
||||
@ -167,7 +167,7 @@
|
||||
>
|
||||
<!-- Date group title -->
|
||||
<p
|
||||
class="font-medium text-xs md:text-sm text-immich-fg dark:text-immich-dark-fg mb-2 flex place-items-center h-6"
|
||||
class="mb-2 flex h-6 place-items-center text-xs font-medium text-immich-fg dark:text-immich-dark-fg md:text-sm"
|
||||
style="width: {geometry[groupIndex].containerWidth}px"
|
||||
>
|
||||
{#if (hoveredDateGroup == dateGroupTitle && isMouseOverGroup) || $selectedGroup.has(dateGroupTitle)}
|
||||
@ -185,7 +185,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<span class="first-letter:capitalize truncate" title={dateGroupTitle}>
|
||||
<span class="truncate first-letter:capitalize" title={dateGroupTitle}>
|
||||
{dateGroupTitle}
|
||||
</span>
|
||||
</p>
|
||||
|
@ -283,7 +283,7 @@
|
||||
<!-- Right margin MUST be equal to the width of immich-scrubbable-scrollbar -->
|
||||
<section
|
||||
id="asset-grid"
|
||||
class="overflow-y-auto ml-4 mb-4 mr-[60px] scrollbar-hidden"
|
||||
class="scrollbar-hidden mb-4 ml-4 mr-[60px] overflow-y-auto"
|
||||
bind:clientHeight={viewportHeight}
|
||||
bind:clientWidth={viewportWidth}
|
||||
bind:this={assetGridElement}
|
||||
|
@ -37,7 +37,7 @@
|
||||
<section
|
||||
id="memory-lane"
|
||||
bind:this={memoryLaneElement}
|
||||
class="relative overflow-x-hidden whitespace-nowrap mt-5 transition-all"
|
||||
class="relative mt-5 overflow-x-hidden whitespace-nowrap transition-all"
|
||||
bind:offsetWidth
|
||||
on:scroll={onScroll}
|
||||
>
|
||||
@ -46,7 +46,7 @@
|
||||
{#if canScrollLeft}
|
||||
<div class="absolute left-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}>
|
||||
<button
|
||||
class="rounded-full opacity-50 hover:opacity-100 p-2 border border-gray-500 bg-gray-100 text-gray-500"
|
||||
class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
|
||||
on:click={scrollLeft}
|
||||
>
|
||||
<ChevronLeft size="36" /></button
|
||||
@ -56,7 +56,7 @@
|
||||
{#if canScrollRight}
|
||||
<div class="absolute right-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}>
|
||||
<button
|
||||
class="rounded-full opacity-50 hover:opacity-100 p-2 border border-gray-500 bg-gray-100 text-gray-500"
|
||||
class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
|
||||
on:click={scrollRight}
|
||||
>
|
||||
<ChevronRight size="36" /></button
|
||||
@ -69,18 +69,18 @@
|
||||
<div class="inline-block" bind:offsetWidth={innerWidth}>
|
||||
{#each $memoryStore as memory, i (memory.title)}
|
||||
<button
|
||||
class="memory-card relative inline-block mr-8 rounded-xl aspect-video h-[215px]"
|
||||
class="memory-card relative mr-8 inline-block aspect-video h-[215px] rounded-xl"
|
||||
on:click={() => goto(`/memory?memory=${i}`)}
|
||||
>
|
||||
<img
|
||||
class="rounded-xl h-full w-full object-cover"
|
||||
class="h-full w-full rounded-xl object-cover"
|
||||
src={api.getAssetThumbnailUrl(memory.assets[0].id, 'JPEG')}
|
||||
alt={memory.title}
|
||||
draggable="false"
|
||||
/>
|
||||
<p class="absolute bottom-2 left-4 text-lg text-white z-10">{memory.title}</p>
|
||||
<p class="absolute bottom-2 left-4 z-10 text-lg text-white">{memory.title}</p>
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent z-0 hover:bg-black/20 transition-all"
|
||||
class="absolute left-0 top-0 z-0 h-full w-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent transition-all hover:bg-black/20"
|
||||
/>
|
||||
</button>
|
||||
{/each}
|
||||
|
@ -86,7 +86,7 @@
|
||||
<svelte:fragment slot="leading">
|
||||
<a
|
||||
data-sveltekit-preload-data="hover"
|
||||
class="flex gap-2 place-items-center hover:cursor-pointer ml-6"
|
||||
class="ml-6 flex place-items-center gap-2 hover:cursor-pointer"
|
||||
href="https://immich.app"
|
||||
>
|
||||
<ImmichLogo height="30" width="30" />
|
||||
@ -105,7 +105,7 @@
|
||||
</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
{/if}
|
||||
<section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40">
|
||||
<section class="my-[160px] flex flex-col px-6 sm:px-12 md:px-24 lg:px-40">
|
||||
<GalleryViewer {assets} {sharedLink} bind:selectedAssets viewFrom="shared-link-page" />
|
||||
</section>
|
||||
</section>
|
||||
|
@ -49,23 +49,23 @@
|
||||
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<p class="font-medium">
|
||||
Add to {#if shared}Shared {/if} Album
|
||||
</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
|
||||
<div class="max-h-[400px] flex flex-col mb-2">
|
||||
<div class="mb-2 flex max-h-[400px] flex-col">
|
||||
{#if loading}
|
||||
{#each { length: 3 } as _}
|
||||
<div class="animate-pulse flex gap-4 px-6 py-2">
|
||||
<div class="h-12 w-12 bg-slate-200 rounded-xl" />
|
||||
<div class="flex animate-pulse gap-4 px-6 py-2">
|
||||
<div class="h-12 w-12 rounded-xl bg-slate-200" />
|
||||
<div class="flex flex-col items-start justify-center gap-2">
|
||||
<span class="animate-pulse w-36 h-4 bg-slate-200" />
|
||||
<span class="h-4 w-36 animate-pulse bg-slate-200" />
|
||||
<div class="flex animate-pulse gap-1">
|
||||
<span class="w-8 h-3 bg-slate-200" />
|
||||
<span class="w-20 h-3 bg-slate-200" />
|
||||
<span class="h-3 w-8 bg-slate-200" />
|
||||
<span class="h-3 w-20 bg-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -73,17 +73,17 @@
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input
|
||||
class="px-6 py-2 text-2xl border-b-4 bg-immich-bg border-immich-bg focus:border-immich-primary dark:bg-immich-dark-gray dark:border-immich-dark-gray dark:focus:border-immich-dark-primary"
|
||||
class="border-b-4 border-immich-bg bg-immich-bg px-6 py-2 text-2xl focus:border-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:focus:border-immich-dark-primary"
|
||||
placeholder="Search"
|
||||
autofocus
|
||||
bind:value={search}
|
||||
/>
|
||||
<div class="overflow-y-auto immich-scrollbar">
|
||||
<div class="immich-scrollbar overflow-y-auto">
|
||||
<button
|
||||
on:click={handleNew}
|
||||
class="w-full flex gap-4 px-6 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors items-center"
|
||||
class="flex w-full items-center gap-4 px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div class="h-12 w-12 flex justify-center items-center">
|
||||
<div class="flex h-12 w-12 items-center justify-center">
|
||||
<Plus size="30" />
|
||||
</div>
|
||||
<p class="">
|
||||
@ -92,14 +92,14 @@
|
||||
</button>
|
||||
{#if filteredAlbums.length > 0}
|
||||
{#if !shared && search.length === 0}
|
||||
<p class="text-xs px-5 py-3">RECENT</p>
|
||||
<p class="px-5 py-3 text-xs">RECENT</p>
|
||||
{#each recentAlbums as album (album.id)}
|
||||
<AlbumListItem variant="simple" {album} on:album={() => handleSelect(album)} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if !shared}
|
||||
<p class="text-xs px-5 py-3">
|
||||
<p class="px-5 py-3 text-xs">
|
||||
{#if search.length === 0}ALL {/if}ALBUMS
|
||||
</p>
|
||||
{/if}
|
||||
@ -107,9 +107,9 @@
|
||||
<AlbumListItem {album} searchQuery={search} on:album={() => handleSelect(album)} />
|
||||
{/each}
|
||||
{:else if albums.length > 0}
|
||||
<p class="text-sm px-5 py-1">It looks like you do not have any albums with this name yet.</p>
|
||||
<p class="px-5 py-1 text-sm">It looks like you do not have any albums with this name yet.</p>
|
||||
{:else}
|
||||
<p class="text-sm px-5 py-1">It looks like you do not have any albums yet.</p>
|
||||
<p class="px-5 py-1 text-sm">It looks like you do not have any albums yet.</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -31,14 +31,14 @@
|
||||
id="immich-modal"
|
||||
style:z-index={zIndex}
|
||||
transition:fade={{ duration: 100, easing: quintOut }}
|
||||
class="fixed top-0 left-0 w-full h-full bg-black/50 flex place-items-center place-content-center overflow-hidden"
|
||||
class="fixed left-0 top-0 flex h-full w-full place-content-center place-items-center overflow-hidden bg-black/50"
|
||||
>
|
||||
<div
|
||||
use:clickOutside
|
||||
on:outclick={() => dispatch('close')}
|
||||
class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg w-[450px] min-h-[200px] max-h-[600px] rounded-lg shadow-md"
|
||||
class="max-h-[600px] min-h-[200px] w-[450px] rounded-lg bg-immich-bg shadow-md dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div class="flex justify-between place-items-center px-5 py-3">
|
||||
<div class="flex place-items-center justify-between px-5 py-3">
|
||||
<div>
|
||||
<slot name="title">
|
||||
<p>Modal Title</p>
|
||||
|
@ -26,23 +26,23 @@
|
||||
|
||||
<FullScreenModal on:clickOutside={handleCancel}>
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg"
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
>
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium pb-2">
|
||||
<h1 class="pb-2 text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<div class="px-4 py-5 text-md text-center">
|
||||
<div class="text-md px-4 py-5 text-center">
|
||||
<slot name="prompt">
|
||||
<p>{prompt}</p>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="flex w-full px-4 gap-4 mt-4">
|
||||
<div class="mt-4 flex w-full gap-4 px-4">
|
||||
{#if !hideCancelButton}
|
||||
<Button color={cancelColor} fullwidth on:click={handleCancel}>
|
||||
{cancelText}
|
||||
|
@ -23,7 +23,7 @@
|
||||
<div
|
||||
transition:slide={{ duration: 200, easing: quintOut }}
|
||||
bind:this={menuElement}
|
||||
class="absolute w-[200px] z-[99999] rounded-lg overflow-hidden shadow-lg"
|
||||
class="absolute z-[99999] w-[200px] overflow-hidden rounded-lg shadow-lg"
|
||||
style="left: {left}px; top: {top}px;"
|
||||
role="menu"
|
||||
use:clickOutside
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<button
|
||||
on:click
|
||||
class="bg-slate-100 hover:bg-gray-200 text-immich-fg dark:text-immich-dark-bg p-4 w-full text-left text-sm font-medium focus:outline-none focus:ring-inset focus:ring-2"
|
||||
class="w-full bg-slate-100 p-4 text-left text-sm font-medium text-immich-fg hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-inset dark:text-immich-dark-bg"
|
||||
role="menuitem"
|
||||
>
|
||||
{#if text}
|
||||
|
@ -40,14 +40,14 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div in:fly={{ y: 10, duration: 200 }} class="fixed top-0 w-full bg-transparent z-[100]">
|
||||
<div in:fly={{ y: 10, duration: 200 }} class="fixed top-0 z-[100] w-full bg-transparent">
|
||||
<div
|
||||
id="asset-selection-app-bar"
|
||||
class={`grid grid-cols-3 justify-between ${appBarBorder} rounded-lg p-2 mx-2 mt-2 transition-all place-items-center ${tailwindClasses} dark:bg-immich-dark-gray ${
|
||||
class={`grid grid-cols-3 justify-between ${appBarBorder} mx-2 mt-2 place-items-center rounded-lg p-2 transition-all ${tailwindClasses} dark:bg-immich-dark-gray ${
|
||||
forceDark && 'bg-immich-dark-gray text-white'
|
||||
}`}
|
||||
>
|
||||
<div class="flex place-items-center gap-6 dark:text-immich-dark-fg justify-self-start">
|
||||
<div class="flex place-items-center gap-6 justify-self-start dark:text-immich-dark-fg">
|
||||
{#if showBackButton}
|
||||
<CircleIconButton
|
||||
on:click={() => dispatch('close-button-click')}
|
||||
@ -65,7 +65,7 @@
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div class="flex place-items-center gap-1 mr-4 justify-self-end">
|
||||
<div class="mr-4 flex place-items-center gap-1 justify-self-end">
|
||||
<slot name="trailing" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -140,7 +140,7 @@
|
||||
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<Link size={24} />
|
||||
{#if editingLink}
|
||||
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Edit link</p>
|
||||
@ -175,10 +175,10 @@
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="mt-4 mb-2">
|
||||
<div class="mb-2 mt-4">
|
||||
<p class="text-xs">LINK OPTIONS</p>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-100 dark:bg-black/40 rounded-lg">
|
||||
<div class="rounded-lg bg-gray-100 p-4 dark:bg-black/40">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-2">
|
||||
<SettingInputField inputType={SettingInputFieldType.TEXT} label="Description" bind:value={description} />
|
||||
@ -198,11 +198,11 @@
|
||||
|
||||
<div class="text-sm">
|
||||
{#if editingLink}
|
||||
<p class="my-2 immich-form-label">
|
||||
<p class="immich-form-label my-2">
|
||||
<SettingSwitch bind:checked={shouldChangeExpirationTime} title={'Change expiration time'} />
|
||||
</p>
|
||||
{:else}
|
||||
<p class="my-2 immich-form-label">Expire after</p>
|
||||
<p class="immich-form-label my-2">Expire after</p>
|
||||
{/if}
|
||||
|
||||
<DropdownButton
|
||||
|
@ -26,7 +26,7 @@
|
||||
{#if dragStartTarget}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="fixed inset-0 w-full h-full z-[1000] flex flex-col items-center justify-center bg-gray-100/90 dark:bg-immich-dark-bg/90 text-immich-dark-gray dark:text-immich-gray"
|
||||
class="fixed inset-0 z-[1000] flex h-full w-full flex-col items-center justify-center bg-gray-100/90 text-immich-dark-gray dark:bg-immich-dark-bg/90 dark:text-immich-gray"
|
||||
transition:fade={{ duration: 250 }}
|
||||
on:dragover={(e) => {
|
||||
// Prevent browser from opening the dropped file.
|
||||
@ -34,7 +34,7 @@
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<ImmichLogo class="animate-bounce w-48 m-16" />
|
||||
<ImmichLogo class="m-16 w-48 animate-bounce" />
|
||||
<div class="text-2xl">Drop files anywhere to upload</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -25,7 +25,7 @@
|
||||
{disabled}
|
||||
on:click={toggle}
|
||||
aria-expanded={isOpen}
|
||||
class="bg-gray-200 w-full flex p-2 rounded-lg dark:bg-gray-600 place-items-center justify-between disabled:cursor-not-allowed dark:disabled:bg-gray-300 disabled:bg-gray-600"
|
||||
class="flex w-full place-items-center justify-between rounded-lg bg-gray-200 p-2 disabled:cursor-not-allowed disabled:bg-gray-600 dark:bg-gray-600 dark:disabled:bg-gray-300"
|
||||
>
|
||||
<div>
|
||||
{selected}
|
||||
@ -49,14 +49,14 @@
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
<div class="flex flex-col mt-2 absolute w-full">
|
||||
<div class="absolute mt-2 flex w-full flex-col">
|
||||
{#each options.options as option}
|
||||
<button
|
||||
on:click={() => {
|
||||
selected = option;
|
||||
isOpen = false;
|
||||
}}
|
||||
class="bg-gray-200 dark:bg-gray-500 dark:hover:bg-gray-700 w-full flex p-2 hover:bg-gray-300 transition-all"
|
||||
class="flex w-full bg-gray-200 p-2 transition-all hover:bg-gray-300 dark:bg-gray-500 dark:hover:bg-gray-700"
|
||||
>
|
||||
{option}
|
||||
</button>
|
||||
|
@ -13,16 +13,16 @@
|
||||
<div
|
||||
on:click={actionHandler}
|
||||
on:keydown={actionHandler}
|
||||
class="border dark:border-immich-dark-gray {hoverClasses} p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center"
|
||||
class="border dark:border-immich-dark-gray {hoverClasses} m-auto mt-10 flex w-[50%] flex-col place-content-center place-items-center rounded-3xl bg-gray-50 p-5 dark:bg-immich-dark-gray"
|
||||
>
|
||||
<img src={empty1Url} {alt} width="500" draggable="false" />
|
||||
<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg">{text}</p>
|
||||
<p class="text-immich-text-gray-500 text-center dark:text-immich-dark-fg">{text}</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="border dark:border-immich-dark-gray p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center"
|
||||
class="m-auto mt-10 flex w-[50%] flex-col place-content-center place-items-center rounded-3xl border bg-gray-50 p-5 dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||
>
|
||||
<img src={empty1Url} {alt} width="500" draggable="false" />
|
||||
<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg">{text}</p>
|
||||
<p class="text-immich-text-gray-500 text-center dark:text-immich-dark-fg">{text}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<section
|
||||
in:fade={{ duration: 100 }}
|
||||
out:fade={{ duration: 100 }}
|
||||
class="fixed left-0 top-0 w-screen h-screen bg-black/40 z-[990] flex place-items-center place-content-center"
|
||||
class="fixed left-0 top-0 z-[990] flex h-screen w-screen place-content-center place-items-center bg-black/40"
|
||||
>
|
||||
<div class="z-[9999]" use:clickOutside on:outclick={() => dispatch('clickOutside')}>
|
||||
<slot />
|
||||
|
@ -5,20 +5,20 @@
|
||||
export let showMessage = $$slots.message;
|
||||
</script>
|
||||
|
||||
<section class="min-h-screen w-screen flex place-items-center place-content-center p-4">
|
||||
<section class="flex min-h-screen w-screen place-content-center place-items-center p-4">
|
||||
<div
|
||||
class="flex flex-col gap-4 border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-8 shadow-sm w-full max-w-lg rounded-3xl"
|
||||
class="flex w-full max-w-lg flex-col gap-4 rounded-3xl border bg-white p-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||
>
|
||||
<div class="flex flex-col place-items-center place-content-center gap-4 py-4">
|
||||
<div class="flex flex-col place-content-center place-items-center gap-4 py-4">
|
||||
<ImmichLogo class="h-24 w-24" />
|
||||
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
|
||||
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{title}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{#if showMessage}
|
||||
<div
|
||||
class="text-sm rounded-xl p-4 text-immich-primary dark:text-immich-dark-primary font-medium bg-immich-primary/5 dark:border-immich-dark-bg w-full border-immich-primary border-2"
|
||||
class="w-full rounded-xl border-2 border-immich-primary bg-immich-primary/5 p-4 text-sm font-medium text-immich-primary dark:border-immich-dark-bg dark:text-immich-dark-primary"
|
||||
>
|
||||
<slot name="message" />
|
||||
</div>
|
||||
|
@ -28,7 +28,7 @@
|
||||
</script>
|
||||
|
||||
{#if assets.length > 0}
|
||||
<div class="flex flex-wrap gap-1 w-full pb-20" bind:clientWidth={viewWidth}>
|
||||
<div class="flex w-full flex-wrap gap-1 pb-20" bind:clientWidth={viewWidth}>
|
||||
{#each assets as asset (asset.id)}
|
||||
<div animate:flip={{ duration: 500 }}>
|
||||
<Thumbnail
|
||||
|
@ -98,7 +98,7 @@
|
||||
</script>
|
||||
|
||||
{#if assets.length > 0}
|
||||
<div class="flex flex-wrap gap-1 w-full pb-20" bind:clientWidth={viewWidth}>
|
||||
<div class="flex w-full flex-wrap gap-1 pb-20" bind:clientWidth={viewWidth}>
|
||||
{#each assets as asset (asset.id)}
|
||||
<div animate:flip={{ duration: 500 }}>
|
||||
<Thumbnail
|
||||
|
@ -37,7 +37,7 @@
|
||||
$: if (map) map.setView(center, zoom);
|
||||
</script>
|
||||
|
||||
<div bind:this={container} class="w-full h-full" class:map-dark={allowDarkMode}>
|
||||
<div bind:this={container} class="h-full w-full" class:map-dark={allowDarkMode}>
|
||||
{#if map}
|
||||
<slot />
|
||||
{/if}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div>
|
||||
<svg
|
||||
role="status"
|
||||
class={`w-[24px] h-[24px] text-gray-400 animate-spin dark:text-gray-600 fill-immich-primary`}
|
||||
class={`h-[24px] w-[24px] animate-spin fill-immich-primary text-gray-400 dark:text-gray-600`}
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -17,15 +17,15 @@
|
||||
in:fade={{ duration: 100 }}
|
||||
out:fade={{ duration: 100 }}
|
||||
id="account-info-panel"
|
||||
class="absolute right-[25px] top-[75px] bg-gray-200 dark:bg-immich-dark-gray dark:border dark:border-immich-dark-gray shadow-lg rounded-3xl w-[360px] z-[100]"
|
||||
class="absolute right-[25px] top-[75px] z-[100] w-[360px] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col items-center justify-center gap-4 bg-white dark:bg-immich-dark-primary/10 rounded-3xl mx-4 mt-4 p-4"
|
||||
class="mx-4 mt-4 flex flex-col items-center justify-center gap-4 rounded-3xl bg-white p-4 dark:bg-immich-dark-primary/10"
|
||||
>
|
||||
<UserAvatar size="lg" {user} />
|
||||
|
||||
<div>
|
||||
<p class="text-lg text-immich-primary dark:text-immich-dark-primary font-medium text-center">
|
||||
<p class="text-center text-lg font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{user.firstName}
|
||||
{user.lastName}
|
||||
</p>
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
<a href={AppRoute.USER_SETTINGS} on:click={() => dispatch('close')}>
|
||||
<Button color="dark-gray" size="sm" shadow={false} border>
|
||||
<div class="flex gap-2 place-items-center place-content-center px-2">
|
||||
<div class="flex place-content-center place-items-center gap-2 px-2">
|
||||
<Cog size="18" />
|
||||
Account Settings
|
||||
</div>
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
<div class="mb-4 flex flex-col">
|
||||
<button
|
||||
class="py-3 w-full font-medium flex place-items-center gap-2 hover:bg-immich-primary/10 text-gray-500 dark:text-gray-300 place-content-center"
|
||||
class="flex w-full place-content-center place-items-center gap-2 py-3 font-medium text-gray-500 hover:bg-immich-primary/10 dark:text-gray-300"
|
||||
on:click={() => dispatch('logout')}
|
||||
>
|
||||
<Logout size={24} />
|
||||
|
@ -33,23 +33,23 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<section id="dashboard-navbar" class="fixed h-[var(--navbar-height)] w-screen z-[900] text-sm">
|
||||
<section id="dashboard-navbar" class="fixed z-[900] h-[var(--navbar-height)] w-screen text-sm">
|
||||
<div
|
||||
class="grid h-full md:grid-cols-[theme(spacing.64)_auto] grid-cols-[theme(spacing.18)_auto] border-b dark:border-b-immich-dark-gray items-center py-2 bg-immich-bg dark:bg-immich-dark-bg"
|
||||
class="grid h-full grid-cols-[theme(spacing.18)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
|
||||
>
|
||||
<a data-sveltekit-preload-data="hover" class="flex gap-2 md:mx-6 mx-4 place-items-center" href={AppRoute.PHOTOS}>
|
||||
<a data-sveltekit-preload-data="hover" class="mx-4 flex place-items-center gap-2 md:mx-6" href={AppRoute.PHOTOS}>
|
||||
<ImmichLogo height="35" width="35" />
|
||||
<h1 class="font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary md:block hidden">
|
||||
<h1 class="hidden font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary md:block">
|
||||
IMMICH
|
||||
</h1>
|
||||
</a>
|
||||
<div class="flex justify-between gap-16 pr-6">
|
||||
<div class="w-full max-w-5xl flex-1 pl-4 sm:block hidden">
|
||||
<div class="hidden w-full max-w-5xl flex-1 pl-4 sm:block">
|
||||
<SearchBar grayTheme={true} />
|
||||
</div>
|
||||
|
||||
<section class="flex gap-4 place-items-center justify-end max-sm:w-full">
|
||||
<a href={AppRoute.SEARCH} id="search-button" class="sm:hidden pl-4">
|
||||
<section class="flex place-items-center justify-end gap-4 max-sm:w-full">
|
||||
<a href={AppRoute.SEARCH} id="search-button" class="pl-4 sm:hidden">
|
||||
<IconButton title="Search">
|
||||
<div class="flex gap-2">
|
||||
<Magnify size="1.5em" />
|
||||
@ -64,7 +64,7 @@
|
||||
<LinkButton on:click={() => dispatch('uploadClicked')}>
|
||||
<div class="flex gap-2">
|
||||
<TrayArrowUp size="1.5em" />
|
||||
<span class="md:block hidden">Upload</span>
|
||||
<span class="hidden md:block">Upload</span>
|
||||
</div>
|
||||
</LinkButton>
|
||||
</div>
|
||||
@ -72,18 +72,18 @@
|
||||
|
||||
{#if user.isAdmin}
|
||||
<a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}>
|
||||
<div class="sm:block hidden">
|
||||
<div class="hidden sm:block">
|
||||
<LinkButton>
|
||||
<span
|
||||
class={$page.url.pathname.includes('/admin')
|
||||
? 'text-immich-primary dark:text-immich-dark-primary underline item'
|
||||
? 'item text-immich-primary underline dark:text-immich-dark-primary'
|
||||
: ''}
|
||||
>
|
||||
Administration
|
||||
</span>
|
||||
</LinkButton>
|
||||
</div>
|
||||
<div class="sm:hidden block">
|
||||
<div class="block sm:hidden">
|
||||
<IconButton title="Administration">
|
||||
<Cog
|
||||
size="1.5em"
|
||||
@ -94,7 +94,7 @@
|
||||
</IconButton>
|
||||
<hr
|
||||
class={$page.url.pathname.includes('/admin')
|
||||
? 'block border-1 w-2/3 mx-auto border-immich-primary dark:border-immich-dark-primary'
|
||||
? 'border-1 mx-auto block w-2/3 border-immich-primary dark:border-immich-dark-primary'
|
||||
: 'hidden'}
|
||||
/>
|
||||
</div>
|
||||
@ -117,7 +117,7 @@
|
||||
<div
|
||||
in:fade={{ delay: 500, duration: 150 }}
|
||||
out:fade={{ delay: 200, duration: 150 }}
|
||||
class="absolute -bottom-12 right-5 border bg-gray-500 dark:bg-immich-dark-gray text-[12px] text-gray-100 p-2 rounded-md shadow-md dark:border-immich-dark-gray"
|
||||
class="absolute -bottom-12 right-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||
>
|
||||
<p>{user.firstName} {user.lastName}</p>
|
||||
<p>{user.email}</p>
|
||||
|
@ -13,6 +13,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="absolute top-0 left-0 w-screen h-[3px] bg-white z-[999999999]">
|
||||
<span class="absolute bg-immich-primary h-[3px]" style:width={`${$progress}%`} />
|
||||
<div class="absolute left-0 top-0 z-[999999999] h-[3px] w-screen bg-white">
|
||||
<span class="absolute h-[3px] bg-immich-primary" style:width={`${$progress}%`} />
|
||||
</div>
|
||||
|
@ -74,12 +74,12 @@
|
||||
transition:fade={{ duration: 250 }}
|
||||
style:background-color={backgroundColor()}
|
||||
style:border={borderStyle()}
|
||||
class="min-h-[80px] w-[300px] rounded-2xl z-[999999] shadow-md p-4 mb-4 hover:cursor-pointer"
|
||||
class="z-[999999] mb-4 min-h-[80px] w-[300px] rounded-2xl p-4 shadow-md hover:cursor-pointer"
|
||||
on:click={handleClick}
|
||||
on:keydown={handleClick}
|
||||
>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex gap-2 place-items-center">
|
||||
<div class="flex place-items-center gap-2">
|
||||
<svelte:component this={icon} color={primaryColor()} size="20" />
|
||||
<h2 style:color={primaryColor()} class="font-medium" data-testid="title">
|
||||
{notificationInfo.type.toString()}
|
||||
@ -90,7 +90,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="whitespace-pre-wrap text-sm pl-[28px] pr-[16px]" data-testid="message">
|
||||
<p class="whitespace-pre-wrap pl-[28px] pr-[16px] text-sm" data-testid="message">
|
||||
{notificationInfo.message}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -65,21 +65,21 @@
|
||||
|
||||
<BaseModal on:close>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<p class="font-medium">Set profile picture</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
<div class="flex justify-center place-items-center items-center">
|
||||
<div class="flex place-items-center items-center justify-center">
|
||||
<div
|
||||
class="w-1/2 aspect-square rounded-full overflow-hidden relative flex border-immich-primary dark:border-immich-dark-primary border-4 bg-immich-dark-primary dark:bg-immich-primary"
|
||||
class="relative flex aspect-square w-1/2 overflow-hidden rounded-full border-4 border-immich-primary bg-immich-dark-primary dark:border-immich-dark-primary dark:bg-immich-primary"
|
||||
>
|
||||
<PhotoViewer bind:element={imgElement} {asset} />
|
||||
</div>
|
||||
</div>
|
||||
<span class="p-4 flex justify-end">
|
||||
<span class="flex justify-end p-4">
|
||||
<Button on:click={handleSetProfilePicture}>
|
||||
<p>Set as profile picture</p>
|
||||
</Button>
|
||||
</span>
|
||||
<div class="max-h-[400px] flex flex-col mb-2" />
|
||||
<div class="mb-2 flex max-h-[400px] flex-col" />
|
||||
</BaseModal>
|
||||
|
@ -94,7 +94,7 @@
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
id="immich-scrubbable-scrollbar"
|
||||
class="fixed right-0 bg-immich-bg z-[100] hover:cursor-row-resize select-none"
|
||||
class="fixed right-0 z-[100] select-none bg-immich-bg hover:cursor-row-resize"
|
||||
style:width={isDragging ? '100vw' : '60px'}
|
||||
style:background-color={isDragging ? 'transparent' : 'transparent'}
|
||||
on:mouseenter={() => (isHover = true)}
|
||||
@ -109,7 +109,7 @@
|
||||
>
|
||||
{#if isHover}
|
||||
<div
|
||||
class="border-b-2 border-immich-primary dark:border-immich-dark-primary w-[100px] right-0 pr-6 py-1 text-sm pl-1 font-medium absolute bg-immich-bg dark:bg-immich-dark-gray z-[100] pointer-events-none rounded-tl-md shadow-lg dark:text-immich-dark-fg"
|
||||
class="pointer-events-none absolute right-0 z-[100] w-[100px] rounded-tl-md border-b-2 border-immich-primary bg-immich-bg py-1 pl-1 pr-6 text-sm font-medium shadow-lg dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
style:top={currentMouseYLocation + 'px'}
|
||||
>
|
||||
{hoveredDate?.toLocaleString('default', { month: 'short' })}
|
||||
@ -120,7 +120,7 @@
|
||||
<!-- Scroll Position Indicator Line -->
|
||||
{#if !isDragging}
|
||||
<div
|
||||
class="absolute right-0 w-10 h-[2px] bg-immich-primary dark:bg-immich-dark-primary"
|
||||
class="absolute right-0 h-[2px] w-10 bg-immich-primary dark:bg-immich-dark-primary"
|
||||
style:top={scrollbarPosition + 'px'}
|
||||
/>
|
||||
{/if}
|
||||
@ -139,7 +139,7 @@
|
||||
{#if segment.height > 8}
|
||||
<div
|
||||
aria-label={segment.timeGroup + ' ' + segment.count}
|
||||
class="absolute right-0 pr-5 z-10 text-xs font-medium dark:text-immich-dark-fg"
|
||||
class="absolute right-0 z-10 pr-5 text-xs font-medium dark:text-immich-dark-fg"
|
||||
>
|
||||
{groupDate.getFullYear()}
|
||||
</div>
|
||||
@ -147,7 +147,7 @@
|
||||
{:else if segment.height > 5}
|
||||
<div
|
||||
aria-label={segment.timeGroup + ' ' + segment.count}
|
||||
class="absolute right-0 rounded-full h-[4px] w-[4px] mr-3 bg-gray-300 block"
|
||||
class="absolute right-0 mr-3 block h-[4px] w-[4px] rounded-full bg-gray-300"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -66,9 +66,9 @@
|
||||
name="q"
|
||||
class="w-full transition-all {grayTheme
|
||||
? 'dark:bg-immich-dark-gray'
|
||||
: 'dark:bg-immich-dark-bg'} text-immich-fg/75 dark:text-immich-dark-fg px-14 py-4 {showBigSearchBar
|
||||
? 'rounded-t-3xl bg-white border border-gray-200 dark:border-gray-800'
|
||||
: 'rounded-3xl bg-gray-200 border border-transparent'}"
|
||||
: 'dark:bg-immich-dark-bg'} px-14 py-4 text-immich-fg/75 dark:text-immich-dark-fg {showBigSearchBar
|
||||
? 'rounded-t-3xl border border-gray-200 bg-white dark:border-gray-800'
|
||||
: 'rounded-3xl border border-transparent bg-gray-200'}"
|
||||
placeholder="Search your photos"
|
||||
required
|
||||
pattern="^(?!m:$).*$"
|
||||
@ -79,7 +79,7 @@
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<button
|
||||
type="reset"
|
||||
class="dark:text-immich-dark-fg/75 hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/25 rounded-full p-2 active:bg-immich-primary/10 dark:active:bg-immich-dark-primary/[.35]"
|
||||
class="rounded-full p-2 hover:bg-immich-primary/5 active:bg-immich-primary/10 dark:text-immich-dark-fg/75 dark:hover:bg-immich-dark-primary/25 dark:active:bg-immich-dark-primary/[.35]"
|
||||
>
|
||||
<Close size="1.5em" />
|
||||
</button>
|
||||
@ -89,23 +89,23 @@
|
||||
{#if showBigSearchBar}
|
||||
<div
|
||||
transition:fly={{ y: 25, duration: 250 }}
|
||||
class="w-full pb-5 absolute bg-white transition-all rounded-b-3xl shadow-2xl border border-gray-200 dark:bg-immich-dark-gray dark:border-gray-800 dark:text-gray-300"
|
||||
class="absolute w-full rounded-b-3xl border border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-800 dark:bg-immich-dark-gray dark:text-gray-300"
|
||||
>
|
||||
<div class="px-5 pt-5 text-xs">
|
||||
<p>
|
||||
Smart search is enabled by default, to search for metadata use the syntax <span
|
||||
class="font-mono p-2 font-semibold text-immich-primary dark:text-immich-dark-primary bg-gray-100 rounded-lg dark:bg-gray-900 leading-7"
|
||||
class="rounded-lg bg-gray-100 p-2 font-mono font-semibold leading-7 text-immich-primary dark:bg-gray-900 dark:text-immich-dark-primary"
|
||||
>m:your-search-term</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{#if $savedSearchTerms.length > 0}
|
||||
<div class="px-5 pt-5 text-xs flex justify-between">
|
||||
<div class="flex justify-between px-5 pt-5 text-xs">
|
||||
<p>RECENT SEARCHES</p>
|
||||
<button
|
||||
type="button"
|
||||
class="text-immich-primary dark:text-immich-dark-primary font-semibold p-2 hover:bg-immich-primary/25 rounded-lg"
|
||||
class="rounded-lg p-2 font-semibold text-immich-primary hover:bg-immich-primary/25 dark:text-immich-dark-primary"
|
||||
on:click={clearSearchTerm}>Clear all</button
|
||||
>
|
||||
</div>
|
||||
@ -114,7 +114,7 @@
|
||||
{#each $savedSearchTerms as savedSearchTerm, i (i)}
|
||||
<button
|
||||
type="button"
|
||||
class="w-full hover:bg-gray-100 dark:hover:bg-gray-500/10 px-5 py-3 cursor-pointer flex gap-3 text-black dark:text-gray-300"
|
||||
class="flex w-full cursor-pointer gap-3 px-5 py-3 text-black hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-500/10"
|
||||
on:click={() => {
|
||||
value = savedSearchTerm;
|
||||
onSearch(false);
|
||||
|
@ -19,35 +19,35 @@
|
||||
<div
|
||||
on:click={onButtonClicked}
|
||||
on:keydown={onButtonClicked}
|
||||
class="flex gap-4 justify-between place-items-center w-full transition-[padding] delay-100 duration-100 py-3 rounded-r-full hover:bg-immich-gray dark:hover:bg-immich-dark-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary hover:cursor-pointer
|
||||
class="flex w-full place-items-center justify-between gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary
|
||||
{isSelected
|
||||
? 'bg-immich-primary/10 dark:bg-immich-dark-primary/10 text-immich-primary dark:text-immich-dark-primary hover:bg-immich-primary/25'
|
||||
? 'bg-immich-primary/10 text-immich-primary hover:bg-immich-primary/25 dark:bg-immich-dark-primary/10 dark:text-immich-dark-primary'
|
||||
: ''}
|
||||
pl-5 group-hover:sm:px-5 md:px-5
|
||||
"
|
||||
>
|
||||
<div class="flex gap-4 place-items-center w-full overflow-hidden truncate">
|
||||
<div class="flex w-full place-items-center gap-4 overflow-hidden truncate">
|
||||
<svelte:component this={logo} size="1.5em" class="shrink-0 {flippedLogo ? '-scale-x-100' : ''}" />
|
||||
<p class="font-medium text-sm">{title}</p>
|
||||
<p class="text-sm font-medium">{title}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="transition-[height] group-hover:sm:overflow-visible md:overflow-visible overflow-hidden duration-100 delay-1000 sm:group-hover:h-auto md:h-auto h-0"
|
||||
class="h-0 overflow-hidden transition-[height] delay-1000 duration-100 sm:group-hover:h-auto group-hover:sm:overflow-visible md:h-auto md:overflow-visible"
|
||||
>
|
||||
{#if $$slots.moreInformation}
|
||||
<div
|
||||
class="relative flex justify-center select-none cursor-default"
|
||||
class="relative flex cursor-default select-none justify-center"
|
||||
on:mouseenter={() => (showMoreInformation = true)}
|
||||
on:mouseleave={() => (showMoreInformation = false)}
|
||||
>
|
||||
<div class="hover:cursor-help p-1 text-gray-600 dark:text-gray-400">
|
||||
<div class="p-1 text-gray-600 hover:cursor-help dark:text-gray-400">
|
||||
<InformationOutline />
|
||||
</div>
|
||||
|
||||
{#if showMoreInformation}
|
||||
<div class="absolute right-6 top-0">
|
||||
<div
|
||||
class="flex place-items-center place-content-center whitespace-nowrap rounded-3xl shadow-lg py-3 px-6 bg-immich-bg text-immich-fg dark:bg-gray-600 dark:text-immich-dark-fg text-xs border dark:border-immich-dark-gray"
|
||||
class="flex place-content-center place-items-center whitespace-nowrap rounded-3xl border bg-immich-bg px-6 py-3 text-xs text-immich-fg shadow-lg dark:border-immich-dark-gray dark:bg-gray-600 dark:text-immich-dark-fg"
|
||||
class:hidden={!showMoreInformation}
|
||||
transition:fade={{ duration: 200 }}
|
||||
>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<section
|
||||
id="sidebar"
|
||||
class="group flex flex-col gap-1 pt-8 bg-immich-bg dark:bg-immich-dark-bg transition-all duration-200 z-10 w-18 md:w-64 hover:sm:pr-6 md:pr-6 hover:sm:w-64 hover:sm:shadow-2xl hover:md:shadow-none hover:md:border-none hover:sm:border-r hover:sm:dark:border-r-immich-dark-gray relative overflow-y-auto immich-scrollbar"
|
||||
class="immich-scrollbar group relative z-10 flex w-18 flex-col gap-1 overflow-y-auto bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg hover:sm:w-64 hover:sm:border-r hover:sm:pr-6 hover:sm:shadow-2xl hover:sm:dark:border-r-immich-dark-gray md:w-64 md:pr-6 hover:md:border-none hover:md:shadow-none"
|
||||
>
|
||||
<slot />
|
||||
</section>
|
||||
|
@ -80,9 +80,9 @@
|
||||
</SideBarButton>
|
||||
</a>
|
||||
|
||||
<div class="text-xs dark:text-immich-dark-fg transition-all duration-200">
|
||||
<p class="p-6 hidden md:block group-hover:sm:block">LIBRARY</p>
|
||||
<hr class="mt-8 mb-[31px] mx-4 block md:hidden group-hover:sm:hidden" />
|
||||
<div class="text-xs transition-all duration-200 dark:text-immich-dark-fg">
|
||||
<p class="hidden p-6 group-hover:sm:block md:block">LIBRARY</p>
|
||||
<hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
|
||||
</div>
|
||||
<a data-sveltekit-preload-data="hover" href={AppRoute.FAVORITES} draggable="false">
|
||||
<SideBarButton
|
||||
|
@ -51,16 +51,16 @@
|
||||
|
||||
<div class="dark:text-immich-dark-fg">
|
||||
<div class="storage-status grid grid-cols-[64px_auto]">
|
||||
<div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary pb-[2.15rem] group-hover:sm:pb-0 md:pb-0">
|
||||
<div class="pb-[2.15rem] pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
|
||||
<Cloud size={'24'} />
|
||||
</div>
|
||||
<div class="hidden md:block group-hover:sm:block">
|
||||
<div class="hidden group-hover:sm:block md:block">
|
||||
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Storage</p>
|
||||
{#if serverInfo}
|
||||
<div class="w-full bg-gray-200 rounded-full h-[7px] dark:bg-gray-700 my-2">
|
||||
<div class="my-2 h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||
<!-- style={`width: ${$downloadAssets[fileName]}%`} -->
|
||||
<div
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary h-[7px] rounded-full"
|
||||
class="h-[7px] rounded-full bg-immich-primary dark:bg-immich-dark-primary"
|
||||
style="width: {getStorageUsagePercentage()}%"
|
||||
/>
|
||||
</div>
|
||||
@ -76,16 +76,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<hr class="ml-5 my-4 dark:border-immich-dark-gray" />
|
||||
<hr class="my-4 ml-5 dark:border-immich-dark-gray" />
|
||||
</div>
|
||||
<div class="server-status grid grid-cols-[64px_auto]">
|
||||
<div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary pb-11 md:pb-0 group-hover:sm:pb-0">
|
||||
<div class="pb-11 pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
|
||||
<Dns size={'24'} />
|
||||
</div>
|
||||
<div class="text-xs hidden md:block group-hover:sm:block">
|
||||
<div class="hidden text-xs group-hover:sm:block md:block">
|
||||
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Server</p>
|
||||
|
||||
<div class="flex justify-items-center justify-between mt-2">
|
||||
<div class="mt-2 flex justify-between justify-items-center">
|
||||
<p>Status</p>
|
||||
|
||||
{#if isServerOk}
|
||||
@ -95,7 +95,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex justify-items-center justify-between mt-2">
|
||||
<div class="mt-2 flex justify-between justify-items-center">
|
||||
<p>Version</p>
|
||||
<p class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
{serverVersion}
|
||||
|
@ -20,11 +20,11 @@
|
||||
|
||||
<IconButton on:click={toggleTheme} title="Toggle theme">
|
||||
{#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="h-6 w-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
|
||||
>
|
||||
{:else}
|
||||
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
|
||||
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
||||
fill-rule="evenodd"
|
||||
|
@ -15,12 +15,12 @@
|
||||
<div
|
||||
in:fade={{ duration: 250 }}
|
||||
out:fade={{ duration: 100 }}
|
||||
class="text-xs mt-3 rounded-lg bg-immich-bg grid grid-cols-[70px_auto] gap-2 h-[70px]"
|
||||
class="mt-3 grid h-[70px] grid-cols-[70px_auto] gap-2 rounded-lg bg-immich-bg text-xs"
|
||||
>
|
||||
<div class="relative">
|
||||
{#if showFallbackImage}
|
||||
<div in:fade={{ duration: 250 }}>
|
||||
<ImmichLogo class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg" />
|
||||
<ImmichLogo class="h-[70px] w-[70px] rounded-bl-lg rounded-tl-lg object-cover" />
|
||||
</div>
|
||||
{:else}
|
||||
<img
|
||||
@ -34,30 +34,30 @@
|
||||
}}
|
||||
src={previewURL}
|
||||
alt="Preview of asset"
|
||||
class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg"
|
||||
class="h-[70px] w-[70px] rounded-bl-lg rounded-tl-lg object-cover"
|
||||
draggable="false"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="bottom-0 left-0 absolute w-full h-[25px] bg-immich-primary/30">
|
||||
<div class="absolute bottom-0 left-0 h-[25px] w-full bg-immich-primary/30">
|
||||
<p
|
||||
class="absolute bottom-1 right-1 object-right-bottom text-gray-50/95 font-semibold stroke-immich-primary uppercase"
|
||||
class="absolute bottom-1 right-1 stroke-immich-primary object-right-bottom font-semibold uppercase text-gray-50/95"
|
||||
>
|
||||
.{getFilenameExtension(uploadAsset.file.name)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-2 pr-4 flex flex-col justify-between">
|
||||
<div class="flex flex-col justify-between p-2 pr-4">
|
||||
<input
|
||||
disabled
|
||||
class="bg-gray-100 border w-full p-1 rounded-md text-[10px] px-2"
|
||||
class="w-full rounded-md border bg-gray-100 p-1 px-2 text-[10px]"
|
||||
value={`[${asByteUnitString(uploadAsset.file.size, $locale)}] ${uploadAsset.file.name}`}
|
||||
/>
|
||||
|
||||
<div class="w-full bg-gray-300 h-[15px] rounded-md mt-[5px] text-white relative">
|
||||
<div class="bg-immich-primary h-[15px] rounded-md transition-all" style={`width: ${uploadAsset.progress}%`} />
|
||||
<p class="absolute h-full w-full text-center top-0 text-[10px]">
|
||||
<div class="relative mt-[5px] h-[15px] w-full rounded-md bg-gray-300 text-white">
|
||||
<div class="h-[15px] rounded-md bg-immich-primary transition-all" style={`width: ${uploadAsset.progress}%`} />
|
||||
<p class="absolute top-0 h-full w-full text-center text-[10px]">
|
||||
{uploadAsset.progress}/100
|
||||
</p>
|
||||
</div>
|
||||
|
@ -33,24 +33,24 @@
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
}}
|
||||
class="absolute right-6 bottom-6 z-[10000]"
|
||||
class="absolute bottom-6 right-6 z-[10000]"
|
||||
>
|
||||
{#if showDetail}
|
||||
<div
|
||||
in:scale={{ duration: 250, easing: quartInOut }}
|
||||
class="bg-gray-200 p-4 text-sm w-[300px] rounded-lg shadow-sm border"
|
||||
class="w-[300px] rounded-lg border bg-gray-200 p-4 text-sm shadow-sm"
|
||||
>
|
||||
<div class="flex justify-between place-item-center mb-4">
|
||||
<div class="place-item-center mb-4 flex justify-between">
|
||||
<p class="text-xs text-gray-500">UPLOADING {$uploadAssetsStore.length}</p>
|
||||
<button
|
||||
on:click={() => (showDetail = false)}
|
||||
class="w-[20px] h-[20px] bg-gray-50 rounded-full flex place-items-center place-content-center transition-colors hover:bg-gray-100"
|
||||
class="flex h-[20px] w-[20px] place-content-center place-items-center rounded-full bg-gray-50 transition-colors hover:bg-gray-100"
|
||||
>
|
||||
<WindowMinimize />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="max-h-[400px] overflow-y-auto pr-2 rounded-lg immich-scrollbar">
|
||||
<div class="immich-scrollbar max-h-[400px] overflow-y-auto rounded-lg pr-2">
|
||||
{#each $uploadAssetsStore as uploadAsset}
|
||||
{#key uploadAsset.id}
|
||||
<UploadAssetPreview {uploadAsset} />
|
||||
@ -63,14 +63,14 @@
|
||||
<button
|
||||
in:scale={{ duration: 250, easing: quartInOut }}
|
||||
on:click={() => (showDetail = true)}
|
||||
class="absolute -top-4 -left-4 text-xs rounded-full w-10 h-10 p-5 flex place-items-center place-content-center bg-immich-primary text-gray-200"
|
||||
class="absolute -left-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-primary p-5 text-xs text-gray-200"
|
||||
>
|
||||
{$uploadAssetsStore.length}
|
||||
</button>
|
||||
<button
|
||||
in:scale={{ duration: 250, easing: quartInOut }}
|
||||
on:click={() => (showDetail = true)}
|
||||
class="bg-gray-300 p-5 rounded-full w-16 h-16 flex place-items-center place-content-center text-sm shadow-lg"
|
||||
class="flex h-16 w-16 place-content-center place-items-center rounded-full bg-gray-300 p-5 text-sm shadow-lg"
|
||||
>
|
||||
<div class="animate-pulse">
|
||||
<CloudUploadOutline size="30" color="#4250af" />
|
||||
|
@ -49,7 +49,7 @@
|
||||
</script>
|
||||
|
||||
<figure
|
||||
class="{sizeClass} {colorClass} {interactiveClass} shadow-md overflow-hidden"
|
||||
class="{sizeClass} {colorClass} {interactiveClass} overflow-hidden shadow-md"
|
||||
class:rounded-full={rounded}
|
||||
title={showTitle ? title : undefined}
|
||||
>
|
||||
@ -57,7 +57,7 @@
|
||||
<img
|
||||
src={api.getProfileImageUrl(user.id)}
|
||||
alt="Profile image of {title}"
|
||||
class="object-cover w-full h-full"
|
||||
class="h-full w-full object-cover"
|
||||
class:hidden={showFallback}
|
||||
draggable="false"
|
||||
use:imageLoad
|
||||
@ -66,7 +66,7 @@
|
||||
{/if}
|
||||
{#if showFallback}
|
||||
<span
|
||||
class="flex justify-center items-center w-full h-full select-none"
|
||||
class="flex h-full w-full select-none items-center justify-center"
|
||||
class:text-xs={size === 'sm'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:font-medium={!autoColor}
|
||||
|
@ -43,15 +43,15 @@
|
||||
{#if showModal}
|
||||
<FullScreenModal on:clickOutside={() => (showModal = false)}>
|
||||
<div
|
||||
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray shadow-sm max-w-lg rounded-3xl py-10 px-8 dark:text-immich-dark-fg"
|
||||
class="max-w-lg rounded-3xl border bg-immich-bg px-8 py-10 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<p class="text-2xl mb-4">🎉 NEW VERSION AVAILABLE 🎉</p>
|
||||
<p class="mb-4 text-2xl">🎉 NEW VERSION AVAILABLE 🎉</p>
|
||||
|
||||
<div>
|
||||
Hi friend, there is a new release of
|
||||
<span class="font-immich-title text-immich-primary dark:text-immich-dark-primary font-bold">IMMICH</span>,
|
||||
<span class="font-immich-title font-bold text-immich-primary dark:text-immich-dark-primary">IMMICH</span>,
|
||||
please take your time to visit the
|
||||
<span class="underline font-medium"
|
||||
<span class="font-medium underline"
|
||||
><a href="https://github.com/immich-app/immich/releases/latest" target="_blank" rel="noopener noreferrer"
|
||||
>release notes</a
|
||||
></span
|
||||
@ -60,7 +60,7 @@
|
||||
especially if you use WatchTower or any mechanism that handles updating your application automatically.
|
||||
</div>
|
||||
|
||||
<div class="font-medium mt-4">Your friend, Alex</div>
|
||||
<div class="mt-4 font-medium">Your friend, Alex</div>
|
||||
|
||||
<div class="font-sm mt-8">
|
||||
<code>Server Version: {serverVersionName}</code>
|
||||
@ -68,7 +68,7 @@
|
||||
<code>Latest Version: {githubVersion}</code>
|
||||
</div>
|
||||
|
||||
<div class="text-right mt-8">
|
||||
<div class="mt-8 text-right">
|
||||
<Button fullwidth on:click={onAcknowledge}>Acknowledge</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -59,7 +59,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="w-full flex gap-4 dark:text-immich-gray transition-all border-b border-gray-200 dark:border-gray-600 hover:border-immich-primary dark:hover:border-immich-dark-primary py-4"
|
||||
class="flex w-full gap-4 border-b border-gray-200 py-4 transition-all hover:border-immich-primary dark:border-gray-600 dark:text-immich-gray dark:hover:border-immich-dark-primary"
|
||||
>
|
||||
<div>
|
||||
{#await getAssetInfo()}
|
||||
@ -69,7 +69,7 @@
|
||||
id={asset.id}
|
||||
src={api.getAssetThumbnailUrl(asset.id, ThumbnailFormat.Webp)}
|
||||
alt={asset.id}
|
||||
class="object-cover w-[100px] h-[100px] rounded-lg"
|
||||
class="h-[100px] w-[100px] rounded-lg object-cover"
|
||||
loading="lazy"
|
||||
draggable="false"
|
||||
/>
|
||||
@ -78,10 +78,10 @@
|
||||
|
||||
<div class="flex flex-col justify-between">
|
||||
<div class="info-top">
|
||||
<div class="text-xs font-mono font-semibold text-gray-500 dark:text-gray-400">
|
||||
<div class="font-mono text-xs font-semibold text-gray-500 dark:text-gray-400">
|
||||
{#if link.expiresAt}
|
||||
{#if isExpired(link.expiresAt)}
|
||||
<p class="text-red-600 dark:text-red-400 font-bold">Expired</p>
|
||||
<p class="font-bold text-red-600 dark:text-red-400">Expired</p>
|
||||
{:else}
|
||||
<p>
|
||||
Expires {getCountDownExpirationDate()}
|
||||
@ -93,7 +93,7 @@
|
||||
</div>
|
||||
|
||||
<div class="text-sm">
|
||||
<div class="flex gap-2 place-items-center text-immich-primary dark:text-immich-dark-primary">
|
||||
<div class="flex place-items-center gap-2 text-immich-primary dark:text-immich-dark-primary">
|
||||
{#if link.type === SharedLinkType.Album}
|
||||
<p>
|
||||
{link.album?.albumName.toUpperCase()}
|
||||
@ -122,7 +122,7 @@
|
||||
<div class="info-bottom flex gap-4">
|
||||
{#if link.allowUpload}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[80px]"
|
||||
class="flex w-[80px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
|
||||
>
|
||||
Upload
|
||||
</div>
|
||||
@ -130,7 +130,7 @@
|
||||
|
||||
{#if link.allowDownload}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[100px]"
|
||||
class="flex w-[100px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
|
||||
>
|
||||
Download
|
||||
</div>
|
||||
@ -138,7 +138,7 @@
|
||||
|
||||
{#if link.showExif}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[60px]"
|
||||
class="flex w-[60px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
|
||||
>
|
||||
EXIF
|
||||
</div>
|
||||
@ -146,7 +146,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-auto flex flex-col place-content-center place-items-end text-right">
|
||||
<div class="flex flex-auto flex-col place-content-center place-items-end text-right">
|
||||
<div class="flex">
|
||||
<CircleIconButton logo={Delete} on:click={() => dispatch('delete')} />
|
||||
<CircleIconButton logo={CircleEditOutline} on:click={() => dispatch('edit')} />
|
||||
|
@ -42,7 +42,7 @@
|
||||
<section class="my-4">
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<form autocomplete="off" on:submit|preventDefault>
|
||||
<div class="flex flex-col gap-4 ml-4 mt-4">
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.PASSWORD}
|
||||
label="PASSWORD"
|
||||
|
@ -22,9 +22,9 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="flex flex-row w-full">
|
||||
<div class="flex w-full flex-row">
|
||||
<!-- TODO: Device Image -->
|
||||
<div class="hidden sm:flex pr-2 justify-center items-center text-immich-primary dark:text-immich-dark-primary">
|
||||
<div class="hidden items-center justify-center pr-2 text-immich-primary dark:text-immich-dark-primary sm:flex">
|
||||
{#if device.deviceOS === 'Android'}
|
||||
<Android size="40" />
|
||||
{:else if device.deviceOS === 'iOS' || device.deviceOS === 'Mac OS'}
|
||||
@ -41,8 +41,8 @@
|
||||
<Help size="40" />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="pl-4 sm:pl-0 flex flex-row grow justify-between gap-1">
|
||||
<div class="flex flex-col gap-1 justify-center dark:text-white">
|
||||
<div class="flex grow flex-row justify-between gap-1 pl-4 sm:pl-0">
|
||||
<div class="flex flex-col justify-center gap-1 dark:text-white">
|
||||
<span class="text-sm">
|
||||
{#if device.deviceType || device.deviceOS}
|
||||
<span>{device.deviceOS || 'Unknown'} • {device.deviceType || 'Unknown'}</span>
|
||||
@ -56,10 +56,10 @@
|
||||
</div>
|
||||
</div>
|
||||
{#if !device.current}
|
||||
<div class="text-sm flex flex-col justify-center">
|
||||
<div class="flex flex-col justify-center text-sm">
|
||||
<button
|
||||
on:click={() => dispatcher('delete')}
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75"
|
||||
class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
|
||||
title="Log out"
|
||||
>
|
||||
<TrashCanOutline size="16" />
|
||||
|
@ -71,13 +71,13 @@
|
||||
<section class="my-4">
|
||||
{#if currentDevice}
|
||||
<div class="mb-6">
|
||||
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">CURRENT DEVICE</h3>
|
||||
<h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">CURRENT DEVICE</h3>
|
||||
<DeviceCard device={currentDevice} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if otherDevices.length > 0}
|
||||
<div class="mb-6">
|
||||
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">OTHER DEVICES</h3>
|
||||
<h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">OTHER DEVICES</h3>
|
||||
{#each otherDevices as device, i}
|
||||
<DeviceCard {device} on:delete={() => (deleteDevice = device)} />
|
||||
{#if i !== otherDevices.length - 1}
|
||||
@ -85,7 +85,7 @@
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">LOG OUT ALL DEVICES</h3>
|
||||
<h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">LOG OUT ALL DEVICES</h3>
|
||||
<div class="flex justify-end">
|
||||
<Button color="red" size="sm" on:click={() => (deleteAll = true)}>Log Out All Devices</Button>
|
||||
</div>
|
||||
|
@ -60,7 +60,7 @@
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<div class="flex justify-end">
|
||||
{#if loading}
|
||||
<div class="flex place-items-center place-content-center">
|
||||
<div class="flex place-content-center place-items-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{:else if config.enabled}
|
||||
|
@ -37,22 +37,22 @@
|
||||
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<span class="flex place-items-center gap-2">
|
||||
<ImmichLogo width={24} />
|
||||
<p class="font-medium">Add partner</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
|
||||
<div class="max-h-[300px] overflow-y-auto immich-scrollbar">
|
||||
<div class="immich-scrollbar max-h-[300px] overflow-y-auto">
|
||||
{#if availableUsers.length > 0}
|
||||
{#each availableUsers as user}
|
||||
<button
|
||||
on:click={() => selectUser(user)}
|
||||
class="w-full flex place-items-center gap-4 py-4 px-5 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all"
|
||||
class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
>
|
||||
{#if selectedUsers.includes(user)}
|
||||
<span
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-bg rounded-full w-12 h-12 border flex place-items-center place-content-center text-3xl dark:border-immich-dark-gray"
|
||||
class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg"
|
||||
>✓</span
|
||||
>
|
||||
{:else}
|
||||
@ -71,7 +71,7 @@
|
||||
</button>
|
||||
{/each}
|
||||
{:else}
|
||||
<p class="text-sm p-5">
|
||||
<p class="p-5 text-sm">
|
||||
Looks like you shared your photos with all users or you don't have any user to share with.
|
||||
</p>
|
||||
{/if}
|
||||
|
@ -56,7 +56,7 @@
|
||||
{#if partners.length > 0}
|
||||
<div class="flex flex-row gap-4">
|
||||
{#each partners as partner (partner.id)}
|
||||
<div class="flex rounded-lg gap-4 py-4 px-5 transition-all">
|
||||
<div class="flex gap-4 rounded-lg px-5 py-4 transition-all">
|
||||
<UserAvatar user={partner} size="md" autoColor />
|
||||
<div class="text-left">
|
||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||
|
@ -116,43 +116,43 @@
|
||||
|
||||
<section class="my-4">
|
||||
<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
|
||||
<div class="flex justify-end mb-2">
|
||||
<div class="mb-2 flex justify-end">
|
||||
<Button size="sm" on:click={() => (newKey = { name: 'API Key' })}>New API Key</Button>
|
||||
</div>
|
||||
|
||||
{#if keys.length > 0}
|
||||
<table class="text-left w-full">
|
||||
<table class="w-full text-left">
|
||||
<thead
|
||||
class="border rounded-md mb-4 bg-gray-50 flex text-immich-primary w-full h-12 dark:bg-immich-dark-gray dark:text-immich-dark-primary dark:border-immich-dark-gray"
|
||||
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary"
|
||||
>
|
||||
<tr class="flex w-full place-items-center">
|
||||
<th class="text-center w-1/3 font-medium text-sm">Name</th>
|
||||
<th class="text-center w-1/3 font-medium text-sm">Created</th>
|
||||
<th class="text-center w-1/3 font-medium text-sm">Action</th>
|
||||
<th class="w-1/3 text-center text-sm font-medium">Name</th>
|
||||
<th class="w-1/3 text-center text-sm font-medium">Created</th>
|
||||
<th class="w-1/3 text-center text-sm font-medium">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="overflow-y-auto rounded-md w-full block border dark:border-immich-dark-gray">
|
||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||
{#each keys as key, i}
|
||||
{#key key.id}
|
||||
<tr
|
||||
class={`text-center flex place-items-center w-full h-[80px] dark:text-immich-dark-fg ${
|
||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
||||
i % 2 == 0 ? 'bg-immich-gray dark:bg-immich-dark-gray/75' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
||||
}`}
|
||||
>
|
||||
<td class="text-sm px-4 w-1/3 text-ellipsis">{key.name}</td>
|
||||
<td class="text-sm px-4 w-1/3 text-ellipsis"
|
||||
<td class="w-1/3 text-ellipsis px-4 text-sm">{key.name}</td>
|
||||
<td class="w-1/3 text-ellipsis px-4 text-sm"
|
||||
>{new Date(key.createdAt).toLocaleDateString($locale, format)}
|
||||
</td>
|
||||
<td class="text-sm px-4 w-1/3 text-ellipsis">
|
||||
<td class="w-1/3 text-ellipsis px-4 text-sm">
|
||||
<button
|
||||
on:click={() => (editKey = key)}
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75"
|
||||
class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
|
||||
>
|
||||
<PencilOutline size="16" />
|
||||
</button>
|
||||
<button
|
||||
on:click={() => (deleteKey = key)}
|
||||
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75"
|
||||
class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
|
||||
>
|
||||
<TrashCanOutline size="16" />
|
||||
</button>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user