fix(ui): align usage data contracts, add timezone setting, and fix empty usage page (#146)

- Fix 6 data contract mismatches between Go backend JSON tags and React
  frontend TypeScript interfaces (field renames, response envelope changes)
- Add timezone selector to topbar with 12 common timezone options
- Replace date-fns formatting with native Intl.DateTimeFormat for
  timezone-aware chart labels (reduces bundle ~20KB)
- Add missing SnapshotTimeSeries fields (memory_docs, memory_chunks,
  kg_entities, kg_relations) that caused empty usage page
- Add error banner to usage page for API error visibility
- Sanitize backend error messages in usage HTTP handlers
- Add batch chunking (max 3000 rows) for snapshot upserts
- Remove userId display from topbar
- Add usage analytics i18n strings for en/vi/zh
This commit is contained in:
Viet Tran authored and GitHub committed 2026-03-11 14:22:03 +07:00
1 parent 0926d053b0
commit 73389d2715
39 files changed
+3256 -134

No files matched your search

+22
View File
@@ -291,6 +291,23 @@ func runGateway() {
initOTelExporter(context.Background(), cfg, traceCollector)
}
// Start snapshot worker for hourly usage aggregation
if pgStores.Snapshots != nil {
snapshotWorker := tracing.NewSnapshotWorker(pgStores.DB, pgStores.Snapshots)
snapshotWorker.Start()
defer snapshotWorker.Stop()
// Backfill historical data in background
go func() {
count, err := snapshotWorker.Backfill(context.Background())
if err != nil {
slog.Warn("snapshot backfill failed", "error", err)
} else if count > 0 {
slog.Info("snapshot backfill complete", "hours", count)
}
}()
}
// Redis cache: compiled via build tags. Build with 'go build -tags redis' to enable.
redisClient := initRedisClient(cfg)
defer shutdownRedis(redisClient)
@@ -638,6 +655,11 @@ func runGateway() {
server.SetActivityHandler(httpapi.NewActivityHandler(pgStores.Activity, cfg.Gateway.Token))
}
// Usage analytics API
if pgStores.Snapshots != nil {
server.SetUsageHandler(httpapi.NewUsageHandler(pgStores.Snapshots, pgStores.DB, cfg.Gateway.Token))
}
// Memory management API (wired directly, only needs MemoryStore + token)
if pgStores != nil && pgStores.Memory != nil {
server.SetMemoryHandler(httpapi.NewMemoryHandler(pgStores.Memory, cfg.Gateway.Token))