144 lines
4.8 KiB
Rust
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>
|
|
</>
|
|
}
|
|
}
|
|
}
|