1
0
mirror of https://github.com/immich-app/immich.git synced 2024-11-24 08:52:28 +02:00
This commit is contained in:
Jason Rasmussen 2024-11-20 10:16:34 -05:00
parent 69e50d0d27
commit fcb4fb8c33
No known key found for this signature in database
GPG Key ID: 2EF24B77EAFA4A41
8 changed files with 255 additions and 54 deletions

188
web/package-lock.json generated
View File

@ -34,6 +34,7 @@
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.8.0",
"@faker-js/faker": "^9.0.0",
"@immich/ui": "^0.6.0",
"@socket.io/component-emitter": "^3.1.0",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/enhanced-img": "^0.3.9",
@ -788,6 +789,34 @@
"npm": ">=9.0.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
"integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.12",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz",
"integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
"dev": true,
"license": "MIT"
},
"node_modules/@formatjs/ecma402-abstract": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.1.tgz",
@ -1343,6 +1372,32 @@
"resolved": "../open-api/typescript-sdk",
"link": true
},
"node_modules/@immich/ui": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.6.0.tgz",
"integrity": "sha512-E5MelkHzcbi5BsweH+WWL7DDr9WJFOPJN+edjxJf/q/roCD2MNyYYvK3Ydm6SYNDAI5ttqpFgOjO8xGcZv6dwg==",
"dev": true,
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@mdi/js": "^7.4.47",
"bits-ui": "^1.0.0-next.46",
"tailwind-merge": "^2.5.4",
"tailwind-variants": "^0.3.0"
},
"peerDependencies": {
"svelte": "^5.0.0"
}
},
"node_modules/@internationalized/date": {
"version": "3.5.6",
"resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.6.tgz",
"integrity": "sha512-jLxQjefH9VI5P9UQuqB6qNKnvFt1Ky1TPIzHGsIlCi7sZZoMR8SdYbBGRvM0y+Jtb+ez4ieBzmiAUcpmPYpyOw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@swc/helpers": "^0.5.0"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -2036,6 +2091,16 @@
"vite": "^5.0.0"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
}
},
"node_modules/@testing-library/dom": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.2.0.tgz",
@ -2993,6 +3058,31 @@
"node": ">=8"
}
},
"node_modules/bits-ui": {
"version": "1.0.0-next.63",
"resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-1.0.0-next.63.tgz",
"integrity": "sha512-3z4+N+KudMK8AeBzhy/0568zVoEJCUgL4RkElB41BWGjofk68en2TaAfKFhhc/bn4z+uKrs9r1NtybDdsy0bpA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.6.4",
"@floating-ui/dom": "^1.6.7",
"@internationalized/date": "^3.5.6",
"esm-env": "^1.1.2",
"runed": "^0.15.2",
"svelte-toolbelt": "^0.4.4"
},
"engines": {
"node": ">=18",
"pnpm": ">=8.7.0"
},
"funding": {
"url": "https://github.com/sponsors/huntabyte"
},
"peerDependencies": {
"svelte": "^5.0.0-next.1"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -3282,6 +3372,16 @@
"node": ">=6"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@ -4136,9 +4236,10 @@
}
},
"node_modules/esm-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA=="
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.1.4.tgz",
"integrity": "sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg==",
"license": "MIT"
},
"node_modules/esniff": {
"version": "2.0.1",
@ -4814,6 +4915,13 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/inline-style-parser": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
"integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==",
"dev": true,
"license": "MIT"
},
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
@ -6662,6 +6770,22 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/runed": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/runed/-/runed-0.15.3.tgz",
"integrity": "sha512-HtayB+loDcGdqJDHW8JFdsZzGQMyVzim6+s3052MkjZnwmwDstmF+cusMeTssBe6TCdt5i9D/Tb+KYXN3L0kXA==",
"dev": true,
"funding": [
"https://github.com/sponsors/huntabyte",
"https://github.com/sponsors/tglide"
],
"dependencies": {
"esm-env": "^1.0.0"
},
"peerDependencies": {
"svelte": "^5.0.0-next.1"
}
},
"node_modules/rw": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
@ -7096,6 +7220,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/style-to-object": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz",
"integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"inline-style-parser": "0.2.4"
}
},
"node_modules/sucrase": {
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
@ -7803,6 +7937,26 @@
"svelte": "^3.0.0 || ^4.0.0 || ^5.0.0-next.1"
}
},
"node_modules/svelte-toolbelt": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.4.6.tgz",
"integrity": "sha512-k8OUvXBUifHZcAlWeY/HLg/4J0v5m2iOfOhn8fDmjt4AP8ZluaDh9eBFus9lFiLX6O5l6vKqI1dKL5wy7090NQ==",
"dev": true,
"funding": [
"https://github.com/sponsors/huntabyte"
],
"dependencies": {
"clsx": "^2.1.1",
"style-to-object": "^1.0.8"
},
"engines": {
"node": ">=18",
"pnpm": ">=8.7.0"
},
"peerDependencies": {
"svelte": "^5.0.0-next.126"
}
},
"node_modules/svelte/node_modules/aria-query": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
@ -7820,6 +7974,34 @@
"optional": true,
"peer": true
},
"node_modules/tailwind-merge": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
"integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwind-variants": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-0.3.0.tgz",
"integrity": "sha512-ho2k5kn+LB1fT5XdNS3Clb96zieWxbStE9wNLK7D0AV64kdZMaYzAKo0fWl6fXLPY99ffF9oBJnIj5escEl/8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"tailwind-merge": "^2.5.4"
},
"engines": {
"node": ">=16.x",
"pnpm": ">=7.x"
},
"peerDependencies": {
"tailwindcss": "*"
}
},
"node_modules/tailwindcss": {
"version": "3.4.14",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",

View File

@ -26,6 +26,7 @@
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.8.0",
"@faker-js/faker": "^9.0.0",
"@immich/ui": "^0.6.0",
"@socket.io/component-emitter": "^3.1.0",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/enhanced-img": "^0.3.9",

View File

@ -22,6 +22,28 @@
--immich-dark-success: 56 142 60;
--immich-dark-warning: 245 124 0;
}
:root {
/* light */
--immich-ui-primary: 66 80 175;
--immich-ui-dark: 0 0 0;
--immich-ui-light: 255 255 255;
--immich-ui-success: 34 197 94;
--immich-ui-danger: 180 0 0;
--immich-ui-warning: 255 170 0;
--immich-ui-info: 14 165 233;
}
.dark {
/* dark */
--immich-ui-primary: 172 203 250;
--immich-ui-light: 0 0 0;
--immich-ui-dark: 229 231 235;
/* --immich-success: 56 142 60; */
--immich-ui-danger: 239 68 68;
--immich-ui-warning: 255 170 0;
--immich-ui-info: 14 165 233;
}
}
@font-face {

View File

@ -6,10 +6,8 @@
import { oauth } from '$lib/utils';
import { getServerErrorMessage, handleError } from '$lib/utils/handle-error';
import { login } from '@immich/sdk';
import { Alert, Button, Field, Input } from '@immich/ui';
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
import Button from '../elements/buttons/button.svelte';
import PasswordField from '../shared-components/password-field.svelte';
import { t } from 'svelte-i18n';
interface Props {
@ -27,6 +25,8 @@
let loading = $state(false);
let oauthLoading = $state(true);
oauthError = 'RPError invalid configuration';
onMount(async () => {
if (!$featureFlags.oauth) {
oauthLoading = false;
@ -99,42 +99,29 @@
</script>
{#if !oauthLoading && $featureFlags.passwordLogin}
<form {onsubmit} class="mt-5 flex flex-col gap-5">
<form {onsubmit} class="mt-5 flex flex-col gap-5 text-dark">
{#if errorMessage}
<p class="text-red-400" transition:fade>
{errorMessage}
</p>
<Alert color="danger" title={errorMessage} />
{/if}
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="email">{$t('email')}</label>
<input
class="immich-form-input"
id="email"
name="email"
type="email"
autocomplete="email"
bind:value={email}
required
/>
</div>
<Field label={$t('email')}>
<Input name="email" type="email" autocomplete="email" bind:value={email} />
</Field>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">{$t('password')}</label>
<PasswordField id="password" bind:password autocomplete="current-password" />
</div>
<Field label={$t('password')}>
<!-- TODO password component -->
<Input type="password" bind:value={password} autocomplete="current-password" />
</Field>
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth disabled={loading}>
{#if loading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
{$t('to_login')}
{/if}
</Button>
</div>
<Button type="submit" size="large" fullWidth disabled={loading} class="mt-6">
{#if loading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
{$t('to_login')}
{/if}
</Button>
</form>
{/if}
@ -151,13 +138,13 @@
{/if}
<div class="my-5 flex flex-col gap-5">
{#if oauthError}
<p class="text-center text-red-400" transition:fade>{oauthError}</p>
<Alert color="danger" title={oauthError} />
{/if}
<Button
type="button"
disabled={loading || oauthLoading}
size="lg"
fullwidth
size="large"
fullWidth
color={$featureFlags.passwordLogin ? 'secondary' : 'primary'}
onclick={handleOAuthLogin}
>
@ -173,5 +160,5 @@
{/if}
{#if !$featureFlags.passwordLogin && !$featureFlags.oauth}
<p class="p-4 text-center dark:text-immich-dark-fg">{$t('login_has_been_disabled')}</p>
<Alert color="warning" title={$t('login_has_been_disabled')} />
{/if}

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { Heading, Logo } from '@immich/ui';
import type { Snippet } from 'svelte';
import ImmichLogo from './immich-logo.svelte';
interface Props {
title: string;
@ -16,11 +16,9 @@
<div
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-content-center place-items-center gap-4 py-4">
<ImmichLogo noText class="h-24 w-24" />
<h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
{title}
</h1>
<div class="flex flex-col place-content-center place-items-center">
<Logo variant="icon" size="giant" />
<Heading size="large" color="primary">{title}</Heading>
</div>
{#if showMessage}

View File

@ -12,14 +12,15 @@
import { mdiHelpCircleOutline, mdiMagnify, mdiTrayArrowUp } from '@mdi/js';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import { AppRoute } from '$lib/constants';
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
import { AppRoute, Theme } from '$lib/constants';
import SearchBar from '$lib/components/shared-components/search-bar/search-bar.svelte';
import ThemeButton from '../theme-button.svelte';
import UserAvatar from '../user-avatar.svelte';
import AccountInfoPanel from './account-info-panel.svelte';
import HelpAndFeedbackModal from '$lib/components/shared-components/help-and-feedback-modal.svelte';
import { onMount } from 'svelte';
import { Logo } from '@immich/ui';
import { colorTheme } from '$lib/stores/preferences.store';
interface Props {
showUploadButton?: boolean;
@ -43,6 +44,8 @@
onMount(async () => {
aboutInfo = await getAboutInfo();
});
let isDark = $derived($colorTheme.value === Theme.DARK);
</script>
<svelte:window bind:innerWidth />
@ -57,7 +60,7 @@
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="ml-4" href={AppRoute.PHOTOS}>
<ImmichLogo width="55%" noText={innerWidth < 768} />
<Logo variant={innerWidth < 768 ? 'icon' : 'inline'} theme={isDark ? 'dark' : 'light'} />
</a>
<div class="flex justify-between gap-4 lg:gap-8 pr-6">
<div class="hidden w-full max-w-5xl flex-1 tall:pl-0 sm:block">

View File

@ -17,7 +17,7 @@
</script>
<script lang="ts">
import Button from '$lib/components/elements/buttons/button.svelte';
import { Button } from '@immich/ui';
import { AssetTypeEnum, type SmartSearchDto, type MetadataSearchDto } from '@immich/sdk';
import SearchPeopleSection from './search-people-section.svelte';
import SearchLocationSection from './search-location-section.svelte';
@ -163,7 +163,7 @@
</form>
{#snippet stickyBottom()}
<Button type="reset" color="gray" fullwidth form={formId}>{$t('clear_all')}</Button>
<Button type="submit" fullwidth form={formId}>{$t('search')}</Button>
<Button shape="round" size="large" type="reset" color="secondary" fullWidth form={formId}>{$t('clear_all')}</Button>
<Button shape="round" size="large" type="submit" fullWidth form={formId}>{$t('search')}</Button>
{/snippet}
</FullScreenModal>

View File

@ -2,7 +2,7 @@ import plugin from 'tailwindcss/plugin';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
content: ['./src/**/*.{html,js,svelte,ts}', './node_modules/@immich/ui/dist/**/*.{svelte,js}'],
darkMode: 'class',
theme: {
extend: {
@ -24,6 +24,14 @@ export default {
'immich-dark-error': 'rgb(var(--immich-dark-error) / <alpha-value>)',
'immich-dark-success': 'rgb(var(--immich-dark-success) / <alpha-value>)',
'immich-dark-warning': 'rgb(var(--immich-dark-warning) / <alpha-value>)',
primary: 'rgb(var(--immich-ui-primary) / <alpha-value>)',
light: 'rgb(var(--immich-ui-light) / <alpha-value>)',
dark: 'rgb(var(--immich-ui-dark) / <alpha-value>)',
success: 'rgb(var(--immich-ui-success) / <alpha-value>)',
danger: 'rgb(var(--immich-ui-danger) / <alpha-value>)',
warning: 'rgb(var(--immich-ui-warning) / <alpha-value>)',
info: 'rgb(var(--immich-ui-info) / <alpha-value>)',
},
fontFamily: {
'immich-mono': ['Overpass Mono', 'monospace'],