Implemented updating users
at /users/{id}
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
use gloo_net::http::Request;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
use web_sys::js_sys::Atomics::load;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@@ -29,6 +30,16 @@ pub struct LoginScheme {
|
||||
pub pwd: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct UserUpdateScheme {
|
||||
pub id: i16,
|
||||
pub first_name: String,
|
||||
pub last_name: String,
|
||||
pub username: String,
|
||||
pub make_admin: bool,
|
||||
pub new_pwd: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct FilteredUser {
|
||||
pub id: i16,
|
||||
@@ -297,7 +308,6 @@ pub fn user_by_id_component(props: &UserProps) -> Html {
|
||||
let error = use_state(|| None::<String>);
|
||||
let loading = use_state(|| false);
|
||||
let id = props.id;
|
||||
let status = use_state(|| "".to_string());
|
||||
|
||||
{
|
||||
let user = user.clone();
|
||||
@@ -341,6 +351,97 @@ pub fn user_by_id_component(props: &UserProps) -> Html {
|
||||
});
|
||||
}
|
||||
|
||||
let first_name = use_state(|| "".to_string());
|
||||
let last_name = use_state(|| "".to_string());
|
||||
let username = use_state(|| "".to_string());
|
||||
let make_admin = use_state(|| false);
|
||||
let new_pwd = use_state(|| String::new());
|
||||
let saving = use_state(|| false);
|
||||
let save_error = use_state(|| None::<String>);
|
||||
let save_success = use_state(|| false);
|
||||
|
||||
{
|
||||
let user = user.clone();
|
||||
let first_name = first_name.clone();
|
||||
let last_name = last_name.clone();
|
||||
let username = username.clone();
|
||||
let make_admin = make_admin.clone();
|
||||
|
||||
use_effect_with(user, move |user_ref| {
|
||||
if let Some(u) = &**user_ref {
|
||||
first_name.set(u.first_name.clone());
|
||||
last_name.set(u.last_name.clone());
|
||||
username.set(u.username.clone());
|
||||
make_admin.set(u.is_admin);
|
||||
}
|
||||
|| ()
|
||||
});
|
||||
}
|
||||
|
||||
let onsubmit = {
|
||||
let first_name = first_name.clone();
|
||||
let last_name = last_name.clone();
|
||||
let username = username.clone();
|
||||
let make_admin = make_admin.clone();
|
||||
let new_pwd = new_pwd.clone();
|
||||
let saving = saving.clone();
|
||||
let save_error = save_error.clone();
|
||||
let save_success = save_success.clone();
|
||||
let user_state = user.clone();
|
||||
|
||||
Callback::from(move |e: SubmitEvent| {
|
||||
e.prevent_default();
|
||||
let first_name = (*first_name).clone();
|
||||
let last_name = (*last_name).clone();
|
||||
let username = (*username).clone();
|
||||
let make_admin = *make_admin;
|
||||
let new_pwd = (*new_pwd).clone();
|
||||
|
||||
saving.set(true);
|
||||
save_error.set(None);
|
||||
save_success.set(false);
|
||||
|
||||
let saving = saving.clone();
|
||||
let save_error = save_error.clone();
|
||||
let save_success = save_success.clone();
|
||||
let user_state = user_state.clone();
|
||||
let id = id;
|
||||
|
||||
spawn_local(async move {
|
||||
let payload = UserUpdateScheme {
|
||||
id: id,
|
||||
first_name,
|
||||
last_name,
|
||||
username,
|
||||
make_admin,
|
||||
new_pwd,
|
||||
};
|
||||
|
||||
let url = format!("/api/users/{}", id);
|
||||
let request = Request::patch(&url)
|
||||
.header("Content-Type", "application/json")
|
||||
.credentials(web_sys::RequestCredentials::Include)
|
||||
.json(&payload)
|
||||
.expect("Failed to construct Request");
|
||||
|
||||
match request.send().await {
|
||||
Ok(resp) if resp.status() == 200 => {
|
||||
if let Ok(updated) = resp.json::<FilteredUser>().await {
|
||||
user_state.set(Some(updated));
|
||||
}
|
||||
save_success.set(true);
|
||||
}
|
||||
Ok(resp) => {
|
||||
let txt = resp.text().await.unwrap_or_else(|_| "Unknown".into());
|
||||
save_error.set(Some(format!("HTTP {}: {}", resp.status(), txt)));
|
||||
}
|
||||
Err(err) => save_error.set(Some(format!("Network error: {}", err))),
|
||||
}
|
||||
saving.set(false);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
if *loading {
|
||||
html! {<p>{ "Loading" }</p>}
|
||||
} else if let Some(e) = &*error {
|
||||
@@ -348,12 +449,77 @@ pub fn user_by_id_component(props: &UserProps) -> Html {
|
||||
} else if let Some(u) = &*user {
|
||||
html! {
|
||||
<div>
|
||||
<h1>{ format!("User #{}", u.id) }</h1>
|
||||
<div>
|
||||
<p><strong>{ "Vorname: " }</strong>{ &u.first_name }</p>
|
||||
<p><strong>{ "Nachname: " }</strong>{ &u.last_name }</p>
|
||||
<p><strong>{ "Benutzername: " }</strong>{ &u.username }</p>
|
||||
<p><strong>{ "Ist Admin: " }</strong>{ u.is_admin }</p>
|
||||
</div>
|
||||
|
||||
<h1>{ format!("User #{}", u.id) }</h1>
|
||||
<form onsubmit={onsubmit}>
|
||||
<div>
|
||||
<label>{ "Vorname" }
|
||||
<input name="first_name"
|
||||
value={(*first_name).clone()}
|
||||
oninput={Callback::from(move |e: InputEvent| {
|
||||
let input: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
first_name.set(input.value());
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Nachname" }
|
||||
<input name="last_name"
|
||||
value={(*last_name).clone()}
|
||||
oninput={Callback::from(move |e: InputEvent| {
|
||||
let input: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
last_name.set(input.value());
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Benutzername" }
|
||||
<input name="username"
|
||||
value={(*username).clone()}
|
||||
oninput={Callback::from(move |e: InputEvent| {
|
||||
let input: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
username.set(input.value());
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Ist Admin" }
|
||||
<input type="checkbox" name="make_admin" checked={*make_admin} onchange={Callback::from(move |e: Event| {
|
||||
let input: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
make_admin.set(input.checked());
|
||||
})}/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Neues Passwort (leer = unchanged)" }
|
||||
<input name="new_pwd" type="password"
|
||||
value={(*new_pwd).clone()}
|
||||
oninput={Callback::from(move |e: InputEvent| {
|
||||
let input: web_sys::HtmlInputElement = e.target_unchecked_into();
|
||||
new_pwd.set(input.value());
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" disabled={*saving}>{ if *saving { "Speichern..." } else { "Speichern" } }</button>
|
||||
if *save_success {
|
||||
<p style="color:green">{ "Updated successfully" }</p>
|
||||
}
|
||||
if let Some(err) = &*save_error {
|
||||
<p style="color:red">{ err.clone() }</p>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
} else {
|
||||
html! { <p>{ "No ticket found." }</p> }
|
||||
|
||||
Reference in New Issue
Block a user