309 lines
16 KiB
Rust
309 lines
16 KiB
Rust
use graphql_client::reqwest::post_graphql;
|
|
use yew::prelude::*;
|
|
|
|
use crate::components;
|
|
use crate::graphql;
|
|
use crate::routes::settings::new_user_modal;
|
|
|
|
pub enum Msg {
|
|
DoneFetching {
|
|
errors: graphql::Errors,
|
|
students: Option<Vec<graphql::queries::users_by_role::students::StudentsStudents>>,
|
|
teachers: Option<Vec<graphql::queries::users_by_role::teachers::TeachersTeachers>>,
|
|
},
|
|
SwitchTab(UsersTab),
|
|
OpenModal,
|
|
CloseModal,
|
|
}
|
|
|
|
#[derive(Properties, PartialEq, Eq)]
|
|
pub struct UsersProps {
|
|
pub token: String,
|
|
}
|
|
|
|
#[derive(PartialEq, Clone, Debug)]
|
|
pub enum UsersTab {
|
|
All,
|
|
Students,
|
|
Teachers,
|
|
}
|
|
|
|
pub struct Users {
|
|
tab: UsersTab,
|
|
fetching: bool,
|
|
errors: graphql::Errors,
|
|
students: Option<Vec<graphql::queries::users_by_role::students::StudentsStudents>>,
|
|
teachers: Option<Vec<graphql::queries::users_by_role::teachers::TeachersTeachers>>,
|
|
modal_active: bool,
|
|
}
|
|
|
|
impl Component for Users {
|
|
type Message = Msg;
|
|
type Properties = UsersProps;
|
|
|
|
fn create(ctx: &Context<Self>) -> Self {
|
|
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
|
ctx.link().send_future(async move {
|
|
let students_response = post_graphql::<graphql::queries::users_by_role::Students, _>(
|
|
&client,
|
|
graphql::URL.as_str(),
|
|
graphql::queries::users_by_role::students::Variables,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
let teachers_response = post_graphql::<graphql::queries::users_by_role::Teachers, _>(
|
|
&client,
|
|
graphql::URL.as_str(),
|
|
graphql::queries::users_by_role::teachers::Variables,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
let x = [
|
|
students_response.errors.map_or_else(|| vec![], |e| e),
|
|
teachers_response.errors.map_or_else(|| vec![], |e| e),
|
|
]
|
|
.concat();
|
|
|
|
if x.is_empty() {
|
|
Msg::DoneFetching {
|
|
errors: None,
|
|
students: Some(students_response.data.unwrap().students.unwrap()),
|
|
teachers: Some(teachers_response.data.unwrap().teachers),
|
|
}
|
|
} else {
|
|
Msg::DoneFetching {
|
|
errors: graphql::convert(Some(x)),
|
|
students: None,
|
|
teachers: None,
|
|
}
|
|
}
|
|
});
|
|
|
|
Self {
|
|
tab: UsersTab::All,
|
|
fetching: true,
|
|
errors: None,
|
|
students: None,
|
|
teachers: None,
|
|
modal_active: false,
|
|
}
|
|
}
|
|
|
|
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
match msg {
|
|
Msg::DoneFetching {
|
|
errors,
|
|
students,
|
|
teachers,
|
|
} => {
|
|
self.fetching = false;
|
|
self.errors = errors;
|
|
self.students = students;
|
|
self.teachers = teachers;
|
|
|
|
true
|
|
}
|
|
Msg::SwitchTab(tab) => {
|
|
if self.tab == tab {
|
|
false
|
|
} else {
|
|
self.tab = tab;
|
|
true
|
|
}
|
|
}
|
|
Msg::OpenModal => {
|
|
self.modal_active = true;
|
|
true
|
|
}
|
|
Msg::CloseModal => {
|
|
self.modal_active = false;
|
|
true
|
|
}
|
|
}
|
|
}
|
|
|
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
html! {
|
|
<fieldset class={classes!("fieldset")}>
|
|
<legend>{ "Benutzer" }</legend>
|
|
<div class={classes!("tabs")}>
|
|
<ul>
|
|
<li class={classes!(if self.tab == UsersTab::All { Some("is-active") } else { None })}>
|
|
<a onclick={ctx.link().callback(|_| Msg::SwitchTab(UsersTab::All))}>{ "Alle" }</a>
|
|
</li>
|
|
<li class={classes!(if self.tab == UsersTab::Students { Some("is-active") } else { None })}>
|
|
<a onclick={ctx.link().callback(|_| Msg::SwitchTab(UsersTab::Students))}>{ "Schüler" }</a>
|
|
</li>
|
|
<li class={classes!(if self.tab == UsersTab::Teachers { Some("is-active") } else { None })}>
|
|
<a onclick={ctx.link().callback(|_| Msg::SwitchTab(UsersTab::Teachers))}>{ "Lehrer" }</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
if self.fetching {
|
|
<components::fetching::Fetching />
|
|
} else {
|
|
<div>
|
|
{
|
|
match self.tab {
|
|
UsersTab::All => html! {
|
|
<table class={classes!("table")}>
|
|
<thead>
|
|
<tr>
|
|
<th><abbr title="ID des Benutzers in der Datenbank / API">{ "ID" }</abbr></th>
|
|
<th>{ "Nachname" }</th>
|
|
<th>{ "Vorname" }</th>
|
|
<th>{ "Benutzername" }</th>
|
|
<th>{ "Rolle" }</th>
|
|
<th><abbr title="ID des externen Benutzerobjekts">{ "Externe Rollen-ID" }</abbr></th>
|
|
<th>{ "Admin" }</th>
|
|
<th><abbr title="Wenn Schüler, dann ob Lehrer gewählt wurde">{ "Gewählt" }</abbr></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{
|
|
for self.students.as_ref().unwrap().iter().map(|s| html! {
|
|
<tr>
|
|
<td><code>{ &s.user.id }</code></td>
|
|
<td>{ &s.user.last_name }</td>
|
|
<td>{ &s.user.first_name }</td>
|
|
<td><code>{ &s.user.username }</code></td>
|
|
|
|
<td>
|
|
<code>
|
|
{
|
|
match &s.user.role {
|
|
graphql::queries::users_by_role::students::UserRole::Student => "S",
|
|
graphql::queries::users_by_role::students::UserRole::Teacher => "T",
|
|
graphql::queries::users_by_role::students::UserRole::Other(_) => "N/A",
|
|
}
|
|
}
|
|
</code>
|
|
</td>
|
|
<td><code>{ &s.id }</code></td>
|
|
<td><code>{ if s.user.admin { 1 } else { 0 } }</code></td>
|
|
<td><code>{ if s.vote.is_some() { 1 } else { 0 } }</code></td>
|
|
</tr>
|
|
})
|
|
}
|
|
{
|
|
for self.teachers.as_ref().unwrap().iter().map(|t| html! {
|
|
<tr>
|
|
<td><code>{ &t.user.id }</code></td>
|
|
<td>{ &t.user.last_name }</td>
|
|
<td>{ &t.user.first_name }</td>
|
|
<td><code>{ &t.user.username }</code></td>
|
|
<td>
|
|
<code>
|
|
{
|
|
match &t.user.role {
|
|
graphql::queries::users_by_role::teachers::UserRole::Student => "S",
|
|
graphql::queries::users_by_role::teachers::UserRole::Teacher => "T",
|
|
graphql::queries::users_by_role::teachers::UserRole::Other(_) => "N/A",
|
|
}
|
|
}
|
|
</code>
|
|
</td>
|
|
<td><code>{ &t.id }</code></td>
|
|
<td><code>{ if t.user.admin { 1 } else { 0 } }</code></td>
|
|
<td><code>{ "N/A" }</code></td>
|
|
</tr>
|
|
})
|
|
}
|
|
</tbody>
|
|
</table>
|
|
},
|
|
UsersTab::Students => html! {
|
|
<table class={classes!("table")}>
|
|
<thead>
|
|
<tr>
|
|
<th><abbr title="ID des Schülers in der Datenbank / API">{ "ID" }</abbr></th>
|
|
<th>{ "Nachname" }</th>
|
|
<th>{ "Vorname" }</th>
|
|
<th>{ "Benutzername" }</th>
|
|
<th>{ "Benutzer-ID" }</th>
|
|
<th>{ "Admin" }</th>
|
|
<th>{ "Gewählt" }</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{
|
|
for self.students.as_ref().unwrap().iter().map(|s| html! {
|
|
<tr>
|
|
<td><code>{ &s.id }</code></td>
|
|
<td>{ &s.user.last_name }</td>
|
|
<td>{ &s.user.first_name }</td>
|
|
<td><code>{ &s.user.username }</code></td>
|
|
<td><code>{ &s.user.id }</code></td>
|
|
<td><code>{ if s.user.admin { 1 } else { 0 } }</code></td>
|
|
<td><code>{ if s.vote.is_some() { 1 } else { 0 } }</code></td>
|
|
</tr>
|
|
})
|
|
}
|
|
</tbody>
|
|
</table>
|
|
},
|
|
UsersTab::Teachers => html! {
|
|
<table class={classes!("table")}>
|
|
<thead>
|
|
<tr>
|
|
<th><abbr title="ID des Lehrers in der Datenbank / API">{ "ID" }</abbr></th>
|
|
<th>{ "Nachname" }</th>
|
|
<th>{ "Vorname" }</th>
|
|
<th>{ "Benutzername" }</th>
|
|
<th>{ "Email" }</th>
|
|
<th>{ "Benutzer-ID" }</th>
|
|
<th>{ "Admin" }</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{
|
|
for self.teachers.as_ref().unwrap().iter().map(|t| html! {
|
|
<tr>
|
|
<td><code>{ &t.id }</code></td>
|
|
<td>{ &t.user.last_name }</td>
|
|
<td>{ &t.user.first_name }</td>
|
|
<td><code>{ &t.user.username }</code></td>
|
|
<td>
|
|
<code>
|
|
{
|
|
match &t.user.role {
|
|
graphql::queries::users_by_role::teachers::UserRole::Student => "S",
|
|
graphql::queries::users_by_role::teachers::UserRole::Teacher => "T",
|
|
graphql::queries::users_by_role::teachers::UserRole::Other(_) => "N/A",
|
|
}
|
|
}
|
|
</code>
|
|
</td>
|
|
<td><code>{ &t.user.id }</code></td>
|
|
<td><code>{ if t.user.admin { 1 } else { 0 } }</code></td>
|
|
</tr>
|
|
})
|
|
}
|
|
</tbody>
|
|
</table>
|
|
},
|
|
}
|
|
}
|
|
|
|
<button onclick={ctx.link().callback(|_| Msg::OpenModal)}
|
|
class={classes!("button", "is-success", "is-fullwidth")}
|
|
>
|
|
<span class={classes!("icon")}>
|
|
<i class={classes!("fas", "fa-user-plus")} />
|
|
</span>
|
|
<span>{ "Neuer Benutzer" }</span>
|
|
</button>
|
|
|
|
<new_user_modal::NewUserModal close={ctx.link().callback(|_| Msg::CloseModal)}
|
|
active={self.modal_active}
|
|
/>
|
|
</div>
|
|
|
|
<components::graphql_errors::GraphQLErrors errors={self.errors.to_owned()} />
|
|
}
|
|
</fieldset>
|
|
}
|
|
}
|
|
}
|