mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
app: Extract a RemoveUserFromGroup component
This commit is contained in:
parent
14be1170f2
commit
00efdb42af
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -1770,6 +1770,7 @@ dependencies = [
|
|||||||
"yew-router",
|
"yew-router",
|
||||||
"yew_form",
|
"yew_form",
|
||||||
"yew_form_derive",
|
"yew_form_derive",
|
||||||
|
"yewtil",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3537,6 +3538,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0"
|
checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3757,6 +3760,19 @@ dependencies = [
|
|||||||
"yew_form",
|
"yew_form",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yewtil"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8543663ac49cd613df079282a1d8bdbdebdad6e02bac229f870fd4237b5d9aaa"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"yew",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
@ -18,6 +18,7 @@ validator = "*"
|
|||||||
validator_derive = "*"
|
validator_derive = "*"
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
yew = "0.18"
|
yew = "0.18"
|
||||||
|
yewtil = "*"
|
||||||
yew-router = "0.15"
|
yew-router = "0.15"
|
||||||
yew_form = "0.1.8"
|
yew_form = "0.1.8"
|
||||||
yew_form_derive = "*"
|
yew_form_derive = "*"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::{
|
components::{
|
||||||
select::{Select, SelectOption, SelectOptionProps},
|
select::{Select, SelectOption, SelectOptionProps},
|
||||||
user_details::{Group, User},
|
user_details::Group,
|
||||||
},
|
},
|
||||||
infra::api::HostService,
|
infra::api::HostService,
|
||||||
};
|
};
|
||||||
@ -12,6 +12,7 @@ use yew::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
services::{fetch::FetchTask, ConsoleService},
|
services::{fetch::FetchTask, ConsoleService},
|
||||||
};
|
};
|
||||||
|
use yewtil::NeqAssign;
|
||||||
|
|
||||||
#[derive(GraphQLQuery)]
|
#[derive(GraphQLQuery)]
|
||||||
#[graphql(
|
#[graphql(
|
||||||
@ -63,7 +64,8 @@ pub enum Msg {
|
|||||||
|
|
||||||
#[derive(yew::Properties, Clone, PartialEq)]
|
#[derive(yew::Properties, Clone, PartialEq)]
|
||||||
pub struct Props {
|
pub struct Props {
|
||||||
pub user: User,
|
pub username: String,
|
||||||
|
pub groups: Vec<Group>,
|
||||||
pub on_user_added_to_group: Callback<Group>,
|
pub on_user_added_to_group: Callback<Group>,
|
||||||
pub on_error: Callback<Error>,
|
pub on_error: Callback<Error>,
|
||||||
}
|
}
|
||||||
@ -89,7 +91,7 @@ impl AddUserToGroupComponent {
|
|||||||
};
|
};
|
||||||
self._task = HostService::graphql_query::<AddUserToGroup>(
|
self._task = HostService::graphql_query::<AddUserToGroup>(
|
||||||
add_user_to_group::Variables {
|
add_user_to_group::Variables {
|
||||||
user: self.props.user.id.clone(),
|
user: self.props.username.clone(),
|
||||||
group: group_id,
|
group: group_id,
|
||||||
},
|
},
|
||||||
self.link.callback(Msg::AddGroupResponse),
|
self.link.callback(Msg::AddGroupResponse),
|
||||||
@ -133,7 +135,7 @@ impl AddUserToGroupComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_selectable_group_list(&self, group_list: &[Group]) -> Vec<Group> {
|
fn get_selectable_group_list(&self, group_list: &[Group]) -> Vec<Group> {
|
||||||
let user_groups = self.props.user.groups.iter().collect::<HashSet<_>>();
|
let user_groups = self.props.groups.iter().collect::<HashSet<_>>();
|
||||||
group_list
|
group_list
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| !user_groups.contains(g))
|
.filter(|g| !user_groups.contains(g))
|
||||||
@ -168,12 +170,7 @@ impl Component for AddUserToGroupComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
||||||
if props.user.groups != self.props.user.groups {
|
self.props.neq_assign(props)
|
||||||
self.props.user = props.user;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Html {
|
fn view(&self) -> Html {
|
||||||
|
@ -4,6 +4,7 @@ pub mod change_password;
|
|||||||
pub mod create_user;
|
pub mod create_user;
|
||||||
pub mod login;
|
pub mod login;
|
||||||
pub mod logout;
|
pub mod logout;
|
||||||
|
pub mod remove_user_from_group;
|
||||||
pub mod router;
|
pub mod router;
|
||||||
pub mod select;
|
pub mod select;
|
||||||
pub mod user_details;
|
pub mod user_details;
|
||||||
|
111
app/src/components/remove_user_from_group.rs
Normal file
111
app/src/components/remove_user_from_group.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use crate::{components::user_details::Group, infra::api::HostService};
|
||||||
|
use anyhow::{Error, Result};
|
||||||
|
use graphql_client::GraphQLQuery;
|
||||||
|
use yew::{
|
||||||
|
prelude::*,
|
||||||
|
services::{fetch::FetchTask, ConsoleService},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GraphQLQuery)]
|
||||||
|
#[graphql(
|
||||||
|
schema_path = "../schema.graphql",
|
||||||
|
query_path = "queries/remove_user_from_group.graphql",
|
||||||
|
response_derives = "Debug",
|
||||||
|
variables_derives = "Clone",
|
||||||
|
custom_scalars_module = "crate::infra::graphql"
|
||||||
|
)]
|
||||||
|
pub struct RemoveUserFromGroup;
|
||||||
|
|
||||||
|
pub struct RemoveUserFromGroupComponent {
|
||||||
|
link: ComponentLink<Self>,
|
||||||
|
props: Props,
|
||||||
|
// Used to keep the request alive long enough.
|
||||||
|
_task: Option<FetchTask>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(yew::Properties, Clone, PartialEq)]
|
||||||
|
pub struct Props {
|
||||||
|
pub username: String,
|
||||||
|
pub group: Group,
|
||||||
|
pub is_admin: bool,
|
||||||
|
pub on_user_removed_from_group: Callback<Group>,
|
||||||
|
pub on_error: Callback<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Msg {
|
||||||
|
SubmitRemoveGroup,
|
||||||
|
RemoveGroupResponse(Result<remove_user_from_group::ResponseData>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemoveUserFromGroupComponent {
|
||||||
|
fn submit_remove_group(&mut self) -> Result<bool> {
|
||||||
|
let group = self.props.group.id;
|
||||||
|
self._task = HostService::graphql_query::<RemoveUserFromGroup>(
|
||||||
|
remove_user_from_group::Variables {
|
||||||
|
user: self.props.username.clone(),
|
||||||
|
group,
|
||||||
|
},
|
||||||
|
self.link.callback(Msg::RemoveGroupResponse),
|
||||||
|
"Error trying to initiate removing the user from a group",
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
ConsoleService::log(&e.to_string());
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_msg(&mut self, msg: <Self as Component>::Message) -> Result<bool> {
|
||||||
|
match msg {
|
||||||
|
Msg::SubmitRemoveGroup => return self.submit_remove_group(),
|
||||||
|
Msg::RemoveGroupResponse(response) => {
|
||||||
|
response?;
|
||||||
|
self.props
|
||||||
|
.on_user_removed_from_group
|
||||||
|
.emit(self.props.group.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for RemoveUserFromGroupComponent {
|
||||||
|
type Message = Msg;
|
||||||
|
type Properties = Props;
|
||||||
|
|
||||||
|
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||||
|
Self {
|
||||||
|
link,
|
||||||
|
props,
|
||||||
|
_task: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||||
|
match self.handle_msg(msg) {
|
||||||
|
Err(e) => {
|
||||||
|
self.props.on_error.emit(e);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Ok(b) => b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change(&mut self, _: Self::Properties) -> ShouldRender {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> Html {
|
||||||
|
let group = &self.props.group;
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<td>{&group.display_name}</td>
|
||||||
|
{ if self.props.is_admin { html! {
|
||||||
|
<td><button onclick=self.link.callback(|_| Msg::SubmitRemoveGroup)>{"-"}</button></td>
|
||||||
|
}} else { html!{} }
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
use yew::{html::ChangeData, prelude::*};
|
use yew::{html::ChangeData, prelude::*};
|
||||||
|
use yewtil::NeqAssign;
|
||||||
|
|
||||||
pub struct Select {
|
pub struct Select {
|
||||||
link: ComponentLink<Self>,
|
link: ComponentLink<Self>,
|
||||||
props: SelectProps,
|
props: SelectProps,
|
||||||
|
node_ref: NodeRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(yew::Properties, Clone, PartialEq, Debug)]
|
#[derive(yew::Properties, Clone, PartialEq, Debug)]
|
||||||
@ -26,49 +28,48 @@ impl Select {
|
|||||||
.nth(nth as usize)
|
.nth(nth as usize)
|
||||||
.map(|child| child.props)
|
.map(|child| child.props)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_selection_update(&self) {
|
||||||
|
let select_node = self.node_ref.cast::<web_sys::HtmlSelectElement>().unwrap();
|
||||||
|
self.props
|
||||||
|
.on_selection_change
|
||||||
|
.emit(self.get_nth_child_props(select_node.selected_index()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Select {
|
impl Component for Select {
|
||||||
type Message = SelectMsg;
|
type Message = SelectMsg;
|
||||||
type Properties = SelectProps;
|
type Properties = SelectProps;
|
||||||
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||||
let res = Self { link, props };
|
Self {
|
||||||
res.props
|
link,
|
||||||
.on_selection_change
|
props,
|
||||||
.emit(res.get_nth_child_props(0));
|
node_ref: NodeRef::default(),
|
||||||
res
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rendered(&mut self, _first_render: bool) {
|
||||||
|
self.send_selection_update();
|
||||||
|
}
|
||||||
|
|
||||||
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||||
match msg {
|
let SelectMsg::OnSelectChange(data) = msg;
|
||||||
SelectMsg::OnSelectChange(data) => match data {
|
match data {
|
||||||
ChangeData::Select(e) => {
|
ChangeData::Select(_) => self.send_selection_update(),
|
||||||
self.props
|
_ => unreachable!(),
|
||||||
.on_selection_change
|
|
||||||
.emit(self.get_nth_child_props(e.selected_index()));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
||||||
if self.props.children.len() != props.children.len() {
|
self.props.children.neq_assign(props.children)
|
||||||
let was_empty = self.props.children.is_empty();
|
|
||||||
self.props = props;
|
|
||||||
if self.props.children.is_empty() || was_empty {
|
|
||||||
self.props
|
|
||||||
.on_selection_change
|
|
||||||
.emit(self.get_nth_child_props(0));
|
|
||||||
}
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Html {
|
fn view(&self) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<select
|
<select
|
||||||
onchange=self.link.callback(SelectMsg::OnSelectChange)>
|
ref=self.node_ref.clone()
|
||||||
|
onchange=self.link.callback(SelectMsg::OnSelectChange)>
|
||||||
{ self.props.children.clone() }
|
{ self.props.children.clone() }
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ pub struct SelectOption {
|
|||||||
props: SelectOptionProps,
|
props: SelectOptionProps,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(yew::Properties, Clone, PartialEq)]
|
#[derive(yew::Properties, Clone, PartialEq, Debug)]
|
||||||
pub struct SelectOptionProps {
|
pub struct SelectOptionProps {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
@ -88,20 +89,19 @@ pub struct SelectOptionProps {
|
|||||||
impl Component for SelectOption {
|
impl Component for SelectOption {
|
||||||
type Message = ();
|
type Message = ();
|
||||||
type Properties = SelectOptionProps;
|
type Properties = SelectOptionProps;
|
||||||
|
|
||||||
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
|
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
|
||||||
Self { props }
|
Self { props }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, _: Self::Message) -> ShouldRender {
|
fn update(&mut self, _: Self::Message) -> ShouldRender {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
||||||
if self.props != props {
|
self.props.neq_assign(props)
|
||||||
self.props = props;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Html {
|
fn view(&self) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<option value=self.props.value.clone()>
|
<option value=self.props.value.clone()>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::{
|
components::{
|
||||||
add_user_to_group::AddUserToGroupComponent,
|
add_user_to_group::AddUserToGroupComponent,
|
||||||
|
remove_user_from_group::RemoveUserFromGroupComponent,
|
||||||
router::{AppRoute, NavButton},
|
router::{AppRoute, NavButton},
|
||||||
user_details_form::UserDetailsForm,
|
user_details_form::UserDetailsForm,
|
||||||
},
|
},
|
||||||
@ -25,30 +26,14 @@ pub struct GetUserDetails;
|
|||||||
pub type User = get_user_details::GetUserDetailsUser;
|
pub type User = get_user_details::GetUserDetailsUser;
|
||||||
pub type Group = get_user_details::GetUserDetailsUserGroups;
|
pub type Group = get_user_details::GetUserDetailsUserGroups;
|
||||||
|
|
||||||
#[derive(GraphQLQuery)]
|
|
||||||
#[graphql(
|
|
||||||
schema_path = "../schema.graphql",
|
|
||||||
query_path = "queries/remove_user_from_group.graphql",
|
|
||||||
response_derives = "Debug",
|
|
||||||
variables_derives = "Clone",
|
|
||||||
custom_scalars_module = "crate::infra::graphql"
|
|
||||||
)]
|
|
||||||
pub struct RemoveUserFromGroup;
|
|
||||||
|
|
||||||
pub struct UserDetails {
|
pub struct UserDetails {
|
||||||
link: ComponentLink<Self>,
|
link: ComponentLink<Self>,
|
||||||
/// Which user this is about.
|
props: Props,
|
||||||
username: String,
|
|
||||||
/// The user info. If none, the error is in `error`. If `error` is None, then we haven't
|
/// The user info. If none, the error is in `error`. If `error` is None, then we haven't
|
||||||
/// received the server response yet.
|
/// received the server response yet.
|
||||||
user: Option<User>,
|
user: Option<User>,
|
||||||
/// Error message displayed to the user.
|
/// Error message displayed to the user.
|
||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
/// True iff we just finished updating the user, to display a successful message.
|
|
||||||
update_successful: bool,
|
|
||||||
is_admin: bool,
|
|
||||||
/// The group that we're requesting to remove, if any.
|
|
||||||
group_to_remove: Option<Group>,
|
|
||||||
// Used to keep the request alive long enough.
|
// Used to keep the request alive long enough.
|
||||||
_task: Option<FetchTask>,
|
_task: Option<FetchTask>,
|
||||||
}
|
}
|
||||||
@ -58,10 +43,9 @@ pub struct UserDetails {
|
|||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
/// Received the user details response, either the user data or an error.
|
/// Received the user details response, either the user data or an error.
|
||||||
UserDetailsResponse(Result<get_user_details::ResponseData>),
|
UserDetailsResponse(Result<get_user_details::ResponseData>),
|
||||||
SubmitRemoveGroup(Group),
|
|
||||||
RemoveGroupResponse(Result<remove_user_from_group::ResponseData>),
|
|
||||||
OnError(Error),
|
OnError(Error),
|
||||||
OnUserAddedToGroup(Group),
|
OnUserAddedToGroup(Group),
|
||||||
|
OnUserRemovedFromGroup(Group),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(yew::Properties, Clone, PartialEq)]
|
#[derive(yew::Properties, Clone, PartialEq)]
|
||||||
@ -74,7 +58,7 @@ impl UserDetails {
|
|||||||
fn get_user_details(&mut self) {
|
fn get_user_details(&mut self) {
|
||||||
self._task = HostService::graphql_query::<GetUserDetails>(
|
self._task = HostService::graphql_query::<GetUserDetails>(
|
||||||
get_user_details::Variables {
|
get_user_details::Variables {
|
||||||
id: self.username.clone(),
|
id: self.props.username.clone(),
|
||||||
},
|
},
|
||||||
self.link.callback(Msg::UserDetailsResponse),
|
self.link.callback(Msg::UserDetailsResponse),
|
||||||
"Error trying to fetch user details",
|
"Error trying to fetch user details",
|
||||||
@ -86,26 +70,7 @@ impl UserDetails {
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit_remove_group(&mut self, group: Group) -> Result<bool> {
|
|
||||||
self._task = HostService::graphql_query::<RemoveUserFromGroup>(
|
|
||||||
remove_user_from_group::Variables {
|
|
||||||
user: self.username.clone(),
|
|
||||||
group: group.id,
|
|
||||||
},
|
|
||||||
self.link.callback(Msg::RemoveGroupResponse),
|
|
||||||
"Error trying to initiate removing the user from a group",
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
ConsoleService::log(&e.to_string());
|
|
||||||
e
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
self.group_to_remove = Some(group);
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_msg(&mut self, msg: <Self as Component>::Message) -> Result<bool> {
|
fn handle_msg(&mut self, msg: <Self as Component>::Message) -> Result<bool> {
|
||||||
self.update_successful = false;
|
|
||||||
match msg {
|
match msg {
|
||||||
Msg::UserDetailsResponse(response) => match response {
|
Msg::UserDetailsResponse(response) => match response {
|
||||||
Ok(user) => self.user = Some(user.user),
|
Ok(user) => self.user = Some(user.user),
|
||||||
@ -114,27 +79,19 @@ impl UserDetails {
|
|||||||
bail!("Error getting user details: {}", e);
|
bail!("Error getting user details: {}", e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Msg::SubmitRemoveGroup(group) => return self.submit_remove_group(group),
|
|
||||||
Msg::RemoveGroupResponse(response) => {
|
|
||||||
response?;
|
|
||||||
let group = self.group_to_remove.take().unwrap();
|
|
||||||
// Remove the group from the user and add it to the dropdown.
|
|
||||||
self.user.as_mut().unwrap().groups.retain(|g| g != &group);
|
|
||||||
}
|
|
||||||
Msg::OnError(e) => return Err(e),
|
Msg::OnError(e) => return Err(e),
|
||||||
Msg::OnUserAddedToGroup(group) => {
|
Msg::OnUserAddedToGroup(group) => {
|
||||||
self.user.as_mut().unwrap().groups.push(group);
|
self.user.as_mut().unwrap().groups.push(group);
|
||||||
}
|
}
|
||||||
|
Msg::OnUserRemovedFromGroup(group) => {
|
||||||
|
self.user.as_mut().unwrap().groups.retain(|g| g != &group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_messages(&self, error: &Option<Error>) -> Html {
|
fn view_messages(&self, error: &Option<Error>) -> Html {
|
||||||
if self.update_successful {
|
if let Some(e) = error {
|
||||||
html! {
|
|
||||||
<span>{"Update successful!"}</span>
|
|
||||||
}
|
|
||||||
} else if let Some(e) = error {
|
|
||||||
html! {
|
html! {
|
||||||
<div>
|
<div>
|
||||||
<span>{"Error: "}{e.to_string()}</span>
|
<span>{"Error: "}{e.to_string()}</span>
|
||||||
@ -147,15 +104,15 @@ impl UserDetails {
|
|||||||
|
|
||||||
fn view_group_memberships(&self, u: &User) -> Html {
|
fn view_group_memberships(&self, u: &User) -> Html {
|
||||||
let make_group_row = |group: &Group| {
|
let make_group_row = |group: &Group| {
|
||||||
let id = group.id;
|
|
||||||
let display_name = group.display_name.clone();
|
let display_name = group.display_name.clone();
|
||||||
html! {
|
html! {
|
||||||
<tr key="groupRow_".to_string() + &display_name>
|
<tr key="groupRow_".to_string() + &display_name>
|
||||||
<td>{&group.display_name}</td>
|
<RemoveUserFromGroupComponent
|
||||||
{ if self.is_admin { html! {
|
username=u.id.clone()
|
||||||
<td><button onclick=self.link.callback(move |_| Msg::SubmitRemoveGroup(Group{id, display_name: display_name.clone()}))>{"-"}</button></td>
|
group=group.clone()
|
||||||
}} else { html!{} }
|
is_admin=self.props.is_admin
|
||||||
}
|
on_user_removed_from_group=self.link.callback(Msg::OnUserRemovedFromGroup)
|
||||||
|
on_error=self.link.callback(Msg::OnError)/>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -165,7 +122,7 @@ impl UserDetails {
|
|||||||
<table>
|
<table>
|
||||||
<tr key="headerRow">
|
<tr key="headerRow">
|
||||||
<th>{"Group"}</th>
|
<th>{"Group"}</th>
|
||||||
{ if self.is_admin { html!{ <th></th> }} else { html!{} }}
|
{ if self.props.is_admin { html!{ <th></th> }} else { html!{} }}
|
||||||
</tr>
|
</tr>
|
||||||
{u.groups.iter().map(make_group_row).collect::<Vec<_>>()}
|
{u.groups.iter().map(make_group_row).collect::<Vec<_>>()}
|
||||||
<tr key="groupToAddRow">
|
<tr key="groupToAddRow">
|
||||||
@ -177,10 +134,11 @@ impl UserDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view_add_group_button(&self, u: &User) -> Html {
|
fn view_add_group_button(&self, u: &User) -> Html {
|
||||||
if self.is_admin {
|
if self.props.is_admin {
|
||||||
html! {
|
html! {
|
||||||
<AddUserToGroupComponent
|
<AddUserToGroupComponent
|
||||||
user=u.clone()
|
username=u.id.clone()
|
||||||
|
groups=u.groups.clone()
|
||||||
on_error=self.link.callback(Msg::OnError)
|
on_error=self.link.callback(Msg::OnError)
|
||||||
on_user_added_to_group=self.link.callback(Msg::OnUserAddedToGroup)/>
|
on_user_added_to_group=self.link.callback(Msg::OnUserAddedToGroup)/>
|
||||||
}
|
}
|
||||||
@ -197,13 +155,10 @@ impl Component for UserDetails {
|
|||||||
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||||
let mut table = Self {
|
let mut table = Self {
|
||||||
link,
|
link,
|
||||||
username: props.username,
|
props,
|
||||||
_task: None,
|
_task: None,
|
||||||
user: None,
|
user: None,
|
||||||
error: None,
|
error: None,
|
||||||
update_successful: false,
|
|
||||||
is_admin: props.is_admin,
|
|
||||||
group_to_remove: None,
|
|
||||||
};
|
};
|
||||||
table.get_user_details();
|
table.get_user_details();
|
||||||
table
|
table
|
||||||
|
Loading…
Reference in New Issue
Block a user