login.rs
⎇
Raw
1use leptos::prelude::*;
2use wasm_bindgen_futures::spawn_local;
3
4use crate::api::{self, Me, input_value};
5use crate::app::AuthPhase;
6use crate::components::logo::Logo;
7
8#[component]
9pub fn LoginView(
10 set_me: WriteSignal<Option<Me>>,
11 set_phase: WriteSignal<AuthPhase>,
12) -> impl IntoView {
13 let (error, set_error) = signal(String::new());
14 let (busy, set_busy) = signal(false);
15
16 let on_submit = move |ev: web_sys::SubmitEvent| {
17 ev.prevent_default();
18 let name = input_value("login-name");
19 let pass = input_value("login-pass");
20 if name.trim().is_empty() || pass.is_empty() {
21 set_error.set("Please enter your name and password.".into());
22 return;
23 }
24 set_error.set(String::new());
25 set_busy.set(true);
26 let name = name.trim().to_string();
27 spawn_local(async move {
28 match api::login(name, pass).await {
29 Ok(_) => match api::me().await {
30 Ok(m) => {
31 // Keep the current hash: deep links (e.g. #/users) survive
32 // the sign-in. A non-admin landing on an admin section is
33 // redirected to the files view by the shell instead.
34 set_me.set(Some(m));
35 set_phase.set(AuthPhase::Authed);
36 }
37 Err(e) => {
38 set_error.set(e.to_string());
39 set_busy.set(false);
40 }
41 },
42 Err(e) => {
43 set_error.set(e.to_string());
44 set_busy.set(false);
45 }
46 }
47 });
48 };
49
50 view! {
51 <div class="center-screen">
52 <div class="card auth-card">
53 <Logo class="auth-logo".to_string()/>
54 <h1>"filebrowser-ng"</h1>
55 <p class="muted">"Sign in to continue."</p>
56 <form on:submit=on_submit>
57 <label class="field">
58 <span>"Name"</span>
59 <input
60 id="login-name"
61 type="text"
62 autofocus=true
63 autocomplete="username"
64 />
65 </label>
66 <label class="field">
67 <span>"Password"</span>
68 <input
69 id="login-pass"
70 type="password"
71 autocomplete="current-password"
72 />
73 </label>
74 <p class="error">{move || error.get()}</p>
75 <button class="btn-primary" type="submit" disabled=move || busy.get()>
76 "Sign in"
77 </button>
78 </form>
79 </div>
80 </div>
81 }
82}
83