// file: crates/ksp-app-config-desk/frontend/ts/main.ts // version: 6 import "bootstrap"; import ResizeObserver from "resize-observer-polyfill"; import "simplebar"; import { getCurrentWindow } from "@tauri-apps/api/window"; import type { AppSnapshotDto } from "./bindings/ksp_app_config_desk/dto_common/AppSnapshotDto.ts"; import { frontendDebug, frontendInfo, frontendTrace, installFrontendConsoleBridge } from "./frontend_log"; import { initializeDocumentsPanel } from "./documents"; import { initializeEnvironmentPanel } from "./environment"; import { initializeProfilesPanel } from "./profiles"; import { invokeKsp } from "./invoke"; (window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver; installFrontendConsoleBridge("main"); type ViewId = "overview" | "documents" | "profiles" | "environment" | "logging"; const viewCopy: Record = { overview: { title: "Vue d'ensemble", description: "État sûr du bootstrap Config Desk et du runtime Logging actuellement actif.", }, documents: { title: "Documents", description: "Inventaire, diagnostics et réparation validée des documents Config enregistrés.", }, profiles: { title: "Profils", description: "Sélection default/explicite, vues global/profil/effective sûre et provenance Config.", }, environment: { title: "Environnement / .env", description: "Rapport sûr desired/effective/source/shadow des variables KSP/KSPB ; mutations .env prévues en pre.012.", }, logging: { title: "Logging", description: "Édition des profils et hot reload du runtime Logging — surfaces fonctionnelles prévues en pre.014 à pre.017.", }, }; function isViewId(value: string): value is ViewId { return Object.prototype.hasOwnProperty.call(viewCopy, value); } function activateView(viewId: ViewId, source: "startup" | "user"): void { if (source === "user") { frontendDebug("main", "Main navigation activated", { viewId }); } const copy = viewCopy[viewId]; const title = document.querySelector("#viewTitle"); const headerTitle = document.querySelector("#headerViewTitle"); const description = document.querySelector("#viewDescription"); if (title) { title.textContent = copy.title; } if (headerTitle) { headerTitle.textContent = copy.title; } document.title = `Config Desk — ${copy.title}`; if (description) { description.textContent = copy.description; } document.querySelectorAll("[data-view]").forEach(button => { const active = button.dataset.view === viewId; button.classList.toggle("active", active); button.setAttribute("aria-current", active ? "page" : "false"); }); frontendTrace("main", "Main navigation tab state changed", { viewId, source }); const overview = document.querySelector("#overviewPanel"); if (overview) { overview.hidden = viewId !== "overview"; } const documents = document.querySelector("#documentsPanel"); if (documents) { documents.hidden = viewId !== "documents"; } const profiles = document.querySelector("#profilesPanel"); if (profiles) { profiles.hidden = viewId !== "profiles"; } const environment = document.querySelector("#environmentPanel"); if (environment) { environment.hidden = viewId !== "environment"; } const placeholder = document.querySelector("#placeholderPanel"); if (placeholder) { placeholder.hidden = viewId !== "logging"; } frontendTrace("main", "Main view DOM updated", { viewId, source }); } function bindNavigation(): void { document.querySelectorAll("[data-view]").forEach(button => { button.addEventListener("click", () => { const requestedView = button.dataset.view; frontendTrace("main", "Main navigation tab clicked", { requestedView: requestedView ?? null }); if (requestedView && isViewId(requestedView)) { activateView(requestedView, "user"); } }); }); frontendTrace("main", "Main navigation handlers installed"); } function renderSnapshot(snapshot: AppSnapshotDto): void { const version = document.querySelector("#overviewVersion"); const documents = document.querySelector("#overviewDocuments"); const profile = document.querySelector("#overviewLoggingProfile"); const generation = document.querySelector("#overviewLoggingGeneration"); const fallback = document.querySelector("#overviewLoggingFallback"); if (version) { version.textContent = snapshot.applicationVersion; } if (documents) { documents.textContent = snapshot.configDocumentCount.toString(); } if (profile) { profile.textContent = snapshot.activeLoggingProfile ?? "fallback transitoire"; } if (generation) { generation.textContent = snapshot.loggingGeneration.toString(); } if (fallback) { fallback.textContent = snapshot.fallbackLoggingActive ? "oui" : "non"; } frontendTrace("main", "Application snapshot rendered", { loggingGeneration: snapshot.loggingGeneration, fallbackLoggingActive: snapshot.fallbackLoggingActive, }); } async function loadSnapshot(): Promise { const status = document.querySelector("#shellStatus"); const snapshot = await invokeKsp("main", "get_app_snapshot"); renderSnapshot(snapshot); if (status) { status.textContent = "Shell principal prêt."; } frontendTrace("main", "Main shell status replaced", { status: "ready" }); } async function initializeMain(): Promise { const windowLabel = getCurrentWindow().label; frontendInfo("main", "Config Desk main frontend loaded", { windowLabel }); bindNavigation(); initializeDocumentsPanel(); initializeProfilesPanel(); initializeEnvironmentPanel(); activateView("overview", "startup"); try { await loadSnapshot(); } catch { const status = document.querySelector("#shellStatus"); if (status) { status.textContent = "Le snapshot initial n'a pas pu être chargé."; } frontendTrace("main", "Main shell status replaced", { status: "snapshot_error" }); } } document.addEventListener("DOMContentLoaded", () => { void initializeMain(); });