MHRN-Space / src /dashboard /static /box-state-controller.js
ThomasHeisig's picture
Sync GitHub main 4645f4137666463023fa501984a14336dd2fc666 (part 11)
31226fd verified
Raw History Blame Contribute Delete
6.65 kB
/* Compact reusable panel controls. Workspace routing lives in frontend/workspace-router.js. */
"use strict";
const STORAGE_KEY="brain5d-box-states";
const BOX_SELECTOR=[".card",".panel",".control-card",".overview-surface",".snapshot-info-card",".workspace-tile",".wesen-card",".wesen-stage-card",".wesen-console",".wesen-symbiosis-card",".experiment-workflow",".release-view-panel",".gate-section",".connection-manager",".embodiment-system-strip",".embodiment-loop",".research-focus-rail",".research-catalog-selector",".research-contract-card",".experiment-library-card",".human-review-card",".rq-proposal-card",".research-review-inbox",".mhrn-area-map",".mhrn-science-transparency",".mhrn-scientific-metrics"].join(",");
const EXCLUDED_SELECTOR=[".site-footer",".workspace-header",".overview-command-bar",".dashboard-generated-header",".dashboard-utility-bar",".experience-ribbon",".experience-welcome",".research-chat-modal",".mhrn-context-nav","dialog","[hidden]"].join(",");
const HEADER_SELECTOR=[":scope > .panel-title",":scope > .overview-surface-title",":scope > .control-card__header",":scope > .console-header",":scope > .experiment-workflow-header",":scope > .gate-header",":scope > .release-header",":scope > header"].join(",");
let states={},queued=false;
function load(){try{states=JSON.parse(localStorage.getItem(STORAGE_KEY)||"{}");}catch(_){states={};}}
function save(){try{localStorage.setItem(STORAGE_KEY,JSON.stringify(states));}catch(_) {}}
function key(box,index){return box.id||`${box.closest(".tab-content")?.id||"dashboard"}:${box.querySelector("h2,h3,h4")?.textContent?.trim()||box.className}:${index}`;}
function header(box){let h=box.querySelector(HEADER_SELECTOR);if(h)return h;h=document.createElement("div");h.className="box-state-generated-header";const title=document.createElement("strong");title.textContent=box.getAttribute("aria-label")||box.querySelector(":scope > h2,:scope > h3,:scope > h4")?.textContent?.trim()||"Panel";h.append(title);box.prepend(h);return h;}
function button(label,icon,state,action){const b=document.createElement("button");b.type="button";b.className="box-state-button";if(state)b.dataset.boxState=state;if(action)b.dataset.boxAction=action;b.setAttribute("aria-label",label);b.title=label;b.textContent=icon;return b;}
function release(except){document.querySelectorAll(".box-state-maximized").forEach(box=>{if(box!==except){box.classList.remove("box-state-maximized");box.dataset.boxState=states[box.dataset.boxKey]||"standard";}});if(!document.querySelector(".box-state-maximized"))document.body.classList.remove("box-state-lock");}
function setState(box,k,state,persist=true){const next=["minimized","maximized"].includes(state)?state:"standard";if(next==="maximized")release(box);box.dataset.boxState=next;box.classList.toggle("box-state-minimized",next==="minimized");box.classList.toggle("box-state-maximized",next==="maximized");document.body.classList.toggle("box-state-lock",Boolean(document.querySelector(".box-state-maximized")));if(persist&&next!=="maximized"){states[k]=next;save();}box.querySelectorAll(":scope > .box-state-header .box-state-button[data-box-state]").forEach(b=>b.setAttribute("aria-pressed",String(b.dataset.boxState===next)));}
function infoText(box){return box.dataset.panelInfo||box.querySelector(":scope > header p,:scope > p,.panel-subtitle")?.textContent?.trim()||`${box.getAttribute("aria-label")||box.querySelector("h2,h3,h4")?.textContent?.trim()||"Panel"}: Daten und Aktionen verwenden die vorhandenen MHRN-Backend-Verträge.`;}
function toggleInfo(box,b){let p=box.querySelector(":scope > .box-info-popover");if(!p){p=document.createElement("aside");p.className="box-info-popover";p.hidden=true;p.innerHTML="<strong>Über dieses Element</strong><p></p><small>Darstellungssteuerung verändert keine wissenschaftlichen Daten.</small>";p.querySelector("p").textContent=infoText(box);box.append(p);}const open=p.hidden;document.querySelectorAll(".box-info-popover:not([hidden])").forEach(n=>{if(n!==p)n.hidden=true;});p.hidden=!open;b.setAttribute("aria-pressed",String(open));}
async function fullscreen(box,b){try{if(document.fullscreenElement===box)await document.exitFullscreen();else if(box.requestFullscreen)await box.requestFullscreen();else box.classList.toggle("box-state-native-fullscreen");}catch(_){box.classList.toggle("box-state-native-fullscreen");}b.setAttribute("aria-pressed",String(document.fullscreenElement===box||box.classList.contains("box-state-native-fullscreen")));}
function enhance(box,index){if(box.classList.contains("box-state-ready")||box.matches(EXCLUDED_SELECTOR)||box.parentElement?.closest(BOX_SELECTOR))return;const h=header(box),k=key(box,index),tools=document.createElement("div");tools.className="box-state-tools";tools.setAttribute("aria-label","Paneldarstellung");tools.append(button("Minimieren","−","minimized"),button("Standardgröße","□","standard"),button("Maximieren","▣","maximized"),button("Vollbild","⛶",null,"fullscreen"),button("Information","?",null,"info"));tools.onclick=e=>{const b=e.target.closest(".box-state-button");if(!b)return;e.preventDefault();e.stopPropagation();if(b.dataset.boxState)setState(box,k,b.dataset.boxState);else if(b.dataset.boxAction==="fullscreen")void fullscreen(box,b);else if(b.dataset.boxAction==="info")toggleInfo(box,b);};h.classList.add("box-state-header");h.append(tools);[...box.children].forEach(c=>{if(c!==h&&!c.classList.contains("box-info-popover"))c.classList.add("box-state-content");});box.dataset.boxKey=k;box.classList.add("box-state-ready");setState(box,k,states[k]||"standard",false);}
function hover(){document.querySelectorAll("button,a,summary,input,select,textarea,[role='button'],[role='tab'],[data-detail-key]").forEach(el=>{if(el.title)return;const text=(el.getAttribute("aria-label")||el.textContent||el.placeholder||"").trim().replace(/\s+/g," ");if(text)el.title=text.slice(0,220);});}
function scan(){queued=false;let i=0;document.querySelectorAll(`.tab-content ${BOX_SELECTOR}`).forEach(box=>enhance(box,i++));hover();}
function queue(){if(queued)return;queued=true;requestAnimationFrame(scan);}
export function initBoxStates(){load();scan();document.addEventListener("keydown",e=>{if(e.key!=="Escape")return;if(document.fullscreenElement){void document.exitFullscreen();return;}const box=document.querySelector(".box-state-maximized");if(box)setState(box,box.dataset.boxKey,states[box.dataset.boxKey]||"standard",false);document.querySelectorAll(".box-info-popover:not([hidden])").forEach(n=>n.hidden=true);});new MutationObserver(queue).observe(document.querySelector("main")||document.body,{childList:true,subtree:true});}