339 lines
26 KiB
HTML
339 lines
26 KiB
HTML
<!-- file: crates/ksp-app-store-desk/frontend/main.html -->
|
||
<!-- version: 6 -->
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||
<link rel="icon" href="imgs/logo.png">
|
||
<link rel="stylesheet" href="sass/main.scss">
|
||
<title>Store Desk — Overview</title>
|
||
</head>
|
||
|
||
<body>
|
||
<header class="app-header">
|
||
<nav class="navbar h-100 py-0 bg-light text-dark">
|
||
<div class="container-fluid px-4 flex-nowrap">
|
||
<div class="navbar-brand d-flex align-items-center me-4 flex-nowrap">
|
||
<img alt="KSP" src="imgs/logo.png" class="app-logo">
|
||
<span class="ps-2 fs-4 fw-semibold text-primary text-nowrap">Store Desk</span>
|
||
<span class="mx-2 fs-5 text-body-secondary" aria-hidden="true">—</span>
|
||
<span id="headerViewTitle" class="fs-5 text-body text-nowrap">Overview</span>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
|
||
<main class="app-main container-fluid p-0">
|
||
<div class="row g-0 h-100 flex-nowrap">
|
||
<aside class="col-auto app-sidebar border-end bg-body-tertiary">
|
||
<div class="app-sidebar-scroll h-100" data-simplebar>
|
||
<nav class="nav nav-pills flex-column gap-1 p-3" aria-label="Navigation Store Desk">
|
||
<button class="nav-link text-start active" type="button" data-view="overview">
|
||
<i class="fa-solid fa-gauge-high me-2" aria-hidden="true"></i>Overview
|
||
</button>
|
||
<button class="nav-link text-start" type="button" data-view="transactions">
|
||
<i class="fa-solid fa-receipt me-2" aria-hidden="true"></i>RAW Transactions
|
||
</button>
|
||
<button class="nav-link text-start" type="button" data-view="accounts">
|
||
<i class="fa-solid fa-box-archive me-2" aria-hidden="true"></i>RAW Accounts
|
||
</button>
|
||
<button class="nav-link text-start" type="button" data-view="diagnostics">
|
||
<i class="fa-solid fa-stethoscope me-2" aria-hidden="true"></i>Diagnostics
|
||
</button>
|
||
</nav>
|
||
</div>
|
||
</aside>
|
||
|
||
<section class="col app-content app-scrollable h-100" data-simplebar>
|
||
<div class="container-fluid px-4 py-4">
|
||
<div class="card app-shell-card mx-auto shadow-sm border-0">
|
||
<div class="card-body p-4">
|
||
<section data-view-panel="overview">
|
||
<div class="d-flex align-items-center justify-content-between gap-3 flex-wrap mb-4">
|
||
<div>
|
||
<h1 class="h3 mb-1">Overview</h1>
|
||
<p class="text-body-secondary mb-0">État backend-neutral du Store sélectionné par le composite Config. Aucune donnée RAW complète n'est chargée ici.</p>
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<span id="appVersionBadge" class="badge text-bg-secondary">—</span>
|
||
<button id="refreshOverview" class="btn btn-outline-primary" type="button">
|
||
<i class="fa-solid fa-arrows-rotate me-1" aria-hidden="true"></i>Refresh
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="row g-3">
|
||
<div class="col-md-6 col-xl-3"><div class="card h-100 shadow-sm"><div class="card-body"><span class="text-body-secondary small">Store profile</span><div id="overviewStoreProfile" class="fw-semibold mt-2">—</div></div></div></div>
|
||
<div class="col-md-6 col-xl-3"><div class="card h-100 shadow-sm"><div class="card-body"><span class="text-body-secondary small">Target</span><div id="overviewStoreTarget" class="fw-semibold mt-2">—</div></div></div></div>
|
||
<div class="col-md-6 col-xl-3"><div class="card h-100 shadow-sm"><div class="card-body"><span class="text-body-secondary small">Health</span><div id="overviewStoreHealth" class="fw-semibold mt-2">—</div></div></div></div>
|
||
<div class="col-md-6 col-xl-3"><div class="card h-100 shadow-sm"><div class="card-body"><span class="text-body-secondary small">Pool</span><div id="overviewStorePool" class="fw-semibold mt-2">—</div></div></div></div>
|
||
<div class="col-md-6 col-xl-3"><div class="card h-100 shadow-sm"><div class="card-body"><span class="text-body-secondary small">Migration</span><div id="overviewStoreMigration" class="fw-semibold mt-2">—</div></div></div></div>
|
||
</div>
|
||
<div id="overviewStoreDiagnostic" class="alert alert-warning mt-3 mb-0" role="status" aria-live="polite" hidden></div>
|
||
</section>
|
||
|
||
<section data-view-panel="transactions" hidden>
|
||
<div class="d-flex flex-wrap align-items-start justify-content-between gap-3 mb-3">
|
||
<div>
|
||
<h1 class="h3 mb-1">RAW Transactions</h1>
|
||
<p class="text-body-secondary mb-0">Inspection Store random-access ; DataTables reste l'unique propriétaire de la pagination visible.</p>
|
||
</div>
|
||
<button id="refreshTransactions" class="btn btn-outline-primary" type="button">
|
||
<i class="fa-solid fa-rotate me-2" aria-hidden="true"></i>Refresh
|
||
</button>
|
||
</div>
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-body">
|
||
<div class="row g-3 align-items-end">
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="transactionSlotMin">Slot minimum</label>
|
||
<input id="transactionSlotMin" class="form-control font-monospace" type="text" inputmode="numeric" autocomplete="off" placeholder="optionnel">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="transactionSlotMax">Slot maximum</label>
|
||
<input id="transactionSlotMax" class="form-control font-monospace" type="text" inputmode="numeric" autocomplete="off" placeholder="optionnel">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="transactionDirection">Direction canonique</label>
|
||
<select id="transactionDirection" class="form-select">
|
||
<option value="descending" selected>Descending</option>
|
||
<option value="ascending">Ascending</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="transactionsQueryError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<div class="table-responsive app-store-table-container">
|
||
<table id="rawTransactionsTable" class="table table-hover align-middle mb-0 app-store-table">
|
||
<caption class="visually-hidden">Inspection server-side des transactions RAW.</caption>
|
||
<thead>
|
||
<tr>
|
||
<th>Signature</th>
|
||
<th>Slot</th>
|
||
<th>Block time</th>
|
||
<th>Format ID</th>
|
||
<th>Version</th>
|
||
<th>Payload size</th>
|
||
<th>Content hash</th>
|
||
<th>Retention</th>
|
||
<th>Détail</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section data-view-panel="accounts" hidden>
|
||
<div class="d-flex flex-wrap align-items-start justify-content-between gap-3 mb-3">
|
||
<div>
|
||
<h1 class="h3 mb-1">RAW Accounts</h1>
|
||
<p class="text-body-secondary mb-0">Inspection Store random-access ; DataTables reste l'unique propriétaire de la pagination visible.</p>
|
||
</div>
|
||
<button id="refreshAccounts" class="btn btn-outline-primary" type="button">
|
||
<i class="fa-solid fa-rotate me-2" aria-hidden="true"></i>Refresh
|
||
</button>
|
||
</div>
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-body">
|
||
<div class="row g-3 align-items-end">
|
||
<div class="col-lg-5">
|
||
<label class="form-label" for="accountPubkey">Pubkey exacte</label>
|
||
<input id="accountPubkey" class="form-control font-monospace" type="text" autocomplete="off" placeholder="optionnel">
|
||
</div>
|
||
<div class="col-md-4 col-lg-2">
|
||
<label class="form-label" for="accountSlotMin">Slot minimum</label>
|
||
<input id="accountSlotMin" class="form-control font-monospace" type="text" inputmode="numeric" autocomplete="off" placeholder="optionnel">
|
||
</div>
|
||
<div class="col-md-4 col-lg-2">
|
||
<label class="form-label" for="accountSlotMax">Slot maximum</label>
|
||
<input id="accountSlotMax" class="form-control font-monospace" type="text" inputmode="numeric" autocomplete="off" placeholder="optionnel">
|
||
</div>
|
||
<div class="col-md-4 col-lg-3">
|
||
<label class="form-label" for="accountDirection">Direction canonique</label>
|
||
<select id="accountDirection" class="form-select">
|
||
<option value="descending" selected>Descending</option>
|
||
<option value="ascending">Ascending</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="accountsQueryError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<div class="table-responsive app-store-table-container">
|
||
<table id="rawAccountsTable" class="table table-hover align-middle mb-0 app-store-table">
|
||
<caption class="visually-hidden">Inspection server-side des états RAW Account.</caption>
|
||
<thead>
|
||
<tr>
|
||
<th>Pubkey</th>
|
||
<th>Slot</th>
|
||
<th>State hash</th>
|
||
<th>Owner</th>
|
||
<th>Lamports</th>
|
||
<th>Executable</th>
|
||
<th>Rent epoch</th>
|
||
<th>Data length</th>
|
||
<th>Détail</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section data-view-panel="diagnostics" hidden>
|
||
<div class="d-flex align-items-center justify-content-between gap-3 flex-wrap mb-4">
|
||
<div>
|
||
<h1 class="h3 mb-1">Diagnostics</h1>
|
||
<p class="text-body-secondary mb-0">État sûr Config / Logging / Store. Les URI et détails physiques sensibles restent hors IPC.</p>
|
||
</div>
|
||
<button id="refreshDiagnostics" class="btn btn-outline-primary" type="button">
|
||
<i class="fa-solid fa-arrows-rotate me-1" aria-hidden="true"></i>Refresh
|
||
</button>
|
||
</div>
|
||
<div class="card shadow-sm">
|
||
<div class="card-header fw-semibold">Runtime</div>
|
||
<div class="card-body">
|
||
<dl class="row mb-0 app-runtime-list">
|
||
<dt class="col-sm-5">Version</dt><dd id="runtimeVersion" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Phase</dt><dd id="runtimeShellPhase" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Documents Config</dt><dd id="runtimeConfigDocuments" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Profil Logging</dt><dd id="runtimeLoggingProfile" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Fallback Logging</dt><dd id="runtimeLoggingFallback" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Store profile</dt><dd id="runtimeStoreProfile" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Store target</dt><dd id="runtimeStoreTarget" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Store health</dt><dd id="runtimeStoreHealth" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Migration</dt><dd id="runtimeStoreMigration" class="col-sm-7">—</dd>
|
||
<dt class="col-sm-5">Pool</dt><dd id="runtimeStorePool" class="col-sm-7">—</dd>
|
||
</dl>
|
||
<div id="runtimeDiagnostic" class="alert alert-warning mt-3 mb-0" role="status" aria-live="polite" hidden></div>
|
||
<div id="runtimeStoreDiagnostic" class="alert alert-warning mt-3 mb-0" role="status" aria-live="polite" hidden></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
|
||
<div id="transactionDetailModal" class="modal fade" tabindex="-1" aria-labelledby="transactionDetailTitle" aria-hidden="true">
|
||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 id="transactionDetailTitle" class="modal-title h5">RAW Transaction detail</h2>
|
||
<button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div id="transactionDetailError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<dl class="row app-runtime-list mb-4">
|
||
<dt class="col-sm-3">Signature</dt><dd id="transactionDetailSignature" class="col-sm-9 text-break">—</dd>
|
||
<dt class="col-sm-3">Slot</dt><dd id="transactionDetailSlot" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Block time</dt><dd id="transactionDetailBlockTime" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Format</dt><dd id="transactionDetailFormat" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Content hash</dt><dd id="transactionDetailContentHash" class="col-sm-9 text-break">—</dd>
|
||
<dt class="col-sm-3">Retention</dt><dd id="transactionDetailRetention" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Payload size</dt><dd id="transactionDetailPayloadSize" class="col-sm-9">—</dd>
|
||
</dl>
|
||
<div class="d-flex align-items-center justify-content-between gap-3 mb-2">
|
||
<h3 class="h6 mb-0">Payload preview hex</h3>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<button id="transactionDetailPayloadPreviewCopy" class="btn btn-sm btn-outline-secondary" type="button" title="Copier le preview hex affiché" aria-label="Copier le preview hex affiché" hidden>
|
||
<i class="fa-regular fa-copy" aria-hidden="true"></i>
|
||
<span>Copier</span>
|
||
</button>
|
||
<span id="transactionDetailPreviewTruncated" class="badge text-bg-warning" hidden>Preview tronquée à 512 bytes</span>
|
||
</div>
|
||
</div>
|
||
<pre id="transactionDetailPayloadPreview" class="small bg-body-tertiary border rounded p-3 overflow-auto text-break mb-0">—</pre>
|
||
<section class="border-top mt-4 pt-4" aria-labelledby="transactionObservationsTitle">
|
||
<div class="d-flex align-items-center justify-content-between gap-3 mb-3">
|
||
<div>
|
||
<h3 id="transactionObservationsTitle" class="h6 mb-1">Observations d’acquisition</h3>
|
||
<p class="small text-body-secondary mb-0">Provenance sûre uniquement ; aucun payload source n’est chargé.</p>
|
||
</div>
|
||
</div>
|
||
<div id="transactionObservationsError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<div class="table-responsive">
|
||
<table id="transactionObservationsTable" class="table table-hover align-middle mb-0 app-store-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Received</th><th>Observed</th><th>Provider</th><th>Protocol</th><th>Method</th><th>Origin</th><th>Endpoint</th><th>Commitment</th><th>Session</th><th>Filter</th><th>Source hash</th><th>Source bytes</th><th>Observation key</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="accountDetailModal" class="modal fade" tabindex="-1" aria-labelledby="accountDetailTitle" aria-hidden="true">
|
||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 id="accountDetailTitle" class="modal-title h5">RAW Account detail</h2>
|
||
<button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div id="accountDetailError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<dl class="row app-runtime-list mb-4">
|
||
<dt class="col-sm-3">Pubkey</dt><dd id="accountDetailPubkey" class="col-sm-9 text-break">—</dd>
|
||
<dt class="col-sm-3">Slot</dt><dd id="accountDetailSlot" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">State hash</dt><dd id="accountDetailStateHash" class="col-sm-9 text-break">—</dd>
|
||
<dt class="col-sm-3">Owner</dt><dd id="accountDetailOwner" class="col-sm-9 text-break">—</dd>
|
||
<dt class="col-sm-3">Lamports</dt><dd id="accountDetailLamports" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Executable</dt><dd id="accountDetailExecutable" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Rent epoch</dt><dd id="accountDetailRentEpoch" class="col-sm-9">—</dd>
|
||
<dt class="col-sm-3">Data length</dt><dd id="accountDetailDataLength" class="col-sm-9">—</dd>
|
||
</dl>
|
||
<div class="d-flex align-items-center justify-content-between gap-3 mb-2">
|
||
<h3 class="h6 mb-0">Account data preview hex</h3>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<button id="accountDetailDataPreviewCopy" class="btn btn-sm btn-outline-secondary" type="button" title="Copier le preview hex affiché" aria-label="Copier le preview hex affiché" hidden>
|
||
<i class="fa-regular fa-copy" aria-hidden="true"></i>
|
||
<span>Copier</span>
|
||
</button>
|
||
<span id="accountDetailPreviewTruncated" class="badge text-bg-warning" hidden>Preview tronquée à 512 bytes</span>
|
||
</div>
|
||
</div>
|
||
<pre id="accountDetailDataPreview" class="small bg-body-tertiary border rounded p-3 overflow-auto text-break mb-0">—</pre>
|
||
<section class="border-top mt-4 pt-4" aria-labelledby="accountObservationsTitle">
|
||
<div class="d-flex align-items-center justify-content-between gap-3 mb-3">
|
||
<div>
|
||
<h3 id="accountObservationsTitle" class="h6 mb-1">Observations d’acquisition</h3>
|
||
<p class="small text-body-secondary mb-0">Provenance sûre et métadonnées Yellowstone optionnelles ; aucun byte Account n’est chargé.</p>
|
||
</div>
|
||
</div>
|
||
<div id="accountObservationsError" class="alert alert-danger" role="status" aria-live="polite" hidden></div>
|
||
<div class="table-responsive">
|
||
<table id="accountObservationsTable" class="table table-hover align-middle mb-0 app-store-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Received</th><th>Observed</th><th>Provider</th><th>Protocol</th><th>Method</th><th>Origin</th><th>Endpoint</th><th>Commitment</th><th>Session</th><th>Filter</th><th>Source hash</th><th>Source bytes</th><th>Observation key</th><th>Startup</th><th>Write version</th><th>Tx signature</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="app-footer bg-dark text-light">
|
||
<div class="container h-100 d-flex align-items-center justify-content-center">
|
||
<small>© 2026 SASEDEV</small>
|
||
</div>
|
||
</footer>
|
||
<script type="module" src="ts/main.ts" defer></script>
|
||
</body>
|
||
|
||
</html>
|