2021-10-11 16:41:55 +00:00
|
|
|
use crate::{
|
|
|
|
components::select::{Select, SelectOption, SelectOptionProps},
|
2021-10-31 12:31:15 +00:00
|
|
|
infra::common_component::{CommonComponent, CommonComponentParts},
|
2021-10-11 16:41:55 +00:00
|
|
|
};
|
|
|
|
use anyhow::{Error, Result};
|
|
|
|
use graphql_client::GraphQLQuery;
|
|
|
|
use std::collections::HashSet;
|
2021-10-31 12:31:15 +00:00
|
|
|
use yew::prelude::*;
|
2021-10-11 16:41:55 +00:00
|
|
|
|
|
|
|
#[derive(GraphQLQuery)]
|
|
|
|
#[graphql(
|
|
|
|
schema_path = "../schema.graphql",
|
|
|
|
query_path = "queries/add_user_to_group.graphql",
|
|
|
|
response_derives = "Debug",
|
|
|
|
variables_derives = "Clone",
|
|
|
|
custom_scalars_module = "crate::infra::graphql"
|
|
|
|
)]
|
|
|
|
pub struct AddUserToGroup;
|
|
|
|
|
|
|
|
#[derive(GraphQLQuery)]
|
|
|
|
#[graphql(
|
|
|
|
schema_path = "../schema.graphql",
|
|
|
|
query_path = "queries/list_users.graphql",
|
|
|
|
response_derives = "Debug,Clone,PartialEq,Eq,Hash",
|
|
|
|
variables_derives = "Clone",
|
|
|
|
custom_scalars_module = "crate::infra::graphql"
|
|
|
|
)]
|
|
|
|
pub struct ListUserNames;
|
|
|
|
pub type User = list_user_names::ListUserNamesUsers;
|
|
|
|
|
|
|
|
pub struct AddGroupMemberComponent {
|
2021-10-31 12:31:15 +00:00
|
|
|
common: CommonComponentParts<Self>,
|
2021-10-11 16:41:55 +00:00
|
|
|
/// The list of existing users, initially not loaded.
|
|
|
|
user_list: Option<Vec<User>>,
|
|
|
|
/// The currently selected user.
|
|
|
|
selected_user: Option<User>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Msg {
|
|
|
|
UserListResponse(Result<list_user_names::ResponseData>),
|
|
|
|
SubmitAddMember,
|
|
|
|
AddMemberResponse(Result<add_user_to_group::ResponseData>),
|
|
|
|
SelectionChanged(Option<SelectOptionProps>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(yew::Properties, Clone, PartialEq)]
|
|
|
|
pub struct Props {
|
|
|
|
pub group_id: i64,
|
|
|
|
pub users: Vec<User>,
|
|
|
|
pub on_user_added_to_group: Callback<User>,
|
|
|
|
pub on_error: Callback<Error>,
|
|
|
|
}
|
|
|
|
|
2021-10-31 12:31:15 +00:00
|
|
|
impl CommonComponent<AddGroupMemberComponent> for AddGroupMemberComponent {
|
2021-10-11 16:41:55 +00:00
|
|
|
fn handle_msg(&mut self, msg: <Self as Component>::Message) -> Result<bool> {
|
|
|
|
match msg {
|
|
|
|
Msg::UserListResponse(response) => {
|
|
|
|
self.user_list = Some(response?.users);
|
2021-10-31 12:31:15 +00:00
|
|
|
self.common.cancel_task();
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
Msg::SubmitAddMember => return self.submit_add_member(),
|
|
|
|
Msg::AddMemberResponse(response) => {
|
|
|
|
response?;
|
2021-10-31 12:31:15 +00:00
|
|
|
self.common.cancel_task();
|
2021-10-11 16:41:55 +00:00
|
|
|
let user = self
|
|
|
|
.selected_user
|
|
|
|
.as_ref()
|
|
|
|
.expect("Could not get selected user")
|
|
|
|
.clone();
|
|
|
|
// Remove the user from the dropdown.
|
2021-10-31 14:42:19 +00:00
|
|
|
self.common.on_user_added_to_group.emit(user);
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
Msg::SelectionChanged(option_props) => {
|
2021-10-11 17:20:13 +00:00
|
|
|
let was_some = self.selected_user.is_some();
|
2021-10-11 16:41:55 +00:00
|
|
|
self.selected_user = option_props.map(|u| User {
|
|
|
|
id: u.value,
|
|
|
|
display_name: u.text,
|
|
|
|
});
|
2021-10-11 17:20:13 +00:00
|
|
|
return Ok(self.selected_user.is_some() != was_some);
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
|
2021-10-31 12:31:15 +00:00
|
|
|
fn mut_common(&mut self) -> &mut CommonComponentParts<Self> {
|
|
|
|
&mut self.common
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AddGroupMemberComponent {
|
|
|
|
fn get_user_list(&mut self) {
|
|
|
|
self.common.call_graphql::<ListUserNames, _>(
|
|
|
|
list_user_names::Variables { filters: None },
|
|
|
|
Msg::UserListResponse,
|
|
|
|
"Error trying to fetch user list",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn submit_add_member(&mut self) -> Result<bool> {
|
|
|
|
let user_id = match self.selected_user.clone() {
|
|
|
|
None => return Ok(false),
|
|
|
|
Some(user) => user.id,
|
|
|
|
};
|
|
|
|
self.common.call_graphql::<AddUserToGroup, _>(
|
|
|
|
add_user_to_group::Variables {
|
|
|
|
user: user_id,
|
2021-10-31 14:42:19 +00:00
|
|
|
group: self.common.group_id,
|
2021-10-31 12:31:15 +00:00
|
|
|
},
|
|
|
|
Msg::AddMemberResponse,
|
|
|
|
"Error trying to initiate adding the user to a group",
|
|
|
|
);
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:41:55 +00:00
|
|
|
fn get_selectable_user_list(&self, user_list: &[User]) -> Vec<User> {
|
2021-10-31 14:42:19 +00:00
|
|
|
let user_groups = self.common.users.iter().collect::<HashSet<_>>();
|
2021-10-11 16:41:55 +00:00
|
|
|
user_list
|
|
|
|
.iter()
|
|
|
|
.filter(|u| !user_groups.contains(u))
|
|
|
|
.map(Clone::clone)
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Component for AddGroupMemberComponent {
|
|
|
|
type Message = Msg;
|
|
|
|
type Properties = Props;
|
2021-10-31 12:31:15 +00:00
|
|
|
|
2021-10-11 16:41:55 +00:00
|
|
|
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
|
|
|
let mut res = Self {
|
2021-10-31 12:31:15 +00:00
|
|
|
common: CommonComponentParts::<Self>::create(props, link),
|
2021-10-11 16:41:55 +00:00
|
|
|
user_list: None,
|
|
|
|
selected_user: None,
|
|
|
|
};
|
|
|
|
res.get_user_list();
|
|
|
|
res
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
2021-10-31 12:31:15 +00:00
|
|
|
CommonComponentParts::<Self>::update_and_report_error(
|
|
|
|
self,
|
|
|
|
msg,
|
2021-10-31 14:42:19 +00:00
|
|
|
self.common.on_error.clone(),
|
2021-10-31 12:31:15 +00:00
|
|
|
)
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn change(&mut self, props: Self::Properties) -> ShouldRender {
|
2021-10-31 14:42:19 +00:00
|
|
|
self.common.change(props)
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn view(&self) -> Html {
|
|
|
|
if let Some(user_list) = &self.user_list {
|
|
|
|
let to_add_user_list = self.get_selectable_user_list(user_list);
|
|
|
|
#[allow(unused_braces)]
|
|
|
|
let make_select_option = |user: User| {
|
|
|
|
html_nested! {
|
|
|
|
<SelectOption value=user.id.clone() text=user.display_name.clone() key=user.id />
|
|
|
|
}
|
|
|
|
};
|
|
|
|
html! {
|
2021-10-11 17:20:13 +00:00
|
|
|
<div class="row">
|
|
|
|
<div class="col-sm-3">
|
2021-10-31 12:31:15 +00:00
|
|
|
<Select on_selection_change=self.common.callback(Msg::SelectionChanged)>
|
2021-10-11 16:41:55 +00:00
|
|
|
{
|
|
|
|
to_add_user_list
|
|
|
|
.into_iter()
|
|
|
|
.map(make_select_option)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
</Select>
|
2021-10-11 17:20:13 +00:00
|
|
|
</div>
|
|
|
|
<div class="col-sm-1">
|
|
|
|
<button
|
|
|
|
class="btn btn-success"
|
2021-10-31 12:31:15 +00:00
|
|
|
disabled=self.selected_user.is_none() || self.common.is_task_running()
|
|
|
|
onclick=self.common.callback(|_| Msg::SubmitAddMember)>
|
2021-10-11 17:20:13 +00:00
|
|
|
{"Add"}
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
html! {
|
2021-10-11 17:20:13 +00:00
|
|
|
{"Loading groups"}
|
2021-10-11 16:41:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|