tawasuyu

tawasuyu/brahman

Rust 492TOML 194Markdown 53JSON 176939 Definiciones

gioser-web: integrate gioser-graph-web widget below page content

- Add gioser-graph-web dependency to gioser-web
- After markdown loads, mount SVG semantic graph below content
- Graph fetches from api.gioser.net/graph endpoint
- Uses Qdrant k-NN edges, colored by camino
- Callback navigation placeholder (will be wired in next commit)

cb5d83b1f7b4510452c1b72a34282b6aa567300d · por Sergio · (hace 5 meses) · padre 38e95e062 · ver el árbol en este commit

Delta semántico · 2

crates/apps/gioser-web/src/lib.rs

2 archivos · +62 −1

diff --git a/crates/apps/gioser-web/Cargo.toml b/crates/apps/gioser-web/Cargo.toml
index c9d0cf6..d537ae2 100644
--- a/crates/apps/gioser-web/Cargo.toml
+++ b/crates/apps/gioser-web/Cargo.toml
@@ -14,6 +14,7 @@ gioser-canvas-web = { path = "../../modules/gioser/gioser-canvas-web" }
 fana-md-reader-web = { path = "../../modules/fana/fana-md-reader-web" }
 revista-web = { path = "../../modules/revista/revista-web" }
 barra-web = { path = "../../modules/barra/barra-web" }
+gioser-graph-web = { path = "../../modules/gioser/gioser-graph-web" }
 wasm-bindgen.workspace = true
 wasm-bindgen-futures.workspace = true
 js-sys.workspace = true
diff --git a/crates/apps/gioser-web/src/lib.rs b/crates/apps/gioser-web/src/lib.rs
index 9a22053..8382c01 100644
--- a/crates/apps/gioser-web/src/lib.rs
+++ b/crates/apps/gioser-web/src/lib.rs
@@ -21,6 +21,7 @@ use std::rc::Rc;
 
 use barra_web::{Task, TaskList};
 use gioser_canvas_web::{tips, Renderer};
+use gioser_graph_web::GraphWidget;
 use fana_md_reader_web::Reader;
 use revista_web::Deck;
 use wasm_bindgen::prelude::*;
@@ -272,13 +273,53 @@ impl AppState {
         if inner.contains("pluma-doc") {
             return; // ya hidratado
         }
-        let reader = Reader::new(content);
+        let document_clone = self.document.clone();
         let element_owned = element.to_string();
         let url_owned = md_url.to_string();
         wasm_bindgen_futures::spawn_local(async move {
+            let content_clone = content.clone();
             if let Err(e) = reader.open_url(&url_owned, &element_owned).await {
                 web_sys::console::warn_1(&e);
             }
+            // Después de cargar el md, montar el grafo debajo
+            let graph_container_id = format!("graph-{}-container", element_owned);
+            // Si ya existe, no lo duplicamos
+            if document_clone.get_element_by_id(&graph_container_id).is_some() {
+                return;
+            }
+            // Crear contenedor debajo del content
+            let wrapper: HtmlElement = document_clone
+                .create_element("div")
+                .ok()
+                .and_then(|e| e.dyn_into::<HtmlElement>().ok())
+                .unwrap();
+            wrapper.set_id(&graph_container_id);
+            wrapper.style().set_property("margin-top", "1rem").ok();
+            wrapper.style().set_property("padding-top", "1rem").ok();
+            wrapper.style().set_property("border-top", "1px solid rgba(255,255,255,0.08)").ok();
+            // Label
+            let label: HtmlElement = document_clone
+                .create_element("div")
+                .ok()
+                .and_then(|e| e.dyn_into::<HtmlElement>().ok())
+                .unwrap();
+            label.set_inner_html(
+                "<span style=\"font-family: Inter, sans-serif; font-size: 0.75rem; \
+                 letter-spacing: 0.3em; text-transform: uppercase; color: rgba(232,234,245,0.45);\">
+                 · grafo semántico ·
+                 </span>"
+            );
+            wrapper.append_child(&label).ok();
+            content_clone.append_child(&wrapper).ok();
+            // Cargar el grafo
+            let mut graph = GraphWidget::new(
+                wrapper,
+                "https://api.gioser.net",
+                None, // callback simplificado por ahora
+            );
+            if let Err(e) = graph.load().await {
+                web_sys::console::warn_1(&format!("grafo: error al cargar: {:?}", e));
+            }
         });
     }
 
@@ -639,6 +680,25 @@ fn position_tips(document: &Document, canvas: &HtmlCanvasElement, renderer: &Ren
     }
 }
 
+/// Mapea un doc_id de Qdrant al nombre del elemento (aire/fuego/tierra/agua)
+/// y su ruta md. Los doc_ids se generan con uuid5 en el indexador, pero
+/// podemos inferir por el nombre del camino o del elemento.
+fn map_doc_id_to_element(doc_id: &str) -> (String, String) {
+    // Inferir del doc_id: contiene el nombre del elemento
+    let el = if doc_id.contains("aire") || doc_id.contains("logos") {
+        "aire"
+    } else if doc_id.contains("fuego") || doc_id.contains("nomos") {
+        "fuego"
+    } else if doc_id.contains("tierra") || doc_id.contains("kay") {
+        "tierra"
+    } else if doc_id.contains("agua") || doc_id.contains("uku") {
+        "agua"
+    } else {
+        "aire"
+    };
+    (el.to_string(), format!("./md/{}.md", el))
+}
+
 fn install_panic_hook() {
     static SET: std::sync::Once = std::sync::Once::new();
     SET.call_once(|| {