+page.svelte 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <script>
  2. import { goto } from '$app/navigation';
  3. import { userSignIn, userSignUp } from '$lib/apis/auths';
  4. import Spinner from '$lib/components/common/Spinner.svelte';
  5. import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
  6. import { WEBUI_NAME, config, user, socket } from '$lib/stores';
  7. import { onMount, getContext } from 'svelte';
  8. import { toast } from 'svelte-sonner';
  9. import { generateInitialsImage, canvasPixelTest } from '$lib/utils';
  10. const i18n = getContext('i18n');
  11. let loaded = false;
  12. let mode = 'signin';
  13. let name = '';
  14. let email = '';
  15. let password = '';
  16. const setSessionUser = async (sessionUser) => {
  17. if (sessionUser) {
  18. console.log(sessionUser);
  19. toast.success($i18n.t(`You're now logged in.`));
  20. localStorage.token = sessionUser.token;
  21. $socket.emit('user-join', { auth: { token: sessionUser.token } });
  22. await user.set(sessionUser);
  23. goto('/');
  24. }
  25. };
  26. const signInHandler = async () => {
  27. const sessionUser = await userSignIn(email, password).catch((error) => {
  28. toast.error(error);
  29. return null;
  30. });
  31. await setSessionUser(sessionUser);
  32. };
  33. const signUpHandler = async () => {
  34. const sessionUser = await userSignUp(name, email, password, generateInitialsImage(name)).catch(
  35. (error) => {
  36. toast.error(error);
  37. return null;
  38. }
  39. );
  40. await setSessionUser(sessionUser);
  41. };
  42. const submitHandler = async () => {
  43. if (mode === 'signin') {
  44. await signInHandler();
  45. } else {
  46. await signUpHandler();
  47. }
  48. };
  49. onMount(async () => {
  50. if ($user !== undefined) {
  51. await goto('/');
  52. }
  53. loaded = true;
  54. if (($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false) {
  55. await signInHandler();
  56. }
  57. });
  58. </script>
  59. <svelte:head>
  60. <title>
  61. {`${$WEBUI_NAME}`}
  62. </title>
  63. </svelte:head>
  64. {#if loaded}
  65. <div class="fixed m-10 z-50">
  66. <div class="flex space-x-2">
  67. <div class=" self-center">
  68. <img
  69. crossorigin="anonymous"
  70. src="{WEBUI_BASE_URL}/static/favicon.png"
  71. class=" w-8 rounded-full"
  72. alt="logo"
  73. />
  74. </div>
  75. </div>
  76. </div>
  77. <div class=" bg-white dark:bg-gray-950 min-h-screen w-full flex justify-center font-mona">
  78. <!-- <div class="hidden lg:flex lg:flex-1 px-10 md:px-16 w-full bg-yellow-50 justify-center">
  79. <div class=" my-auto pb-16 text-left">
  80. <div>
  81. <div class=" font-bold text-yellow-600 text-4xl">
  82. Get up and running with <br />large language models, locally.
  83. </div>
  84. <div class="mt-2 text-yellow-600 text-xl">
  85. Run Llama 2, Code Llama, and other models. Customize and create your own.
  86. </div>
  87. </div>
  88. </div>
  89. </div> -->
  90. <div class="w-full sm:max-w-md px-10 min-h-screen flex flex-col text-center">
  91. {#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
  92. <div class=" my-auto pb-10 w-full">
  93. <div
  94. class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-bold dark:text-gray-200"
  95. >
  96. <div>
  97. {$i18n.t('Signing in')}
  98. {$i18n.t('to')}
  99. {$WEBUI_NAME}
  100. </div>
  101. <div>
  102. <Spinner />
  103. </div>
  104. </div>
  105. </div>
  106. {:else}
  107. <div class=" my-auto pb-10 w-full dark:text-gray-100">
  108. <form
  109. class=" flex flex-col justify-center"
  110. on:submit|preventDefault={() => {
  111. submitHandler();
  112. }}
  113. >
  114. <div class="mb-1">
  115. <div class=" text-2xl font-bold">
  116. {mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Sign up')}
  117. {$i18n.t('to')}
  118. {$WEBUI_NAME}
  119. </div>
  120. {#if mode === 'signup'}
  121. <div class=" mt-1 text-xs font-medium text-gray-500">
  122. ⓘ {$WEBUI_NAME}
  123. {$i18n.t(
  124. 'does not make any external connections, and your data stays securely on your locally hosted server.'
  125. )}
  126. </div>
  127. {/if}
  128. </div>
  129. <div class="flex flex-col mt-4">
  130. {#if mode === 'signup'}
  131. <div>
  132. <div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Name')}</div>
  133. <input
  134. bind:value={name}
  135. type="text"
  136. class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
  137. autocomplete="name"
  138. placeholder={$i18n.t('Enter Your Full Name')}
  139. required
  140. />
  141. </div>
  142. <hr class=" my-3 dark:border-gray-900" />
  143. {/if}
  144. <div class="mb-2">
  145. <div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Email')}</div>
  146. <input
  147. bind:value={email}
  148. type="email"
  149. class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
  150. autocomplete="email"
  151. placeholder={$i18n.t('Enter Your Email')}
  152. required
  153. />
  154. </div>
  155. <div>
  156. <div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Password')}</div>
  157. <input
  158. bind:value={password}
  159. type="password"
  160. class=" px-5 py-3 rounded-2xl w-full text-sm outline-none border dark:border-none dark:bg-gray-900"
  161. placeholder={$i18n.t('Enter Your Password')}
  162. autocomplete="current-password"
  163. required
  164. />
  165. </div>
  166. </div>
  167. <div class="mt-5">
  168. <button
  169. class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-semibold text-sm py-3 transition"
  170. type="submit"
  171. >
  172. {mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
  173. </button>
  174. {#if $config?.features.enable_signup}
  175. <div class=" mt-4 text-sm text-center">
  176. {mode === 'signin'
  177. ? $i18n.t("Don't have an account?")
  178. : $i18n.t('Already have an account?')}
  179. <button
  180. class=" font-medium underline"
  181. type="button"
  182. on:click={() => {
  183. if (mode === 'signin') {
  184. mode = 'signup';
  185. } else {
  186. mode = 'signin';
  187. }
  188. }}
  189. >
  190. {mode === 'signin' ? $i18n.t('Sign up') : $i18n.t('Sign in')}
  191. </button>
  192. </div>
  193. {/if}
  194. </div>
  195. </form>
  196. </div>
  197. {/if}
  198. </div>
  199. </div>
  200. {/if}
  201. <style>
  202. .font-mona {
  203. font-family: 'Mona Sans', -apple-system, 'Arimo', ui-sans-serif, system-ui, 'Segoe UI', Roboto,
  204. Ubuntu, Cantarell, 'Noto Sans', sans-serif, 'Helvetica Neue', Arial, 'Apple Color Emoji',
  205. 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  206. }
  207. </style>