Files
khadhroony-solana-project/crates/ksp-app-config-desk/frontend/ts/main.ts
2026-08-16 17:38:23 +02:00

172 lines
6.8 KiB
TypeScript

// file: crates/ksp-app-config-desk/frontend/ts/main.ts
// version: 10
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 { initializeLoggingPanel } from "./logging";
import { initializeProfilesPanel } from "./profiles";
import { invokeKsp } from "./invoke";
import { clearTransientSecretReveal } from "./secret_reveal";
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
installFrontendConsoleBridge("main");
type ViewId = "overview" | "documents" | "profiles" | "environment" | "logging";
const viewCopy: Record<ViewId, { title: string; description: string }> = {
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 et management atomique des variables .env KSP/KSPB.",
},
logging: {
title: "Logging",
description: "Édition typée et persistence atomique des profils, sinks et filtres Logging ; le hot reload runtime reste dans la tranche suivante.",
},
};
function isViewId(value: string): value is ViewId {
return Object.prototype.hasOwnProperty.call(viewCopy, value);
}
function activateView(viewId: ViewId, source: "startup" | "user"): void {
if (viewId !== "environment") {
clearTransientSecretReveal();
}
if (source === "user") {
frontendDebug("main", "Main navigation activated", { viewId });
}
const copy = viewCopy[viewId];
const title = document.querySelector<HTMLElement>("#viewTitle");
const headerTitle = document.querySelector<HTMLElement>("#headerViewTitle");
const description = document.querySelector<HTMLElement>("#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<HTMLButtonElement>("[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<HTMLElement>("#overviewPanel");
if (overview) {
overview.hidden = viewId !== "overview";
}
const documents = document.querySelector<HTMLElement>("#documentsPanel");
if (documents) {
documents.hidden = viewId !== "documents";
}
const profiles = document.querySelector<HTMLElement>("#profilesPanel");
if (profiles) {
profiles.hidden = viewId !== "profiles";
}
const environment = document.querySelector<HTMLElement>("#environmentPanel");
if (environment) {
environment.hidden = viewId !== "environment";
}
const logging = document.querySelector<HTMLElement>("#loggingPanel");
if (logging) {
logging.hidden = viewId !== "logging";
}
frontendTrace("main", "Main view DOM updated", { viewId, source });
}
function bindNavigation(): void {
document.querySelectorAll<HTMLButtonElement>("[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<HTMLElement>("#overviewVersion");
const documents = document.querySelector<HTMLElement>("#overviewDocuments");
const profile = document.querySelector<HTMLElement>("#overviewLoggingProfile");
const generation = document.querySelector<HTMLElement>("#overviewLoggingGeneration");
const fallback = document.querySelector<HTMLElement>("#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<void> {
const status = document.querySelector<HTMLElement>("#shellStatus");
const snapshot = await invokeKsp<AppSnapshotDto>("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<void> {
const windowLabel = getCurrentWindow().label;
frontendInfo("main", "Config Desk main frontend loaded", { windowLabel });
bindNavigation();
initializeDocumentsPanel();
initializeProfilesPanel();
initializeEnvironmentPanel();
initializeLoggingPanel();
activateView("overview", "startup");
try {
await loadSnapshot();
} catch {
const status = document.querySelector<HTMLElement>("#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();
});