refactor(web): remove deprecated dashboard components and enhance KPI grid
quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 46s
quality / web (push) Successful in 1m16s
quality / go (push) Successful in 2m42s
quality / bird2 (push) Successful in 16s
CD / quality (push) Successful in 5m19s
CD / publish (push) Successful in 7m19s

- Deleted unused components: `DashboardActivityTimeline`, `DashboardFramePanel`, `DashboardModulesGrid`, `DashboardRecentJobsGrid`, and `DashboardRecentRevisionsGrid` to streamline the dashboard.
- Updated `DashboardKpiGrid` to improve KPI display logic, including progress indicators and enhanced badge functionality.
- Refactored `DashboardNetworkHealth` to provide better status representation based on loading states and network conditions.
- Introduced new properties for KPI cards to support progress tracking and improved visual feedback.

This cleanup aims to enhance performance and maintainability of the dashboard while providing a better user experience.
This commit is contained in:
Denozordec
2026-08-31 10:15:59 +07:00
parent e469c421ca
commit dc803bcb34
51 changed files with 1895 additions and 1078 deletions
+79 -129
View File
@@ -2,147 +2,97 @@ package pipeline
import (
"context"
"encoding/base64"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
"evobgp/internal/store"
"github.com/miekg/dns"
)
func TestResolveDomainIPsWithPolicy_Union(t *testing.T) {
srvRU := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"198.51.100.1"}]}`))
}))
defer srvRU.Close()
srvEU := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"203.0.113.1"}]}`))
}))
defer srvEU.Close()
// TestResolveDomainIPs_ParallelAAndAAAA verifies that A and AAAA queries are issued
// concurrently: with a 250ms upstream latency the combined resolve must stay near
// one round-trip instead of two.
func TestResolveDomainIPs_ParallelAAndAAAA(t *testing.T) {
const delay = 250 * time.Millisecond
var inflight, maxInflight atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cur := inflight.Add(1)
for {
old := maxInflight.Load()
if cur <= old || maxInflight.CompareAndSwap(old, cur) {
break
}
}
defer inflight.Add(-1)
time.Sleep(delay)
profiles := []*store.DohProfile{
{URL: srvRU.URL},
{URL: srvEU.URL},
}
ips, err := resolveDomainIPsWithPolicy(context.Background(), srvRU.Client(), profiles, store.DohPolicyUnion, "example.com")
if wire := r.URL.Query().Get("dns"); wire != "" {
// RFC8484 dns-message: decode the query and answer on the wire.
raw, err := base64.RawURLEncoding.DecodeString(wire)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
msg := new(dns.Msg)
if err := msg.Unpack(raw); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
resp := new(dns.Msg)
resp.SetReply(msg)
switch msg.Question[0].Qtype {
case dns.TypeA:
resp.Answer = append(resp.Answer, &dns.A{
Hdr: dns.RR_Header{Name: msg.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
A: []byte{203, 0, 113, 10},
})
case dns.TypeAAAA:
resp.Answer = append(resp.Answer, &dns.AAAA{
Hdr: dns.RR_Header{Name: msg.Question[0].Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 60},
AAAA: []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10},
})
}
out, err := resp.Pack()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/dns-message")
_, _ = w.Write(out)
return
}
w.Header().Set("Content-Type", "application/dns-json")
switch r.URL.Query().Get("type") {
case "A":
_, _ = w.Write([]byte(`{"Status":0,"Answer":[{"type":1,"data":"203.0.113.10"}]}`))
default:
_, _ = w.Write([]byte(`{"Status":0,"Answer":[{"type":28,"data":"2001:db8::10"}]}`))
}
}))
defer srv.Close()
prof := &store.DohProfile{URL: srv.URL, TimeoutMs: ptrInt(5000)}
ctx := context.Background()
start := time.Now()
ips, err := resolveDomainIPsNoSystemFallback(ctx, srv.Client(), prof, "example.test")
elapsed := time.Since(start)
if err != nil {
t.Fatal(err)
t.Fatalf("resolve failed: %v", err)
}
if len(ips) != 2 {
t.Fatalf("want 2 ips, got %v", ips)
t.Fatalf("expected 2 addrs, got %+v", ips)
}
seen := map[string]bool{ips[0].String(): true, ips[1].String(): true}
if !seen["198.51.100.1"] || !seen["203.0.113.1"] {
t.Fatalf("unexpected ips: %v", ips)
if maxInflight.Load() < 2 {
t.Fatalf("expected concurrent A/AAAA queries, max inflight=%d", maxInflight.Load())
}
if elapsed >= 2*delay {
t.Fatalf("resolve took %v; expected one round-trip (<2*%v)", elapsed, delay)
}
}
func TestResolveDomainIPsWithPolicy_Failover(t *testing.T) {
var calls int
srvBad := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
calls++
http.Error(w, "fail", http.StatusBadGateway)
}))
defer srvBad.Close()
srvOK := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
calls++
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"198.51.100.5"}]}`))
}))
defer srvOK.Close()
profiles := []*store.DohProfile{
{URL: srvBad.URL},
{URL: srvOK.URL},
}
ips, err := resolveDomainIPsWithPolicy(context.Background(), srvBad.Client(), profiles, store.DohPolicyFailover, "example.com")
if err != nil {
t.Fatal(err)
}
if len(ips) != 1 || ips[0].String() != "198.51.100.5" {
t.Fatalf("unexpected ips: %v", ips)
}
if calls < 2 {
t.Fatalf("want at least 2 resolver calls, got %d", calls)
}
}
func TestResolveDomainIPsWithPolicy_PrimaryOnly(t *testing.T) {
var secondCalled bool
srv1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"198.51.100.9"}]}`))
}))
defer srv1.Close()
srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
secondCalled = true
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"203.0.113.9"}]}`))
}))
defer srv2.Close()
profiles := []*store.DohProfile{
{URL: srv1.URL},
{URL: srv2.URL},
}
ips, err := resolveDomainIPsWithPolicy(context.Background(), srv1.Client(), profiles, store.DohPolicyPrimaryOnly, "example.com")
if err != nil {
t.Fatal(err)
}
if len(ips) != 1 || ips[0].String() != "198.51.100.9" {
t.Fatalf("unexpected ips: %v", ips)
}
if secondCalled {
t.Fatal("secondary resolver must not be queried in primary_only mode")
}
}
func TestCollectModulePrefixRows_DohUnion(t *testing.T) {
m := store.NewMemory()
m.SeedDemo()
tenant, _, _, _, _ := m.DemoIDs()
mod, err := m.CreateModule(tenant, &store.Module{
Type: "DOMAINS",
Name: "domains-union",
Enabled: true,
DohResolverPolicy: store.DohPolicyUnion,
})
if err != nil {
t.Fatal(err)
}
srvRU := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"198.51.100.2"}]}`))
}))
defer srvRU.Close()
srvEU := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"Answer":[{"type":1,"data":"203.0.113.2"}]}`))
}))
defer srvEU.Close()
ru, err := m.CreateDohProfile(tenant, &store.DohProfile{Name: "ru", URL: srvRU.URL})
if err != nil {
t.Fatal(err)
}
eu, err := m.CreateDohProfile(tenant, &store.DohProfile{Name: "eu", URL: srvEU.URL})
if err != nil {
t.Fatal(err)
}
if _, err := m.UpdateModule(tenant, mod.ID, &store.ModulePatch{
DohProfileIDs: &[]string{ru.ID, eu.ID},
}); err != nil {
t.Fatal(err)
}
mod, err = m.GetModule(tenant, mod.ID)
if err != nil {
t.Fatal(err)
}
if _, err := m.CreateDomainEntry(tenant, mod.ID, &store.DomainEntry{FQDN: "svc.example.com"}); err != nil {
t.Fatal(err)
}
rows, err := collectModulePrefixRows(context.Background(), m, srvRU.Client(), tenant, mod, nil)
if err != nil {
t.Fatal(err)
}
if len(rows) != 2 {
t.Fatalf("want 2 prefix rows, got %+v", rows)
}
}
func ptrInt(v int) *int { return &v }