v0.2.6-pre.005
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
<span class="fw-semibold">Wallet Desk — <span id="headerViewTitle">Dashboard</span></span>
|
||||
<small id="shellStatus" class="text-white-50 app-shell-status">Initialisation du shell…</small>
|
||||
</div>
|
||||
<button class="btn btn-outline-light btn-sm" type="button" data-shell-action="deselect" disabled>
|
||||
<i class="fa-solid fa-xmark me-2" aria-hidden="true"></i>Deselect
|
||||
</button>
|
||||
<button class="btn btn-outline-light btn-sm" type="button" data-shell-action="lock" disabled>
|
||||
<i class="fa-solid fa-lock me-2" aria-hidden="true"></i>Lock
|
||||
</button>
|
||||
@@ -39,7 +42,7 @@
|
||||
<h1 id="viewTitle" class="h3 mb-1">Dashboard</h1>
|
||||
<p class="text-body-secondary mb-0">Inventaire `.kspwallet` root-scoped et inspection locked actifs.</p>
|
||||
</div>
|
||||
<span class="badge text-bg-secondary">0.2.6-pre.004</span>
|
||||
<span class="badge text-bg-secondary">0.2.6-pre.005</span>
|
||||
</div>
|
||||
<section data-view-panel="dashboard">
|
||||
<div class="row g-3">
|
||||
@@ -73,6 +76,9 @@
|
||||
<dt class="col-5">État</dt><dd id="currentWalletState" class="col-7">—</dd>
|
||||
<dt class="col-5">Format</dt><dd id="currentWalletFormat" class="col-7">—</dd>
|
||||
<dt class="col-5">VIEW</dt><dd id="currentWalletView" class="col-7">—</dd>
|
||||
<dt class="col-5">Pubkey</dt><dd id="currentWalletPubkey" class="col-7 text-break">—</dd>
|
||||
<dt class="col-5">Alias</dt><dd id="currentWalletAlias" class="col-7 text-break">—</dd>
|
||||
<dt class="col-5">Notes</dt><dd id="currentWalletNotes" class="col-7 text-break">—</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,7 +104,60 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-view-panel="create-import" hidden><div class="app-placeholder"><i class="fa-solid fa-circle-plus"></i><p>Create / Import sera branché après la fondation Config et inventory.</p></div></section>
|
||||
<section data-view-panel="create-import" hidden>
|
||||
<div class="row g-3">
|
||||
<div class="col-xl-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header fw-semibold">Créer un wallet natif KSP</div>
|
||||
<div class="card-body">
|
||||
<form id="createWalletForm" autocomplete="off">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="createWalletFilename">Filename</label>
|
||||
<input id="createWalletFilename" class="form-control" type="text" value="wallet-01.kspwallet" required spellcheck="false">
|
||||
<div class="form-text">Un seul filename sous le répertoire Wallet effectif, suffixe exact .kspwallet.</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="createWalletAlias">Alias interne optionnel</label>
|
||||
<input id="createWalletAlias" class="form-control" type="text" autocomplete="off">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="createWalletOwnerPassword">OWNER password</label>
|
||||
<input id="createWalletOwnerPassword" class="form-control" type="password" autocomplete="new-password" required>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-end">
|
||||
<div class="form-check mb-2">
|
||||
<input id="createWalletEnableView" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="createWalletEnableView">Créer aussi une capability VIEW</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="createWalletViewPassword">VIEW password</label>
|
||||
<input id="createWalletViewPassword" class="form-control" type="password" autocomplete="new-password" disabled>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label" for="createWalletInitialNote">Note initiale optionnelle</label>
|
||||
<textarea id="createWalletInitialNote" class="form-control" rows="3" autocomplete="off"></textarea>
|
||||
</div>
|
||||
<div class="col-12 d-flex align-items-center gap-3">
|
||||
<button id="createWalletSubmit" class="btn btn-primary" type="submit">
|
||||
<i class="fa-solid fa-circle-plus me-2" aria-hidden="true"></i>Create wallet
|
||||
</button>
|
||||
<span id="createWalletStatus" class="text-body-secondary" role="status">Prêt.</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4">
|
||||
<div class="alert alert-info mb-0">
|
||||
<i class="fa-solid fa-shield-halved me-2" aria-hidden="true"></i>
|
||||
Les passwords sont envoyés uniquement du frontend vers Rust pour l'opération courante. Ils ne sont jamais renvoyés par Rust ni journalisés.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-view-panel="details" hidden><div class="app-placeholder"><i class="fa-solid fa-id-card"></i><p>Les détails protégés seront affichés uniquement après VIEW/OWNER.</p></div></section>
|
||||
<section data-view-panel="security" hidden><div class="app-placeholder"><i class="fa-solid fa-shield-halved"></i><p>Les opérations OWNER seront ajoutées après le MVP identité + balance.</p></div></section>
|
||||
<section data-view-panel="diagnostics" hidden><div class="app-placeholder"><i class="fa-solid fa-stethoscope"></i><p>Les diagnostics Config/Wallet/Transport seront enrichis progressivement.</p></div></section>
|
||||
@@ -107,7 +166,7 @@
|
||||
</div>
|
||||
</main>
|
||||
<footer class="app-footer bg-dark text-white-50 d-flex align-items-center px-4">
|
||||
<span>KSP Wallet Desk · locked inventory pre.004</span>
|
||||
<span>KSP Wallet Desk · create + session lifecycle pre.005</span>
|
||||
</footer>
|
||||
<script type="module" src="./ts/main.ts"></script>
|
||||
</body>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/frontend/ts/main.ts
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
import "bootstrap";
|
||||
import DataTable from "datatables.net-bs5";
|
||||
@@ -11,6 +11,9 @@ import type { RuntimeStatusDto } from "./bindings/ksp_app_wallet_desk/dto_common
|
||||
import type { LockedWalletDto } from "./bindings/ksp_app_wallet_desk/wallet_inventory/LockedWalletDto.ts";
|
||||
import type { WalletInventoryEntryDto } from "./bindings/ksp_app_wallet_desk/wallet_inventory/WalletInventoryEntryDto.ts";
|
||||
import type { WalletSelectionRequestDto } from "./bindings/ksp_app_wallet_desk/wallet_inventory/WalletSelectionRequestDto.ts";
|
||||
import type { WalletAuthorizedDto } from "./bindings/ksp_app_wallet_desk/wallet_session/WalletAuthorizedDto.ts";
|
||||
import type { WalletCreateRequestDto } from "./bindings/ksp_app_wallet_desk/wallet_session/WalletCreateRequestDto.ts";
|
||||
import type { WalletSessionDto } from "./bindings/ksp_app_wallet_desk/wallet_session/WalletSessionDto.ts";
|
||||
import { frontendDebug, frontendInfo, frontendTrace, frontendWarn, installFrontendConsoleBridge } from "./frontend_log";
|
||||
import { invokeKsp } from "./invoke";
|
||||
import "../sass/main.scss";
|
||||
@@ -19,6 +22,7 @@ import "../sass/main.scss";
|
||||
installFrontendConsoleBridge("main");
|
||||
|
||||
type ViewId = "dashboard" | "wallets" | "create-import" | "details" | "security" | "diagnostics";
|
||||
type ActiveSessionState = "no_selection" | "locked" | "owner_open";
|
||||
|
||||
const viewTitles: Record<ViewId, string> = {
|
||||
dashboard: "Dashboard",
|
||||
@@ -29,6 +33,9 @@ const viewTitles: Record<ViewId, string> = {
|
||||
diagnostics: "Diagnostics",
|
||||
};
|
||||
|
||||
let activeWalletId: string | null = null;
|
||||
let activeSessionState: ActiveSessionState = "no_selection";
|
||||
|
||||
function isViewId(value: string): value is ViewId {
|
||||
return value in viewTitles;
|
||||
}
|
||||
@@ -114,7 +121,11 @@ function renderWalletInventoryRow(entry: WalletInventoryEntryDto): HTMLTableRowE
|
||||
row.dataset.inspectionStatus = entry.inspectionStatus;
|
||||
const state = document.createElement("td");
|
||||
if (entry.state === "locked") {
|
||||
appendIconText(state, "fa-lock", "Locked");
|
||||
if (activeWalletId === entry.walletId && activeSessionState === "owner_open") {
|
||||
appendIconText(state, "fa-lock-open", "OWNER");
|
||||
} else {
|
||||
appendIconText(state, "fa-lock", "Locked");
|
||||
}
|
||||
} else {
|
||||
appendIconText(state, "fa-triangle-exclamation", "Erreur");
|
||||
}
|
||||
@@ -154,7 +165,7 @@ function initializeWalletTable(): void {
|
||||
zeroRecords: "Aucun wallet correspondant.",
|
||||
},
|
||||
});
|
||||
frontendDebug("main", "Wallet inventory DataTable initialized", { phase: "pre.004-wallet-inventory" });
|
||||
frontendDebug("main", "Wallet inventory DataTable initialized", { phase: "pre.005-wallet-session-create" });
|
||||
}
|
||||
|
||||
function renderWalletInventory(entries: WalletInventoryEntryDto[]): void {
|
||||
@@ -170,58 +181,105 @@ function renderWalletInventory(entries: WalletInventoryEntryDto[]): void {
|
||||
frontendDebug("main", "Wallet inventory rendered", { entryCount: entries.length, invalidCount });
|
||||
}
|
||||
|
||||
function setText(selector: string, value: string): void {
|
||||
const element = document.querySelector<HTMLElement>(selector);
|
||||
if (element) {
|
||||
element.textContent = value;
|
||||
}
|
||||
}
|
||||
|
||||
function updateSessionActions(): void {
|
||||
const lock = document.querySelector<HTMLButtonElement>('[data-shell-action="lock"]');
|
||||
const deselect = document.querySelector<HTMLButtonElement>('[data-shell-action="deselect"]');
|
||||
if (lock) {
|
||||
lock.disabled = activeSessionState !== "owner_open";
|
||||
}
|
||||
if (deselect) {
|
||||
deselect.disabled = activeSessionState === "no_selection";
|
||||
}
|
||||
}
|
||||
|
||||
function clearCreateFormSensitiveInputs(): void {
|
||||
const ownerPassword = document.querySelector<HTMLInputElement>("#createWalletOwnerPassword");
|
||||
const viewPassword = document.querySelector<HTMLInputElement>("#createWalletViewPassword");
|
||||
const alias = document.querySelector<HTMLInputElement>("#createWalletAlias");
|
||||
const note = document.querySelector<HTMLTextAreaElement>("#createWalletInitialNote");
|
||||
if (ownerPassword) {
|
||||
ownerPassword.value = "";
|
||||
}
|
||||
if (viewPassword) {
|
||||
viewPassword.value = "";
|
||||
}
|
||||
if (alias) {
|
||||
alias.value = "";
|
||||
}
|
||||
if (note) {
|
||||
note.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
function clearAuthorizedProjection(): void {
|
||||
setText("#currentWalletPubkey", "—");
|
||||
setText("#currentWalletAlias", "—");
|
||||
setText("#currentWalletNotes", "—");
|
||||
clearCreateFormSensitiveInputs();
|
||||
}
|
||||
|
||||
function clearSelectedWallet(): void {
|
||||
activeWalletId = null;
|
||||
activeSessionState = "no_selection";
|
||||
const icon = document.querySelector<HTMLElement>("#currentWalletIcon");
|
||||
const filename = document.querySelector<HTMLElement>("#currentWalletFilename");
|
||||
const state = document.querySelector<HTMLElement>("#currentWalletState");
|
||||
const format = document.querySelector<HTMLElement>("#currentWalletFormat");
|
||||
const view = document.querySelector<HTMLElement>("#currentWalletView");
|
||||
if (icon) {
|
||||
icon.className = "fa-solid fa-lock fa-2x mb-3 text-body-secondary";
|
||||
}
|
||||
if (filename) {
|
||||
filename.textContent = "Aucun wallet sélectionné.";
|
||||
}
|
||||
if (state) {
|
||||
state.textContent = "—";
|
||||
}
|
||||
if (format) {
|
||||
format.textContent = "—";
|
||||
}
|
||||
if (view) {
|
||||
view.textContent = "—";
|
||||
}
|
||||
setText("#currentWalletFilename", "Aucun wallet sélectionné.");
|
||||
setText("#currentWalletState", "—");
|
||||
setText("#currentWalletFormat", "—");
|
||||
setText("#currentWalletView", "—");
|
||||
clearAuthorizedProjection();
|
||||
updateSessionActions();
|
||||
}
|
||||
|
||||
function renderSelectedWallet(wallet: LockedWalletDto): void {
|
||||
function renderLockedWallet(wallet: LockedWalletDto): void {
|
||||
activeWalletId = wallet.walletId;
|
||||
activeSessionState = "locked";
|
||||
clearAuthorizedProjection();
|
||||
const icon = document.querySelector<HTMLElement>("#currentWalletIcon");
|
||||
const filename = document.querySelector<HTMLElement>("#currentWalletFilename");
|
||||
const state = document.querySelector<HTMLElement>("#currentWalletState");
|
||||
const format = document.querySelector<HTMLElement>("#currentWalletFormat");
|
||||
const view = document.querySelector<HTMLElement>("#currentWalletView");
|
||||
if (icon) {
|
||||
icon.className = "fa-solid fa-lock fa-2x mb-3";
|
||||
}
|
||||
if (filename) {
|
||||
filename.textContent = wallet.filename;
|
||||
}
|
||||
if (state) {
|
||||
state.textContent = "Locked";
|
||||
}
|
||||
if (format) {
|
||||
format.textContent = wallet.formatVersion.toString();
|
||||
}
|
||||
if (view) {
|
||||
view.textContent = wallet.viewEnabled ? "enabled" : "disabled";
|
||||
}
|
||||
setText("#currentWalletFilename", wallet.filename);
|
||||
setText("#currentWalletState", "Locked");
|
||||
setText("#currentWalletFormat", wallet.formatVersion.toString());
|
||||
setText("#currentWalletView", wallet.viewEnabled ? "enabled" : "disabled");
|
||||
updateSessionActions();
|
||||
frontendDebug("main", "Locked Wallet selection rendered", { walletId: wallet.walletId, formatVersion: wallet.formatVersion, viewEnabled: wallet.viewEnabled });
|
||||
}
|
||||
|
||||
function renderAuthorizedWallet(wallet: WalletAuthorizedDto): void {
|
||||
activeWalletId = wallet.walletId;
|
||||
activeSessionState = "owner_open";
|
||||
const icon = document.querySelector<HTMLElement>("#currentWalletIcon");
|
||||
if (icon) {
|
||||
icon.className = "fa-solid fa-lock-open fa-2x mb-3 text-success";
|
||||
}
|
||||
setText("#currentWalletFilename", wallet.filename);
|
||||
setText("#currentWalletState", "OWNER open");
|
||||
setText("#currentWalletFormat", wallet.formatVersion.toString());
|
||||
setText("#currentWalletView", wallet.viewEnabled ? "enabled" : "disabled");
|
||||
setText("#currentWalletPubkey", wallet.pubkey);
|
||||
setText("#currentWalletAlias", wallet.alias ?? "—");
|
||||
setText("#currentWalletNotes", wallet.notes.length === 0 ? "—" : wallet.notes.map(note => note.text).join(" · "));
|
||||
updateSessionActions();
|
||||
frontendDebug("main", "OWNER Wallet session rendered after creation", { walletId: wallet.walletId, viewEnabled: wallet.viewEnabled, noteCount: wallet.notes.length });
|
||||
}
|
||||
|
||||
async function selectWallet(walletId: string): Promise<void> {
|
||||
clearSelectedWallet();
|
||||
const request: WalletSelectionRequestDto = { walletId };
|
||||
try {
|
||||
const wallet = await invokeKsp<LockedWalletDto>("main", "select_wallet", { request });
|
||||
renderSelectedWallet(wallet);
|
||||
renderLockedWallet(wallet);
|
||||
} catch {
|
||||
clearSelectedWallet();
|
||||
frontendWarn("main", "Locked Wallet selection failed", { walletId });
|
||||
@@ -256,62 +314,124 @@ function bindWalletTableSelection(): void {
|
||||
frontendTrace("main", "Wallet inventory row selection handler installed");
|
||||
}
|
||||
|
||||
async function loadWalletInventory(command: "list_wallets" | "refresh_wallets"): Promise<void> {
|
||||
async function loadWalletInventory(command: "list_wallets" | "refresh_wallets", clearSession: boolean): Promise<void> {
|
||||
frontendDebug("main", "Wallet inventory load requested", { command });
|
||||
const entries = await invokeKsp<WalletInventoryEntryDto[]>("main", command);
|
||||
clearSelectedWallet();
|
||||
if (clearSession) {
|
||||
clearSelectedWallet();
|
||||
}
|
||||
renderWalletInventory(entries);
|
||||
}
|
||||
|
||||
function createRequestFromForm(): WalletCreateRequestDto | null {
|
||||
const filename = document.querySelector<HTMLInputElement>("#createWalletFilename");
|
||||
const ownerPassword = document.querySelector<HTMLInputElement>("#createWalletOwnerPassword");
|
||||
const enableView = document.querySelector<HTMLInputElement>("#createWalletEnableView");
|
||||
const viewPassword = document.querySelector<HTMLInputElement>("#createWalletViewPassword");
|
||||
const alias = document.querySelector<HTMLInputElement>("#createWalletAlias");
|
||||
const note = document.querySelector<HTMLTextAreaElement>("#createWalletInitialNote");
|
||||
if (!filename || !ownerPassword || !enableView || !viewPassword || !alias || !note) {
|
||||
return null;
|
||||
}
|
||||
const normalizedFilename = filename.value.trim();
|
||||
if (!normalizedFilename.endsWith(".kspwallet") || normalizedFilename.length <= ".kspwallet".length || ownerPassword.value.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (enableView.checked && viewPassword.value.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
alias: alias.value.length === 0 ? null : alias.value,
|
||||
filename: normalizedFilename,
|
||||
initialNote: note.value.length === 0 ? null : note.value,
|
||||
ownerPassword: ownerPassword.value,
|
||||
viewPassword: enableView.checked ? viewPassword.value : null,
|
||||
};
|
||||
}
|
||||
|
||||
function bindCreateWalletForm(): void {
|
||||
const form = document.querySelector<HTMLFormElement>("#createWalletForm");
|
||||
const enableView = document.querySelector<HTMLInputElement>("#createWalletEnableView");
|
||||
const viewPassword = document.querySelector<HTMLInputElement>("#createWalletViewPassword");
|
||||
if (enableView && viewPassword) {
|
||||
enableView.addEventListener("change", () => {
|
||||
viewPassword.disabled = !enableView.checked;
|
||||
if (!enableView.checked) {
|
||||
viewPassword.value = "";
|
||||
}
|
||||
frontendTrace("main", "Create Wallet VIEW option changed", { enabled: enableView.checked });
|
||||
});
|
||||
}
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
form.addEventListener("submit", event => {
|
||||
event.preventDefault();
|
||||
const request = createRequestFromForm();
|
||||
if (!request) {
|
||||
setText("#createWalletStatus", "Filename/passwords invalides ou incomplets.");
|
||||
frontendWarn("main", "Create Wallet form validation rejected request");
|
||||
return;
|
||||
}
|
||||
const requestedWalletId = request.filename;
|
||||
const requestedViewEnabled = request.viewPassword !== null;
|
||||
setText("#createWalletStatus", "Création en cours…");
|
||||
frontendDebug("main", "Create Wallet request submitted", { walletId: requestedWalletId, viewEnabled: requestedViewEnabled });
|
||||
clearSelectedWallet();
|
||||
void invokeKsp<WalletAuthorizedDto>("main", "create_wallet", { request })
|
||||
.then(async wallet => {
|
||||
clearCreateFormSensitiveInputs();
|
||||
renderAuthorizedWallet(wallet);
|
||||
setText("#createWalletStatus", "Wallet créé ; session OWNER ouverte.");
|
||||
await loadWalletInventory("list_wallets", false);
|
||||
activateView("dashboard", "user");
|
||||
})
|
||||
.catch(() => {
|
||||
clearCreateFormSensitiveInputs();
|
||||
setText("#createWalletStatus", "Création impossible. Consulter le diagnostic et les logs.");
|
||||
frontendWarn("main", "Create Wallet operation failed", { walletId: requestedWalletId });
|
||||
});
|
||||
});
|
||||
frontendTrace("main", "Create Wallet form handlers installed");
|
||||
}
|
||||
|
||||
async function lockCurrentWallet(): Promise<void> {
|
||||
clearAuthorizedProjection();
|
||||
try {
|
||||
const wallet = await invokeKsp<LockedWalletDto>("main", "lock_wallet");
|
||||
renderLockedWallet(wallet);
|
||||
await loadWalletInventory("list_wallets", false);
|
||||
} catch {
|
||||
clearSelectedWallet();
|
||||
frontendWarn("main", "Wallet lock operation failed");
|
||||
}
|
||||
}
|
||||
|
||||
async function deselectCurrentWallet(): Promise<void> {
|
||||
try {
|
||||
const session = await invokeKsp<WalletSessionDto>("main", "deselect_wallet");
|
||||
clearSelectedWallet();
|
||||
frontendDebug("main", "Wallet session deselected", { state: session.state });
|
||||
await loadWalletInventory("list_wallets", false);
|
||||
} catch {
|
||||
clearSelectedWallet();
|
||||
frontendWarn("main", "Wallet deselect operation failed");
|
||||
}
|
||||
}
|
||||
|
||||
function renderRuntimeStatus(status: RuntimeStatusDto): void {
|
||||
const version = document.querySelector<HTMLElement>("#runtimeVersion");
|
||||
const compositeProfile = document.querySelector<HTMLElement>("#runtimeCompositeProfile");
|
||||
const loggingProfile = document.querySelector<HTMLElement>("#runtimeLoggingProfile");
|
||||
const walletProfile = document.querySelector<HTMLElement>("#runtimeWalletProfile");
|
||||
const fallback = document.querySelector<HTMLElement>("#runtimeLoggingFallback");
|
||||
const documents = document.querySelector<HTMLElement>("#runtimeConfigDocuments");
|
||||
const walletsRoot = document.querySelector<HTMLElement>("#runtimeWalletsDirectory");
|
||||
const walletsSubdirectory = document.querySelector<HTMLElement>("#runtimeWalletsSubdirectory");
|
||||
const effectiveWalletsDirectory = document.querySelector<HTMLElement>("#runtimeEffectiveWalletsDirectory");
|
||||
const walletDirectoryCreated = document.querySelector<HTMLElement>("#runtimeWalletDirectoryCreated");
|
||||
const phase = document.querySelector<HTMLElement>("#runtimeShellPhase");
|
||||
const shellStatus = document.querySelector<HTMLElement>("#shellStatus");
|
||||
if (version) {
|
||||
version.textContent = status.applicationVersion;
|
||||
}
|
||||
if (compositeProfile) {
|
||||
compositeProfile.textContent = status.activeCompositeProfile;
|
||||
}
|
||||
if (loggingProfile) {
|
||||
loggingProfile.textContent = status.activeLoggingProfile ?? "fallback transitoire";
|
||||
}
|
||||
if (walletProfile) {
|
||||
walletProfile.textContent = status.activeWalletProfile;
|
||||
}
|
||||
if (fallback) {
|
||||
fallback.textContent = status.fallbackLoggingActive ? "oui" : "non";
|
||||
}
|
||||
if (documents) {
|
||||
documents.textContent = status.configDocumentCount.toString();
|
||||
}
|
||||
if (walletsRoot) {
|
||||
walletsRoot.textContent = status.walletsDirectory;
|
||||
}
|
||||
if (walletsSubdirectory) {
|
||||
walletsSubdirectory.textContent = status.walletsSubdirectory ?? "— (racine globale)";
|
||||
}
|
||||
if (effectiveWalletsDirectory) {
|
||||
effectiveWalletsDirectory.textContent = status.effectiveWalletsDirectory;
|
||||
}
|
||||
if (walletDirectoryCreated) {
|
||||
walletDirectoryCreated.textContent = status.effectiveWalletsDirectoryCreatedOnStartup ? "oui" : "non, déjà présent";
|
||||
}
|
||||
if (phase) {
|
||||
phase.textContent = status.shellPhase;
|
||||
}
|
||||
if (shellStatus) {
|
||||
shellStatus.textContent = "Config résolue ; inventaire Wallet prêt.";
|
||||
}
|
||||
setText("#runtimeVersion", status.applicationVersion);
|
||||
setText("#runtimeCompositeProfile", status.activeCompositeProfile);
|
||||
setText("#runtimeLoggingProfile", status.activeLoggingProfile ?? "fallback transitoire");
|
||||
setText("#runtimeWalletProfile", status.activeWalletProfile);
|
||||
setText("#runtimeLoggingFallback", status.fallbackLoggingActive ? "oui" : "non");
|
||||
setText("#runtimeConfigDocuments", status.configDocumentCount.toString());
|
||||
setText("#runtimeWalletsDirectory", status.walletsDirectory);
|
||||
setText("#runtimeWalletsSubdirectory", status.walletsSubdirectory ?? "— (racine globale)");
|
||||
setText("#runtimeEffectiveWalletsDirectory", status.effectiveWalletsDirectory);
|
||||
setText("#runtimeWalletDirectoryCreated", status.effectiveWalletsDirectoryCreatedOnStartup ? "oui" : "non, déjà présent");
|
||||
setText("#runtimeShellPhase", status.shellPhase);
|
||||
setText("#shellStatus", "Config résolue ; création et session Wallet prêtes.");
|
||||
frontendTrace("main", "Wallet Desk runtime status rendered", {
|
||||
compositeProfile: status.activeCompositeProfile,
|
||||
fallbackLoggingActive: status.fallbackLoggingActive,
|
||||
@@ -331,10 +451,19 @@ function bindShellActions(): void {
|
||||
button.addEventListener("click", () => {
|
||||
const action = button.dataset.shellAction ?? "unknown";
|
||||
frontendDebug("main", "Wallet Desk shell action clicked", { action, enabled: !button.disabled });
|
||||
if (action === "refresh-wallets" && !button.disabled) {
|
||||
void loadWalletInventory("refresh_wallets").catch(() => {
|
||||
if (button.disabled) {
|
||||
return;
|
||||
}
|
||||
if (action === "refresh-wallets") {
|
||||
clearSelectedWallet();
|
||||
void loadWalletInventory("refresh_wallets", true).catch(() => {
|
||||
clearSelectedWallet();
|
||||
frontendWarn("main", "Wallet inventory refresh failed");
|
||||
});
|
||||
} else if (action === "lock") {
|
||||
void lockCurrentWallet();
|
||||
} else if (action === "deselect") {
|
||||
void deselectCurrentWallet();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -347,17 +476,16 @@ async function initializeMain(): Promise<void> {
|
||||
bindFrontendInteractions();
|
||||
bindNavigation();
|
||||
bindWalletTableSelection();
|
||||
bindCreateWalletForm();
|
||||
bindShellActions();
|
||||
clearSelectedWallet();
|
||||
activateView("dashboard", "startup");
|
||||
try {
|
||||
await loadRuntimeStatus();
|
||||
await loadWalletInventory("list_wallets");
|
||||
await loadWalletInventory("list_wallets", false);
|
||||
} catch {
|
||||
renderWalletInventory([]);
|
||||
const shellStatus = document.querySelector<HTMLElement>("#shellStatus");
|
||||
if (shellStatus) {
|
||||
shellStatus.textContent = "Le statut runtime ou l'inventaire Wallet n'a pas pu être chargé.";
|
||||
}
|
||||
setText("#shellStatus", "Le statut runtime ou l'inventaire Wallet n'a pas pu être chargé.");
|
||||
frontendWarn("main", "Wallet Desk startup data load failed");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user