Add basic login page
This commit is contained in:
parent
014525b683
commit
8a8e773795
@ -1,7 +1,7 @@
|
||||
pub mod components;
|
||||
mod pages;
|
||||
use components::Nav;
|
||||
use pages::Home;
|
||||
use pages::{Home, Login};
|
||||
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
@ -10,6 +10,8 @@ use yew_router::prelude::*;
|
||||
enum Route {
|
||||
#[at("/")]
|
||||
Home,
|
||||
#[at("/login")]
|
||||
Login,
|
||||
#[not_found]
|
||||
#[at("/404")]
|
||||
NotFound,
|
||||
@ -18,6 +20,7 @@ enum Route {
|
||||
fn switch(routes: Route) -> Html {
|
||||
match routes {
|
||||
Route::Home => html! { <Home /> },
|
||||
Route::Login => html! { <Login /> },
|
||||
Route::NotFound => html! {
|
||||
<>
|
||||
<Nav />
|
||||
|
@ -1,2 +1,4 @@
|
||||
mod home;
|
||||
pub use home::Home;
|
||||
mod login;
|
||||
pub use login::Login;
|
||||
|
@ -2,15 +2,16 @@ use std::time::Duration;
|
||||
|
||||
use chrono::Local;
|
||||
use common::ChatMessage;
|
||||
use gloo::{console::log, events::EventListener, net::http::Request};
|
||||
use gloo::{console::log, events::EventListener};
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{js_sys::Uint8Array, CloseEvent, Event, MessageEvent, WebSocket};
|
||||
use yew::{
|
||||
platform::{spawn_local, time::sleep},
|
||||
prelude::*,
|
||||
};
|
||||
use yew::{platform::time::sleep, prelude::*};
|
||||
use yew_router::prelude::RouterScopeExt;
|
||||
|
||||
use crate::components::{Alert, Message, Nav};
|
||||
use crate::{
|
||||
components::{Alert, Message, Nav},
|
||||
Route,
|
||||
};
|
||||
|
||||
pub enum HomeMessage {
|
||||
SubmittedMessage(String),
|
||||
@ -18,7 +19,6 @@ pub enum HomeMessage {
|
||||
WsClose(CloseEvent),
|
||||
WsOpen,
|
||||
WsReconnect,
|
||||
Authenticated,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
@ -28,7 +28,6 @@ enum WsState {
|
||||
}
|
||||
|
||||
pub struct Home {
|
||||
authenticated: bool,
|
||||
messages: Vec<ChatMessage>,
|
||||
chat_ws: Option<WebSocketConn>,
|
||||
ws_state: WsState,
|
||||
@ -88,26 +87,6 @@ impl Home {
|
||||
listeners: [open_ev, close_ev, msg_ev],
|
||||
});
|
||||
}
|
||||
|
||||
fn authenticate(ctx: &Context<Self>) {
|
||||
log!("Authenticating to backend");
|
||||
let auth_cb = ctx.link().callback(|_: ()| HomeMessage::Authenticated);
|
||||
spawn_local(async move {
|
||||
let location = web_sys::window().unwrap().location();
|
||||
let login_url = format!(
|
||||
"{}//{}/api/login",
|
||||
location.protocol().unwrap(),
|
||||
location.host().unwrap()
|
||||
);
|
||||
Request::post(&login_url)
|
||||
.body("")
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
auth_cb.emit(());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Home {
|
||||
@ -116,9 +95,7 @@ impl Component for Home {
|
||||
type Properties = ();
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
Self::authenticate(ctx);
|
||||
let mut slf = Self {
|
||||
authenticated: false,
|
||||
messages: Vec::new(),
|
||||
chat_ws: None,
|
||||
ws_state: WsState::Closed,
|
||||
@ -147,7 +124,7 @@ impl Component for Home {
|
||||
}
|
||||
})
|
||||
};
|
||||
let disable_input = self.ws_state != WsState::Open || !self.authenticated;
|
||||
let disable_input = self.ws_state != WsState::Open;
|
||||
html! {
|
||||
<div class="myvh-100 d-flex flex-column">
|
||||
<Nav />
|
||||
@ -155,9 +132,6 @@ impl Component for Home {
|
||||
if self.ws_state != WsState::Open {
|
||||
<Alert message="Connection to backend lost, trying to reconnect" />
|
||||
}
|
||||
if !self.authenticated {
|
||||
<Alert message="Authenticating to backend" />
|
||||
}
|
||||
<div
|
||||
ref={self.message_container_ref.clone()}
|
||||
class="d-flex border rounded flex-grow-1 flex-column-reverse overflow-auto mb-3"
|
||||
@ -203,10 +177,8 @@ impl Component for Home {
|
||||
let code = close_event.code();
|
||||
log!("WS connection closed with code", code);
|
||||
if code == 4000 {
|
||||
log!("Unauthorized, reauthenticating");
|
||||
self.ws_state = WsState::Closed;
|
||||
self.authenticated = false;
|
||||
Self::authenticate(ctx);
|
||||
log!("Unauthorized, redirecting to login page");
|
||||
ctx.link().navigator().unwrap().push(&Route::Login);
|
||||
return true;
|
||||
}
|
||||
if self.ws_state == WsState::Closed {
|
||||
@ -245,11 +217,6 @@ impl Component for Home {
|
||||
}
|
||||
false
|
||||
}
|
||||
HomeMessage::Authenticated => {
|
||||
self.connect_ws(ctx);
|
||||
self.authenticated = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
82
frontend/src/pages/login.rs
Normal file
82
frontend/src/pages/login.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::{components::Nav, Route};
|
||||
use gloo::net::http::Request;
|
||||
use yew::{platform::spawn_local, prelude::*};
|
||||
use yew_router::hooks::use_navigator;
|
||||
|
||||
#[function_component]
|
||||
#[allow(non_snake_case)] // Component names should be in PascalCase
|
||||
pub fn Login() -> Html {
|
||||
let disable_input = use_state(|| false);
|
||||
let navigator = use_navigator();
|
||||
let login_submitted = {
|
||||
let disable_input = disable_input.clone();
|
||||
let navigator = navigator.clone();
|
||||
move || {
|
||||
disable_input.set(true);
|
||||
let navigator = navigator.clone();
|
||||
spawn_local(async move {
|
||||
let location = web_sys::window().unwrap().location();
|
||||
let login_url = format!(
|
||||
"{}//{}/api/login",
|
||||
location.protocol().unwrap(),
|
||||
location.host().unwrap()
|
||||
);
|
||||
Request::post(&login_url)
|
||||
.body("")
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
navigator.as_ref().unwrap().push(&Route::Home);
|
||||
});
|
||||
}
|
||||
};
|
||||
let password_keypress = {
|
||||
let login_submitted = login_submitted.clone();
|
||||
Callback::from(move |press: KeyboardEvent| {
|
||||
if press.key() == "Enter" {
|
||||
login_submitted();
|
||||
}
|
||||
})
|
||||
};
|
||||
html! {
|
||||
<>
|
||||
<Nav />
|
||||
<div class="container-fluid d-flex flex-column align-items-center" style="max-width: 570px">
|
||||
<h1>{ "Login" }</h1>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
class="form-control"
|
||||
placeholder="Username"
|
||||
disabled={*disable_input}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
class="form-control"
|
||||
placeholder="Password"
|
||||
disabled={*disable_input}
|
||||
onkeydown={password_keypress}
|
||||
/>
|
||||
if !*disable_input {
|
||||
<input
|
||||
type="button"
|
||||
value="Login"
|
||||
class="btn btn-success mt-3"
|
||||
onclick={Callback::from(move |_| login_submitted())}
|
||||
/>
|
||||
} else {
|
||||
<button class="btn btn-success mt-3" disabled=true>
|
||||
<span
|
||||
class="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{ "Login" }
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user