+page.svelte 6.31 KB
Newer Older
1
2
<script>
	import { goto } from '$app/navigation';
Timothy J. Baek's avatar
Timothy J. Baek committed
3
	import { userSignIn, userSignUp } from '$lib/apis/auths';
Timothy J. Baek's avatar
Timothy J. Baek committed
4
	import Spinner from '$lib/components/common/Spinner.svelte';
5
	import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
Timothy J. Baek's avatar
Timothy J. Baek committed
6
	import { WEBUI_NAME, config, user, socket } from '$lib/stores';
7
	import { onMount, getContext } from 'svelte';
Jannik Streidl's avatar
Jannik Streidl committed
8
	import { toast } from 'svelte-sonner';
9
	import { generateInitialsImage, canvasPixelTest } from '$lib/utils';
10

11
12
	const i18n = getContext('i18n');

Timothy J. Baek's avatar
Timothy J. Baek committed
13
	let loaded = false;
14
15
16
17
18
19
	let mode = 'signin';

	let name = '';
	let email = '';
	let password = '';

Timothy J. Baek's avatar
Timothy J. Baek committed
20
21
22
	const setSessionUser = async (sessionUser) => {
		if (sessionUser) {
			console.log(sessionUser);
23
			toast.success($i18n.t(`You're now logged in.`));
Timothy J. Baek's avatar
Timothy J. Baek committed
24
			localStorage.token = sessionUser.token;
Timothy J. Baek's avatar
Timothy J. Baek committed
25
26

			$socket.emit('user-join', { auth: { token: sessionUser.token } });
Timothy J. Baek's avatar
Timothy J. Baek committed
27
			await user.set(sessionUser);
28
29
30
31
			goto('/');
		}
	};

Timothy J. Baek's avatar
Timothy J. Baek committed
32
33
34
35
36
37
38
39
40
	const signInHandler = async () => {
		const sessionUser = await userSignIn(email, password).catch((error) => {
			toast.error(error);
			return null;
		});

		await setSessionUser(sessionUser);
	};

41
	const signUpHandler = async () => {
Danny Liu's avatar
Danny Liu committed
42
43
44
45
46
47
		const sessionUser = await userSignUp(name, email, password, generateInitialsImage(name)).catch(
			(error) => {
				toast.error(error);
				return null;
			}
		);
Timothy J. Baek's avatar
Timothy J. Baek committed
48
49
50
51
52
53
54
55
56

		await setSessionUser(sessionUser);
	};

	const submitHandler = async () => {
		if (mode === 'signin') {
			await signInHandler();
		} else {
			await signUpHandler();
57
58
59
		}
	};

