gitea_pages/frontend/src/routes/user.rs

144 lines
4.8 KiB
Rust

use bounce::helmet::Helmet;
use cynic::QueryBuilder;
use yew::prelude::*;
use yewdux::prelude::*;
use crate::{
components,
graphql::{self, ReqwestExt},
stores,
};
#[derive(Properties, PartialEq)]
pub struct Props {
pub name: AttrValue,
}
pub enum Msg {
Void,
Done(graphql::GraphQLResult<graphql::queries::UserByName>),
}
struct Repository {
name: String,
url: String,
}
pub struct User {
notifications_dispatch: Dispatch<stores::Notifications>,
loading: bool,
repositories: Vec<Repository>,
}
impl Component for User {
type Message = Msg;
type Properties = Props;
fn create(ctx: &Context<Self>) -> Self {
let operation =
graphql::queries::UserByName::build(graphql::queries::UserByNameVariables {
name: ctx.props().name.to_string(),
});
let client = graphql::client(None);
ctx.link()
.send_future(async move { Msg::Done(client.run_graphql(operation).await) });
Self {
notifications_dispatch: Dispatch::subscribe(ctx.link().callback(|_| Msg::Void)),
loading: true,
repositories: vec![],
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::Void => false,
Msg::Done(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 {
self.repositories = resp
.data
.unwrap()
.user_by_name
.repositories
.into_iter()
.map(|repo| Repository {
name: repo.name,
url: repo.url,
})
.collect();
true
}
}
Err(e) => {
self.notifications_dispatch.reduce_mut(|notifs| {
notifs.push(stores::Notification::danger(Some(
components::notification::NotificationMessage::Text(vec![
e.to_string()
]),
)));
});
false
}
}
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let name = &ctx.props().name;
html! {
<>
<Helmet>
<title>{ name }</title>
</Helmet>
<div class={classes!("columns", "is-centered")}>
<div class={classes!("column", "is-half")}>
<div class={classes!("columns", "is-multiline")}>
if self.loading {
<div class={classes!("column", "is-full")}>
<components::Loading />
</div>
} else {
<div class={classes!("column", "is-full")}>
<components::UserPane
name={&ctx.props().name}
repositories={
self.repositories
.iter()
.map(|repo| components::user_pane::Repository {
name: repo.name.to_owned(),
url: Some(repo.url.to_owned())
})
.collect::<Vec<_>>()
}
/>
</div>
}
</div>
</div>
</div>
</>
}
}
}