From 5f37dc9b6f6b79da04da70ae0c33ec8d02998587 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Wed, 1 Jul 2026 02:21:42 -0400 Subject: feat: qol improvements to items crud in admin gui --- internal/admin/undo.go | 180 +++++++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 80 deletions(-) (limited to 'internal/admin/undo.go') diff --git a/internal/admin/undo.go b/internal/admin/undo.go index 4921ae5..bec3c35 100644 --- a/internal/admin/undo.go +++ b/internal/admin/undo.go @@ -2,6 +2,7 @@ package admin import ( "encoding/json" + "fmt" "log" "os" "path/filepath" @@ -27,6 +28,19 @@ type ChangeDesc struct { ExtraFiles []ExtraFile `json:"extra_files,omitempty"` } +func (c ChangeDesc) ShortDesc() string { + switch { + case c.IsCreate: + return fmt.Sprintf("Created %s", filepath.Base(c.FilePath)) + case c.IsDelete: + return fmt.Sprintf("Deleted %s", filepath.Base(c.FilePath)) + case c.NewFilePath != "": + return fmt.Sprintf("Renamed %s", filepath.Base(c.NewFilePath)) + default: + return fmt.Sprintf("Edited %s", filepath.Base(c.FilePath)) + } +} + type UndoInfo struct { CanUndo bool `json:"can_undo"` CanRedo bool `json:"can_redo"` @@ -52,6 +66,7 @@ func NewUndoStack(dataDir string) *UndoStack { filePath: filepath.Join(dataDir, ".admin_history.json"), } us.load() + us.redo = nil return us } @@ -65,6 +80,7 @@ func (us *UndoStack) Push(desc ChangeDesc) { us.history = us.history[len(us.history)-us.maxSize:] } us.save() + log.Printf("undo: push %s", desc.ShortDesc()) } func (us *UndoStack) Undo() *ChangeDesc { @@ -74,47 +90,16 @@ func (us *UndoStack) Undo() *ChangeDesc { return nil } last := us.history[len(us.history)-1] - us.history = us.history[:len(us.history)-1] - if last.NewFilePath != "" { - os.Remove(last.NewFilePath) - } - if last.IsDelete { - if err := os.WriteFile(last.FilePath, last.OldContent, 0644); err != nil { - log.Printf("undo: failed to restore deleted file %s: %v", last.FilePath, err) - return nil - } - for _, ef := range last.ExtraFiles { - if err := os.WriteFile(ef.FilePath, ef.OldContent, 0644); err != nil { - log.Printf("undo: failed to restore extra file %s: %v", ef.FilePath, err) - } - } - } else if last.IsCreate { - os.Remove(last.FilePath) - for _, ef := range last.ExtraFiles { - os.Remove(ef.FilePath) - } - } else { - if last.NewFilePath != "" { - if err := os.WriteFile(last.FilePath, last.OldContent, 0644); err != nil { - log.Printf("undo: failed to revert move %s: %v", last.FilePath, err) - return nil - } - } else { - if err := os.WriteFile(last.FilePath, last.OldContent, 0644); err != nil { - log.Printf("undo: failed to revert file %s: %v", last.FilePath, err) - return nil - } - } - for _, ef := range last.ExtraFiles { - if err := os.WriteFile(ef.FilePath, ef.OldContent, 0644); err != nil { - log.Printf("undo: failed to restore extra file %s: %v", ef.FilePath, err) - } - } + if err := us.applyUndo(last); err != nil { + log.Printf("undo: failed %s: %v", last.ShortDesc(), err) + return nil } + us.history = us.history[:len(us.history)-1] us.redo = append(us.redo, last) us.save() + log.Printf("undo: undid %s", last.ShortDesc()) return &last } @@ -125,57 +110,88 @@ func (us *UndoStack) Redo() *ChangeDesc { return nil } last := us.redo[len(us.redo)-1] + + if err := us.applyRedo(last); err != nil { + log.Printf("redo: failed %s: %v", last.ShortDesc(), err) + return nil + } + us.redo = us.redo[:len(us.redo)-1] + us.history = append(us.history, last) + us.save() + log.Printf("redo: redid %s", last.ShortDesc()) + return &last +} - if last.NewFilePath != "" { - os.Remove(last.FilePath) +func (us *UndoStack) applyUndo(c ChangeDesc) error { + if c.NewFilePath != "" { + os.Remove(c.NewFilePath) } - if last.IsCreate { - if last.NewFilePath != "" { - if err := os.WriteFile(last.NewFilePath, last.NewContent, 0644); err != nil { - log.Printf("redo: failed to recreate file %s: %v", last.NewFilePath, err) - return nil - } - } else { - if err := os.WriteFile(last.FilePath, last.NewContent, 0644); err != nil { - log.Printf("redo: failed to recreate file %s: %v", last.FilePath, err) - return nil - } + if c.IsDelete { + if c.OldContent == nil { + return fmt.Errorf("no backup content to restore for %s", c.FilePath) } - for _, ef := range last.ExtraFiles { - if err := os.WriteFile(ef.FilePath, ef.NewContent, 0644); err != nil { - log.Printf("redo: failed to create extra file %s: %v", ef.FilePath, err) - } + if err := os.WriteFile(c.FilePath, c.OldContent, 0644); err != nil { + return fmt.Errorf("restore deleted %s: %w", c.FilePath, err) } - } else if last.IsDelete { - os.Remove(last.FilePath) - for _, ef := range last.ExtraFiles { - if err := os.WriteFile(ef.FilePath, ef.NewContent, 0644); err != nil { - log.Printf("redo: failed to write extra file %s: %v", ef.FilePath, err) - } + for _, ef := range c.ExtraFiles { + os.WriteFile(ef.FilePath, ef.OldContent, 0644) + } + } else if c.IsCreate { + os.Remove(c.FilePath) + for _, ef := range c.ExtraFiles { + os.Remove(ef.FilePath) } } else { - if last.NewFilePath != "" { - if err := os.WriteFile(last.NewFilePath, last.NewContent, 0644); err != nil { - log.Printf("redo: failed to reapply move %s: %v", last.NewFilePath, err) - return nil - } - } else { - if err := os.WriteFile(last.FilePath, last.NewContent, 0644); err != nil { - log.Printf("redo: failed to reapply file %s: %v", last.FilePath, err) - return nil - } + target := c.FilePath + content := c.OldContent + if c.NewFilePath != "" { + target = c.FilePath } - for _, ef := range last.ExtraFiles { - if err := os.WriteFile(ef.FilePath, ef.NewContent, 0644); err != nil { - log.Printf("redo: failed to write extra file %s: %v", ef.FilePath, err) - } + if err := os.WriteFile(target, content, 0644); err != nil { + return fmt.Errorf("revert %s: %w", target, err) + } + for _, ef := range c.ExtraFiles { + os.WriteFile(ef.FilePath, ef.OldContent, 0644) } } + return nil +} - us.history = append(us.history, last) - us.save() - return &last +func (us *UndoStack) applyRedo(c ChangeDesc) error { + if c.NewFilePath != "" { + os.Remove(c.FilePath) + } + if c.IsCreate { + target := c.FilePath + if c.NewFilePath != "" { + target = c.NewFilePath + } + if err := os.WriteFile(target, c.NewContent, 0644); err != nil { + return fmt.Errorf("recreate %s: %w", target, err) + } + for _, ef := range c.ExtraFiles { + os.WriteFile(ef.FilePath, ef.NewContent, 0644) + } + } else if c.IsDelete { + os.Remove(c.FilePath) + for _, ef := range c.ExtraFiles { + os.WriteFile(ef.FilePath, ef.NewContent, 0644) + } + } else { + target := c.FilePath + content := c.NewContent + if c.NewFilePath != "" { + target = c.NewFilePath + } + if err := os.WriteFile(target, content, 0644); err != nil { + return fmt.Errorf("reapply %s: %w", target, err) + } + for _, ef := range c.ExtraFiles { + os.WriteFile(ef.FilePath, ef.NewContent, 0644) + } + } + return nil } func (us *UndoStack) Info() UndoInfo { @@ -187,11 +203,11 @@ func (us *UndoStack) Info() UndoInfo { } if len(us.history) > 0 { info.CanUndo = true - info.UndoDesc = us.history[len(us.history)-1].Description + info.UndoDesc = us.history[len(us.history)-1].ShortDesc() } if len(us.redo) > 0 { info.CanRedo = true - info.RedoDesc = us.redo[len(us.redo)-1].Description + info.RedoDesc = us.redo[len(us.redo)-1].ShortDesc() } return info } @@ -251,7 +267,9 @@ func (us *UndoStack) save() { log.Printf("undo: failed to marshal history: %v", err) return } - os.WriteFile(us.filePath, b, 0644) + if err := os.WriteFile(us.filePath, b, 0644); err != nil { + log.Printf("undo: failed to write history file: %v", err) + } } func (us *UndoStack) load() { @@ -259,6 +277,7 @@ func (us *UndoStack) load() { if err != nil { return } + log.Printf("undo: loaded history from %s", us.filePath) type extraEntry struct { FilePath string `json:"file_path"` OldContent string `json:"old_content"` @@ -280,6 +299,7 @@ func (us *UndoStack) load() { Redo []entry `json:"redo"` } if err := json.Unmarshal(data, &saveData); err != nil { + log.Printf("undo: failed to unmarshal history: %v", err) return } fromEntries := func(entries []entry) []ChangeDesc { @@ -308,5 +328,5 @@ func (us *UndoStack) load() { return changes } us.history = fromEntries(saveData.History) - us.redo = fromEntries(saveData.Redo) + log.Printf("undo: loaded %d history entries", len(us.history)) } -- cgit v1.2.3