v0.5.3-pre.005-fix010

This commit is contained in:
2026-08-14 14:40:36 +02:00
parent b6583bd9fb
commit 734a27f2ca
59 changed files with 4337 additions and 747 deletions

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts
// version: 8
// version: 9
import * as bootstrap from "bootstrap";
import "simplebar";
@@ -9,11 +9,21 @@ import DataTable, { type Api } from "datatables.net-bs5";
import "datatables.net-bs5/css/dataTables.bootstrap5.css";
import { listen } from "@tauri-apps/api/event";
import { frontendDebug, frontendError, installFrontendConsoleBridge } from "./frontend_log.ts";
import {
applyStoreBlockMetadata,
createStoreBlockState,
cursorForBlock,
markStoreBlockFiltersDirty,
resetStoreBlockState,
renderStoreBlockControls,
type StoreBlockControls,
} from "./demo_store_block_pagination.ts";
import type { DemoDecodeDiagnosticsPayload } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeDiagnosticsPayload.ts";
import type { DemoDecodeReplayOptionsPayload } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeReplayOptionsPayload.ts";
import type { DemoDecodeReplayProgressPayload } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeReplayProgressPayload.ts";
import type { DemoDecodeReplayRequest } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeReplayRequest.ts";
import type { DemoDecodeReplaySummaryPayload } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeReplaySummaryPayload.ts";
import type { DemoTransactionAnnotationPagePayload } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoTransactionAnnotationPagePayload.ts";
import type { DemoTransactionAnnotationRequest } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoTransactionAnnotationRequest.ts";
import type { DemoTransactionAnnotationRow } from "./bindings/kb_app_demo_desktop/demo_decode_replay/DemoTransactionAnnotationRow.ts";
@@ -23,6 +33,15 @@ import type { DemoTransactionAnnotationRow } from "./bindings/kb_app_demo_deskto
const logLines: string[] = [];
let running = false;
let materializationAvailable = false;
const annotationBlockControls: StoreBlockControls = {
firstSelector: "#annotationFirstBlockButton",
previousSelector: "#annotationPreviousBlockButton",
nextSelector: "#annotationNextBlockButton",
summarySelector: "#annotationBlockSummary",
};
const annotationBlockState = createStoreBlockState();
type AnnotationBaseRequest = Omit<DemoTransactionAnnotationRequest, "cursor" | "blockIndex">;
let annotationBaseRequest: AnnotationBaseRequest | null = null;
function element<T extends HTMLElement>(selector: string): T {
const value = document.querySelector<T>(selector);
@@ -250,7 +269,7 @@ function renderAnnotations(rows: DemoTransactionAnnotationRow[]): void {
annotationJournalTable = new DataTable<DemoTransactionAnnotationRow>("#annotationJournalTable", {
autoWidth: false,
pageLength: 25,
lengthMenu: [10, 25, 50, 100],
lengthMenu: [10, 25, 50, 100, 250, 500],
order: [[0, "desc"]],
scrollX: true,
language: {
@@ -265,23 +284,53 @@ function renderAnnotations(rows: DemoTransactionAnnotationRow[]): void {
element<HTMLElement>("#annotationJournalStatus").textContent = `${rows.length} annotation(s) committed chargée(s).`;
}
async function loadAnnotations(): Promise<void> {
const request: DemoTransactionAnnotationRequest = {
async function startAnnotationLoad(): Promise<void> {
annotationBaseRequest = {
signatureContains: inputValue("#annotationSignatureInput") || null,
limit: integerValue("#annotationLimitInput"),
};
resetStoreBlockState(annotationBlockState);
await loadAnnotationBlock(1, null);
}
async function loadAnnotationBlock(blockIndex: number, cursor: string | null): Promise<void> {
if (annotationBaseRequest === null) {
throw new Error("Rechargez les annotations pour initialiser les filtres Store.");
}
const request: DemoTransactionAnnotationRequest = {
...annotationBaseRequest,
cursor,
blockIndex,
};
try {
frontendDebug("kb_app_demo_desktop.frontend.demo_decode_replay", `Invoke demo_decode_replay_annotations limit=${request.limit}`);
const rows = await invoke<DemoTransactionAnnotationRow[]>("demo_decode_replay_annotations", { request });
renderAnnotations(rows);
frontendDebug("kb_app_demo_desktop.frontend.demo_decode_replay", `Invoke demo_decode_replay_annotations completed rows=${rows.length}`);
frontendDebug("kb_app_demo_desktop.frontend.demo_decode_replay", `Invoke demo_decode_replay_annotations block=${blockIndex}`);
const payload = await invoke<DemoTransactionAnnotationPagePayload>("demo_decode_replay_annotations", { request });
renderAnnotations(payload.rows);
applyStoreBlockMetadata(annotationBlockState, payload.page, annotationBlockControls);
frontendDebug("kb_app_demo_desktop.frontend.demo_decode_replay", `Invoke demo_decode_replay_annotations completed block=${payload.page.blockIndex}/${payload.page.totalBlocks} rows=${payload.rows.length}`);
} catch (caughtError) {
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
element<HTMLElement>("#annotationJournalStatus").textContent = `Erreur : ${message}`;
renderStoreBlockControls(annotationBlockState, annotationBlockControls);
frontendError("kb_app_demo_desktop.frontend.demo_decode_replay", `Annotation journal loading failed: ${message}`);
}
}
async function loadPreviousAnnotationBlock(): Promise<void> {
const targetBlock = annotationBlockState.currentBlock - 1;
const cursor = cursorForBlock(annotationBlockState, targetBlock);
if (targetBlock < 1 || cursor === undefined) {
return;
}
await loadAnnotationBlock(targetBlock, cursor);
}
async function loadNextAnnotationBlock(): Promise<void> {
if (annotationBlockState.nextCursor === null) {
return;
}
await loadAnnotationBlock(annotationBlockState.currentBlock + 1, annotationBlockState.nextCursor);
}
async function openWindow(command: "open_demo_store_core_window" | "open_demo_store_replay_candidates_window"): Promise<void> {
try {
frontendDebug("kb_app_demo_desktop.frontend.demo_decode_replay", `Invoke ${command}`);
@@ -357,7 +406,14 @@ document.addEventListener("DOMContentLoaded", () => {
element<HTMLButtonElement>("#startDecodeReplayButton").addEventListener("click", () => void executeDecodeReplay());
element<HTMLButtonElement>("#cancelDecodeReplayButton").addEventListener("click", () => void cancelDecodeReplay());
element<HTMLButtonElement>("#loadDecodeDiagnosticsButton").addEventListener("click", () => void loadDiagnostics());
element<HTMLButtonElement>("#loadAnnotationsButton").addEventListener("click", () => void loadAnnotations());
element<HTMLButtonElement>("#loadAnnotationsButton").addEventListener("click", () => void startAnnotationLoad());
element<HTMLButtonElement>(annotationBlockControls.firstSelector).addEventListener("click", () => void loadAnnotationBlock(1, null));
element<HTMLButtonElement>(annotationBlockControls.previousSelector).addEventListener("click", () => void loadPreviousAnnotationBlock());
element<HTMLButtonElement>(annotationBlockControls.nextSelector).addEventListener("click", () => void loadNextAnnotationBlock());
element<HTMLInputElement>("#annotationSignatureInput").addEventListener("input", () => {
annotationBaseRequest = null;
markStoreBlockFiltersDirty(annotationBlockState, annotationBlockControls);
});
element<HTMLButtonElement>("#openReplayCandidatesFromDecodeButton").addEventListener("click", () => void openWindow("open_demo_store_replay_candidates_window"));
element<HTMLButtonElement>("#openCoreDiagnosticsFromDecodeButton").addEventListener("click", () => void openWindow("open_demo_store_core_window"));
void listen<DemoDecodeReplayProgressPayload>("demo-decode-replay-progress", event => appendLog(event.payload));