145 lines
6.0 KiB
TypeScript
145 lines
6.0 KiB
TypeScript
// file: crates/ksp-app-config-desk/frontend/ts/main.ts
|
|
// version: 13
|
|
|
|
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 { isViewId, registeredViewIds, viewRegistry, type ViewId } from "./shell_registry";
|
|
import { clearTransientSecretReveal } from "./secret_reveal";
|
|
|
|
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
|
|
installFrontendConsoleBridge("main");
|
|
|
|
function activateView(viewId: ViewId, source: "startup" | "user" | "registry"): void {
|
|
if (viewId !== "environment") {
|
|
clearTransientSecretReveal();
|
|
}
|
|
if (source !== "startup") {
|
|
frontendDebug("main", "Main navigation activated", { viewId, source });
|
|
}
|
|
const descriptor = viewRegistry[viewId];
|
|
const title = document.querySelector<HTMLElement>("#viewTitle");
|
|
const headerTitle = document.querySelector<HTMLElement>("#headerViewTitle");
|
|
const description = document.querySelector<HTMLElement>("#viewDescription");
|
|
if (title) {
|
|
title.textContent = descriptor.title;
|
|
}
|
|
if (headerTitle) {
|
|
headerTitle.textContent = descriptor.title;
|
|
}
|
|
document.title = `Config Desk — ${descriptor.title}`;
|
|
if (description) {
|
|
description.textContent = descriptor.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 });
|
|
for (const registeredViewId of registeredViewIds()) {
|
|
const panel = document.querySelector<HTMLElement>(`#${viewRegistry[registeredViewId].panelId}`);
|
|
if (panel) {
|
|
panel.hidden = registeredViewId !== viewId;
|
|
}
|
|
}
|
|
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");
|
|
}
|
|
});
|
|
});
|
|
window.addEventListener("ksp:activate-view", event => {
|
|
const detail = event instanceof CustomEvent ? event.detail : null;
|
|
const requestedView = typeof detail === "object" && detail !== null && "viewId" in detail ? String(detail.viewId) : "";
|
|
if (isViewId(requestedView)) {
|
|
activateView(requestedView, "registry");
|
|
}
|
|
});
|
|
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" });
|
|
}
|
|
|
|
function bindRuntimeSnapshotRefresh(): void {
|
|
window.addEventListener("ksp:logging-runtime-updated", () => {
|
|
frontendDebug("main", "Application snapshot refresh requested after Logging runtime update");
|
|
void loadSnapshot();
|
|
});
|
|
}
|
|
|
|
async function initializeMain(): Promise<void> {
|
|
const windowLabel = getCurrentWindow().label;
|
|
frontendInfo("main", "Config Desk main frontend loaded", { windowLabel });
|
|
bindNavigation();
|
|
bindRuntimeSnapshotRefresh();
|
|
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();
|
|
});
|