ux(storage): hide 'Eltávolítás a listából' on wizard-enrolled drives

List-removal only deletes the registry entry — it's the undo of a
manual path add. On an enrolled drive (/mnt/felhom-drives/) it leaves a
de-registered-but-still-bound limbo nobody wants; the real lifecycle
there is Biztonságos leválasztás / Végleges leszerelés. New
StoragePathView.IsEnrolled gates the button; manual paths keep it; the
decommissioned-branch removal (final cleanup) is unchanged. Endpoint
untouched.
This commit is contained in:
2026-07-02 21:29:14 +02:00
parent d256166fdd
commit d0c70a7da6
4 changed files with 62 additions and 1 deletions
+2
View File
@@ -109,6 +109,7 @@ type StoragePathView struct {
StoppedApps []string // stacks auto-stopped due to disconnect (for restart UI)
MigratedToLabel string // label of the drive data was migrated to
HasOtherPaths bool // true if other connected non-decommissioned paths exist
IsEnrolled bool // enrolled via the wizard (stable /mnt/felhom-drives/ path) — lifecycle is disconnect/decommission, not list-removal
}
func (s *Server) baseData(page, title string) map[string]interface{} {
@@ -964,6 +965,7 @@ func (s *Server) storagePageData() map[string]interface{} {
StoragePath: sp,
StoppedApps: sp.StoppedStacks,
HasOtherPaths: connectedCount > 1,
IsEnrolled: strings.HasPrefix(sp.Path, "/mnt/felhom-drives/"),
}
if sp.Disconnected {
// Skip I/O calls on disconnected drives — they'd hang or fail
@@ -293,3 +293,47 @@ func TestNoEmojiInTemplates(t *testing.T) {
}
}
}
// TestListRemovalHiddenForEnrolledDrives: "Eltávolítás a listából" is the undo of a MANUAL
// add only — a wizard-enrolled drive (/mnt/felhom-drives/) must not offer it (its lifecycle
// is disconnect/decommission), while a manually added path keeps it.
func TestListRemovalHiddenForEnrolledDrives(t *testing.T) {
s := testPageServer(t)
// two paths so neither is "the last one"; neither is default so the button condition can fire
if err := s.settings.AddStoragePath(settings.StoragePath{Path: "/mnt/felhom-drives/enrolled1", Label: "Enrolled", Schedulable: true, IsDefault: true}); err != nil {
t.Fatal(err)
}
if err := s.settings.AddStoragePath(settings.StoragePath{Path: "/mnt/manual_hdd", Label: "Manual", Schedulable: true}); err != nil {
t.Fatal(err)
}
body := getPage(t, s, "/storage").Body.String()
// the manual card renders the list-removal form, the enrolled card must not
manualForm := `value="/mnt/manual_hdd">`
enrolledForm := `value="/mnt/felhom-drives/enrolled1">`
removeAction := `action="/settings/storage/remove"`
if !strings.Contains(body, removeAction) {
t.Fatal("no list-removal form rendered at all — manual path should have one")
}
// slice per remove-form occurrence and check which path each carries
var enrolledHasRemove, manualHasRemove bool
for _, chunk := range strings.Split(body, removeAction)[1:] {
head := chunk
if len(head) > 400 {
head = head[:400]
}
if strings.Contains(head, enrolledForm) {
enrolledHasRemove = true
}
if strings.Contains(head, manualForm) {
manualHasRemove = true
}
}
if enrolledHasRemove {
t.Error("enrolled drive (/mnt/felhom-drives/) offers 'Eltávolítás a listából' — must be hidden")
}
if !manualHasRemove {
t.Error("manually added path lost its 'Eltávolítás a listából' button")
}
}
@@ -139,7 +139,11 @@
{{if .IsUSB}}
<button class="btn btn-xs btn-danger-outline" onclick="storageDisconnect('{{.Path}}', '{{.Label}}', {{.AppCount}})" title="Az itt tárolt alkalmazások leállnak, a meghajtó biztonságosan kihúzható. Az adatok megmaradnak; a meghajtó később újra csatlakoztatható.">Biztonságos leválasztás</button>
{{end}}
{{if and (not .IsDefault) (eq .AppCount 0)}}
{{/* List-removal is the undo of a MANUAL add only. Wizard-enrolled drives
(/mnt/felhom-drives/) have a real lifecycle — Biztonságos leválasztás /
Végleges leszerelés — and a de-registered-but-still-bound state is never
what the customer wants, so the button is hidden for them. */}}
{{if and (not .IsDefault) (eq .AppCount 0) (not .IsEnrolled)}}
<form method="POST" action="/settings/storage/remove" style="display:inline"
onsubmit="return storageRemoveDialog(event, this, 'Biztosan eltávolítja a(z) {{.Path}} adattárolót?')">
{{$.CSRFField}}