flams_router_login/
components.rs

1#![allow(clippy::must_use_candidate)]
2
3use flams_database::UserData;
4use flams_router_base::LoginState;
5use flams_web_utils::components::{Spinner, display_error};
6use leptos::{either::EitherOf4, prelude::*};
7
8#[component(transparent)]
9pub fn LoginProvider<Ch: IntoView + 'static>(children: TypedChildren<Ch>) -> impl IntoView {
10    let children = children.into_inner();
11    let res = Resource::new_blocking(
12        || (),
13        |()| async {
14            super::server_fns::login_state().await.unwrap_or_else(|e| {
15                leptos::logging::error!("Error getting login state: {e}");
16                LoginState::None
17            })
18        },
19    );
20    let sig = RwSignal::new(LoginState::Loading);
21    let _ = view! {<Suspense>{move || {res.get();}}</Suspense>};
22    let _ = Effect::new(move |_| {
23        if let Some(r) = res.get() {
24            sig.set(r);
25        }
26    });
27    provide_context(sig);
28    children()
29}
30
31#[component]
32pub fn Users() -> impl IntoView {
33    let r = Resource::new(|| (), |()| super::server_fns::get_users());
34    view! {<Suspense fallback = || view!(<Spinner/>)>{move ||
35      match r.get() {
36        Some(Ok(users)) if users.is_empty() => EitherOf4::A("(No users)"),
37        Some(Err(e)) => EitherOf4::B(
38          display_error(e.to_string().into())
39        ),
40        None => EitherOf4::C(view!(<Spinner/>)),
41        Some(Ok(users)) => EitherOf4::D(user_table(users))
42      }
43    }</Suspense>}
44}
45
46fn user_table(v: Vec<UserData>) -> impl IntoView {
47    use thaw::{
48        Button, ButtonSize, Table, TableBody, TableCell, TableCellLayout, TableHeader,
49        TableHeaderCell, TableRow,
50    };
51    view! {<Table>
52      <TableHeader><TableRow>
53        <TableHeaderCell>""</TableHeaderCell>
54        <TableHeaderCell>"Id"</TableHeaderCell>
55        <TableHeaderCell>"Username"</TableHeaderCell>
56        <TableHeaderCell>"Name"</TableHeaderCell>
57        <TableHeaderCell>"Email"</TableHeaderCell>
58        <TableHeaderCell>"Admin Access"</TableHeaderCell>
59      </TableRow></TableHeader>
60      <TableBody>{v.into_iter().map(|UserData {id,name,username,email,avatar_url,is_admin}| {
61        let is_admin = RwSignal::new(is_admin);
62        let a = ArcAction::new(move |()| async move {
63          let nv = !is_admin.get_untracked();
64          if super::server_fns::set_admin(id,nv).await.is_ok() {
65            is_admin.set(nv);
66          }
67        });
68        let f = move || {
69          let on_click = a.clone();
70          if is_admin.get() {
71            leptos::either::Either::Left(
72              view!{
73              "Yes "
74              <Button size=ButtonSize::Small on_click=move |_| {on_click.dispatch(());}>"Demote"</Button>
75              }
76          )
77          } else {
78            leptos::either::Either::Right(
79              view!{
80              "No "
81              <Button size=ButtonSize::Small on_click=move |_| {on_click.dispatch(());}>"Promote"</Button>
82              }
83          )
84          }
85        };
86        view! {<TableRow>
87          <TableCell><TableCellLayout><thaw::Avatar src=avatar_url /></TableCellLayout></TableCell>
88          <TableCell><TableCellLayout>{id}</TableCellLayout></TableCell>
89          <TableCell><TableCellLayout>{username}</TableCellLayout></TableCell>
90          <TableCell><TableCellLayout>{name}</TableCellLayout></TableCell>
91          <TableCell><TableCellLayout>{email}</TableCellLayout></TableCell>
92          <TableCell><TableCellLayout>{f}</TableCellLayout></TableCell>
93        </TableRow>}
94      }).collect_view()}</TableBody>
95    </Table>}
96}