Brain-5D-Space / src /dashboard /static /console-log.js
github-actions[bot]
Sync: publish Space API fix
5e0b58b
Raw History Blame Contribute Delete
6.81 kB
/**
* Brain-5D Dashboard — Console Log (pure output component)
*
* This module provides only the console log output. It does not send
* control commands; it only displays command results and system events.
*
* The dashboard shell, operator experience, real-body embodiment view and
* Wesen workspace are imported for presentation/read-only side effects.
*
* @version 1.4.6
* @license MIT
*/
"use strict";
import "./dashboard-shell.js";
import "./dashboard-experience.js";
import "./embodiment-self-model.js";
import "./wesen.js";
import "./wesen-organism-v2.js";
import "./wesen-anatomy-v3.js";
import "./wesen-neural-symbiosis.js";
import "./neuron-model-viewer.js";
import "./frontend-architecture.js";
import "./footer-controller.js";
const CANONICAL_WESEN_STYLES = Object.freeze([
"/wesen.css",
"/wesen-adaptive.css",
"/wesen-organism.css",
"/wesen-anatomy-v3.css",
"/wesen-neural-symbiosis.css",
]);
function byId(id) {
return document.getElementById(id);
}
function escapeHtml(str) {
if (!str) return "";
const div = document.createElement("div");
div.textContent = String(str);
return div.innerHTML;
}
function formatTime(date = new Date()) {
return date.toLocaleTimeString("en-US", { hour12: false });
}
function ensureWesenStylesheet() {
return CANONICAL_WESEN_STYLES;
}
function activateLegacyWorkspace(name) {
const button = document.querySelector(`.tab-btn[data-tab="${name}"]`);
if (button) {
button.click();
return;
}
document.querySelectorAll(".tab-btn[data-tab]").forEach((item) => item.classList.remove("active"));
document.querySelectorAll(".tab-content[id^='tab-']").forEach((tab) => {
const active = tab.id === `tab-${name}`;
tab.classList.toggle("active", active);
tab.hidden = !active;
});
document.body.dataset.currentTab = name;
document.body.dataset.experienceWorkspace = name;
}
function adaptDashboardNavigation() {
// Keep legacy route buttons in the DOM so app.js remains the sole lifecycle
// owner and can lazy-initialize Network/Release/Settings when contextual
// navigation activates them. The three-area shell hides the legacy nav.
for (const name of ["network", "gate"]) {
const button = document.querySelector(`.tab-btn[data-tab="${name}"]`);
if (button) {
button.classList.add("wesen-utility-hidden");
button.setAttribute("aria-hidden", "true");
button.tabIndex = -1;
}
}
document.querySelectorAll('.experience-command-item[data-command-id="workspace:network"], .experience-command-item[data-command-id="workspace:gate"]').forEach((node) => node.remove());
document.querySelectorAll('[data-jump-workspace="network"]').forEach((node) => {
node.dataset.jumpWorkspace = "wesen";
const strong = node.querySelector("strong");
const small = node.querySelector("small");
if (strong) strong.textContent = "Wesen beobachten";
if (small) small.textContent = "Körper, Zustände, Rückkopplung";
});
document.querySelectorAll('[data-jump-workspace="gate"]').forEach((node) => node.remove());
const bodyShortcut = document.querySelector('[data-overview-tab="embodiment"]');
if (bodyShortcut) {
bodyShortcut.dataset.overviewTab = "wesen";
bodyShortcut.textContent = "◉ Wesen öffnen";
}
}
function ensureReleaseFooterButton() {
const footer = document.querySelector(".site-footer");
if (!footer || footer.querySelector(".footer-tools, [data-footer-release]")) return;
const target = byId("footer-status") || footer.lastElementChild || footer;
const button = document.createElement("button");
button.type = "button";
button.className = "wesen-release-button";
button.dataset.footerRelease = "true";
button.textContent = "Release";
button.title = "Scientific Gate und Release Readiness öffnen";
button.addEventListener("click", () => activateLegacyWorkspace("gate"));
target.appendChild(button);
}
function simplifyEmbodimentCopy() {
const tab = byId("tab-embodiment");
if (!tab || tab.querySelector("[data-simple-embodiment-note]")) return;
const header = tab.querySelector(".workspace-header, .dashboard-generated-header");
if (header) {
const title = header.querySelector("h2");
const paragraph = header.querySelector("p");
if (title) title.textContent = "Embodiment";
if (paragraph) paragraph.textContent = "Reale Sensoren, Geräte, Aktoren und Körpergrenzen konfigurieren und beobachten.";
}
const note = document.createElement("div");
note.dataset.simpleEmbodimentNote = "true";
note.className = "dashboard-utility-bar";
note.innerHTML = '<span class="dashboard-utility-context">Embodiment bleibt die einfache technische Schnittstellen-Seite. Die adaptive Echtzeitdarstellung befindet sich unter <strong>Wesen</strong>.</span>';
header?.insertAdjacentElement("afterend", note);
}
function initWesenShellIntegration() {
ensureWesenStylesheet();
adaptDashboardNavigation();
ensureReleaseFooterButton();
simplifyEmbodimentCopy();
requestAnimationFrame(() => adaptDashboardNavigation());
}
ensureWesenStylesheet();
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initWesenShellIntegration, { once: true });
} else {
initWesenShellIntegration();
}
/**
* Console log output controller.
*/
export class ConsoleLog {
constructor(containerId, options = {}) {
this.container = byId(containerId);
this.entries = [];
this.maxEntries = options.maxEntries || 1000;
this.autoScroll = options.autoScroll !== false;
}
/**
* Log a message.
* @param {string} message
* @param {string} type - 'info', 'success', 'error', 'warning', 'debug'
*/
log(message, type = "info") {
const entry = {
timestamp: new Date(),
message: String(message),
type,
};
this.entries.push(entry);
if (this.entries.length > this.maxEntries) {
this.entries.shift();
}
this.render(entry);
}
/**
* Render a single entry.
* @param {object} entry
*/
render(entry) {
if (!this.container) return;
const div = document.createElement("div");
div.className = `log-entry log-${entry.type}`;
div.innerHTML = `<span class="log-time">[${formatTime(entry.timestamp)}]</span> ${escapeHtml(entry.message)}`;
this.container.appendChild(div);
if (this.autoScroll) {
this.container.scrollTop = this.container.scrollHeight;
}
while (this.container.children.length > this.maxEntries) {
this.container.removeChild(this.container.firstChild);
}
}
/** Clear the log. */
clear() {
if (this.container) this.container.innerHTML = "";
this.entries = [];
}
/** Get all entries. */
getEntries() {
return [...this.entries];
}
}
export const consoleLog = new ConsoleLog("console-output");