2020-04-20 11:22:39 +02:00
|
|
|
use seed::{prelude::*, *};
|
|
|
|
|
2020-04-22 14:12:12 +02:00
|
|
|
use jirs_data::{ToVec, UserRole, UsersFieldId, WsMsg};
|
2020-04-20 11:22:39 +02:00
|
|
|
|
2020-04-22 14:12:12 +02:00
|
|
|
use crate::api::send_ws_msg;
|
|
|
|
use crate::model::{InvitationFormState, Model, Page, PageContent, UsersPage};
|
2020-04-20 11:22:39 +02:00
|
|
|
use crate::shared::styled_button::StyledButton;
|
|
|
|
use crate::shared::styled_field::StyledField;
|
|
|
|
use crate::shared::styled_form::StyledForm;
|
|
|
|
use crate::shared::styled_input::StyledInput;
|
|
|
|
use crate::shared::styled_select::*;
|
|
|
|
use crate::shared::styled_select_child::ToStyledSelectChild;
|
|
|
|
use crate::shared::{inner_layout, ToNode};
|
|
|
|
use crate::validations::is_email;
|
|
|
|
use crate::{FieldId, Msg};
|
|
|
|
|
|
|
|
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
2020-04-22 14:12:12 +02:00
|
|
|
if let Msg::ChangePage(Page::Users) = msg {
|
|
|
|
model.page_content = PageContent::Users(Box::new(UsersPage::default()));
|
2020-04-22 16:03:43 +02:00
|
|
|
// return;
|
2020-04-20 11:22:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let page = match &mut model.page_content {
|
|
|
|
PageContent::Users(page) => page,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
page.user_role_state.update(&msg, orders);
|
|
|
|
|
|
|
|
match msg {
|
2020-04-22 16:03:43 +02:00
|
|
|
Msg::WsMsg(WsMsg::AuthorizeLoaded(Ok(_))) | Msg::ChangePage(Page::Users)
|
|
|
|
if model.user.is_some() =>
|
|
|
|
{
|
2020-04-22 14:12:12 +02:00
|
|
|
send_ws_msg(WsMsg::InvitationListRequest);
|
|
|
|
send_ws_msg(WsMsg::InvitedUsersRequest);
|
|
|
|
}
|
|
|
|
Msg::WsMsg(WsMsg::InvitedUsersLoaded(users)) => {
|
|
|
|
page.invited_users = users;
|
|
|
|
}
|
|
|
|
Msg::WsMsg(WsMsg::InvitationListLoaded(invitations)) => {
|
|
|
|
page.invitations = invitations;
|
|
|
|
}
|
2020-04-20 11:22:39 +02:00
|
|
|
Msg::StyledSelectChanged(
|
|
|
|
FieldId::Users(UsersFieldId::UserRole),
|
|
|
|
StyledSelectChange::Changed(role),
|
|
|
|
) => {
|
|
|
|
page.user_role = role.into();
|
|
|
|
}
|
|
|
|
Msg::InputChanged(FieldId::Users(UsersFieldId::Username), name) => {
|
|
|
|
page.name = name;
|
|
|
|
page.name_touched = true;
|
|
|
|
}
|
|
|
|
Msg::InputChanged(FieldId::Users(UsersFieldId::Email), email) => {
|
|
|
|
page.email = email;
|
|
|
|
page.email_touched = true;
|
|
|
|
}
|
2020-04-22 14:12:12 +02:00
|
|
|
Msg::InviteRequest => {
|
|
|
|
page.form_state = InvitationFormState::Sent;
|
|
|
|
send_ws_msg(WsMsg::InvitationSendRequest {
|
|
|
|
name: page.name.clone(),
|
|
|
|
email: page.email.clone(),
|
|
|
|
})
|
|
|
|
}
|
2020-04-22 16:03:43 +02:00
|
|
|
Msg::WsMsg(WsMsg::InvitationRevokeSuccess(id)) => {
|
|
|
|
let mut old = vec![];
|
|
|
|
std::mem::swap(&mut page.invitations, &mut old);
|
|
|
|
for invitation in old {
|
|
|
|
if invitation.id != id {
|
|
|
|
page.invitations.push(invitation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Msg::InviteRevokeRequest(invitation_id) => {
|
|
|
|
send_ws_msg(WsMsg::InvitationRevokeRequest(invitation_id));
|
|
|
|
}
|
|
|
|
Msg::InvitedUserRemove(email) => {
|
|
|
|
send_ws_msg(WsMsg::InvitedUserRemoveRequest(email));
|
|
|
|
}
|
|
|
|
Msg::WsMsg(WsMsg::InvitedUserRemoveSuccess(email)) => {
|
|
|
|
let mut old = vec![];
|
|
|
|
std::mem::swap(&mut page.invited_users, &mut old);
|
|
|
|
for user in old {
|
|
|
|
if user.email != email {
|
|
|
|
page.invited_users.push(user);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-22 14:12:12 +02:00
|
|
|
Msg::WsMsg(WsMsg::InvitationSendSuccess) => {
|
|
|
|
send_ws_msg(WsMsg::InvitationListRequest);
|
|
|
|
page.form_state = InvitationFormState::Succeed;
|
|
|
|
}
|
|
|
|
Msg::WsMsg(WsMsg::InvitationSendFailure) => {
|
|
|
|
page.form_state = InvitationFormState::Failed;
|
|
|
|
}
|
2020-04-20 11:22:39 +02:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn view(model: &Model) -> Node<Msg> {
|
2020-04-21 08:35:08 +02:00
|
|
|
if model.user.is_none() {
|
|
|
|
return empty![];
|
|
|
|
}
|
|
|
|
|
2020-04-20 11:22:39 +02:00
|
|
|
let page = match &model.page_content {
|
|
|
|
PageContent::Users(page) => page,
|
|
|
|
_ => return empty![],
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = StyledInput::build(FieldId::Users(UsersFieldId::Username))
|
|
|
|
.valid(!page.name_touched || page.name.len() >= 3)
|
|
|
|
.value(page.name.as_str())
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let name_field = StyledField::build()
|
|
|
|
.input(name)
|
|
|
|
.label("Name")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
|
|
|
let email = StyledInput::build(FieldId::Users(UsersFieldId::Email))
|
|
|
|
.valid(!page.email_touched || is_email(page.email.as_str()))
|
|
|
|
.value(page.email.as_str())
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let email_field = StyledField::build()
|
|
|
|
.input(email)
|
|
|
|
.label("E-Mail")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
|
|
|
let user_role = StyledSelect::build(FieldId::Users(UsersFieldId::UserRole))
|
|
|
|
.name("user_role")
|
|
|
|
.valid(true)
|
|
|
|
.normal()
|
|
|
|
.with_state(&page.user_role_state)
|
|
|
|
.selected(vec![page.user_role.to_select_child()])
|
|
|
|
.options(
|
|
|
|
UserRole::ordered()
|
|
|
|
.into_iter()
|
|
|
|
.map(|role| role.to_select_child())
|
|
|
|
.collect(),
|
|
|
|
)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let user_role_field = StyledField::build()
|
|
|
|
.input(user_role)
|
|
|
|
.label("Role")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
|
|
|
let submit = StyledButton::build()
|
|
|
|
.add_class("submitUserInvite")
|
2020-04-22 14:12:12 +02:00
|
|
|
.active(page.form_state != InvitationFormState::Sent)
|
2020-04-20 11:22:39 +02:00
|
|
|
.primary()
|
|
|
|
.text("Invite user")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-22 14:12:12 +02:00
|
|
|
let submit_supplement = match page.form_state {
|
|
|
|
InvitationFormState::Succeed => StyledButton::build()
|
|
|
|
.add_class("resetUserInvite")
|
|
|
|
.active(true)
|
|
|
|
.empty()
|
|
|
|
.set_type_reset()
|
|
|
|
.text("Reset")
|
|
|
|
.build()
|
|
|
|
.into_node(),
|
|
|
|
InvitationFormState::Failed => div![class!["error"], "There was an error"],
|
|
|
|
_ => empty![],
|
|
|
|
};
|
|
|
|
let submit_field = StyledField::build()
|
|
|
|
.input(div![class!["invitationActions"], submit, submit_supplement])
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-20 11:22:39 +02:00
|
|
|
|
|
|
|
let form = StyledForm::build()
|
|
|
|
.heading("Invite new user")
|
|
|
|
.add_field(name_field)
|
|
|
|
.add_field(email_field)
|
|
|
|
.add_field(user_role_field)
|
|
|
|
.add_field(submit_field)
|
2020-04-22 14:12:12 +02:00
|
|
|
.on_submit(ev(Ev::Submit, |ev| {
|
|
|
|
ev.prevent_default();
|
|
|
|
Msg::InviteRequest
|
|
|
|
}))
|
2020-04-20 11:22:39 +02:00
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-22 14:12:12 +02:00
|
|
|
let users: Vec<Node<Msg>> = page
|
|
|
|
.invited_users
|
|
|
|
.iter()
|
|
|
|
.map(|user| {
|
2020-04-22 16:03:43 +02:00
|
|
|
let email = user.email.clone();
|
|
|
|
let remove = StyledButton::build()
|
|
|
|
.text("Remove")
|
|
|
|
.on_click(mouse_ev(Ev::Click, move |_| Msg::InvitedUserRemove(email)))
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-22 14:12:12 +02:00
|
|
|
li![
|
|
|
|
class!["user"],
|
|
|
|
span![user.name],
|
|
|
|
span![user.email],
|
|
|
|
span![format!("{}", user.user_role)],
|
|
|
|
remove,
|
|
|
|
]
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let users_section = section![
|
|
|
|
class!["usersSection"],
|
|
|
|
h1![class!["heading"], "Users"],
|
|
|
|
ul![class!["usersList"], users],
|
|
|
|
];
|
|
|
|
|
|
|
|
let invitations: Vec<Node<Msg>> = page
|
|
|
|
.invitations
|
|
|
|
.iter()
|
|
|
|
.map(|invitation| {
|
2020-04-22 16:03:43 +02:00
|
|
|
let id = invitation.id;
|
|
|
|
let revoke = StyledButton::build()
|
|
|
|
.text("Revoke")
|
|
|
|
.on_click(mouse_ev(Ev::Click, move |_| Msg::InviteRevokeRequest(id)))
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-22 14:12:12 +02:00
|
|
|
li![
|
|
|
|
class!["invitation"],
|
|
|
|
span![invitation.name],
|
|
|
|
span![invitation.email],
|
|
|
|
span![format!("{}", invitation.state)],
|
|
|
|
revoke,
|
|
|
|
]
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let invitations_section = section![
|
|
|
|
class!["invitationsSection"],
|
|
|
|
h1![class!["heading"], "Invitations"],
|
|
|
|
ul![class!["invitationsList"], invitations],
|
|
|
|
];
|
|
|
|
|
|
|
|
inner_layout(
|
|
|
|
model,
|
|
|
|
"users",
|
|
|
|
vec![form, users_section, invitations_section],
|
|
|
|
empty![],
|
|
|
|
)
|
2020-04-20 11:22:39 +02:00
|
|
|
}
|