mentorenwahl/frontend/src/routes/settings/tokens.rs

131 lines
4.1 KiB
Rust

use graphql_client::reqwest::post_graphql;
use yew::prelude::*;
use crate::components;
use crate::graphql;
pub enum Msg {
DoneFetching {
errors: Option<Vec<String>>,
tokens: Vec<graphql::queries::tokens::tokens::TokensTokens>,
},
Revoke(usize),
RevokeDone {
errors: Option<Vec<String>>,
id: usize,
},
}
#[derive(Properties, PartialEq, Eq)]
pub struct TokensProps {
pub token: String,
}
pub struct Tokens {
fetching: bool,
errors: Option<Vec<String>>,
tokens: Option<Vec<graphql::queries::tokens::tokens::TokensTokens>>,
}
impl Component for Tokens {
type Message = Msg;
type Properties = TokensProps;
fn create(ctx: &Context<Self>) -> Self {
let client = graphql::client(Some(&ctx.props().token)).unwrap();
ctx.link().send_future(async move {
let response = post_graphql::<graphql::queries::tokens::Tokens, _>(
&client,
graphql::URL.as_str(),
graphql::queries::tokens::tokens::Variables,
)
.await
.unwrap();
Msg::DoneFetching {
errors: None,
tokens: response.data.unwrap().tokens.unwrap(),
}
});
Self {
fetching: true,
errors: None,
tokens: None,
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::DoneFetching { errors, tokens } => {
self.fetching = false;
self.errors = errors;
self.tokens = Some(tokens);
true
}
Msg::Revoke(id) => {
let client = graphql::client(Some(&ctx.props().token)).unwrap();
let token = self.tokens.as_ref().unwrap()[id].id.to_owned();
ctx.link().send_future(async move {
let response =
post_graphql::<graphql::mutations::revoke_token::RevokeToken, _>(
&client,
graphql::URL.as_str(),
graphql::mutations::revoke_token::revoke_token::Variables { token },
)
.await
.unwrap();
Msg::RevokeDone {
errors: components::graphql_errors::convert(response.errors),
id,
}
});
false
}
Msg::RevokeDone { errors, id } => {
self.errors = errors;
self.tokens.as_mut().unwrap().remove(id);
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<fieldset>
<legend>{ "Tokens" }</legend>
if self.fetching {
<p>{ "Fetching..." }</p>
} else {
<table>
<tr>
<th>{ "ID" }</th>
<th>{ "Issued at" }</th>
<th>{ "Expires at" }</th>
<th>{ "Revoke" }</th>
</tr>
{ for self.tokens.as_ref().unwrap().iter().enumerate().map(|(i, t)| {
html! {
<tr>
<td><code>{ &t.id }</code></td>
<td><code>{ &t.iat }</code></td>
<td><code>{ &t.exp }</code></td>
<td>
<button onclick={ctx.link().callback(move |_| Msg::Revoke(i))}>
{ "Revoke" }
</button>
</td>
</tr>
}
}) }
</table>
<components::graphql_errors::GraphQLErrors errors={self.errors.to_owned()} />
}
</fieldset>
}
}
}