chore: update project changes

This commit is contained in:
2026-09-21 15:33:47 +03:30
parent f7366a1985
commit 810448b6e7
8 changed files with 1459 additions and 810 deletions
+3 -1
View File
@@ -65,6 +65,8 @@ func TestDashboardRendersFullTemplPage(t *testing.T) {
ID: "journal-1", EffectKind: "deposit", SourceService: "wallet",
Blockchain: ledger.BlockchainReference{TransactionHash: "abc123"},
}},
SettlementStats: explorer.SettlementStats{Confirmed: 9, Pending: 2},
Settlements: []explorer.Settlement{{ID: "settlement-1", Status: ledger.SettlementConfirmed, Network: "kuknos", TransactionHash: "chain-hash", SourceService: "wallet", Attempts: 1}},
}}
request := httptest.NewRequest(http.MethodGet, "/", nil)
response := httptest.NewRecorder()
@@ -72,7 +74,7 @@ func TestDashboardRendersFullTemplPage(t *testing.T) {
NewHandler(service).ServeHTTP(response, request)
body := response.Body.String()
for _, expected := range []string{"<!doctype html>", "DARANO", "1,234", "abc123", "htmx.org@2.0.10", "src=\"/theme.js\"", "data-theme-toggle", "html[data-theme=\"dark\"]", "class=\"mark\" src=\"/favicon.ico\"", "#F5F5F5", "#DFF1F1", "#BBD5DA", "#FF0000"} {
for _, expected := range []string{"<!doctype html>", "DARANO", "1,234", "abc123", "Blockchain settlements", "Confirmed on chain", "chain-hash", "htmx.org@2.0.10", "src=\"/theme.js\"", "data-theme-toggle", "html[data-theme=\"dark\"]", "class=\"mark\" src=\"/favicon.ico\"", "#F5F5F5", "#DFF1F1", "#BBD5DA", "#FF0000"} {
if !strings.Contains(body, expected) {
t.Fatalf("response did not contain %q", expected)
}
+24
View File
@@ -109,6 +109,18 @@ var english = map[string]string{
"tracked_accounts": "Tracked accounts",
"last_recorded": "Last recorded",
"latest_activity": "Latest ledger activity",
"blockchain_settlements": "Blockchain settlements",
"settlement_summary": "LATEST SETTLEMENT STATE",
"confirmed_on_chain": "Confirmed on chain",
"pending_submission": "Pending submission",
"retryable": "Retryable",
"manual_review": "Manual review",
"blockchain_transaction": "Blockchain transaction",
"status": "Status",
"attempts": "Attempts",
"updated": "Updated",
"not_submitted": "Not submitted",
"no_settlements": "No blockchain settlements have been queued yet.",
"newest_first": "NEWEST FIRST",
"top_asset_holders": "Top asset holders",
"holder_balance_scope": "AVAILABLE + FROZEN · RECENT ASSETS",
@@ -210,6 +222,18 @@ var persian = map[string]string{
"tracked_accounts": "حساب‌های ردیابی‌شده",
"last_recorded": "آخرین ثبت",
"latest_activity": "آخرین فعالیت دفتر کل",
"blockchain_settlements": "تسویه‌های بلاکچین",
"settlement_summary": "آخرین وضعیت تسویه",
"confirmed_on_chain": "تأییدشده روی زنجیره",
"pending_submission": "در انتظار ارسال",
"retryable": "قابل تلاش مجدد",
"manual_review": "نیازمند بررسی دستی",
"blockchain_transaction": "تراکنش بلاکچین",
"status": "وضعیت",
"attempts": "تعداد تلاش",
"updated": "آخرین تغییر",
"not_submitted": "ارسال‌نشده",
"no_settlements": "هنوز تسویه‌ای برای بلاکچین در صف قرار نگرفته است.",
"newest_first": "جدیدترین ابتدا",
"top_asset_holders": "دارندگان برتر دارایی",
"holder_balance_scope": "در دسترس + مسدود · دارایی‌های اخیر",
+44
View File
@@ -72,6 +72,7 @@ templ Page(title string, active string, locale Locale, englishURL string, persia
.pill { display:inline-flex; padding:6px 9px; border-radius:999px; background:var(--surface); font:750 10px/1 ui-monospace,SFMono-Regular,monospace; text-transform:uppercase; }
.holder-id { max-width:330px; overflow-wrap:anywhere; font-weight:750; }
.holder-id small { display:block; margin-top:5px; color:var(--muted); font:650 10px/1 ui-monospace,SFMono-Regular,monospace; }
td small { display:block; margin-top:5px; color:var(--muted); font:600 10px/1.35 ui-monospace,SFMono-Regular,monospace; overflow-wrap:anywhere; }
.empty { padding:45px 24px; text-align:center; color:var(--muted); }
.notice + .transaction-list { margin-top:46px; }
.pagination { display:flex; align-items:center; justify-content:center; gap:8px; margin-top:18px; direction:ltr; }
@@ -200,6 +201,16 @@ templ DashboardContent(data explorer.Dashboard, locale Locale) {
<div class="stat"><span class="stat-label">{ tr(locale, "tracked_accounts") }</span><strong>{ count(data.Stats.AccountCount) }</strong></div>
<div class="stat"><span class="stat-label">{ tr(locale, "last_recorded") }</span><time>{ formatTime(data.Stats.LastRecordedAt) }</time></div>
</section>
<section class="dashboard-section">
<div class="section-head"><h2>{ tr(locale, "blockchain_settlements") }</h2><span>{ tr(locale, "settlement_summary") }</span></div>
<section class="stats" aria-label={ tr(locale, "blockchain_settlements") }>
<div class="stat"><span class="stat-label">{ tr(locale, "confirmed_on_chain") }</span><strong>{ count(data.SettlementStats.Confirmed) }</strong></div>
<div class="stat"><span class="stat-label">{ tr(locale, "pending_submission") }</span><strong>{ count(data.SettlementStats.Pending) }</strong></div>
<div class="stat"><span class="stat-label">{ tr(locale, "retryable") }</span><strong>{ count(data.SettlementStats.Retryable) }</strong></div>
<div class="stat"><span class="stat-label">{ tr(locale, "manual_review") }</span><strong>{ count(data.SettlementStats.ManualReview) }</strong></div>
</section>
@SettlementTable(data.Settlements, locale)
</section>
<section>
<div class="section-head"><h2>{ tr(locale, "latest_activity") }</h2><span>{ tr(locale, "newest_first") }</span></div>
@JournalTable(data.Journals, locale)
@@ -207,6 +218,39 @@ templ DashboardContent(data explorer.Dashboard, locale Locale) {
</main>
}
templ SettlementTable(settlements []explorer.Settlement, locale Locale) {
<div class="panel">
if len(settlements) == 0 {
<div class="empty">{ tr(locale, "no_settlements") }</div>
} else {
<table>
<thead><tr><th>{ tr(locale, "blockchain_transaction") }</th><th>{ tr(locale, "status") }</th><th>{ tr(locale, "network") }</th><th>{ tr(locale, "source") }</th><th>{ tr(locale, "attempts") }</th><th>{ tr(locale, "updated") }</th></tr></thead>
<tbody>
for _, settlement := range settlements {
<tr>
<td class="mono">
if settlement.TransactionHash != "" {
<a class="hash-link" href={ templ.URL(transactionURL(settlement.TransactionHash)) } title={ settlement.TransactionHash }>{ short(settlement.TransactionHash, 22) }</a>
} else {
<span title={ settlement.ID }>{ tr(locale, "not_submitted") } · { short(settlement.ID, 14) }</span>
}
if settlement.LastError != "" {
<small>{ short(settlement.LastError, 70) }</small>
}
</td>
<td><span class="pill">{ string(settlement.Status) }</span></td>
<td>{ settlement.Network }</td>
<td>{ settlement.SourceService }<small class="mono">{ short(settlement.SourceTransactionID, 18) }</small></td>
<td class="mono">{ strconv.Itoa(settlement.Attempts) }</td>
<td class="mono">{ formatTime(settlement.UpdatedAt) }</td>
</tr>
}
</tbody>
</table>
}
</div>
}
templ AssetsContent(data explorer.Assets, locale Locale) {
<main id="explorer-content" class="shell">
<div class="breadcrumb"><a href="/">{ tr(locale, "network") }</a> / { tr(locale, "assets") }</div>
File diff suppressed because one or more lines are too long