v0.1.4-pre.011
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-app-config-desk/frontend/main.html -->
|
||||
<!-- version: 5 -->
|
||||
<!-- version: 6 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
@@ -204,6 +204,42 @@
|
||||
<div id="profilesStatus" class="alert alert-primary mb-0" role="status" aria-live="polite">Chargement des profils Config...</div>
|
||||
</section>
|
||||
|
||||
<section id="environmentPanel" hidden aria-label="Environnement Config">
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center justify-content-between mb-3">
|
||||
<div>
|
||||
<h2 class="h5 mb-1">Rapport Environnement / .env</h2>
|
||||
<p class="text-body-secondary small mb-0">Valeurs desired/effective sûres, provenance externe et shadowing calculés exclusivement par ksp-config-lib.</p>
|
||||
</div>
|
||||
<button id="refreshEnvironment" class="btn btn-outline-primary btn-sm" type="button">
|
||||
<i class="fa-solid fa-rotate me-1" aria-hidden="true"></i>
|
||||
Rafraîchir
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-light border small" role="note">
|
||||
Les valeurs Secret restent redacted. Cette tranche est en lecture seule : création, modification et suppression de valeurs `.env` arrivent en pre.012.
|
||||
</div>
|
||||
|
||||
<div class="table-responsive mb-4">
|
||||
<table id="environmentReportTable" class="table table-striped table-hover align-middle w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Variable</th>
|
||||
<th scope="col">Namespace</th>
|
||||
<th scope="col">Sensibilité</th>
|
||||
<th scope="col">Desired .env (safe)</th>
|
||||
<th scope="col">Effective (safe)</th>
|
||||
<th scope="col">Source</th>
|
||||
<th scope="col">Shadowed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="environmentStatus" class="alert alert-primary mb-0" role="status" aria-live="polite">Chargement du rapport environnement...</div>
|
||||
</section>
|
||||
|
||||
<section id="placeholderPanel" hidden aria-live="polite">
|
||||
<div class="alert alert-secondary mb-4" role="status">
|
||||
Cette route du shell est prête ; son contenu fonctionnel sera ajouté dans la prerelease prévue par le plan 0.1.4.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-config-desk/frontend/sass/_app.scss
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
$app-header-height: 72px;
|
||||
$app-footer-height: 42px;
|
||||
@@ -111,3 +111,10 @@ body {
|
||||
background: var(--bs-body-bg);
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
|
||||
#environmentReportTable td:first-child,
|
||||
#environmentReportTable td:nth-child(4),
|
||||
#environmentReportTable td:nth-child(5) {
|
||||
font-family: var(--bs-font-monospace);
|
||||
}
|
||||
|
||||
136
crates/ksp-app-config-desk/frontend/ts/environment.ts
Normal file
136
crates/ksp-app-config-desk/frontend/ts/environment.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
// file: crates/ksp-app-config-desk/frontend/ts/environment.ts
|
||||
// version: 1
|
||||
|
||||
//! Safe environment report panel backed exclusively by ConfigManagement::environment_report().
|
||||
|
||||
import DataTable from "datatables.net-bs5";
|
||||
import "datatables.net-bs5/css/dataTables.bootstrap5.css";
|
||||
import type { ConfigEnvironmentReportDto } from "./bindings/ksp_app_config_desk/environment/ConfigEnvironmentReportDto";
|
||||
import { frontendDebug, frontendTrace } from "./frontend_log";
|
||||
import { invokeKsp } from "./invoke";
|
||||
|
||||
interface EnvironmentDataTable {
|
||||
destroy(): unknown;
|
||||
}
|
||||
|
||||
let environmentTable: EnvironmentDataTable | null = null;
|
||||
|
||||
function setEnvironmentStatus(message: string, tone: "primary" | "success" | "warning" | "danger" = "primary"): void {
|
||||
const status = document.querySelector<HTMLElement>("#environmentStatus");
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
status.className = `alert alert-${tone} mb-0`;
|
||||
status.textContent = message;
|
||||
frontendTrace("main", "Environment panel status replaced", { tone });
|
||||
}
|
||||
|
||||
function sensitivityLabel(value: string): string {
|
||||
if (value === "public") {
|
||||
return "Public";
|
||||
}
|
||||
if (value === "internal") {
|
||||
return "Internal";
|
||||
}
|
||||
if (value === "secret") {
|
||||
return "Secret";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function sourceLabel(value: string): string {
|
||||
if (value === "process") {
|
||||
return "process";
|
||||
}
|
||||
if (value === "dotenv") {
|
||||
return "dotenv";
|
||||
}
|
||||
if (value === "fallback") {
|
||||
return "fallback";
|
||||
}
|
||||
return "—";
|
||||
}
|
||||
|
||||
function safeValue(value: string | null): string {
|
||||
return value ?? "—";
|
||||
}
|
||||
|
||||
function appendCell(row: HTMLTableRowElement, text: string, className?: string): void {
|
||||
const cell = document.createElement("td");
|
||||
cell.textContent = text;
|
||||
if (className) {
|
||||
cell.className = className;
|
||||
}
|
||||
row.append(cell);
|
||||
}
|
||||
|
||||
function populateTableRows(reports: ConfigEnvironmentReportDto[]): void {
|
||||
const body = document.querySelector<HTMLTableSectionElement>("#environmentReportTable tbody");
|
||||
if (!body) {
|
||||
return;
|
||||
}
|
||||
body.replaceChildren();
|
||||
for (const report of reports) {
|
||||
const row = document.createElement("tr");
|
||||
appendCell(row, report.variableName, "font-monospace");
|
||||
appendCell(row, report.namespace);
|
||||
appendCell(row, sensitivityLabel(report.sensitivity));
|
||||
appendCell(row, safeValue(report.desiredSafeValue), "font-monospace text-break");
|
||||
appendCell(row, safeValue(report.effectiveSafeValue), "font-monospace text-break");
|
||||
appendCell(row, sourceLabel(report.effectiveSource));
|
||||
appendCell(row, report.shadowedByProcessEnvironment ? "oui" : "non");
|
||||
body.append(row);
|
||||
}
|
||||
frontendTrace("main", "Environment report table DOM replaced", { variableCount: reports.length });
|
||||
}
|
||||
|
||||
function initializeDataTable(): void {
|
||||
if (environmentTable) {
|
||||
environmentTable.destroy();
|
||||
environmentTable = null;
|
||||
}
|
||||
environmentTable = new DataTable("#environmentReportTable", {
|
||||
order: [[0, "asc"]],
|
||||
pageLength: 10,
|
||||
language: {
|
||||
emptyTable: "Aucune variable KSP/KSPB présente dans process ou .env.",
|
||||
info: "_START_ à _END_ sur _TOTAL_ variable(s)",
|
||||
infoEmpty: "0 variable",
|
||||
lengthMenu: "Afficher _MENU_",
|
||||
search: "Filtrer :",
|
||||
zeroRecords: "Aucune variable correspondante.",
|
||||
},
|
||||
}) as unknown as EnvironmentDataTable;
|
||||
frontendTrace("main", "DataTables Environment initialized");
|
||||
}
|
||||
|
||||
async function refreshEnvironmentReport(): Promise<void> {
|
||||
frontendDebug("main", "Config environment report refresh requested");
|
||||
setEnvironmentStatus("Chargement du rapport environnement sûr...", "primary");
|
||||
try {
|
||||
const reports = await invokeKsp<ConfigEnvironmentReportDto[]>("main", "get_environment_report");
|
||||
populateTableRows(reports);
|
||||
initializeDataTable();
|
||||
const shadowedCount = reports.filter(report => report.shadowedByProcessEnvironment).length;
|
||||
setEnvironmentStatus(`${reports.length} variable(s) KSP/KSPB évaluée(s) par Config ; ${shadowedCount} valeur(s) .env shadowed.`, "success");
|
||||
frontendDebug("main", "Config environment report refresh completed", {
|
||||
variableCount: reports.length,
|
||||
shadowedCount,
|
||||
});
|
||||
} catch {
|
||||
setEnvironmentStatus("Le rapport environnement n'a pas pu être chargé par Config.", "danger");
|
||||
}
|
||||
}
|
||||
|
||||
function bindEnvironmentActions(): void {
|
||||
document.querySelector<HTMLButtonElement>("#refreshEnvironment")?.addEventListener("click", () => {
|
||||
frontendTrace("main", "Environment refresh button clicked");
|
||||
void refreshEnvironmentReport();
|
||||
});
|
||||
frontendTrace("main", "Environment panel handlers installed");
|
||||
}
|
||||
|
||||
export function initializeEnvironmentPanel(): void {
|
||||
bindEnvironmentActions();
|
||||
void refreshEnvironmentReport();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-config-desk/frontend/ts/main.ts
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
import "bootstrap";
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
@@ -8,6 +8,7 @@ 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";
|
||||
|
||||
@@ -31,7 +32,7 @@ const viewCopy: Record<ViewId, { title: string; description: string }> = {
|
||||
},
|
||||
environment: {
|
||||
title: "Environnement / .env",
|
||||
description: "Rapports et management des variables KSP/KSPB — surfaces fonctionnelles prévues en pre.011/pre.012.",
|
||||
description: "Rapport sûr desired/effective/source/shadow des variables KSP/KSPB ; mutations .env prévues en pre.012.",
|
||||
},
|
||||
logging: {
|
||||
title: "Logging",
|
||||
@@ -79,9 +80,13 @@ function activateView(viewId: ViewId, source: "startup" | "user"): void {
|
||||
if (profiles) {
|
||||
profiles.hidden = viewId !== "profiles";
|
||||
}
|
||||
const environment = document.querySelector<HTMLElement>("#environmentPanel");
|
||||
if (environment) {
|
||||
environment.hidden = viewId !== "environment";
|
||||
}
|
||||
const placeholder = document.querySelector<HTMLElement>("#placeholderPanel");
|
||||
if (placeholder) {
|
||||
placeholder.hidden = viewId === "overview" || viewId === "documents" || viewId === "profiles";
|
||||
placeholder.hidden = viewId !== "logging";
|
||||
}
|
||||
frontendTrace("main", "Main view DOM updated", { viewId, source });
|
||||
}
|
||||
@@ -142,6 +147,7 @@ async function initializeMain(): Promise<void> {
|
||||
bindNavigation();
|
||||
initializeDocumentsPanel();
|
||||
initializeProfilesPanel();
|
||||
initializeEnvironmentPanel();
|
||||
activateView("overview", "startup");
|
||||
try {
|
||||
await loadSnapshot();
|
||||
|
||||
Reference in New Issue
Block a user