use crate::infra::api::HostService; use anyhow::{Error, Result}; use graphql_client::GraphQLQuery; use yew::{ prelude::*, services::{fetch::FetchTask, ConsoleService}, }; pub trait CommonComponent>: Component { fn handle_msg(&mut self, msg: ::Message) -> Result; fn mut_common(&mut self) -> &mut CommonComponentParts; } pub struct CommonComponentParts> { link: ComponentLink, pub props: ::Properties, pub error: Option, task: Option, } impl> CommonComponentParts { pub fn is_task_running(&self) -> bool { self.task.is_some() } pub fn cancel_task(&mut self) { self.task = None; } pub fn create(props: ::Properties, link: ComponentLink) -> Self { Self { link, props, error: None, task: None, } } pub fn update(com: &mut C, msg: ::Message) -> ShouldRender { com.mut_common().error = None; match com.handle_msg(msg) { Err(e) => { ConsoleService::error(&e.to_string()); com.mut_common().error = Some(e); true } Ok(b) => b, } } pub fn callback(&self, function: F) -> Callback where M: Into, F: Fn(IN) -> M + 'static, { self.link.callback(function) } pub fn call_backend( &mut self, method: M, req: Req, callback: Cb, ) -> Result<()> where M: Fn(Req, Callback) -> Result, Cb: FnOnce(Resp) -> ::Message + 'static, { self.task = Some(method(req, self.link.callback_once(callback))?); Ok(()) } pub fn call_graphql( &mut self, variables: QueryType::Variables, enum_callback: EnumCallback, error_message: &'static str, ) where QueryType: GraphQLQuery + 'static, EnumCallback: Fn(Result) -> ::Message + 'static, { self.task = HostService::graphql_query::( variables, self.link.callback(enum_callback), error_message, ) .map_err::<(), _>(|e| { ConsoleService::log(&e.to_string()); self.error = Some(e); }) .ok(); } } impl> std::ops::Deref for CommonComponentParts { type Target = ::Properties; fn deref(&self) -> &::Target { &self.props } } impl> std::ops::DerefMut for CommonComponentParts { fn deref_mut(&mut self) -> &mut ::Target { &mut self.props } }