use bounce::helmet::Helmet; use cynic::{MutationBuilder, QueryBuilder}; use std::rc::Rc; use web_sys::HtmlInputElement; use yew::prelude::*; use yewdux::prelude::*; use crate::{ components, graphql::{self, ReqwestExt}, stores, }; pub enum Msg { Void, UpdateUser(Rc), LoadUsers, UsersDone(graphql::GraphQLResult), OpenNewModal, CloseNewModal, NewModalSubmit, NewModalSubmitDone(graphql::GraphQLResult), OpenEditModal(usize, usize), CloseEditModal, Delete, DeleteDone(graphql::GraphQLResult), } pub struct Index { notifications_dispatch: Dispatch, user: Rc, _user_dispatch: Dispatch, loading: bool, users: Vec, new_modal: bool, new_modal_save_loading: bool, new_modal_user: NodeRef, new_modal_repo: NodeRef, delete_modal: Option<(usize, usize)>, delete_modal_delete_loading: bool, } impl Component for Index { type Message = Msg; type Properties = (); fn create(ctx: &Context) -> Self { let notifications_dispatch = Dispatch::subscribe(ctx.link().callback(|_| Msg::Void)); let user_dispatch = Dispatch::subscribe(ctx.link().callback(Msg::UpdateUser)); ctx.link().send_message(Msg::LoadUsers); Self { notifications_dispatch, user: user_dispatch.get(), _user_dispatch: user_dispatch, loading: false, users: vec![], new_modal: false, new_modal_save_loading: false, new_modal_user: NodeRef::default(), new_modal_repo: NodeRef::default(), delete_modal: None, delete_modal_delete_loading: false, } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::Void => false, Msg::UpdateUser(x) => { self.user = x; true } Msg::LoadUsers => { self.loading = true; let client = graphql::client(None); let operation = graphql::queries::Users::build(()); ctx.link().send_future(async move { Msg::UsersDone(client.run_graphql(operation).await) }); true } Msg::UsersDone(x) => { self.loading = false; match x { Ok(resp) => { if let Some(errors) = resp.errors { self.notifications_dispatch.reduce_mut(|notifs| { for e in errors { notifs.push(stores::Notification::danger(Some( components::notification::NotificationMessage::GraphQLError( e, ), ))); } }); false } else { let data = resp.data.unwrap(); self.users = data.users; true } } Err(e) => { self.notifications_dispatch.reduce_mut(|notifs| { notifs.push(stores::Notification::danger(Some( components::notification::NotificationMessage::Text(vec![ e.to_string() ]), ))); }); false } } } Msg::OpenNewModal => { self.new_modal = true; true } Msg::CloseNewModal => { self.new_modal = false; self.new_modal_save_loading = false; ctx.link().send_message(Msg::LoadUsers); true } Msg::NewModalSubmit => { let user = match self.new_modal_user.cast::() { Some(x) => x.value(), None => return false, }; let name = match self.new_modal_repo.cast::() { Some(x) => x.value(), None => return false, }; self.new_modal_save_loading = true; let operation = graphql::queries::CreateRepository::build( graphql::queries::CreateRepositoryVariables { user, name }, ); let client = graphql::client(self.user.0.as_ref()); ctx.link().send_future(async move { Msg::NewModalSubmitDone(client.run_graphql(operation).await) }); true } Msg::NewModalSubmitDone(x) => { self.new_modal_save_loading = false; match x { Ok(resp) => { if let Some(errors) = resp.errors { self.notifications_dispatch.reduce_mut(|notifs| { for e in errors { notifs.push(stores::Notification { notification_type: components::notification::NotificationType::Danger, message: Some(components::notification::NotificationMessage::GraphQLError(e)), }); } }); true } else { ctx.link().send_message(Msg::CloseNewModal); true } } Err(e) => { self.notifications_dispatch.reduce_mut(|notifs| { notifs.push(stores::Notification::danger(Some( components::notification::NotificationMessage::Text(vec![ e.to_string() ]), ))); }); false } } } Msg::OpenEditModal(i, j) => { self.delete_modal = Some((i, j)); true } Msg::CloseEditModal => { self.delete_modal = None; self.delete_modal_delete_loading = false; ctx.link().send_message(Msg::LoadUsers); true } Msg::Delete => { let modal = self.delete_modal.unwrap(); self.delete_modal_delete_loading = true; let operation = graphql::queries::DeleteRepository::build( graphql::queries::DeleteRepositoryVariables { id: self.users[modal.0].repositories[modal.1].id.to_owned(), }, ); let client = graphql::client(self.user.0.as_ref()); ctx.link().send_future(async move { Msg::DeleteDone(client.run_graphql(operation).await) }); true } Msg::DeleteDone(x) => match x { Ok(_) => { self.delete_modal = None; self.delete_modal_delete_loading = false; ctx.link().send_message(Msg::LoadUsers); true } Err(e) => { self.notifications_dispatch.reduce_mut(|notifs| { notifs.push(stores::Notification { notification_type: components::notification::NotificationType::Danger, message: Some(components::notification::NotificationMessage::Text( vec![e.to_string()], )), }); }); false } }, } } fn view(&self, ctx: &Context) -> Html { html! { <> { "Home" }
if self.loading {
} else { { for self.users.iter().enumerate().map(|(i, user)| html! {
>() } on_click={ctx.link().callback(move |j| Msg::OpenEditModal(i, j))} />
}) } }
if self.new_modal {

{ "Edit" }

{ "User" }
{ "Repository" }

} if let Some(modal) = &self.delete_modal {

{ "Edit" }

{ &self.users[modal.0].name } { "/" } { &self.users[modal.0].repositories[modal.1].name }

} } } }