diff --git a/Makefile b/Makefile index f15b4c1..f23d35e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ BINARY=nasctl -VERSION?=0.2.1 +VERSION?=0.3.0 GO?=go LDFLAGS=-s -w -X github.com/darroyo/nasctl/internal/web.Version=$(VERSION) -X github.com/darroyo/nasctl/internal/web.Commit=$(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) BUILD_FLAGS=CGO_ENABLED=0 diff --git a/internal/web/handlers_system.go b/internal/web/handlers_system.go index ecfc67c..84a47ba 100644 --- a/internal/web/handlers_system.go +++ b/internal/web/handlers_system.go @@ -14,14 +14,14 @@ import ( type diskUsage struct { Path string `json:"path"` - TotalBytes uint64 `json:"total_bytes"` - FreeBytes uint64 `json:"free_bytes"` - UsedBytes uint64 `json:"used_bytes"` + TotalBytes uint64 `json:"total_bytes"` + FreeBytes uint64 `json:"free_bytes"` + UsedBytes uint64 `json:"used_bytes"` UsedPercent float64 `json:"used_percent"` - Source string `json:"source"` - UsedBy []string `json:"used_by,omitempty"` - Available bool `json:"available"` - Error string `json:"error,omitempty"` + Sources []string `json:"sources"` + UsedBy []string `json:"used_by,omitempty"` + Available bool `json:"available"` + Error string `json:"error,omitempty"` } type serviceStatus struct { @@ -45,6 +45,15 @@ func (s *Server) handleVersion(w http.ResponseWriter, r *http.Request) { }) } +func addSource(e *diskUsage, src string) { + for _, s := range e.Sources { + if s == src { + return + } + } + e.Sources = append(e.Sources, src) +} + func (s *Server) collectDiskUsage() []diskUsage { entries := make(map[string]*diskUsage) @@ -52,11 +61,13 @@ func (s *Server) collectDiskUsage() []diskUsage { if err == nil { for _, share := range shares { key := share.Path - if e, ok := entries[key]; ok { - e.UsedBy = append(e.UsedBy, share.Name) - } else { - entries[key] = &diskUsage{Path: key, Source: "samba", UsedBy: []string{share.Name}, Available: true} + e, ok := entries[key] + if !ok { + e = &diskUsage{Path: key, Sources: []string{}, Available: true} + entries[key] = e } + addSource(e, "samba") + e.UsedBy = append(e.UsedBy, share.Name) } } @@ -64,12 +75,12 @@ func (s *Server) collectDiskUsage() []diskUsage { if err == nil { for _, exp := range exports { key := exp.Path - label := "nfs:" + exp.Path - if e, ok := entries[key]; ok { - e.UsedBy = append(e.UsedBy, label) - } else { - entries[key] = &diskUsage{Path: key, Source: "nfs", UsedBy: []string{label}, Available: true} + e, ok := entries[key] + if !ok { + e = &diskUsage{Path: key, Sources: []string{}, Available: true} + entries[key] = e } + addSource(e, "nfs") } } @@ -77,21 +88,28 @@ func (s *Server) collectDiskUsage() []diskUsage { if err == nil { for _, m := range watched { key := m.Path - if _, ok := entries[key]; !ok { - entries[key] = &diskUsage{Path: key, Source: "manual", Available: true} + e, ok := entries[key] + if !ok { + e = &diskUsage{Path: key, Sources: []string{}, Available: true} + entries[key] = e } + addSource(e, "manual") } } var result []diskUsage for _, e := range entries { + sort.Strings(e.Sources) fillDiskUsage(e) result = append(result, *e) } sort.Slice(result, func(i, j int) bool { - if result[i].Source != result[j].Source { - return result[i].Source < result[j].Source + if len(result[i].Sources) == 0 || len(result[j].Sources) == 0 { + return len(result[i].Sources) > 0 + } + if result[i].Sources[0] != result[j].Sources[0] { + return result[i].Sources[0] < result[j].Sources[0] } return result[i].Path < result[j].Path }) diff --git a/web/src/api.ts b/web/src/api.ts index 527ff93..5018920 100644 --- a/web/src/api.ts +++ b/web/src/api.ts @@ -48,7 +48,7 @@ export interface DiskUsage { free_bytes: number; used_bytes: number; used_percent: number; - source: "system" | "mount" | "samba" | "nfs" | "manual"; + sources: ("manual" | "samba" | "nfs")[]; used_by?: string[]; available: boolean; error?: string; diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index ee5d022..c2c6689 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -2,6 +2,18 @@ import { useEffect, useState } from "react"; import { api, formatBytes, SystemStatus } from "../api"; import { useDirty } from "../DirtyContext"; +const SOURCE_COLORS: Record = { + samba: "bg-emerald-500/20 text-emerald-300", + nfs: "bg-amber-500/20 text-amber-300", + manual: "bg-cyan-500/20 text-cyan-300", +}; + +const SOURCE_LABELS: Record = { + samba: "SMB", + nfs: "NFS", + manual: "Vigilado", +}; + export default function Dashboard() { const [status, setStatus] = useState(null); const { modules } = useDirty(); @@ -11,7 +23,7 @@ export default function Dashboard() { }, []); const visibleDisks = status?.disks.filter( - (d) => d.source === "manual" || d.source === "samba" || d.source === "nfs" + (d) => d.sources.includes("manual") || d.sources.includes("samba") || d.sources.includes("nfs") ) ?? []; return ( @@ -27,9 +39,22 @@ export default function Dashboard() {
{visibleDisks.map((d) => (
-
- {d.path} - +
+
+ {d.path} + {d.sources.map((s) => ( + + {SOURCE_LABELS[s] ?? s} + + ))} + {d.used_by && d.used_by.length > 0 && ( + {d.used_by.join(", ")} + )} +
+ {formatBytes(d.used_bytes)} / {formatBytes(d.total_bytes)}
diff --git a/web/src/pages/Settings.tsx b/web/src/pages/Settings.tsx index 6cd3876..abe84c9 100644 --- a/web/src/pages/Settings.tsx +++ b/web/src/pages/Settings.tsx @@ -23,9 +23,14 @@ function DiskUsageItem({ disk }: { disk: SystemStatus["disks"][number] }) {
{disk.path} - - {SOURCE_LABELS[disk.source] ?? disk.source} - + {disk.sources.map((s) => ( + + {SOURCE_LABELS[s] ?? s} + + ))} {disk.used_by && disk.used_by.length > 0 && (
{disk.used_by.map((name) => ( @@ -125,8 +130,8 @@ export default function Settings() { setWatched(prev => prev.filter(m => m.id !== id)); } - const manualDisks = status?.disks.filter(d => d.source === "manual") ?? []; - const shareDisks = status?.disks.filter(d => d.source === "samba" || d.source === "nfs") ?? []; + const manualDisks = status?.disks.filter(d => d.sources.includes("manual")) ?? []; + const shareDisks = status?.disks.filter(d => d.sources.includes("samba") || d.sources.includes("nfs")) ?? []; return (