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
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:
@@ -0,0 +1,123 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ComputeModuleInputHash fingerprints module config and child entries so snapshots
|
||||
// invalidate on CRUD without re-reading every child at render time.
|
||||
func ComputeModuleInputHash(st Backend, tenantID string, mod *Module) (string, error) {
|
||||
if st == nil || mod == nil {
|
||||
return "", fmt.Errorf("store: module hash: missing store or module")
|
||||
}
|
||||
h := sha256.New()
|
||||
_, _ = fmt.Fprintf(h, "type=%s\n", strings.TrimSpace(mod.Type))
|
||||
_, _ = fmt.Fprintf(h, "enabled=%t\n", mod.Enabled)
|
||||
if mod.DefaultCommunityID != nil {
|
||||
_, _ = fmt.Fprintf(h, "default_community=%s\n", strings.TrimSpace(*mod.DefaultCommunityID))
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "doh_policy=%s\n", NormalizeDohResolverPolicy(mod.DohResolverPolicy))
|
||||
for _, pid := range mod.EffectiveDohProfileIDs() {
|
||||
_, _ = fmt.Fprintf(h, "doh_profile=%s\n", pid)
|
||||
if prof, err := st.GetDohProfile(tenantID, pid); err == nil && prof != nil {
|
||||
_, _ = fmt.Fprintf(h, "doh_url=%s\n", strings.TrimSpace(prof.URL))
|
||||
if prof.TimeoutMs != nil {
|
||||
_, _ = fmt.Fprintf(h, "doh_timeout=%d\n", *prof.TimeoutMs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch mod.Type {
|
||||
case "IP_RANGES":
|
||||
list, err := st.ListIPRangeEntries(tenantID, mod.ID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].Prefix < list[j].Prefix })
|
||||
for _, e := range list {
|
||||
comm := ""
|
||||
if e.CommunityID != nil {
|
||||
comm = *e.CommunityID
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "ip=%s|c=%s\n", e.Prefix, comm)
|
||||
}
|
||||
case "AS_PREFIXES":
|
||||
list, err := st.ListASEntries(tenantID, mod.ID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].ASN < list[j].ASN })
|
||||
for _, e := range list {
|
||||
comm := ""
|
||||
if e.CommunityID != nil {
|
||||
comm = *e.CommunityID
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "as=%d|c=%s\n", e.ASN, comm)
|
||||
}
|
||||
case "CDN_CIDRS":
|
||||
list, err := st.ListCDNSources(tenantID, mod.ID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].ID < list[j].ID })
|
||||
for _, s := range list {
|
||||
comm := ""
|
||||
if s.CommunityID != nil {
|
||||
comm = *s.CommunityID
|
||||
}
|
||||
interval := 0
|
||||
if s.RefreshIntervalSec != nil {
|
||||
interval = *s.RefreshIntervalSec
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "cdn=%s|url=%s|kind=%s|path=%s|c=%s|etag=%s|interval=%d\n",
|
||||
s.ID, strings.TrimSpace(s.URL), s.SourceKind, strings.TrimSpace(s.PrefixPath), comm,
|
||||
strings.TrimSpace(s.Etag), interval)
|
||||
}
|
||||
case "DOMAINS":
|
||||
list, err := st.ListDomainEntries(tenantID, mod.ID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].FQDN < list[j].FQDN })
|
||||
for _, e := range list {
|
||||
comm := ""
|
||||
if e.CommunityID != nil {
|
||||
comm = *e.CommunityID
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "dom=%s|c=%s\n", strings.TrimSpace(e.FQDN), comm)
|
||||
}
|
||||
default:
|
||||
_, _ = fmt.Fprintf(h, "unknown_type=%s\n", mod.Type)
|
||||
}
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
// TouchModuleInputHash recomputes and stores module.input_hash (ARCH-01: hash lives in store).
|
||||
func TouchModuleInputHash(st Backend, tenantID, moduleID string) {
|
||||
if st == nil {
|
||||
return
|
||||
}
|
||||
mod, err := st.GetModule(tenantID, moduleID)
|
||||
if err != nil || mod == nil {
|
||||
return
|
||||
}
|
||||
h, err := ComputeModuleInputHash(st, tenantID, mod)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = st.SetModuleInputHash(tenantID, moduleID, h)
|
||||
}
|
||||
|
||||
// CDNPatchAffectsInputHash reports whether a CDN source patch changes ingest fingerprint
|
||||
// fields (URL/kind/path/community/interval). ETag and last_refreshed_at do not.
|
||||
func CDNPatchAffectsInputHash(patch *CDNSourcePatch) bool {
|
||||
if patch == nil {
|
||||
return false
|
||||
}
|
||||
return patch.SourceKind != nil || patch.URL != nil || patch.PrefixPath != nil ||
|
||||
patch.CommunityID != nil || patch.RefreshIntervalSec != nil
|
||||
}
|
||||
Reference in New Issue
Block a user