Timothy J. Baek's avatar
Timothy J. Baek committed
60
	onMount(async () => {
Timothy J. Baek's avatar
Timothy J. Baek committed
61
		if ($user !== undefined) {
Timothy J. Baek's avatar
Timothy J. Baek committed
62
63
64
			await goto('/');
		}
		loaded = true;
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
65
		if (($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false) {
66
67
			await signInHandler();
		}
Timothy J. Baek's avatar
Timothy J. Baek committed
68
	});
69
70
</script>

Timothy J. Baek's avatar
Timothy J. Baek committed
71
72
73
74
75
76
<svelte:head>
	<title>
		{`${$WEBUI_NAME}`}
	</title>
</svelte:head>

Timothy J. Baek's avatar
Timothy J. Baek committed
77
{#if loaded}
78
79
80
	<div class="fixed m-10 z-50">
		<div class="flex space-x-2">
			<div class=" self-center">
Timothy J. Baek's avatar
Timothy J. Baek committed
81
82
83
84
85
86
				<img
					crossorigin="anonymous"
					src="{WEBUI_BASE_URL}/static/favicon.png"
					class=" w-8 rounded-full"
					alt="logo"
				/>
87
88
89
90
			</div>
		</div>
	</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
91
	<div class=" bg-white dark:bg-gray-950 min-h-screen w-full flex justify-center font-mona">
Timothy J. Baek's avatar
Timothy J. Baek committed
92
		<!-- <div class="hidden lg:flex lg:flex-1 px-10 md:px-16 w-full bg-yellow-50 justify-center">
93
94
95
96
97
98
99
100
101
102
103
			<div class=" my-auto pb-16 text-left">
				<div>
					<div class=" font-bold text-yellow-600 text-4xl">
						Get up and running with <br />large language models, locally.
					</div>

					<div class="mt-2 text-yellow-600 text-xl">
						Run Llama 2, Code Llama, and other models. Customize and create your own.
					</div>
				</div>
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
104
		</div> -->
105

Timothy J. Baek's avatar
Timothy J. Baek committed
106
		<div class="w-full sm:max-w-md px-10 min-h-screen flex flex-col text-center">
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
107
			{#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
108
				<div class=" my-auto pb-10 w-full">
Timothy J. Baek's avatar
Timothy J. Baek committed
109
					<div
Timothy J. Baek's avatar
Timothy J. Baek committed
110
						class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-medium dark:text-gray-200"
Timothy J. Baek's avatar
Timothy J. Baek committed
111
112
113
114
115
116
117
118
119
120
					>
						<div>
							{$i18n.t('Signing in')}
							{$i18n.t('to')}
							{$WEBUI_NAME}
						</div>

						<div>
							<Spinner />
						</div>
121
122
123
					</div>
				</div>
			{:else}
Timothy J. Baek's avatar
Timothy J. Baek committed
124
				<div class="  my-auto pb-10 w-full dark:text-gray-100">
Timothy J. Baek's avatar
Timothy J. Baek committed
125
					<form
Timothy J. Baek's avatar
Timothy J. Baek committed
126
						class=" flex flex-col justify-center"
Timothy J. Baek's avatar
Timothy J. Baek committed
127
128
129
130
						on:submit|preventDefault={() => {
							submitHandler();
						}}
					>
Timothy J. Baek's avatar
Timothy J. Baek committed
131
						<div class="mb-1">
Timothy J. Baek's avatar
Timothy J. Baek committed
132
							<div class=" text-2xl font-medium">
Timothy J. Baek's avatar
Timothy J. Baek committed
133
134
135
								{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Sign up')}
								{$i18n.t('to')}
								{$WEBUI_NAME}
Timothy J. Baek's avatar
Timothy J. Baek committed
136
							</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
137
138
139
140
141
142
143
144
145
146

							{#if mode === 'signup'}
								<div class=" mt-1 text-xs font-medium text-gray-500">
									ⓘ {$WEBUI_NAME}
									{$i18n.t(
										'does not make any external connections, and your data stays securely on your locally hosted server.'
									)}
								</div>
							{/if}
						</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
147
148
149
150

						<div class="flex flex-col mt-4">
							{#if mode === 'signup'}
								<div>
Timothy J. Baek's avatar
Timothy J. Baek committed
151
									<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Name')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
152
153
154
									<input
										bind:value={name}
										type="text"
Timothy J. Baek's avatar
Timothy J. Baek committed
155
										class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
Timothy J. Baek's avatar
Timothy J. Baek committed
156
157
158
159
160
161
										autocomplete="name"
										placeholder={$i18n.t('Enter Your Full Name')}
										required
									/>
								</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
162
								<hr class=" my-3 dark:border-gray-900" />
Timothy J. Baek's avatar
Timothy J. Baek committed
163
164
165
							{/if}

							<div class="mb-2">
Timothy J. Baek's avatar
Timothy J. Baek committed
166
								<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Email')}</div>
167
								<input
Timothy J. Baek's avatar
Timothy J. Baek committed
168
169
									bind:value={email}
									type="email"
Timothy J. Baek's avatar
Timothy J. Baek committed
170
									class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
Timothy J. Baek's avatar
Timothy J. Baek committed
171
172
									autocomplete="email"
									placeholder={$i18n.t('Enter Your Email')}
173
174
175
									required
								/>
							</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
176

Timothy J. Baek's avatar
Timothy J. Baek committed
177
							<div>
Timothy J. Baek's avatar
Timothy J. Baek committed
178
								<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Password')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
179

Timothy J. Baek's avatar
Timothy J. Baek committed
180
181
182
								<input
									bind:value={password}
									type="password"
Timothy J. Baek's avatar
Timothy J. Baek committed
183
									class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
Timothy J. Baek's avatar
Timothy J. Baek committed
184
185
186
187
188
									placeholder={$i18n.t('Enter Your Password')}
									autocomplete="current-password"
									required
								/>
							</div>
189
						</div>
190

Timothy J. Baek's avatar
Timothy J. Baek committed
191
						<div class="mt-5">
192
							<button
Timothy J. Baek's avatar
Timothy J. Baek committed
193
								class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-medium text-sm py-3 transition"
Timothy J. Baek's avatar
Timothy J. Baek committed
194
								type="submit"
195
							>
Timothy J. Baek's avatar
Timothy J. Baek committed
196
								{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
197
							</button>
Timothy J. Baek's avatar
Timothy J. Baek committed
198

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
199
							{#if $config?.features.enable_signup}
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
								<div class=" mt-4 text-sm text-center">
									{mode === 'signin'
										? $i18n.t("Don't have an account?")
										: $i18n.t('Already have an account?')}

									<button
										class=" font-medium underline"
										type="button"
										on:click={() => {
											if (mode === 'signin') {
												mode = 'signup';
											} else {
												mode = 'signin';
											}
										}}
									>
										{mode === 'signin' ? $i18n.t('Sign up') : $i18n.t('Sign in')}
									</button>
								</div>
							{/if}
220
						</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
221
222
					</form>
				</div>
223
			{/if}
224
225
226
		</div>
	</div>
{/if}
Timothy J. Baek's avatar
Timothy J. Baek committed
227
228
229

<style>
	.font-mona {
Timothy J. Baek's avatar
Timothy J. Baek committed
230
231
232
		font-family: 'Mona Sans', -apple-system, 'Arimo', ui-sans-serif, system-ui, 'Segoe UI', Roboto,
			Ubuntu, Cantarell, 'Noto Sans', sans-serif, 'Helvetica Neue', Arial, 'Apple Color Emoji',
			'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
Timothy J. Baek's avatar
Timothy J. Baek committed
233
234
	}
</style>