File size: 3,583 Bytes
31226fd
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
"use strict";
import { apiGet } from "../core/api.js";
let refreshTimer = null;
function escapeHtml(v){const d=document.createElement("div");d.textContent=v==null?"":String(v);return d.innerHTML;}
function openFile(path){if(!path)return;document.dispatchEvent(new CustomEvent("brain5d:open-file",{detail:{source:"docs",path}}));window.MHRNWorkspaceArchitecture?.selectRoute?.("files","browse");}
function ensurePanel(){let p=document.getElementById("mhrn-docs-browser");const target=document.querySelector('#tab-research .research-subpanel[data-subpanel="registry"]')||document.getElementById("tab-research");if(!target)return null;if(p){if(p.parentElement!==target)target.appendChild(p);return p;}p=document.createElement("section");p.id="mhrn-docs-browser";p.className="mhrn-docs-browser card";p.dataset.panelInfo="Read-only Dokumentindex. Dateien werden ausschließlich im kanonischen File Viewer gerendert.";p.innerHTML=`<header><div><span class="workspace-kicker">DOCS API INDEX</span><h2>Dokumentindex</h2><p>Backend-Suche und Statistik; Darstellung ausschließlich im zentralen File Viewer.</p></div><span id="docs-count-badge">lade …</span></header><div class="docs-toolbar"><input type="search" id="docs-search-input" placeholder="Dokumente durchsuchen…"><button id="docs-search-btn">Suchen</button><button id="docs-refresh-btn">Aktualisieren</button></div><div class="docs-grid"><section><h3>Index / Treffer</h3><div id="docs-tree">lade …</div></section><section><h3>Statistik</h3><div id="docs-statistics">lade …</div></section></div>`;target.appendChild(p);p.querySelector("#docs-search-btn").onclick=search;p.querySelector("#docs-refresh-btn").onclick=load;p.querySelector("#docs-search-input").onkeydown=e=>{if(e.key==="Enter")search();};p.onclick=e=>{const b=e.target.closest("[data-doc-path]");if(b)openFile(b.dataset.docPath);};return p;}
function entries(payload){const list=Array.isArray(payload)?payload:(payload?.results||payload?.entries||payload?.tree||[]);return list.flatMap(x=>Array.isArray(x?.children)?[x,...x.children]:[x]).filter(x=>x&&x.path&&x.type!=="dir");}
function render(payload){const t=document.getElementById("docs-tree");if(!t)return;const list=entries(payload);t.innerHTML=list.length?list.slice(0,150).map(x=>`<button class="docs-index-row" data-doc-path="${escapeHtml(x.path)}"><strong>${escapeHtml(x.name||x.title||x.path.split("/").pop())}</strong><span>${escapeHtml(x.path)}</span></button>`).join(""):"<p>Keine Dokumente.</p>";const badge=document.getElementById("docs-count-badge");if(badge)badge.textContent=`${list.length} Einträge`;}
function stats(data){const t=document.getElementById("docs-statistics");if(t)t.innerHTML=Object.entries(data||{}).map(([k,v])=>`<div><span>${escapeHtml(k)}</span><strong>${escapeHtml(typeof v==="object"?JSON.stringify(v):v)}</strong></div>`).join("")||"Keine Statistik.";}
async function search(){const q=document.getElementById("docs-search-input")?.value.trim();if(!q)return loadTree();try{render(await apiGet(`/api/docs/search?q=${encodeURIComponent(q)}`));}catch(e){document.getElementById("docs-tree").textContent=`Fehler: ${e.message}`;}}
async function loadTree(){try{render(await apiGet("/api/docs/tree"));}catch(e){document.getElementById("docs-tree").textContent=`Fehler: ${e.message}`;}}
async function load(){const p=ensurePanel();if(!p||p.hidden)return;await Promise.allSettled([loadTree(),apiGet("/api/docs/statistics").then(stats)]);}
export function initDocsBrowser(){ensurePanel();load();if(refreshTimer)clearInterval(refreshTimer);refreshTimer=setInterval(load,30000);}