flams_router_dashboard/
query.rs

1use ftml_dom::utils::css::inject_css;
2use leptos::prelude::*;
3
4#[server(QueryApi,
5  prefix="/api/backend",
6  endpoint="query",
7  input=server_fn::codec::PostUrl,
8  output=server_fn::codec::Json
9)]
10#[cfg_attr(
11    feature = "ssr",
12    tracing::instrument(level = "info", name = "query", target = "query", skip_all)
13)]
14pub async fn query_api(query: String) -> Result<String, ServerFnError<String>> {
15    use flams_math_archives::backend::GlobalBackend;
16    use flams_math_archives::triple_store::sparql::QueryResult;
17    use flams_system::TokioEngine;
18    tracing::info!("Query: {query}");
19    let r = tokio::task::spawn_blocking(move || {
20        GlobalBackend
21            .triple_store()
22            .query_str::<TokioEngine>(&query)
23            .map(QueryResult::into_json)
24    })
25    .await; //.in_current_span().await;
26    match r {
27        Ok(Ok(Ok(r))) => Ok(r),
28        Ok(Ok(Err(e))) => Err(ServerFnError::WrappedServerError(e.to_string())),
29        Ok(Err(e)) => Err(ServerFnError::WrappedServerError(e.to_string())),
30        Err(e) => Err(ServerFnError::WrappedServerError(e.to_string())),
31    }
32}
33
34const QUERY: &str = r"SELECT ?x ?y WHERE {
35  ?x rdf:type ulo:declaration .
36  ?y rdf:type ulo:notation .
37  ?y ulo:notation-for ?x.
38}";
39
40#[component]
41pub fn Query() -> impl IntoView {
42    use leptos::form::ActionForm;
43    use thaw::Checkbox;
44    inject_css("flams-query", include_str!("query.css"));
45
46    let action = ServerAction::<QueryApi>::new();
47    let rf = NodeRef::<leptos::html::Div>::new();
48    let pretty_print = RwSignal::new(false);
49    let result = Memo::new(move |_| {
50        action.value().get().map(|result| match result {
51            Ok(r) => {
52                if pretty_print.get() {
53                    serde_json::from_str::<serde_json::Value>(&r)
54                        .map_or_else(|e| format!("Error: {e}"), |v| format!("{v:#}"))
55                } else {
56                    r
57                }
58            }
59            Err(e) => format!("Error: {e}"),
60        })
61    });
62
63    view! {
64      <div>
65        <h1>Query</h1>
66        <ActionForm action>
67            <span class="flams-query-container">
68                <textarea name="query" class="flams-query-inner">{QUERY.to_string()}</textarea>
69            </span>
70            <br/><input type="submit" value="Query"/>
71        </ActionForm>
72        <Checkbox checked=pretty_print label="pretty printed"/>
73        <div node_ref=rf style="text-align:left;margin:10px;font-family:monospace;white-space:pre;border:var(--strokeWidthThickest) solid var(--colorNeutralStroke1);text-wrap:pretty;">
74            {move || result.get().unwrap_or_default()}
75        </div>
76      </div>
77    }
78}