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:
@@ -1,5 +1,16 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v0.98.3 — hide "Eltávolítás a listából" on wizard-enrolled drives (2026-07-02)
|
||||||
|
|
||||||
|
User feedback follow-up: list-removal (registry-entry delete; data + mount untouched) is only
|
||||||
|
meaningful as the undo of a MANUAL path add. On a wizard-enrolled drive (/mnt/felhom-drives/) the
|
||||||
|
resulting de-registered-but-still-agent-bound limbo is never what the customer wants — its real
|
||||||
|
lifecycle is Biztonságos leválasztás / Végleges leszerelés. New `StoragePathView.IsEnrolled`
|
||||||
|
(path-prefix check) gates the button; manually added paths keep it, and the decommissioned-branch
|
||||||
|
"Eltávolítás a rendszerből" (final cleanup) is unchanged. Endpoint untouched.
|
||||||
|
Test: enrolled card must not render the remove form, manual card must (TestListRemovalHiddenForEnrolledDrives).
|
||||||
|
|
||||||
|
|
||||||
### v0.98.2 — drive-card action clarity: dedupe + self-documenting labels (2026-07-02)
|
### v0.98.2 — drive-card action clarity: dedupe + self-documenting labels (2026-07-02)
|
||||||
|
|
||||||
User feedback: two "Leválasztás" buttons per drive, and four near-synonymous labels (Letiltás /
|
User feedback: two "Leválasztás" buttons per drive, and four near-synonymous labels (Letiltás /
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ type StoragePathView struct {
|
|||||||
StoppedApps []string // stacks auto-stopped due to disconnect (for restart UI)
|
StoppedApps []string // stacks auto-stopped due to disconnect (for restart UI)
|
||||||
MigratedToLabel string // label of the drive data was migrated to
|
MigratedToLabel string // label of the drive data was migrated to
|
||||||
HasOtherPaths bool // true if other connected non-decommissioned paths exist
|
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{} {
|
func (s *Server) baseData(page, title string) map[string]interface{} {
|
||||||
@@ -964,6 +965,7 @@ func (s *Server) storagePageData() map[string]interface{} {
|
|||||||
StoragePath: sp,
|
StoragePath: sp,
|
||||||
StoppedApps: sp.StoppedStacks,
|
StoppedApps: sp.StoppedStacks,
|
||||||
HasOtherPaths: connectedCount > 1,
|
HasOtherPaths: connectedCount > 1,
|
||||||
|
IsEnrolled: strings.HasPrefix(sp.Path, "/mnt/felhom-drives/"),
|
||||||
}
|
}
|
||||||
if sp.Disconnected {
|
if sp.Disconnected {
|
||||||
// Skip I/O calls on disconnected drives — they'd hang or fail
|
// 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}}
|
{{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>
|
<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}}
|
{{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"
|
<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?')">
|
onsubmit="return storageRemoveDialog(event, this, 'Biztosan eltávolítja a(z) {{.Path}} adattárolót?')">
|
||||||
{{$.CSRFField}}
|
{{$.CSRFField}}
|
||||||
|
|||||||
Reference in New Issue
Block a user