v0.2.12-pre.005
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-app-solprices-desk/frontend/main.html -->
|
||||
<!-- version: 5 -->
|
||||
<!-- version: 6 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<h1 class="h3 mb-1">Prices</h1>
|
||||
<p class="text-body-secondary mb-0">Inventaire provider-neutral du registry Off-chain. Aucun refresh réseau n'est encore déclenché dans cette tranche.</p>
|
||||
<p class="text-body-secondary mb-0">Inventaire provider-neutral du registry Off-chain. Chaque ligne peut être rafraîchie explicitement sans polling ni fallback automatique.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pricesLoading" class="app-placeholder">
|
||||
@@ -78,6 +78,7 @@
|
||||
<th scope="col">Provider timestamp (ms)</th>
|
||||
<th scope="col">Received at (ms)</th>
|
||||
<th scope="col">Retry at (ms)</th>
|
||||
<th scope="col">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="marketPriceRows"></tbody>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-solprices-desk/frontend/ts/main.ts
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
import "bootstrap";
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
@@ -20,6 +20,8 @@ const viewTitles: Record<ViewId, string> = {
|
||||
diagnostics: "Diagnostics",
|
||||
};
|
||||
|
||||
let currentMarketPriceRows: MarketPriceProviderRowDto[] = [];
|
||||
|
||||
function isViewId(value: string | undefined): value is ViewId {
|
||||
return value === "prices" || value === "diagnostics";
|
||||
}
|
||||
@@ -60,6 +62,64 @@ function appendMarketPriceCell(row: HTMLTableRowElement, value: string): void {
|
||||
row.append(cell);
|
||||
}
|
||||
|
||||
function clearPricesDiagnostic(): void {
|
||||
const diagnostic = document.querySelector<HTMLElement>("#pricesDiagnostic");
|
||||
if (diagnostic) {
|
||||
diagnostic.hidden = true;
|
||||
diagnostic.textContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
function showPricesDiagnostic(message: string): void {
|
||||
const diagnostic = document.querySelector<HTMLElement>("#pricesDiagnostic");
|
||||
if (diagnostic) {
|
||||
diagnostic.hidden = false;
|
||||
diagnostic.textContent = message;
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshMarketPrice(providerId: string): Promise<void> {
|
||||
frontendDebug("main", "SOL Prices Desk market-price refresh control clicked", { providerId });
|
||||
clearPricesDiagnostic();
|
||||
currentMarketPriceRows = currentMarketPriceRows.map(provider => {
|
||||
return provider.providerId === providerId ? { ...provider, loading: true } : provider;
|
||||
});
|
||||
renderMarketPriceRows(currentMarketPriceRows);
|
||||
try {
|
||||
const refreshed = await invokeKsp<MarketPriceProviderRowDto>("main", "refresh_market_price", { providerId });
|
||||
currentMarketPriceRows = currentMarketPriceRows.map(provider => {
|
||||
return provider.providerId === refreshed.providerId ? refreshed : provider;
|
||||
});
|
||||
renderMarketPriceRows(currentMarketPriceRows);
|
||||
frontendTrace("main", "SOL Prices Desk market-price refresh row applied", { providerId });
|
||||
} catch {
|
||||
frontendWarn("main", "SOL Prices Desk market-price refresh failed", { providerId });
|
||||
showPricesDiagnostic("Le provider sélectionné n'a pas pu être rafraîchi. L'état précédent est conservé lorsqu'il reste disponible.");
|
||||
try {
|
||||
await loadMarketPrices();
|
||||
} catch {
|
||||
frontendWarn("main", "SOL Prices Desk market-price refresh recovery reload failed", { providerId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function appendRefreshCell(row: HTMLTableRowElement, provider: MarketPriceProviderRowDto): void {
|
||||
const cell = document.createElement("td");
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.className = "btn btn-sm btn-outline-primary text-nowrap";
|
||||
button.disabled = provider.loading;
|
||||
button.dataset.providerId = provider.providerId;
|
||||
button.innerHTML = provider.loading
|
||||
? '<i class="fa-solid fa-spinner fa-spin me-1" aria-hidden="true"></i>Refreshing…'
|
||||
: '<i class="fa-solid fa-rotate me-1" aria-hidden="true"></i>Refresh';
|
||||
button.addEventListener("click", () => {
|
||||
void refreshMarketPrice(provider.providerId);
|
||||
});
|
||||
cell.append(button);
|
||||
row.append(cell);
|
||||
}
|
||||
|
||||
function renderMarketPriceRows(rows: MarketPriceProviderRowDto[]): void {
|
||||
const loading = document.querySelector<HTMLElement>("#pricesLoading");
|
||||
const empty = document.querySelector<HTMLElement>("#pricesEmpty");
|
||||
@@ -77,6 +137,7 @@ function renderMarketPriceRows(rows: MarketPriceProviderRowDto[]): void {
|
||||
tableContainer.hidden = rows.length === 0;
|
||||
for (const provider of rows) {
|
||||
const row = document.createElement("tr");
|
||||
row.dataset.providerId = provider.providerId;
|
||||
appendMarketPriceCell(row, provider.displayName);
|
||||
appendMarketPriceCell(row, provider.pair);
|
||||
appendMarketPriceCell(row, provider.semantics);
|
||||
@@ -86,6 +147,7 @@ function renderMarketPriceRows(rows: MarketPriceProviderRowDto[]): void {
|
||||
appendMarketPriceCell(row, provider.providerTimestampUnixMillis ?? "—");
|
||||
appendMarketPriceCell(row, provider.receivedAtUnixMillis ?? "—");
|
||||
appendMarketPriceCell(row, provider.retryAtUnixMillis ?? "—");
|
||||
appendRefreshCell(row, provider);
|
||||
tableBody.append(row);
|
||||
}
|
||||
frontendTrace("main", "SOL Prices Desk market-price registry rows rendered", { rowCount: rows.length });
|
||||
@@ -127,6 +189,7 @@ function renderRuntimeStatus(status: MarketPriceRuntimeStatusDto): void {
|
||||
async function loadMarketPrices(): Promise<void> {
|
||||
frontendTrace("main", "SOL Prices Desk provider registry load started");
|
||||
const rows = await invokeKsp<MarketPriceProviderRowDto[]>("main", "list_market_prices");
|
||||
currentMarketPriceRows = rows;
|
||||
renderMarketPriceRows(rows);
|
||||
frontendTrace("main", "SOL Prices Desk provider registry load completed", { rowCount: rows.length });
|
||||
}
|
||||
@@ -155,14 +218,10 @@ async function initializeMain(): Promise<void> {
|
||||
await loadMarketPrices();
|
||||
} catch {
|
||||
const loading = document.querySelector<HTMLElement>("#pricesLoading");
|
||||
const diagnostic = document.querySelector<HTMLElement>("#pricesDiagnostic");
|
||||
if (loading) {
|
||||
loading.hidden = true;
|
||||
}
|
||||
if (diagnostic) {
|
||||
diagnostic.hidden = false;
|
||||
diagnostic.textContent = "L'inventaire provider-neutral n'a pas pu être chargé.";
|
||||
}
|
||||
showPricesDiagnostic("L'inventaire provider-neutral n'a pas pu être chargé.");
|
||||
frontendWarn("main", "SOL Prices Desk provider registry load failed");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user