flams_router_dashboard/
query.rs

1use flams_web_utils::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_system::backend::GlobalBackend;
16    use flams_system::backend::rdf::QueryResult;
17    tracing::info!("Query: {query}");
18    let r = tokio::task::spawn_blocking(move || {
19        GlobalBackend::get()
20            .triple_store()
21            .query_str(&query)
22            .map(QueryResult::into_json)
23    })
24    .await; //.in_current_span().await;
25    match r {
26        Ok(Ok(Ok(r))) => Ok(r),
27        Ok(Ok(Err(e)) | Err(e)) => Err(ServerFnError::WrappedServerError(e.to_string())),
28        Err(e) => Err(ServerFnError::WrappedServerError(e.to_string())),
29    }
30}
31
32const QUERY: &str = r"SELECT ?x ?y WHERE {
33  ?x rdf:type ulo:declaration .
34  ?y rdf:type ulo:notation .
35  ?y ulo:notation-for ?x.
36}";
37
38#[component]
39pub fn Query() -> impl IntoView {
40    use leptos::form::ActionForm;
41    inject_css("flams-query", include_str!("query.css"));
42
43    let action = ServerAction::<QueryApi>::new();
44    let rf = NodeRef::<leptos::html::Div>::new();
45    let result = Memo::new(move |_| {
46        action.value().get().map(|result| match result {
47            Ok(r) => r,
48            Err(e) => format!("Error: {e}"),
49        })
50    });
51
52    view! {
53      <div>
54        <h1>Query</h1>
55        <ActionForm action>
56            <span class="flams-query-container">
57                <textarea name="query" class="flams-query-inner">{QUERY.to_string()}</textarea>
58            </span>
59            <br/><input type="submit" value="Query"/>
60        </ActionForm>
61        <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;">
62            {move || result.get().unwrap_or_default()}
63        </div>
64      </div>
65    }
66}