TASK BACKLOG REFINEMENT fix for closing reason

This commit is contained in:
Ine Maria Nilssen Aanonsen
2026-03-12 11:46:58 +01:00
parent 9aa940fcca
commit 2ce04896ee
7 changed files with 229 additions and 28 deletions

View File

@@ -56,11 +56,15 @@ type Model struct {
editingAssignee bool // true while editing assignee
assigneeInput textinput.Model
assigneeIssueID string
feedbackChan chan models.ValidationFeedback
quitChan chan bool
submitChan chan<- struct{}
currentFeedback models.ValidationFeedback
showComplete bool
choosingCloseReason bool // true while choosing a close reason
closeReasonIssueID string
closingOtherReason bool // true while entering a custom close reason
closeReasonInput textarea.Model
feedbackChan chan models.ValidationFeedback
quitChan chan bool
submitChan chan<- struct{}
currentFeedback models.ValidationFeedback
showComplete bool
}
func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool, submitChan chan<- struct{}) *Model {
@@ -94,6 +98,12 @@ func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, qui
m.descriptionInput = inputs.Description
m.assigneeInput = inputs.Assignee
closeReasonTa := textarea.New()
closeReasonTa.Placeholder = "Enter closing reason..."
closeReasonTa.SetWidth(56)
closeReasonTa.SetHeight(4)
m.closeReasonInput = closeReasonTa
if selected := m.todoList.SelectedItem(); selected.ID != "" {
m.issueDetail.SetIssue(selected.Issue)
} else if selected := m.inProgList.SelectedItem(); selected.ID != "" {
@@ -160,7 +170,9 @@ func (m *Model) Init() tea.Cmd {
// IsInModal returns true when a modal (edit, create, delete confirm, choose status/priority/type) is active.
func (m *Model) IsInModal() bool {
return m.editingTitle || m.creatingIssue || m.editingDescription ||
m.choosingStatus || m.choosingPriority || m.confirmingDelete || m.choosingType || m.editingAssignee
m.choosingStatus || m.choosingPriority || m.confirmingDelete ||
m.choosingType || m.editingAssignee ||
m.choosingCloseReason || m.closingOtherReason
}
func (m *Model) IsFocusedOnList() bool {

View File

@@ -262,7 +262,9 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
issueID := m.statusIssueID
m.choosingStatus = false
m.statusIssueID = ""
return m, issues.UpdateIssueStatusCmd(m.app, issueID, string(models.StatusClosed))
m.choosingCloseReason = true
m.closeReasonIssueID = issueID
return m, nil
case "esc":
m.choosingStatus = false
m.statusIssueID = ""
@@ -270,6 +272,56 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
if m.choosingCloseReason {
var reason string
switch msg.String() {
case "d":
reason = "Done"
case "u":
reason = "Duplicate issue"
case "w":
reason = "Won't fix"
case "o":
reason = "Obsolete"
case "h":
m.choosingCloseReason = false
m.closingOtherReason = true
m.closeReasonInput.SetValue("")
return m, nil
case "esc":
m.choosingCloseReason = false
m.closeReasonIssueID = ""
return m, nil
}
if reason != "" {
issueID := m.closeReasonIssueID
m.choosingCloseReason = false
m.closeReasonIssueID = ""
return m, issues.CloseIssueCmd(m.app, issueID, reason)
}
}
if m.closingOtherReason {
switch msg.String() {
case "enter":
reason := m.closeReasonInput.Value()
if reason != "" {
issueID := m.closeReasonIssueID
m.closingOtherReason = false
m.closeReasonIssueID = ""
return m, issues.CloseIssueCmd(m.app, issueID, reason)
}
case "esc":
m.closingOtherReason = false
m.closeReasonIssueID = ""
return m, nil
}
var cmd tea.Cmd
m.closeReasonInput, cmd = m.closeReasonInput.Update(msg)
return m, cmd
}
if m.choosingPriority {
switch msg.String() {
case "0", "1", "2", "3", "4":

View File

@@ -76,6 +76,35 @@ func (m *Model) View() string {
mainView = lipgloss.JoinVertical(lipgloss.Left, header, content, spacer, footer)
}
if m.choosingCloseReason {
reasonContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Choose closing reason for "+m.closeReasonIssueID+":"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("d = Done u = Duplicate issue w = Won't fix o = Obsolete h = Other"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"),
)
reasonBoxWidth := min(70, m.width-4)
reasonBox := styles.ContainerStyle.
Width(reasonBoxWidth).
BorderForeground(styles.PrimaryBorder).
Render(reasonContent)
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, reasonBox)
}
if m.closingOtherReason {
editBoxWidth := min(60, m.width-4)
m.closeReasonInput.SetWidth(editBoxWidth - 2)
m.closeReasonInput.SetHeight(4)
editContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Enter closing reason for "+m.closeReasonIssueID+" (Enter to save, Esc to cancel):"),
m.closeReasonInput.View(),
)
editBox := styles.ContainerStyle.
Width(editBoxWidth).
BorderForeground(styles.PrimaryBorder).
Render(editContent)
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, editBox)
}
return components.RenderModals(
m.width,
m.height,