Files
boc/aamos-admin-upgrade/backend/handlers/dashboard.go
T
Bernt 6de2455917 v1.2.0: Add Global Markets footer, translated to 9 languages
- Added GLOBAL_MARKETS_TITLE to all translation files
- Updated footer with 12 markets (4 active + 8 upcoming)
- Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi
- Built and deployed to production
- CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
2026-07-08 19:56:03 +00:00

109 lines
3.0 KiB
Go

package handlers
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"aamos-admin/models"
)
type DashboardResponse struct {
UsersCount int `json:"users_count"`
ModulesHealthy int `json:"modules_healthy"`
ModulesTotal int `json:"modules_total"`
RecentAudit []models.AuditLog `json:"recent_audit"`
SystemMetrics DashboardSystemMetrics `json:"system_metrics"`
}
type DashboardSystemMetrics struct {
CPU CPUMetrics `json:"cpu"`
RAM RAMMetrics `json:"ram"`
Disk DiskMetrics `json:"disk"`
}
func DashboardHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var usersCount int
if err := db.QueryRowContext(r.Context(), `SELECT COUNT(*) FROM users`).Scan(&usersCount); err != nil {
http.Error(w, fmt.Sprintf("db error: %v", err), http.StatusInternalServerError)
return
}
var modulesTotal, modulesHealthy int
if err := db.QueryRowContext(r.Context(), `SELECT COUNT(*) FROM modules`).Scan(&modulesTotal); err != nil {
http.Error(w, fmt.Sprintf("db error: %v", err), http.StatusInternalServerError)
return
}
if err := db.QueryRowContext(r.Context(),
`SELECT COUNT(*) FROM modules WHERE status = $1`, string(models.ModuleStatusRunning),
).Scan(&modulesHealthy); err != nil {
http.Error(w, fmt.Sprintf("db error: %v", err), http.StatusInternalServerError)
return
}
rows, err := db.QueryContext(r.Context(), `
SELECT id, user_id, action, resource, ip, timestamp, details
FROM audit_logs
ORDER BY timestamp DESC
LIMIT 5
`)
if err != nil {
http.Error(w, fmt.Sprintf("db error: %v", err), http.StatusInternalServerError)
return
}
defer rows.Close()
audit := make([]models.AuditLog, 0, 5)
for rows.Next() {
var a models.AuditLog
if err := rows.Scan(&a.ID, &a.UserID, &a.Action, &a.Resource, &a.IP, &a.Timestamp, &a.Details); err != nil {
http.Error(w, fmt.Sprintf("scan error: %v", err), http.StatusInternalServerError)
return
}
audit = append(audit, a)
}
if err := rows.Err(); err != nil {
http.Error(w, fmt.Sprintf("rows error: %v", err), http.StatusInternalServerError)
return
}
cpu, err := readCPU()
if err != nil {
http.Error(w, fmt.Sprintf("cpu read error: %v", err), http.StatusInternalServerError)
return
}
ram, err := readRAM()
if err != nil {
http.Error(w, fmt.Sprintf("ram read error: %v", err), http.StatusInternalServerError)
return
}
disk, err := readDisk("/")
if err != nil {
http.Error(w, fmt.Sprintf("disk read error: %v", err), http.StatusInternalServerError)
return
}
resp := DashboardResponse{
UsersCount: usersCount,
ModulesHealthy: modulesHealthy,
ModulesTotal: modulesTotal,
RecentAudit: audit,
SystemMetrics: DashboardSystemMetrics{
CPU: cpu,
RAM: ram,
Disk: disk,
},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
}
}