use yew::html;
use yew::prelude::*;
use yew::ComponentLink;
use yew_router::agent::RouteAgentDispatcher;
use yew_router::agent::RouteRequest;
use yew_router::prelude::RouterAnchor;
use yew_router::route::Route;
use yewtil::fetch::FetchAction;
use yewtil::fetch::FetchState;
use yewtil::future::LinkFuture;
use crate::component::utils::Loader;
use crate::component::utils::Reloader;
use crate::models::contributor::contributors_query::FetchActionContributors;
use crate::models::contributor::contributors_query::FetchContributors;
use crate::models::contributor::Contributor;
use crate::route::AdminRoute;
use crate::route::AppRoute;
pub struct ContributorsComponent {
markdown: FetchContributors,
link: ComponentLink<Self>,
router: RouteAgentDispatcher<()>,
}
pub enum Msg {
SetMarkdownFetchState(FetchActionContributors),
GetMarkdown,
ChangeRoute(AppRoute),
}
impl Component for ContributorsComponent {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let router = RouteAgentDispatcher::new();
ContributorsComponent {
markdown: Default::default(),
link,
router,
}
}
fn rendered(&mut self, first_render: bool) {
if first_render {
self.link
.send_future(self.markdown.fetch(Msg::SetMarkdownFetchState));
self.link
.send_message(Msg::SetMarkdownFetchState(FetchAction::Fetching));
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SetMarkdownFetchState(fetch_state) => {
self.markdown.apply(fetch_state);
true
}
Msg::GetMarkdown => {
self.link
.send_future(self.markdown.fetch(Msg::SetMarkdownFetchState));
self.link
.send_message(Msg::SetMarkdownFetchState(FetchAction::Fetching));
false
}
Msg::ChangeRoute(r) => {
let route = Route::from(r);
self.router.send(RouteRequest::ChangeRoute(route));
false
}
}
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
match self.markdown.as_ref().state() {
FetchState::NotFetching(_) => {
html! {<Reloader onclick=self.link.callback(|_| Msg::GetMarkdown)/>}
}
FetchState::Fetching(_) => html! {<Loader/>},
FetchState::Fetched(body) => html! {
<>
<nav class="level">
<div class="level-left">
<div class="level-item">
<p class="subtitle is-5">
<strong>{ body.data.contributors.iter().count() }</strong> { " contributors" }
</p>
</div>
</div>
<div class="level-right">
<p class="level-item">
<RouterAnchor<AppRoute>
classes="button is-success"
route=AppRoute::Admin(AdminRoute::NewContributor)
>
{"New"}
</ RouterAnchor<AppRoute>>
</p>
</div>
</nav>
<table class="table is-fullwidth is-hoverable">
<thead>
<tr>
<th>{ "ID" }</th>
<th>{ "Full Name" }</th>
<th>{ "ORCID" }</th>
</tr>
</thead>
<tbody>
{ for body.data.contributors.iter().map(|p| self.render_contributor(p)) }
</tbody>
</table>
</>
},
FetchState::Failed(_, err) => html! {&err},
}
}
}
impl ContributorsComponent {
fn change_route(&self, app_route: AppRoute) -> Callback<MouseEvent> {
self.link.callback(move |_| {
let route = app_route.clone();
Msg::ChangeRoute(route)
})
}
fn render_contributor(&self, p: &Contributor) -> Html {
html! {
<tr
class="row"
onclick=&self.change_route(AppRoute::Admin(AdminRoute::Contributor(p.contributor_id.clone())))
>
<td>{&p.contributor_id}</td>
<td>{&p.full_name}</td>
<td>{&p.orcid.clone().unwrap_or("".to_string())}</td>
</tr>
}
}
}