chore(web): prettier (#2821)

Co-authored-by: Thomas Way <thomas@6f.io>
This commit is contained in:
Jason Rasmussen 2023-07-01 00:50:47 -04:00 committed by GitHub
parent 7c2f7d6c51
commit f55b3add80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
242 changed files with 12794 additions and 13426 deletions

View file

@ -1,123 +1,102 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { AppRoute } from '$lib/constants';
import { api } from '@api';
import Button from '../elements/buttons/button.svelte';
import { goto } from '$app/navigation';
import { AppRoute } from '$lib/constants';
import { api } from '@api';
import Button from '../elements/buttons/button.svelte';
let error: string;
let password = '';
let confirmPassowrd = '';
let canRegister = false;
let error: string;
let password = '';
let confirmPassowrd = '';
let canRegister = false;
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
canRegister = false;
} else {
error = '';
canRegister = true;
}
}
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
canRegister = false;
} else {
error = '';
canRegister = true;
}
}
async function registerAdmin(event: SubmitEvent & { currentTarget: HTMLFormElement }) {
if (canRegister) {
error = '';
async function registerAdmin(event: SubmitEvent & { currentTarget: HTMLFormElement }) {
if (canRegister) {
error = '';
const form = new FormData(event.currentTarget);
const form = new FormData(event.currentTarget);
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const { status } = await api.authenticationApi.adminSignUp({
signUpDto: {
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName)
}
});
const { status } = await api.authenticationApi.adminSignUp({
signUpDto: {
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName),
},
});
if (status === 201) {
goto(AppRoute.AUTH_LOGIN);
return;
} else {
error = 'Error create admin account';
return;
}
}
}
if (status === 201) {
goto(AppRoute.AUTH_LOGIN);
return;
} else {
error = 'Error create admin account';
return;
}
}
}
</script>
<form on:submit|preventDefault={registerAdmin} method="post" class="flex flex-col gap-5 mt-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
/>
</div>
<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 />
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">Admin Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={password}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">Admin Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={password}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Admin Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={confirmPassowrd}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Admin Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={confirmPassowrd}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input
class="immich-form-input"
id="firstName"
name="firstName"
type="text"
autocomplete="given-name"
required
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input class="immich-form-input" id="firstName" name="firstName" type="text" autocomplete="given-name" required />
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input
class="immich-form-input"
id="lastName"
name="lastName"
type="text"
autocomplete="family-name"
required
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input class="immich-form-input" id="lastName" name="lastName" type="text" autocomplete="family-name" required />
</div>
{#if error}
<p class="text-red-400">{error}</p>
{/if}
{#if error}
<p class="text-red-400">{error}</p>
{/if}
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth>Sign up</Button>
</div>
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth>Sign up</Button>
</div>
</form>

View file

@ -1,49 +1,43 @@
<script lang="ts">
import type { APIKeyResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
import Button from '../elements/buttons/button.svelte';
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
import type { APIKeyResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
import Button from '../elements/buttons/button.svelte';
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
export let apiKey: Partial<APIKeyResponseDto>;
export let title = 'API Key';
export let cancelText = 'Cancel';
export let submitText = 'Save';
export let apiKey: Partial<APIKeyResponseDto>;
export let title = 'API Key';
export let cancelText = 'Cancel';
export let submitText = 'Save';
const dispatch = createEventDispatcher();
const handleCancel = () => dispatch('cancel');
const handleSubmit = () => dispatch('submit', { ...apiKey, name: apiKey.name });
const dispatch = createEventDispatcher();
const handleCancel = () => dispatch('cancel');
const handleSubmit = () => dispatch('submit', { ...apiKey, name: apiKey.name });
</script>
<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"
>
<div
class="flex flex-col place-items-center place-content-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">
{title}
</h1>
</div>
<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"
>
<div
class="flex flex-col place-items-center place-content-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">
{title}
</h1>
</div>
<form on:submit|preventDefault={() => handleSubmit()} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Name</label>
<input
class="immich-form-input"
id="name"
name="name"
type="text"
bind:value={apiKey.name}
/>
</div>
<form on:submit|preventDefault={() => handleSubmit()} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Name</label>
<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">
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
<Button type="submit" fullwidth>{submitText}</Button>
</div>
</form>
</div>
<div class="flex w-full px-4 gap-4 mt-8">
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
<Button type="submit" fullwidth>{submitText}</Button>
</div>
</form>
</div>
</FullScreenModal>

View file

@ -1,70 +1,59 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
import { handleError } from '../../utils/handle-error';
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
import {
notificationController,
NotificationType
} from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
import { createEventDispatcher, onMount } from 'svelte';
import KeyVariant from 'svelte-material-icons/KeyVariant.svelte';
import { handleError } from '../../utils/handle-error';
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
export let secret = '';
export let secret = '';
const dispatch = createEventDispatcher();
const handleDone = () => dispatch('done');
let canCopyImagesToClipboard = true;
const dispatch = createEventDispatcher();
const handleDone = () => dispatch('done');
let canCopyImagesToClipboard = true;
onMount(async () => {
const module = await import('copy-image-clipboard');
canCopyImagesToClipboard = module.canCopyImagesToClipboard();
});
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(secret);
notificationController.show({
message: 'Copied to clipboard!',
type: NotificationType.Info
});
} catch (error) {
handleError(error, 'Unable to copy to clipboard');
}
};
onMount(async () => {
const module = await import('copy-image-clipboard');
canCopyImagesToClipboard = module.canCopyImagesToClipboard();
});
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(secret);
notificationController.show({
message: 'Copied to clipboard!',
type: NotificationType.Info,
});
} catch (error) {
handleError(error, 'Unable to copy to clipboard');
}
};
</script>
<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"
>
<div
class="flex flex-col place-items-center place-content-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>
<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"
>
<div
class="flex flex-col place-items-center place-content-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>
<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.
</p>
</div>
<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.
</p>
</div>
<div class="m-4 flex flex-col gap-2">
<!-- <label class="immich-form-label" for="email">API Key</label> -->
<textarea
class="immich-form-input"
id="secret"
name="secret"
readonly={true}
value={secret}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<!-- <label class="immich-form-label" for="email">API Key</label> -->
<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">
{#if canCopyImagesToClipboard}
<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button>
{/if}
<Button on:click={() => handleDone()} fullwidth>Done</Button>
</div>
</div>
<div class="flex w-full px-4 gap-4 mt-8">
{#if canCopyImagesToClipboard}
<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button>
{/if}
<Button on:click={() => handleDone()} fullwidth>Done</Button>
</div>
</div>
</FullScreenModal>

View file

@ -1,86 +1,86 @@
<script lang="ts">
import { api, UserResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import Button from '../elements/buttons/button.svelte';
import { api, UserResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import Button from '../elements/buttons/button.svelte';
export let user: UserResponseDto;
let error: string;
let success: string;
export let user: UserResponseDto;
let error: string;
let success: string;
let password = '';
let confirmPassowrd = '';
let password = '';
let confirmPassowrd = '';
let changeChagePassword = false;
let changeChagePassword = false;
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
changeChagePassword = false;
} else {
error = '';
changeChagePassword = true;
}
}
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
changeChagePassword = false;
} else {
error = '';
changeChagePassword = true;
}
}
const dispatch = createEventDispatcher();
const dispatch = createEventDispatcher();
async function changePassword() {
if (changeChagePassword) {
error = '';
async function changePassword() {
if (changeChagePassword) {
error = '';
const { status } = await api.userApi.updateUser({
updateUserDto: {
id: user.id,
password: String(password),
shouldChangePassword: false
}
});
const { status } = await api.userApi.updateUser({
updateUserDto: {
id: user.id,
password: String(password),
shouldChangePassword: false,
},
});
if (status === 200) {
dispatch('success');
return;
} else {
console.error('Error changing password');
}
}
}
if (status === 200) {
dispatch('success');
return;
} else {
console.error('Error changing password');
}
}
}
</script>
<form on:submit|preventDefault={changePassword} method="post" class="flex flex-col gap-5 mt-5">
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">New Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={password}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">New Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="new-password"
required
bind:value={password}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
autocomplete="current-password"
required
bind:value={confirmPassowrd}
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
autocomplete="current-password"
required
bind:value={confirmPassowrd}
/>
</div>
{#if error}
<p class="text-red-400 text-sm">{error}</p>
{/if}
{#if error}
<p class="text-red-400 text-sm">{error}</p>
{/if}
{#if success}
<p class="text-immich-primary text-sm">{success}</p>
{/if}
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth>Change password</Button>
</div>
{#if success}
<p class="text-immich-primary text-sm">{success}</p>
{/if}
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth>Change password</Button>
</div>
</form>

View file

@ -1,150 +1,135 @@
<script lang="ts">
import { api } from '@api';
import { createEventDispatcher } from 'svelte';
import ImmichLogo from '../shared-components/immich-logo.svelte';
import {
notificationController,
NotificationType
} from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
import { api } from '@api';
import { createEventDispatcher } from 'svelte';
import ImmichLogo from '../shared-components/immich-logo.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
let error: string;
let success: string;
let error: string;
let success: string;
let password = '';
let confirmPassowrd = '';
let password = '';
let confirmPassowrd = '';
let canCreateUser = false;
let canCreateUser = false;
let isCreatingUser = false;
let isCreatingUser = false;
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
canCreateUser = false;
} else {
error = '';
canCreateUser = true;
}
}
const dispatch = createEventDispatcher();
$: {
if (password !== confirmPassowrd && confirmPassowrd.length > 0) {
error = 'Password does not match';
canCreateUser = false;
} else {
error = '';
canCreateUser = true;
}
}
const dispatch = createEventDispatcher();
async function registerUser(event: SubmitEvent) {
if (canCreateUser && !isCreatingUser) {
isCreatingUser = true;
async function registerUser(event: SubmitEvent) {
if (canCreateUser && !isCreatingUser) {
isCreatingUser = true;
error = '';
error = '';
const formElement = event.target as HTMLFormElement;
const formElement = event.target as HTMLFormElement;
const form = new FormData(formElement);
const form = new FormData(formElement);
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
try {
const { status } = await api.userApi.createUser({
createUserDto: {
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName)
}
});
try {
const { status } = await api.userApi.createUser({
createUserDto: {
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName),
},
});
if (status === 201) {
success = 'New user created';
if (status === 201) {
success = 'New user created';
dispatch('user-created');
dispatch('user-created');
isCreatingUser = false;
return;
} else {
error = 'Error create user account';
isCreatingUser = false;
}
} catch (e) {
error = 'Error create user account';
isCreatingUser = false;
isCreatingUser = false;
return;
} else {
error = 'Error create user account';
isCreatingUser = false;
}
} catch (e) {
error = 'Error create user account';
isCreatingUser = false;
console.log('[ERROR] registerUser', e);
console.log('[ERROR] registerUser', e);
notificationController.show({
message: `Error create new user, check console for more detail`,
type: NotificationType.Error
});
}
}
}
notificationController.show({
message: `Error create new user, check console for more detail`,
type: NotificationType.Error,
});
}
}
}
</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="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"
>
<div class="flex flex-col place-items-center place-content-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"
>
Please provide your user with the password, they will have to change it on their first sign
in.
</p>
</div>
<div class="flex flex-col place-items-center place-content-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">
Please provide your user with the password, they will have to change it on their first sign in.
</p>
</div>
<form on:submit|preventDefault={registerUser} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input class="immich-form-input" id="email" name="email" type="email" required />
</div>
<form on:submit|preventDefault={registerUser} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input class="immich-form-input" id="email" name="email" type="email" required />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="password">Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
required
bind:value={password}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="password">Password</label>
<input class="immich-form-input" id="password" name="password" type="password" required bind:value={password} />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
required
bind:value={confirmPassowrd}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="confirmPassword">Confirm Password</label>
<input
class="immich-form-input"
id="confirmPassword"
name="password"
type="password"
required
bind:value={confirmPassowrd}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input class="immich-form-input" id="firstName" name="firstName" type="text" required />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input class="immich-form-input" id="firstName" name="firstName" type="text" required />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input class="immich-form-input" id="lastName" name="lastName" type="text" required />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input class="immich-form-input" id="lastName" name="lastName" type="text" required />
</div>
{#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p>
{/if}
{#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p>
{/if}
{#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p>
{/if}
<div class="flex w-full p-4">
<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button>
</div>
</form>
{#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p>
{/if}
<div class="flex w-full p-4">
<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button>
</div>
</form>
</div>

View file

@ -1,187 +1,167 @@
<script lang="ts">
import { api, UserResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import AccountEditOutline from 'svelte-material-icons/AccountEditOutline.svelte';
import {
notificationController,
NotificationType
} from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
import { handleError } from '../../utils/handle-error';
import { api, UserResponseDto } from '@api';
import { createEventDispatcher } from 'svelte';
import AccountEditOutline from 'svelte-material-icons/AccountEditOutline.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import Button from '../elements/buttons/button.svelte';
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
import { handleError } from '../../utils/handle-error';
export let user: UserResponseDto;
export let canResetPassword = true;
export let user: UserResponseDto;
export let canResetPassword = true;
let error: string;
let success: string;
let error: string;
let success: string;
let isShowResetPasswordConfirmation = false;
let isShowResetPasswordConfirmation = false;
const dispatch = createEventDispatcher();
const dispatch = createEventDispatcher();
const editUser = async () => {
try {
const { id, email, firstName, lastName, storageLabel, externalPath } = user;
const { status } = await api.userApi.updateUser({
updateUserDto: {
id,
email,
firstName,
lastName,
storageLabel: storageLabel || '',
externalPath: externalPath || ''
}
});
const editUser = async () => {
try {
const { id, email, firstName, lastName, storageLabel, externalPath } = user;
const { status } = await api.userApi.updateUser({
updateUserDto: {
id,
email,
firstName,
lastName,
storageLabel: storageLabel || '',
externalPath: externalPath || '',
},
});
if (status === 200) {
dispatch('edit-success');
}
} catch (error) {
handleError(error, 'Unable to update user');
}
};
if (status === 200) {
dispatch('edit-success');
}
} catch (error) {
handleError(error, 'Unable to update user');
}
};
const resetPassword = async () => {
try {
const defaultPassword = 'password';
const resetPassword = async () => {
try {
const defaultPassword = 'password';
const { status } = await api.userApi.updateUser({
updateUserDto: {
id: user.id,
password: defaultPassword,
shouldChangePassword: true
}
});
const { status } = await api.userApi.updateUser({
updateUserDto: {
id: user.id,
password: defaultPassword,
shouldChangePassword: true,
},
});
if (status == 200) {
dispatch('reset-password-success');
}
} catch (e) {
console.error('Error reseting user password', e);
notificationController.show({
message: 'Error reseting user password, check console for more details',
type: NotificationType.Error
});
} finally {
isShowResetPasswordConfirmation = false;
}
};
if (status == 200) {
dispatch('reset-password-success');
}
} catch (e) {
console.error('Error reseting user password', e);
notificationController.show({
message: 'Error reseting user password, check console for more details',
type: NotificationType.Error,
});
} finally {
isShowResetPasswordConfirmation = false;
}
};
</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="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"
>
<div
class="flex flex-col place-items-center place-content-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>
</div>
<div
class="flex flex-col place-items-center place-content-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>
</div>
<form on:submit|preventDefault={editUser} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input
class="immich-form-input"
id="email"
name="email"
type="email"
bind:value={user.email}
/>
</div>
<form on:submit|preventDefault={editUser} autocomplete="off">
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input class="immich-form-input" id="email" name="email" type="email" bind:value={user.email} />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input
class="immich-form-input"
id="firstName"
name="firstName"
type="text"
required
bind:value={user.firstName}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="firstName">First Name</label>
<input
class="immich-form-input"
id="firstName"
name="firstName"
type="text"
required
bind:value={user.firstName}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input
class="immich-form-input"
id="lastName"
name="lastName"
type="text"
required
bind:value={user.lastName}
/>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="lastName">Last Name</label>
<input class="immich-form-input" id="lastName" name="lastName" type="text" required bind:value={user.lastName} />
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="storage-label">Storage Label</label>
<input
class="immich-form-input"
id="storage-label"
name="storage-label"
type="text"
bind:value={user.storageLabel}
/>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="storage-label">Storage Label</label>
<input
class="immich-form-input"
id="storage-label"
name="storage-label"
type="text"
bind:value={user.storageLabel}
/>
<p>
Note: To apply the Storage Label to previously uploaded assets, run the
<a href="/admin/jobs-status" class="text-immich-primary dark:text-immich-dark-primary">
Storage Migration Job</a
>
</p>
</div>
<p>
Note: To apply the Storage Label to previously uploaded assets, run the
<a href="/admin/jobs-status" class="text-immich-primary dark:text-immich-dark-primary">
Storage Migration Job</a
>
</p>
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="external-path">External Path</label>
<input
class="immich-form-input"
id="external-path"
name="external-path"
type="text"
bind:value={user.externalPath}
/>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="external-path">External Path</label>
<input
class="immich-form-input"
id="external-path"
name="external-path"
type="text"
bind:value={user.externalPath}
/>
<p>
Note: Absolute path of parent import directory. A user can only import files if they exist
at or under this path.
</p>
</div>
<p>
Note: Absolute path of parent import directory. A user can only import files if they exist at or under this
path.
</p>
</div>
{#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p>
{/if}
{#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p>
{/if}
{#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p>
{/if}
<div class="flex w-full px-4 gap-4 mt-8">
{#if canResetPassword}
<Button
color="light-red"
fullwidth
on:click={() => (isShowResetPasswordConfirmation = true)}>Reset password</Button
>
{/if}
<Button type="submit" fullwidth>Confirm</Button>
</div>
</form>
{#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p>
{/if}
<div class="flex w-full px-4 gap-4 mt-8">
{#if canResetPassword}
<Button color="light-red" fullwidth on:click={() => (isShowResetPasswordConfirmation = true)}
>Reset password</Button
>
{/if}
<Button type="submit" fullwidth>Confirm</Button>
</div>
</form>
</div>
{#if isShowResetPasswordConfirmation}
<ConfirmDialogue
title="Reset Password"
confirmText="Reset"
on:confirm={resetPassword}
on:cancel={() => (isShowResetPasswordConfirmation = false)}
>
<svelte:fragment slot="prompt">
<p>
Are you sure you want to reset <b>{user.firstName} {user.lastName}</b>'s password?
</p>
</svelte:fragment>
</ConfirmDialogue>
<ConfirmDialogue
title="Reset Password"
confirmText="Reset"
on:confirm={resetPassword}
on:cancel={() => (isShowResetPasswordConfirmation = false)}
>
<svelte:fragment slot="prompt">
<p>
Are you sure you want to reset <b>{user.firstName} {user.lastName}</b>'s password?
</p>
</svelte:fragment>
</ConfirmDialogue>
{/if}

View file

@ -1,166 +1,166 @@
<script lang="ts">
import { goto } from '$app/navigation';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { AppRoute } from '$lib/constants';
import { handleError } from '$lib/utils/handle-error';
import { api, oauth, OAuthConfigResponseDto } from '@api';
import { createEventDispatcher, onMount } from 'svelte';
import { fade } from 'svelte/transition';
import Button from '../elements/buttons/button.svelte';
import { goto } from '$app/navigation';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { AppRoute } from '$lib/constants';
import { handleError } from '$lib/utils/handle-error';
import { api, oauth, OAuthConfigResponseDto } from '@api';
import { createEventDispatcher, onMount } from 'svelte';
import { fade } from 'svelte/transition';
import Button from '../elements/buttons/button.svelte';
let error: string;
let email = '';
let password = '';
let oauthError: string;
export let authConfig: OAuthConfigResponseDto;
let loading = false;
let oauthLoading = true;
let error: string;
let email = '';
let password = '';
let oauthError: string;
export let authConfig: OAuthConfigResponseDto;
let loading = false;
let oauthLoading = true;
const dispatch = createEventDispatcher();
const dispatch = createEventDispatcher();
onMount(async () => {
if (oauth.isCallback(window.location)) {
try {
await oauth.login(window.location);
dispatch('success');
return;
} catch (e) {
console.error('Error [login-form] [oauth.callback]', e);
oauthError = 'Unable to complete OAuth login';
} finally {
oauthLoading = false;
}
}
onMount(async () => {
if (oauth.isCallback(window.location)) {
try {
await oauth.login(window.location);
dispatch('success');
return;
} catch (e) {
console.error('Error [login-form] [oauth.callback]', e);
oauthError = 'Unable to complete OAuth login';
} finally {
oauthLoading = false;
}
}
try {
const { data } = await oauth.getConfig(window.location);
authConfig = data;
try {
const { data } = await oauth.getConfig(window.location);
authConfig = data;
const { enabled, url, autoLaunch } = authConfig;
const { enabled, url, autoLaunch } = authConfig;
if (enabled && url && autoLaunch && !oauth.isAutoLaunchDisabled(window.location)) {
await goto(`${AppRoute.AUTH_LOGIN}?autoLaunch=0`, { replaceState: true });
await goto(url);
return;
}
} catch (error) {
authConfig.passwordLoginEnabled = true;
handleError(error, 'Unable to connect!');
}
if (enabled && url && autoLaunch && !oauth.isAutoLaunchDisabled(window.location)) {
await goto(`${AppRoute.AUTH_LOGIN}?autoLaunch=0`, { replaceState: true });
await goto(url);
return;
}
} catch (error) {
authConfig.passwordLoginEnabled = true;
handleError(error, 'Unable to connect!');
}
oauthLoading = false;
});
oauthLoading = false;
});
const login = async () => {
try {
error = '';
loading = true;
const login = async () => {
try {
error = '';
loading = true;
const { data } = await api.authenticationApi.login({
loginCredentialDto: {
email,
password
}
});
const { data } = await api.authenticationApi.login({
loginCredentialDto: {
email,
password,
},
});
if (!data.isAdmin && data.shouldChangePassword) {
dispatch('first-login');
return;
}
if (!data.isAdmin && data.shouldChangePassword) {
dispatch('first-login');
return;
}
dispatch('success');
return;
} catch (e) {
error = 'Incorrect email or password';
loading = false;
return;
}
};
dispatch('success');
return;
} catch (e) {
error = 'Incorrect email or password';
loading = false;
return;
}
};
</script>
{#if authConfig.passwordLoginEnabled}
<form on:submit|preventDefault={login} class="flex flex-col gap-5 mt-5">
{#if error}
<p class="text-red-400" transition:fade>
{error}
</p>
{/if}
<form on:submit|preventDefault={login} class="flex flex-col gap-5 mt-5">
{#if error}
<p class="text-red-400" transition:fade>
{error}
</p>
{/if}
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input
class="immich-form-input"
id="email"
name="email"
type="email"
autocomplete="email"
bind:value={email}
required
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="email">Email</label>
<input
class="immich-form-input"
id="email"
name="email"
type="email"
autocomplete="email"
bind:value={email}
required
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="current-password"
bind:value={password}
required
/>
</div>
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">Password</label>
<input
class="immich-form-input"
id="password"
name="password"
type="password"
autocomplete="current-password"
bind:value={password}
required
/>
</div>
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth disabled={loading || oauthLoading}>
{#if loading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
Login
{/if}
</Button>
</div>
</form>
<div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth disabled={loading || oauthLoading}>
{#if loading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
Login
{/if}
</Button>
</div>
</form>
{/if}
{#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" />
<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"
>
or
</span>
</div>
{/if}
<div class="my-5 flex flex-col gap-5">
{#if oauthError}
<p class="text-red-400" transition:fade>{oauthError}</p>
{/if}
<a href={authConfig.url} class="flex w-full">
<Button
type="button"
disabled={loading || oauthLoading}
size="lg"
fullwidth
color={authConfig.passwordLoginEnabled ? 'secondary' : 'primary'}
>
{#if oauthLoading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
{authConfig.buttonText || 'Login with OAuth'}
{/if}
</Button>
</a>
</div>
{#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" />
<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"
>
or
</span>
</div>
{/if}
<div class="my-5 flex flex-col gap-5">
{#if oauthError}
<p class="text-red-400" transition:fade>{oauthError}</p>
{/if}
<a href={authConfig.url} class="flex w-full">
<Button
type="button"
disabled={loading || oauthLoading}
size="lg"
fullwidth
color={authConfig.passwordLoginEnabled ? 'secondary' : 'primary'}
>
{#if oauthLoading}
<span class="h-6">
<LoadingSpinner />
</span>
{:else}
{authConfig.buttonText || 'Login with OAuth'}
{/if}
</Button>
</a>
</div>
{/if}
{#if !authConfig.enabled && !authConfig.passwordLoginEnabled}
<p class="text-center dark:text-immich-dark-fg p-4">Login has been disabled.</p>
<p class="text-center dark:text-immich-dark-fg p-4">Login has been disabled.</p>
{/if}