Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger-ui

src/pages/front_certs.rs

//! Admin → **Certificates** (owner 2026-10-25): this front's certificates as the front says
//! them, and "try now" where it allows it. Every decision is in [`crate::front_certs`].

use leptos::prelude::*;

use crate::components::feedback::{ErrorText, Loading};
use crate::front_certs::{button, read, try_body, Cert, CERTS_PATH, TRY_PATH};

/// The Certificates pane.
#[component]
pub fn CertsPane(generation: RwSignal<u32>) -> impl IntoView {
    let certs = LocalResource::new(move || {
        let _ = generation.get();
        async move {
            let (status, body) = crate::session::door(CERTS_PATH, None).await?;
            read(status, &body)
        }
    });
    let said = RwSignal::new(None::<String>);
    let press = move |c: Cert| {
        leptos::task::spawn_local(async move {
            let words = match crate::session::door(TRY_PATH, Some(&try_body(&c))).await {
                Ok((200, body)) => serde_json::from_str::<serde_json::Value>(&body).ok().and_then(|v| v["words"].as_str().map(str::to_string)).unwrap_or(body),
                Ok((_, body)) => body,
                Err(e) => e,
            };
            said.set(Some(words));
            generation.update(|g| *g += 1);
        });
    };
    view! {
        <div>
            {move || said.get().map(|w| view! { <p class="count" role="status">{w}</p> })}
            {move || match certs.get() {
                None => view! { <Loading what="the certificates"/> }.into_any(),
                Some(Err(e)) => view! { <ErrorText context="certificates" message=e/> }.into_any(),
                Some(Ok(c)) if c.certificates.is_empty() => view! { <p class="count">"No certificate is known to this front yet."</p> }.into_any(),
                Some(Ok(c)) => view! {
                    <div>
                        {c.certificates.into_iter().map(|cert| {
                            let (may, why) = button(&cert);
                            let shown = cert.clone();
                            view! {
                                <section class="card">
                                    <h3 class="mono">{cert.host.clone()}</h3>
                                    {cert.alert.clone().map(|a| view! { <p class="bad" role="alert">{a}</p> })}
                                    <pre class="mono">{cert.lines.join("\n")}</pre>
                                    <button title=why disabled=!may on:click=move |_| press(shown.clone())>"Try now"</button>
                                </section>
                            }
                        }).collect_view()}
                    </div>
                }.into_any(),
            }}
        </div>
    }
}