Skip to content

Commit 0d42cc7

Browse files
marcusclaude
andcommitted
fix: add undo data and missing field updates to TUI actions
TUI action handlers were missing PreviousData/NewData in LogAction calls, making undo impossible. Also fixes markForReview not setting ImplementerSession and reopenIssue not clearing ReviewerSession. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f4e4ef9 commit 0d42cc7

1 file changed

Lines changed: 57 additions & 20 deletions

File tree

pkg/monitor/actions.go

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package monitor
22

33
import (
4+
"encoding/json"
45
"time"
56

67
tea "github.com/charmbracelet/bubbletea"
@@ -50,18 +51,27 @@ func (m Model) markForReview() (tea.Model, tea.Cmd) {
5051
return m, nil
5152
}
5253

54+
// Capture previous state for undo
55+
prevData, _ := json.Marshal(issue)
56+
5357
// Update status
5458
issue.Status = models.StatusInReview
59+
if issue.ImplementerSession == "" {
60+
issue.ImplementerSession = m.SessionID
61+
}
5562
if err := m.DB.UpdateIssue(issue); err != nil {
5663
return m, nil
5764
}
5865

5966
// Log action for undo
67+
newData, _ := json.Marshal(issue)
6068
m.DB.LogAction(&models.ActionLog{
61-
SessionID: m.SessionID,
62-
ActionType: models.ActionReview,
63-
EntityType: "issue",
64-
EntityID: issueID,
69+
SessionID: m.SessionID,
70+
ActionType: models.ActionReview,
71+
EntityType: "issue",
72+
EntityID: issueID,
73+
PreviousData: string(prevData),
74+
NewData: string(newData),
6575
})
6676

6777
// Cascade DOWN to descendants if this is a parent issue (epic)
@@ -137,6 +147,13 @@ func (m Model) executeDelete() (tea.Model, tea.Cmd) {
137147

138148
deletedID := m.ConfirmIssueID
139149

150+
// Capture previous state for undo (before deletion)
151+
issue, err := m.DB.GetIssue(deletedID)
152+
var prevData []byte
153+
if err == nil && issue != nil {
154+
prevData, _ = json.Marshal(issue)
155+
}
156+
140157
// Delete issue
141158
if err := m.DB.DeleteIssue(deletedID); err != nil {
142159
m.closeDeleteConfirmModal()
@@ -145,10 +162,11 @@ func (m Model) executeDelete() (tea.Model, tea.Cmd) {
145162

146163
// Log action for undo
147164
m.DB.LogAction(&models.ActionLog{
148-
SessionID: m.SessionID,
149-
ActionType: models.ActionDelete,
150-
EntityType: "issue",
151-
EntityID: deletedID,
165+
SessionID: m.SessionID,
166+
ActionType: models.ActionDelete,
167+
EntityType: "issue",
168+
EntityID: deletedID,
169+
PreviousData: string(prevData),
152170
})
153171

154172
// Close the delete confirmation modal
@@ -231,6 +249,9 @@ func (m Model) executeCloseWithReason() (tea.Model, tea.Cmd) {
231249
return m, nil
232250
}
233251

252+
// Capture previous state for undo
253+
prevData, _ := json.Marshal(issue)
254+
234255
// Update status
235256
now := time.Now()
236257
issue.Status = models.StatusClosed
@@ -241,11 +262,14 @@ func (m Model) executeCloseWithReason() (tea.Model, tea.Cmd) {
241262
}
242263

243264
// Log action for undo
265+
newData, _ := json.Marshal(issue)
244266
m.DB.LogAction(&models.ActionLog{
245-
SessionID: m.SessionID,
246-
ActionType: models.ActionClose,
247-
EntityType: "issue",
248-
EntityID: issueID,
267+
SessionID: m.SessionID,
268+
ActionType: models.ActionClose,
269+
EntityType: "issue",
270+
EntityID: issueID,
271+
PreviousData: string(prevData),
272+
NewData: string(newData),
249273
})
250274

251275
// Add progress log with optional reason
@@ -340,6 +364,9 @@ func (m Model) approveIssue() (tea.Model, tea.Cmd) {
340364
return m, nil
341365
}
342366

367+
// Capture previous state for undo
368+
prevData, _ := json.Marshal(issue)
369+
343370
// Update status
344371
now := time.Now()
345372
issue.Status = models.StatusClosed
@@ -353,11 +380,14 @@ func (m Model) approveIssue() (tea.Model, tea.Cmd) {
353380
m.DB.RecordSessionAction(issue.ID, m.SessionID, models.ActionSessionReviewed)
354381

355382
// Log action for undo
383+
newData, _ := json.Marshal(issue)
356384
m.DB.LogAction(&models.ActionLog{
357-
SessionID: m.SessionID,
358-
ActionType: models.ActionApprove,
359-
EntityType: "issue",
360-
EntityID: issue.ID,
385+
SessionID: m.SessionID,
386+
ActionType: models.ActionApprove,
387+
EntityType: "issue",
388+
EntityID: issue.ID,
389+
PreviousData: string(prevData),
390+
NewData: string(newData),
361391
})
362392

363393
// Cascade DOWN to descendants if this is a parent issue (epic)
@@ -444,8 +474,12 @@ func (m Model) reopenIssue() (tea.Model, tea.Cmd) {
444474
})
445475
}
446476

477+
// Capture previous state for undo
478+
prevData, _ := json.Marshal(issue)
479+
447480
// Update status
448481
issue.Status = models.StatusOpen
482+
issue.ReviewerSession = ""
449483
issue.ClosedAt = nil
450484
if err := m.DB.UpdateIssue(issue); err != nil {
451485
m.StatusMessage = "Failed to reopen: " + err.Error()
@@ -456,11 +490,14 @@ func (m Model) reopenIssue() (tea.Model, tea.Cmd) {
456490
}
457491

458492
// Log action for undo
493+
newData, _ := json.Marshal(issue)
459494
m.DB.LogAction(&models.ActionLog{
460-
SessionID: m.SessionID,
461-
ActionType: models.ActionReopen,
462-
EntityType: "issue",
463-
EntityID: issueID,
495+
SessionID: m.SessionID,
496+
ActionType: models.ActionReopen,
497+
EntityType: "issue",
498+
EntityID: issueID,
499+
PreviousData: string(prevData),
500+
NewData: string(newData),
464501
})
465502

466503
m.StatusMessage = "REOPENED " + issueID

0 commit comments

Comments
 (0)