173 lines
6.9 KiB
Rust
173 lines
6.9 KiB
Rust
use graphql_client::reqwest::post_graphql;
|
|
use web_sys::HtmlInputElement;
|
|
use yew::prelude::*;
|
|
use yew_router::prelude::*;
|
|
use yew_side_effect::title::Title;
|
|
|
|
use crate::components;
|
|
use crate::cookies;
|
|
use crate::graphql;
|
|
use crate::layouts;
|
|
use crate::routes;
|
|
|
|
#[derive(Properties, PartialEq)]
|
|
pub struct LoginProps {
|
|
pub token: Option<String>,
|
|
pub logged_in: bool,
|
|
}
|
|
|
|
pub enum Msg {
|
|
Submit,
|
|
Login(Option<Vec<String>>),
|
|
}
|
|
|
|
pub struct Login {
|
|
username: NodeRef,
|
|
password: NodeRef,
|
|
fetching: bool,
|
|
errors: Option<Vec<String>>,
|
|
}
|
|
|
|
impl Component for Login {
|
|
type Message = Msg;
|
|
type Properties = LoginProps;
|
|
|
|
fn create(_ctx: &Context<Self>) -> Self {
|
|
Self {
|
|
username: NodeRef::default(),
|
|
password: NodeRef::default(),
|
|
fetching: false,
|
|
errors: None,
|
|
}
|
|
}
|
|
|
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
match msg {
|
|
Msg::Submit => {
|
|
if let (Some(username), Some(password)) = (
|
|
self.username.cast::<HtmlInputElement>().map(|x| x.value()),
|
|
self.password.cast::<HtmlInputElement>().map(|x| x.value()),
|
|
) {
|
|
if !username.is_empty() && !password.is_empty() {
|
|
self.fetching = true;
|
|
|
|
ctx.link().send_future(async {
|
|
let response = post_graphql::<graphql::mutations::login::Login, _>(
|
|
&graphql::client(None).unwrap(),
|
|
graphql::URL.as_str(),
|
|
graphql::mutations::login::login::Variables { username, password },
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
if response.errors.is_some() {
|
|
cookies::logout_clear();
|
|
} else {
|
|
let data = response.data.unwrap().login.unwrap();
|
|
|
|
wasm_cookies::set(
|
|
cookies::TOKEN,
|
|
&data.token,
|
|
&wasm_cookies::CookieOptions::default(),
|
|
);
|
|
if data.user.admin {
|
|
wasm_cookies::set(
|
|
cookies::ADMIN,
|
|
"1",
|
|
&wasm_cookies::CookieOptions::default(),
|
|
);
|
|
} else {
|
|
wasm_cookies::delete(cookies::ADMIN);
|
|
}
|
|
}
|
|
|
|
Msg::Login(graphql::convert(response.errors))
|
|
});
|
|
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
Msg::Login(errors) => {
|
|
self.fetching = false;
|
|
self.errors = errors;
|
|
if self.errors.is_none() {
|
|
ctx.link().history().unwrap().push(routes::Route::Home);
|
|
false
|
|
} else {
|
|
true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
if ctx.props().logged_in {
|
|
ctx.link().history().unwrap().push(routes::Route::Home);
|
|
}
|
|
|
|
html! {
|
|
<>
|
|
<Title value="Login" />
|
|
<layouts::main::Main token={ctx.props().token.to_owned()} logged_in={false}>
|
|
<div class={classes!("columns")}>
|
|
<div class={classes!("column", "is-one-third", "mx-auto")}>
|
|
<form onsubmit={ctx.link().callback(|e: FocusEvent| { e.prevent_default(); Msg::Submit })} class={classes!("box")}>
|
|
<div class={classes!("field")}>
|
|
<p class={classes!("control", "has-icons-left")}>
|
|
<input ref={self.username.clone()}
|
|
class={classes!("input")}
|
|
type="username"
|
|
placeholder="Benutzername"
|
|
/>
|
|
<span class={classes!("icon", "is-small", "is-left")}>
|
|
<i class={classes!("fas", "fa-envelope")} />
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div class={classes!("field")}>
|
|
<p class={classes!("control", "has-icons-left")}>
|
|
<input ref={self.password.clone()}
|
|
class={classes!("input")}
|
|
type="password"
|
|
placeholder="Passwort"
|
|
/>
|
|
<span class={classes!("icon", "is-small", "is-left")}>
|
|
<i class={classes!("fas", "fa-lock")} />
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div class={classes!("field")}>
|
|
<p class="control">
|
|
<button
|
|
class={classes!(
|
|
"button",
|
|
"is-fullwidth",
|
|
"is-success",
|
|
if self.fetching { Some("is-loading") } else { None }
|
|
)}
|
|
type="submit"
|
|
>
|
|
<span class={classes!("icon", "is-small")}>
|
|
<i class={classes!("fas", "fa-right-to-bracket")} />
|
|
</span>
|
|
<span>{ "Login" }</span>
|
|
</button>
|
|
</p>
|
|
</div>
|
|
|
|
<components::graphql_errors::GraphQLErrors errors={self.errors.clone()} />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</layouts::main::Main>
|
|
</>
|
|
|
|
}
|
|
}
|
|
}
|