app,infra: Move more functionality in CommonComponent

This commit is contained in:
Valentin Tolmer 2021-10-31 21:19:54 +09:00 committed by nitnelave
parent ba72e622c2
commit 65dd1d1fd3
3 changed files with 58 additions and 30 deletions

View File

@ -176,7 +176,7 @@ impl CommonComponent<ChangePasswordForm> for ChangePasswordForm {
Ok(false) Ok(false)
} }
Msg::RegistrationFinishResponse(response) => { Msg::RegistrationFinishResponse(response) => {
self.common.task = None; self.common.cancel_task();
if response.is_ok() { if response.is_ok() {
self.route_dispatcher self.route_dispatcher
.send(RouteRequest::ChangeRoute(Route::from( .send(RouteRequest::ChangeRoute(Route::from(
@ -236,7 +236,7 @@ impl Component for ChangePasswordForm {
class_invalid="is-invalid has-error" class_invalid="is-invalid has-error"
class_valid="has-success" class_valid="has-success"
autocomplete="current-password" autocomplete="current-password"
oninput=self.common.link.callback(|_| Msg::FormUpdate) /> oninput=self.common.callback(|_| Msg::FormUpdate) />
<div class="invalid-feedback"> <div class="invalid-feedback">
{&self.form.field_message("old_password")} {&self.form.field_message("old_password")}
</div> </div>
@ -256,7 +256,7 @@ impl Component for ChangePasswordForm {
class_invalid="is-invalid has-error" class_invalid="is-invalid has-error"
class_valid="has-success" class_valid="has-success"
autocomplete="new-password" autocomplete="new-password"
oninput=self.common.link.callback(|_| Msg::FormUpdate) /> oninput=self.common.callback(|_| Msg::FormUpdate) />
<div class="invalid-feedback"> <div class="invalid-feedback">
{&self.form.field_message("password")} {&self.form.field_message("password")}
</div> </div>
@ -275,7 +275,7 @@ impl Component for ChangePasswordForm {
class_invalid="is-invalid has-error" class_invalid="is-invalid has-error"
class_valid="has-success" class_valid="has-success"
autocomplete="new-password" autocomplete="new-password"
oninput=self.common.link.callback(|_| Msg::FormUpdate) /> oninput=self.common.callback(|_| Msg::FormUpdate) />
<div class="invalid-feedback"> <div class="invalid-feedback">
{&self.form.field_message("confirm_password")} {&self.form.field_message("confirm_password")}
</div> </div>
@ -285,8 +285,8 @@ impl Component for ChangePasswordForm {
<button <button
class="btn btn-primary col-sm-1 col-form-label" class="btn btn-primary col-sm-1 col-form-label"
type="submit" type="submit"
disabled=self.common.task.is_some() disabled=self.common.is_task_running()
onclick=self.common.link.callback(|e: MouseEvent| {e.prevent_default(); Msg::Submit})> onclick=self.common.callback(|e: MouseEvent| {e.prevent_default(); Msg::Submit})>
{"Submit"} {"Submit"}
</button> </button>
</div> </div>

View File

@ -4,17 +4,11 @@ use crate::{
remove_user_from_group::RemoveUserFromGroupComponent, remove_user_from_group::RemoveUserFromGroupComponent,
router::{AppRoute, Link}, router::{AppRoute, Link},
}, },
infra::{ infra::common_component::{CommonComponent, CommonComponentParts},
common_component::{CommonComponent, CommonComponentParts},
api::HostService,
}
}; };
use anyhow::{bail, Error, Result}; use anyhow::{bail, Error, Result};
use graphql_client::GraphQLQuery; use graphql_client::GraphQLQuery;
use yew::{ use yew::prelude::*;
prelude::*,
services::ConsoleService,
};
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(
@ -53,18 +47,13 @@ pub struct Props {
impl GroupDetails { impl GroupDetails {
fn get_group_details(&mut self) { fn get_group_details(&mut self) {
self.common.task = HostService::graphql_query::<GetGroupDetails>( self.common.call_graphql::<GetGroupDetails, _>(
get_group_details::Variables { get_group_details::Variables {
id: self.common.group_id, id: self.common.group_id,
}, },
self.common.link.callback(Msg::GroupDetailsResponse), Msg::GroupDetailsResponse,
"Error trying to fetch group details", "Error trying to fetch group details",
) );
.map_err(|e| {
ConsoleService::log(&e.to_string());
e
})
.ok();
} }
fn view_messages(&self, error: &Option<Error>) -> Html { fn view_messages(&self, error: &Option<Error>) -> Html {
@ -95,8 +84,8 @@ impl GroupDetails {
<RemoveUserFromGroupComponent <RemoveUserFromGroupComponent
username=user_id username=user_id
group_id=g.id group_id=g.id
on_user_removed_from_group=self.common.link.callback(Msg::OnUserRemovedFromGroup) on_user_removed_from_group=self.common.callback(Msg::OnUserRemovedFromGroup)
on_error=self.common.link.callback(Msg::OnError)/> on_error=self.common.callback(Msg::OnError)/>
</td> </td>
</tr> </tr>
} }
@ -145,8 +134,8 @@ impl GroupDetails {
<AddGroupMemberComponent <AddGroupMemberComponent
group_id=g.id group_id=g.id
users=users users=users
on_error=self.common.link.callback(Msg::OnError) on_error=self.common.callback(Msg::OnError)
on_user_added_to_group=self.common.link.callback(Msg::OnUserAddedToGroup)/> on_user_added_to_group=self.common.callback(Msg::OnUserAddedToGroup)/>
} }
} }
} }

View File

@ -1,4 +1,6 @@
use crate::infra::api::HostService;
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use graphql_client::GraphQLQuery;
use yew::{ use yew::{
prelude::*, prelude::*,
services::{fetch::FetchTask, ConsoleService}, services::{fetch::FetchTask, ConsoleService},
@ -10,13 +12,21 @@ pub trait CommonComponent<C: Component + CommonComponent<C>>: Component {
} }
pub struct CommonComponentParts<C: CommonComponent<C>> { pub struct CommonComponentParts<C: CommonComponent<C>> {
pub link: ComponentLink<C>, link: ComponentLink<C>,
pub props: <C as Component>::Properties, pub props: <C as Component>::Properties,
pub error: Option<Error>, pub error: Option<Error>,
pub task: Option<FetchTask>, task: Option<FetchTask>,
} }
impl<C: CommonComponent<C>> CommonComponentParts<C> { impl<C: CommonComponent<C>> CommonComponentParts<C> {
pub fn is_task_running(&self) -> bool {
self.task.is_some()
}
pub fn cancel_task(&mut self) {
self.task = None;
}
pub fn create(props: <C as Component>::Properties, link: ComponentLink<C>) -> Self { pub fn create(props: <C as Component>::Properties, link: ComponentLink<C>) -> Self {
Self { Self {
link, link,
@ -38,6 +48,14 @@ impl<C: CommonComponent<C>> CommonComponentParts<C> {
} }
} }
pub fn callback<F, IN, M>(&self, function: F) -> Callback<IN>
where
M: Into<C::Message>,
F: Fn(IN) -> M + 'static,
{
self.link.callback(function)
}
pub fn call_backend<M, Req, Cb, Resp>( pub fn call_backend<M, Req, Cb, Resp>(
&mut self, &mut self,
method: M, method: M,
@ -46,11 +64,32 @@ impl<C: CommonComponent<C>> CommonComponentParts<C> {
) -> Result<()> ) -> Result<()>
where where
M: Fn(Req, Callback<Resp>) -> Result<FetchTask>, M: Fn(Req, Callback<Resp>) -> Result<FetchTask>,
Cb: Fn(Resp) -> <C as Component>::Message + 'static, Cb: FnOnce(Resp) -> <C as Component>::Message + 'static,
{ {
self.task = Some(method(req, self.link.callback(callback))?); self.task = Some(method(req, self.link.callback_once(callback))?);
Ok(()) Ok(())
} }
pub fn call_graphql<QueryType, EnumCallback>(
&mut self,
variables: QueryType::Variables,
enum_callback: EnumCallback,
error_message: &'static str,
) where
QueryType: GraphQLQuery + 'static,
EnumCallback: Fn(Result<QueryType::ResponseData>) -> <C as Component>::Message + 'static,
{
self.task = HostService::graphql_query::<QueryType>(
variables,
self.link.callback(enum_callback),
error_message,
)
.map_err::<(), _>(|e| {
ConsoleService::log(&e.to_string());
self.error = Some(e);
})
.ok();
}
} }
impl<C: Component + CommonComponent<C>> std::ops::Deref for CommonComponentParts<C> { impl<C: Component + CommonComponent<C>> std::ops::Deref for CommonComponentParts<C> {