aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/undo.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-01 02:21:42 -0400
committerhistoria <[not public]>2026-07-01 02:21:42 -0400
commit5f37dc9b6f6b79da04da70ae0c33ec8d02998587 (patch)
treef7c309e36267a4c456fcf5bca800e614507a80af /internal/admin/undo.go
parentfee376102192dc6f24297a7b11324636ace3a07d (diff)
downloadthehouseoficarus-5f37dc9b6f6b79da04da70ae0c33ec8d02998587.tar.gz
feat: qol improvements to items crud in admin gui
Diffstat (limited to 'internal/admin/undo.go')
-rw-r--r--internal/admin/undo.go180
1 files changed, 100 insertions, 80 deletions
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))
}