Login works now

This commit is contained in:
Marko Korhonen 2020-04-28 19:01:29 +03:00
parent 75b3aa7249
commit 43a9beaef8
No known key found for this signature in database
GPG key ID: 911B85FBC6003FE5
4 changed files with 122 additions and 49 deletions

View file

@ -1,20 +1,68 @@
use log::info;
use log::{error, info};
use serde_json::json;
use yew::format::{Json, Text};
use yew::prelude::*;
use yew::services::fetch::{FetchService, FetchTask, Request, Response};
use yew::services::fetch::Mode::Cors;
pub struct LoginComponent {
component_link: ComponentLink<LoginComponent>,
username: String,
password: String,
login_button_disabled: bool,
fetch_service: FetchService,
fetch_task: Option<FetchTask>,
fetching: bool,
}
pub enum Message {
pub enum Msg {
UpdateUsername(String),
UpdatePassword(String),
HandleForm(),
FetchReady(String),
FetchError,
}
impl LoginComponent {
fn update_button_state(&mut self) {
self.login_button_disabled = self.username.is_empty() || self.password.is_empty();
}
fn post_login(&mut self) {
self.fetching = true;
let user = json!({
"username": self.username,
"password": self.password
});
let request = Request::builder()
.method("POST")
.header("Content-Type", "application/json")
.uri("http://localhost:3880/api/auth/login")
.body(Json(&user))
.unwrap();
let callback =
self.component_link
.callback(|response: Response<Result<String, anyhow::Error>>| {
let (meta, body) = response.into_parts();
if meta.status.is_success() {
Msg::FetchReady(body.unwrap())
} else {
error!("{}", body.unwrap());
Msg::FetchError
}
});
let task = self.fetch_service.fetch(request, callback);
self.fetch_task = Some(task.unwrap());
}
}
impl Component for LoginComponent {
type Message = Message;
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
@ -23,6 +71,9 @@ impl Component for LoginComponent {
username: String::new(),
password: String::new(),
login_button_disabled: true,
fetch_service: FetchService::new(),
fetch_task: None,
fetching: false,
}
}
@ -32,60 +83,66 @@ impl Component for LoginComponent {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Message::UpdateUsername(new_username) => {
Msg::UpdateUsername(new_username) => {
self.username = new_username;
self.update_button_state();
}
Message::UpdatePassword(new_password) => {
info!("Password changed");
Msg::UpdatePassword(new_password) => {
self.password = new_password;
self.update_button_state();
}
Message::HandleForm() => {
info!("Submit button clicked");
Msg::HandleForm() => self.post_login(),
Msg::FetchReady(response) => {
self.fetching = false;
info!("Fetch complete. Body: {}", response)
}
Msg::FetchError => {
self.fetching = false;
error!("There was an error connecting to API")
}
}
true
}
fn view(&self) -> Html {
let onclick = self.component_link.callback(|_| Message::HandleForm());
let onclick = self.component_link.callback(|_| Msg::HandleForm());
let oninput_username = self
.component_link
.callback(|e: InputData| Message::UpdateUsername(e.value));
.callback(|e: InputData| Msg::UpdateUsername(e.value));
let oninput_password = self
.component_link
.callback(|e: InputData| Message::UpdatePassword(e.value));
.callback(|e: InputData| Msg::UpdatePassword(e.value));
html! {
<div class="uk-card uk-card-default uk-card-body uk-width-1-3@s uk-position-center">
<h1 class="uk-card-title">{ "Please log in" }</h1>
<form>
<div>
<fieldset class="uk-fieldset">
<input class="uk-input uk-margin",
placeholder="Username",
disabled=self.fetching,
value=&self.username,
oninput=oninput_username, />
<input class="uk-input uk-margin-bottom",
placeholder="Password",
disabled=self.fetching,
type="password",
value=&self.password,
oninput=oninput_password, />
<button
class="uk-button uk-button-primary",
type="submit", onclick=onclick>
{ "Submit" }
type="button",
disabled=self.fetching,
onclick=onclick>
{ "Log in" }
</button>
</fieldset>
</form>
</div>
</div>
}
}
}
impl LoginComponent {
fn update_button_state(&mut self) {
self.login_button_disabled = self.username.is_empty() || self.password.is_empty();
}
}

View file

@ -1,6 +1,10 @@
#![recursion_limit = "256"]
extern crate log;
extern crate web_logger;
mod component;
pub mod utils;
use component::login::LoginComponent;
use yew::prelude::*;
@ -13,9 +17,9 @@ struct App {}
enum AppRoute {
#[to = "/login"]
Login,
PageNotFound(Permissive<String>),
#[to = "/"]
Root,
PageNotFound(Permissive<String>),
}
impl Component for App {
@ -33,32 +37,27 @@ impl Component for App {
fn view(&self) -> VNode {
html! {
<div>
<nav class="menu",>
<RouterButton<AppRoute> route=AppRoute::Root>{"Go to Root"}</RouterButton<AppRoute>>
<RouterButton<AppRoute> route=AppRoute::Login>{"Go to Login"}</RouterButton<AppRoute>>
</nav>
<div>
<Router<AppRoute>
render = Router::render(|switch: AppRoute| {
match switch {
AppRoute::Login => html!{<LoginComponent />},
AppRoute::PageNotFound(Permissive(None)) => html!{"Page not found"},
AppRoute::PageNotFound(Permissive(Some(missed_route))) => html!{format!("Page '{}' not found", missed_route)},
AppRoute::Root => {
html!{"hello there!"}
},
}
})
redirect = Router::redirect(|route: Route| {
AppRoute::PageNotFound(Permissive(Some(route.route)))
})
/>
</div>
<Router<AppRoute>
render = Router::render(|switch: AppRoute| {
match switch {
AppRoute::Login => html!{<LoginComponent />},
AppRoute::PageNotFound(Permissive(None)) => html!{"Page not found"},
AppRoute::PageNotFound(Permissive(Some(missed_route))) => html!{format!("Page '{}' not found", missed_route)},
AppRoute::Root => {
html!{"hello there!"}
},
}
})
redirect = Router::redirect(|route: Route| {
AppRoute::PageNotFound(Permissive(Some(route.route)))
})
/>
</div>
}
}
}
fn main() {
web_logger::init();
yew::start_app::<App>();
}