pib-viewer 0.8.0

A viewer for public governmental data served over OParl
// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

use dioxus::{
    document,
    hooks::use_signal,
    html::FormData,
    prelude::{component, dioxus_elements, rsx},
    signals::WritableExt as _,
};
use dioxus_core::{Element, Event};
use oparl_types::{System, SystemUrl};
use tracing::{info, warn};
use url::Url;

use crate::route::{Route, UrlEncoded};

#[component]
pub fn ConnectDialog() -> Element {
    let mut oparl_system_url = use_signal(|| Option::<SystemUrl>::None);
    let mut oparl_system = use_signal(|| Option::<System>::None);
    let mut checking = use_signal(|| false);

    let read_input = move |event: Event<FormData>| async move {
        oparl_system_url.set(event.value().parse::<SystemUrl>().ok());
    };

    let check = move |_| async move {
        if checking() {
            return;
        }
        let Some(url) = oparl_system_url() else {
            return;
        };
        *checking.write() = true;
        let Ok(base_url) = document::eval("return document.URL;").await else {
            warn!("couldn't load base url.");
            *checking.write() = false;
            return;
        };
        let serde_json::Value::String(base_url) = base_url else {
            warn!("not a string value: {base_url}");
            *checking.write() = false;
            return;
        };
        info!("base url: {base_url:?}");
        let base_url = match base_url.parse::<Url>() {
            Ok(url) => url,
            Err(e) => {
                warn!("Couldn't parse base url {base_url}, reason: {e}");
                *checking.write() = false;
                return;
            }
        };
        let config = crate::client::get_page_config(base_url).await;
        warn!("CONFIG: {config:?}");
        let Ok(system) = reqwest::get(format!("{url}")).await else {
            warn!("couldn't fetch system from {url}");
            *checking.write() = false;
            return;
        };
        let json = match system.json::<serde_json::Value>().await {
            Ok(v) => v,
            Err(e) => {
                warn!("couldn't read json from contents of {url}: {e}");
                *checking.write() = false;
                return;
            }
        };
        match serde_json::from_value::<System>(json) {
            Ok(s) => {
                *oparl_system.write() = Some(s);
                *checking.write() = false;
            }
            Err(e) => {
                warn!("couldn't read json from contents of {url}: {e}");
                *checking.write() = false;
            }
        }
    };

    rsx! {
        p { "Please enter a valid URL to connect." }

        div {
            display: "flex",
            flex_direction: "column",
            gap: ".5rem",

            label {
                class: "label",
                for: "oparl_url",
                "URL"
            }

            input {
                class: "input",
                id: "oparl_url",
                type: "url",
                oninput: read_input
            }

            match (checking(), oparl_system_url(), oparl_system()) {
                (true, _, _) => {
                    rsx! {
                        "Checking…"
                    }
                }
                (false, Some(_), None) => {
                    rsx! {
                        div {
                            "✔️ Looks like a valid URL… "

                            button {
                                class: "button",
                                "data-style": "primary",
                                onclick: check,
                                disabled: oparl_system_url().is_none() || checking(),
                                "Check"
                            }
                        }
                    }
                }
                (false, Some(system_url), Some(_)) => {
                    rsx! {
                        "✔️ This is a valid system "

                        div {
                            dioxus_router::Link {
                                to: Route::OParlSystem {
                                    system_url: UrlEncoded::from(system_url),
                                },
                                "Go there…"
                            }
                        }
                    }
                }
                (false, None, _) => {
                    rsx! {
                        "❗ URL is invalid"
                    }
                }

            }
        }
    }
}