restructure and document list_users
This commit is contained in:
parent
aeac704e89
commit
bfa0bcd0bb
@ -16,29 +16,8 @@ use shared::{
|
|||||||
datatypes::FullLink,
|
datatypes::FullLink,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::i18n::I18n;
|
use crate::{i18n::I18n, unwrap_or_return, unwrap_or_send};
|
||||||
|
|
||||||
/// Unwrap a result and return it's content, or return from the function with another expression.
|
|
||||||
macro_rules! unwrap_or_return {
|
|
||||||
( $e:expr, $result:expr) => {
|
|
||||||
match $e {
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(_) => return $result,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unwrap a result and return it's content, or return from the function with another expression.
|
|
||||||
macro_rules! unwrap_or_send {
|
|
||||||
( $e:expr, $result:expr, $orders:expr) => {
|
|
||||||
match $e {
|
|
||||||
Some(x) => x,
|
|
||||||
None => {
|
|
||||||
$orders.send_msg($result);
|
|
||||||
return;},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Setup the page
|
/// Setup the page
|
||||||
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
||||||
@ -388,11 +367,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
if let Some(message) = &model.last_message {
|
if let Some(message) = &model.last_message {
|
||||||
div![
|
div![
|
||||||
C!["message", "center"],
|
C!["message", "center"],
|
||||||
div![
|
close_button(),
|
||||||
C!["closebutton"],
|
|
||||||
a!["\u{d7}"],
|
|
||||||
ev(Ev::Click, |_| Msg::ClearAll)
|
|
||||||
],
|
|
||||||
match message {
|
match message {
|
||||||
Status::Success(m) | Status::Error(m) => &m.message,
|
Status::Success(m) | Status::Error(m) => &m.message,
|
||||||
}
|
}
|
||||||
@ -404,11 +379,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
if let Some(question) = &model.question {
|
if let Some(question) = &model.question {
|
||||||
div![
|
div![
|
||||||
C!["message", "center"],
|
C!["message", "center"],
|
||||||
div![
|
close_button(),
|
||||||
C!["closebutton"],
|
|
||||||
a!["\u{d7}"],
|
|
||||||
ev(Ev::Click, |_| Msg::ClearAll)
|
|
||||||
],
|
|
||||||
if let EditMsg::MayDeleteSelected(l) = question.clone() {
|
if let EditMsg::MayDeleteSelected(l) = question.clone() {
|
||||||
div![
|
div![
|
||||||
lang.translate(
|
lang.translate(
|
||||||
@ -592,11 +563,7 @@ fn edit_or_create_link<F: Fn(&str) -> String>(l: &RefCell<LinkDelta>, t: F) -> N
|
|||||||
div![
|
div![
|
||||||
// close button top right
|
// close button top right
|
||||||
C!["editdialog", "center"],
|
C!["editdialog", "center"],
|
||||||
div![
|
close_button(),
|
||||||
C!["closebutton"],
|
|
||||||
a!["\u{d7}"],
|
|
||||||
ev(Ev::Click, |_| Msg::ClearAll)
|
|
||||||
],
|
|
||||||
h1![match &link.edit {
|
h1![match &link.edit {
|
||||||
EditMode::Edit => t("edit-link"),
|
EditMode::Edit => t("edit-link"),
|
||||||
EditMode::Create => t("create-link"),
|
EditMode::Create => t("create-link"),
|
||||||
@ -648,3 +615,13 @@ fn edit_or_create_link<F: Fn(&str) -> String>(l: &RefCell<LinkDelta>, t: F) -> N
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// a close button for dialogs
|
||||||
|
fn close_button() -> Node<Msg> {
|
||||||
|
div![
|
||||||
|
C!["closebutton"],
|
||||||
|
a!["\u{d7}"],
|
||||||
|
ev(Ev::Click, |_| Msg::ClearAll)
|
||||||
|
]
|
||||||
|
}
|
@ -12,8 +12,10 @@ use shared::{
|
|||||||
},
|
},
|
||||||
datatypes::User,
|
datatypes::User,
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
use crate::i18n::I18n;
|
* init
|
||||||
|
*/
|
||||||
|
use crate::{i18n::I18n, unwrap_or_return};
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
||||||
orders.send_msg(Msg::Query(UserQueryMsg::Fetch));
|
orders.send_msg(Msg::Query(UserQueryMsg::Fetch));
|
||||||
@ -40,6 +42,13 @@ pub struct Model {
|
|||||||
last_message: Option<Status>,
|
last_message: Option<Status>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Model {
|
||||||
|
fn clean_dialogs(&mut self) {
|
||||||
|
self.last_message = None;
|
||||||
|
self.user_edit = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
struct FilterInput {
|
struct FilterInput {
|
||||||
filter_input: ElRef<web_sys::HtmlInputElement>,
|
filter_input: ElRef<web_sys::HtmlInputElement>,
|
||||||
@ -75,16 +84,15 @@ pub enum UserEditMsg {
|
|||||||
SaveUser,
|
SaveUser,
|
||||||
FailedToCreateUser,
|
FailedToCreateUser,
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/// # Panics
|
* update
|
||||||
/// Sould only panic on bugs.
|
*/
|
||||||
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||||
match msg {
|
match msg {
|
||||||
Msg::Query(msg) => process_query_messages(msg, model, orders),
|
Msg::Query(msg) => process_query_messages(msg, model, orders),
|
||||||
Msg::Edit(msg) => process_user_edit_messages(msg, model, orders),
|
Msg::Edit(msg) => process_user_edit_messages(msg, model, orders),
|
||||||
Msg::ClearAll => {
|
Msg::ClearAll => {
|
||||||
model.last_message = None;
|
model.clean_dialogs();
|
||||||
model.user_edit = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,31 +100,8 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
pub fn process_query_messages(msg: UserQueryMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
pub fn process_query_messages(msg: UserQueryMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||||
match msg {
|
match msg {
|
||||||
UserQueryMsg::Fetch => {
|
UserQueryMsg::Fetch => {
|
||||||
orders.skip(); // No need to rerender
|
orders.skip(); // No need to rerender only after the data is fetched the page has to be rerendered.
|
||||||
let data = model.formconfig.clone(); // complicated way to move into the closure
|
load_users(model.formconfig.clone(), orders);
|
||||||
orders.perform_cmd(async {
|
|
||||||
let data = data;
|
|
||||||
let response = match fetch(
|
|
||||||
Request::new("/admin/json/list_users/")
|
|
||||||
.method(Method::Post)
|
|
||||||
.json(&data)
|
|
||||||
.expect("serialization failed"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(response) => response,
|
|
||||||
Err(_) => return Msg::Query(UserQueryMsg::FailedToFetchUsers),
|
|
||||||
};
|
|
||||||
|
|
||||||
let users: Vec<User> = response
|
|
||||||
.check_status() // ensure we've got 2xx status
|
|
||||||
.expect("status check failed")
|
|
||||||
.json()
|
|
||||||
.await
|
|
||||||
.expect("deserialization failed");
|
|
||||||
|
|
||||||
Msg::Query(UserQueryMsg::Received(users))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
UserQueryMsg::OrderBy(column) => {
|
UserQueryMsg::OrderBy(column) => {
|
||||||
model.formconfig.order = model.formconfig.order.as_ref().map_or_else(
|
model.formconfig.order = model.formconfig.order.as_ref().map_or_else(
|
||||||
@ -173,6 +158,37 @@ pub fn process_query_messages(msg: UserQueryMsg, model: &mut Model, orders: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_users(data: UserRequestForm, orders: &mut impl Orders<Msg>) {
|
||||||
|
orders.perform_cmd(async {
|
||||||
|
let data = data;
|
||||||
|
// create the request
|
||||||
|
let request = unwrap_or_return!(
|
||||||
|
Request::new("/admin/json/list_users/")
|
||||||
|
.method(Method::Post)
|
||||||
|
.json(&data),
|
||||||
|
Msg::Query(UserQueryMsg::FailedToFetchUsers)
|
||||||
|
);
|
||||||
|
// request and get response
|
||||||
|
let response = unwrap_or_return!(
|
||||||
|
fetch(request).await,
|
||||||
|
Msg::Query(UserQueryMsg::FailedToFetchUsers)
|
||||||
|
);
|
||||||
|
// check the response status
|
||||||
|
let response = unwrap_or_return!(
|
||||||
|
response.check_status(),
|
||||||
|
Msg::Query(UserQueryMsg::FailedToFetchUsers)
|
||||||
|
);
|
||||||
|
// deserialize the users list
|
||||||
|
let users: Vec<User> = unwrap_or_return!(
|
||||||
|
response.json().await,
|
||||||
|
Msg::Query(UserQueryMsg::FailedToFetchUsers)
|
||||||
|
);
|
||||||
|
|
||||||
|
Msg::Query(UserQueryMsg::Received(users))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_user_edit_messages(
|
pub fn process_user_edit_messages(
|
||||||
msg: UserEditMsg,
|
msg: UserEditMsg,
|
||||||
model: &mut Model,
|
model: &mut Model,
|
||||||
@ -180,16 +196,14 @@ pub fn process_user_edit_messages(
|
|||||||
) {
|
) {
|
||||||
match msg {
|
match msg {
|
||||||
UserEditMsg::EditUserSelected(user) => {
|
UserEditMsg::EditUserSelected(user) => {
|
||||||
log!("Editing user: ", user);
|
model.clean_dialogs();
|
||||||
model.last_message = None;
|
|
||||||
model.user_edit = Some(RefCell::new(user))
|
model.user_edit = Some(RefCell::new(user))
|
||||||
}
|
}
|
||||||
UserEditMsg::CreateNewUser => {
|
UserEditMsg::CreateNewUser => {
|
||||||
log!("Creating new user");
|
model.clean_dialogs();
|
||||||
model.user_edit = Some(RefCell::new(UserDelta::default()))
|
model.user_edit = Some(RefCell::new(UserDelta::default()))
|
||||||
}
|
}
|
||||||
UserEditMsg::EditUsernameChanged(s) => {
|
UserEditMsg::EditUsernameChanged(s) => {
|
||||||
log!("New Username is: ", &s);
|
|
||||||
if let Some(ref ue) = model.user_edit {
|
if let Some(ref ue) = model.user_edit {
|
||||||
ue.try_borrow_mut()
|
ue.try_borrow_mut()
|
||||||
.expect("Failed to borrow mutably")
|
.expect("Failed to borrow mutably")
|
||||||
@ -197,13 +211,11 @@ pub fn process_user_edit_messages(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
UserEditMsg::EditEmailChanged(s) => {
|
UserEditMsg::EditEmailChanged(s) => {
|
||||||
log!("New Email is: ", &s);
|
|
||||||
if let Some(ref ue) = model.user_edit {
|
if let Some(ref ue) = model.user_edit {
|
||||||
ue.try_borrow_mut().expect("Failed to borrow mutably").email = s;
|
ue.try_borrow_mut().expect("Failed to borrow mutably").email = s;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
UserEditMsg::EditPasswordChanged(s) => {
|
UserEditMsg::EditPasswordChanged(s) => {
|
||||||
log!("New Password is: ", &s);
|
|
||||||
if let Some(ref ue) = model.user_edit {
|
if let Some(ref ue) = model.user_edit {
|
||||||
ue.try_borrow_mut()
|
ue.try_borrow_mut()
|
||||||
.expect("Failed to borrow mutably")
|
.expect("Failed to borrow mutably")
|
||||||
@ -218,33 +230,7 @@ pub fn process_user_edit_messages(
|
|||||||
.borrow()
|
.borrow()
|
||||||
.clone(); // complicated way to move into the closure
|
.clone(); // complicated way to move into the closure
|
||||||
log!("Saving User: ", &data.username);
|
log!("Saving User: ", &data.username);
|
||||||
|
save_user(data, orders);
|
||||||
orders.perform_cmd(async {
|
|
||||||
let data = data;
|
|
||||||
let response = match fetch(
|
|
||||||
Request::new(match data.edit {
|
|
||||||
EditMode::Create => "/admin/json/create_user/",
|
|
||||||
EditMode::Edit => "/admin/json/update_user/",
|
|
||||||
})
|
|
||||||
.method(Method::Post)
|
|
||||||
.json(&data)
|
|
||||||
.expect("serialization failed"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(response) => response,
|
|
||||||
Err(_) => return Msg::Edit(UserEditMsg::FailedToCreateUser),
|
|
||||||
};
|
|
||||||
|
|
||||||
let message: Status = response
|
|
||||||
.check_status() // ensure we've got 2xx status
|
|
||||||
.expect("status check failed")
|
|
||||||
.json()
|
|
||||||
.await
|
|
||||||
.expect("deserialization failed");
|
|
||||||
|
|
||||||
Msg::Edit(UserEditMsg::UserCreated(message))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
UserEditMsg::FailedToCreateUser => {
|
UserEditMsg::FailedToCreateUser => {
|
||||||
log!("Failed to create user");
|
log!("Failed to create user");
|
||||||
@ -258,24 +244,53 @@ pub fn process_user_edit_messages(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn save_user(user: UserDelta, orders: &mut impl Orders<Msg>) {
|
||||||
|
orders.perform_cmd(async {
|
||||||
|
let data = user;
|
||||||
|
// create the request
|
||||||
|
let request = unwrap_or_return!(
|
||||||
|
Request::new(match data.edit {
|
||||||
|
EditMode::Create => "/admin/json/create_user/",
|
||||||
|
EditMode::Edit => "/admin/json/update_user/",
|
||||||
|
})
|
||||||
|
.method(Method::Post)
|
||||||
|
.json(&data),
|
||||||
|
Msg::Edit(UserEditMsg::FailedToCreateUser)
|
||||||
|
);
|
||||||
|
// perform the request and get the response
|
||||||
|
let response = unwrap_or_return!(
|
||||||
|
fetch(request).await,
|
||||||
|
Msg::Edit(UserEditMsg::FailedToCreateUser)
|
||||||
|
);
|
||||||
|
// check for the status
|
||||||
|
let response = unwrap_or_return!(response
|
||||||
|
.check_status(),
|
||||||
|
Msg::Edit(UserEditMsg::FailedToCreateUser));
|
||||||
|
// deserialize the response
|
||||||
|
let message: Status = unwrap_or_return!(response
|
||||||
|
.json()
|
||||||
|
.await, Msg::Edit(UserEditMsg::FailedToCreateUser));
|
||||||
|
|
||||||
|
Msg::Edit(UserEditMsg::UserCreated(message))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// # Panics
|
/// View the users page.
|
||||||
/// Sould only panic on bugs.
|
|
||||||
pub fn view(model: &Model) -> Node<Msg> {
|
pub fn view(model: &Model) -> Node<Msg> {
|
||||||
let lang = model.i18n.clone();
|
let lang = model.i18n.clone();
|
||||||
|
// shortcut for easier translations
|
||||||
let t = move |key: &str| lang.translate(key, None);
|
let t = move |key: &str| lang.translate(key, None);
|
||||||
section![
|
section![
|
||||||
|
// Clear all dialogs on press of the ESC button.
|
||||||
keyboard_ev(Ev::KeyDown, |keyboard_event| {
|
keyboard_ev(Ev::KeyDown, |keyboard_event| {
|
||||||
IF!(keyboard_event.key() == "Escape" => Msg::ClearAll)
|
IF!(keyboard_event.key() == "Escape" => Msg::ClearAll)
|
||||||
}),
|
}),
|
||||||
|
// display the messages to the user
|
||||||
if let Some(message) = &model.last_message {
|
if let Some(message) = &model.last_message {
|
||||||
div![
|
div![
|
||||||
C!["message", "center"],
|
C!["message", "center"],
|
||||||
div![
|
close_button(),
|
||||||
C!["closebutton"],
|
|
||||||
a!["\u{d7}"],
|
|
||||||
ev(Ev::Click, |_| Msg::ClearAll)
|
|
||||||
],
|
|
||||||
match message {
|
match message {
|
||||||
Status::Success(m) | Status::Error(m) => {
|
Status::Success(m) | Status::Error(m) => {
|
||||||
&m.message
|
&m.message
|
||||||
@ -285,6 +300,8 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
} else {
|
} else {
|
||||||
section![]
|
section![]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// display the table with users
|
||||||
table![
|
table![
|
||||||
// Column Headlines
|
// Column Headlines
|
||||||
view_user_table_head(&t),
|
view_user_table_head(&t),
|
||||||
@ -293,10 +310,12 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
// Add all the users one line for each
|
// Add all the users one line for each
|
||||||
model.users.iter().map(view_user)
|
model.users.iter().map(view_user)
|
||||||
],
|
],
|
||||||
|
// A refresh button. This will be removed in future versions.
|
||||||
button![
|
button![
|
||||||
ev(Ev::Click, |_| Msg::Query(UserQueryMsg::Fetch)),
|
ev(Ev::Click, |_| Msg::Query(UserQueryMsg::Fetch)),
|
||||||
"Refresh"
|
"Refresh"
|
||||||
],
|
],
|
||||||
|
// Display the user edit dialog if available
|
||||||
if let Some(l) = &model.user_edit {
|
if let Some(l) = &model.user_edit {
|
||||||
edit_or_create_user(l, t)
|
edit_or_create_user(l, t)
|
||||||
} else {
|
} else {
|
||||||
@ -377,7 +396,6 @@ fn view_user(l: &User) -> Node<Msg> {
|
|||||||
))),
|
))),
|
||||||
td![&l.id],
|
td![&l.id],
|
||||||
td![&l.email],
|
td![&l.email],
|
||||||
//td![a![attrs![At::Href => &l.link.target], &l.link.target]],
|
|
||||||
td![&l.username],
|
td![&l.username],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -386,11 +404,7 @@ fn edit_or_create_user<F: Fn(&str) -> String>(l: &RefCell<UserDelta>, t: F) -> N
|
|||||||
let user = l.borrow();
|
let user = l.borrow();
|
||||||
div![
|
div![
|
||||||
C!["editdialog", "center"],
|
C!["editdialog", "center"],
|
||||||
div![
|
close_button(),
|
||||||
C!["closebutton"],
|
|
||||||
a!["\u{d7}"],
|
|
||||||
ev(Ev::Click, |_| Msg::ClearAll)
|
|
||||||
],
|
|
||||||
h1![match &user.edit {
|
h1![match &user.edit {
|
||||||
EditMode::Edit => t("edit-user"),
|
EditMode::Edit => t("edit-user"),
|
||||||
EditMode::Create => t("new-user"),
|
EditMode::Create => t("new-user"),
|
||||||
@ -463,3 +477,12 @@ fn edit_or_create_user<F: Fn(&str) -> String>(l: &RefCell<UserDelta>, t: F) -> N
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// a close button for dialogs
|
||||||
|
fn close_button() -> Node<Msg> {
|
||||||
|
div![
|
||||||
|
C!["closebutton"],
|
||||||
|
a!["\u{d7}"],
|
||||||
|
ev(Ev::Click, |_| Msg::ClearAll)
|
||||||
|
]
|
||||||
|
}
|
@ -1,3 +1,28 @@
|
|||||||
pub mod home;
|
pub mod home;
|
||||||
pub mod list_links;
|
pub mod list_links;
|
||||||
pub mod list_users;
|
pub mod list_users;
|
||||||
|
|
||||||
|
|
||||||
|
/// Unwrap a result and return it's content, or return from the function with another expression.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! unwrap_or_return {
|
||||||
|
( $e:expr, $result:expr) => {
|
||||||
|
match $e {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => return $result,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unwrap a result and return it's content, or return from the function with another expression.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! unwrap_or_send {
|
||||||
|
( $e:expr, $result:expr, $orders:expr) => {
|
||||||
|
match $e {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
$orders.send_msg($result);
|
||||||
|
return;},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user