Resolved some of suggestions from copilot

This commit is contained in:
Moira Daniella A Sebastian
2026-03-10 15:17:42 +01:00
parent 1cdfb56531
commit 153351ce81
4 changed files with 59 additions and 10 deletions

View File

@@ -6,10 +6,25 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
) )
// modalBoxWidth returns a clamped width for modal content. Never returns a value < 1.
func modalBoxWidth(maxWidth, width int) int {
if width < 5 {
return 1
}
w := min(maxWidth, width-4)
if w < 1 {
return 1
}
return w
}
// components contains reusable TUI modal renderers for issue actions. // components contains reusable TUI modal renderers for issue actions.
func RenderEditTitle(width, height int, inputView string) string { func RenderEditTitle(width, height int, inputView string) string {
editBoxWidth := min(60, width-4) if width < 5 || height < 5 {
return ""
}
editBoxWidth := modalBoxWidth(60, width)
editContent := lipgloss.JoinVertical(lipgloss.Left, editContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Edit title (Enter to save, Esc to cancel):"), styles.LabelStyle.Render("Edit title (Enter to save, Esc to cancel):"),
inputView, inputView,
@@ -22,7 +37,10 @@ func RenderEditTitle(width, height int, inputView string) string {
} }
func RenderEditDescription(width, height int, inputView string) string { func RenderEditDescription(width, height int, inputView string) string {
editBoxWidth := min(60, width-4) if width < 5 || height < 5 {
return ""
}
editBoxWidth := modalBoxWidth(60, width)
editContent := lipgloss.JoinVertical(lipgloss.Left, editContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Edit description (Ctrl+S to save, Esc to cancel):"), styles.LabelStyle.Render("Edit description (Ctrl+S to save, Esc to cancel):"),
inputView, inputView,
@@ -35,7 +53,10 @@ func RenderEditDescription(width, height int, inputView string) string {
} }
func RenderCreateIssue(width, height int, inputView string) string { func RenderCreateIssue(width, height int, inputView string) string {
createBoxWidth := min(60, width-4) if width < 5 || height < 5 {
return ""
}
createBoxWidth := modalBoxWidth(60, width)
createContent := lipgloss.JoinVertical(lipgloss.Left, createContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("New issue (Enter to create, Esc to cancel):"), styles.LabelStyle.Render("New issue (Enter to create, Esc to cancel):"),
inputView, inputView,
@@ -48,11 +69,14 @@ func RenderCreateIssue(width, height int, inputView string) string {
} }
func RenderConfirmDelete(width, height int, issueID string) string { func RenderConfirmDelete(width, height int, issueID string) string {
if width < 5 || height < 5 {
return ""
}
confirmContent := lipgloss.JoinVertical(lipgloss.Left, confirmContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Delete issue "+issueID+"?"), styles.LabelStyle.Render("Delete issue "+issueID+"?"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("Press y to delete, n or Esc to cancel"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("Press y to delete, n or Esc to cancel"),
) )
confirmBoxWidth := min(50, width-4) confirmBoxWidth := modalBoxWidth(50, width)
confirmBox := styles.ContainerStyle. confirmBox := styles.ContainerStyle.
Width(confirmBoxWidth). Width(confirmBoxWidth).
BorderForeground(styles.PrimaryBorder). BorderForeground(styles.PrimaryBorder).
@@ -61,12 +85,15 @@ func RenderConfirmDelete(width, height int, issueID string) string {
} }
func RenderChooseStatus(width, height int, issueID string) string { func RenderChooseStatus(width, height int, issueID string) string {
if width < 5 || height < 5 {
return ""
}
statusContent := lipgloss.JoinVertical(lipgloss.Left, statusContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Change status for "+issueID+":"), styles.LabelStyle.Render("Change status for "+issueID+":"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("o = open i = in_progress c = closed"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("o = open i = in_progress c = closed"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"),
) )
statusBoxWidth := min(50, width-4) statusBoxWidth := modalBoxWidth(50, width)
statusBox := styles.ContainerStyle. statusBox := styles.ContainerStyle.
Width(statusBoxWidth). Width(statusBoxWidth).
BorderForeground(styles.PrimaryBorder). BorderForeground(styles.PrimaryBorder).
@@ -75,12 +102,15 @@ func RenderChooseStatus(width, height int, issueID string) string {
} }
func RenderChoosePriority(width, height int, issueID string) string { func RenderChoosePriority(width, height int, issueID string) string {
if width < 5 || height < 5 {
return ""
}
priorityContent := lipgloss.JoinVertical(lipgloss.Left, priorityContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Change priority for "+issueID+":"), styles.LabelStyle.Render("Change priority for "+issueID+":"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("0 = irrelevant 1 = low 2 = normal 3 = high 4 = critical"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("0 = irrelevant 1 = low 2 = normal 3 = high 4 = critical"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"),
) )
priorityBoxWidth := min(60, width-4) priorityBoxWidth := modalBoxWidth(60, width)
priorityBox := styles.ContainerStyle. priorityBox := styles.ContainerStyle.
Width(priorityBoxWidth). Width(priorityBoxWidth).
BorderForeground(styles.PrimaryBorder). BorderForeground(styles.PrimaryBorder).
@@ -89,12 +119,15 @@ func RenderChoosePriority(width, height int, issueID string) string {
} }
func RenderChooseType(width, height int, issueID string) string { func RenderChooseType(width, height int, issueID string) string {
if width < 5 || height < 5 {
return ""
}
typeContent := lipgloss.JoinVertical(lipgloss.Left, typeContent := lipgloss.JoinVertical(lipgloss.Left,
styles.LabelStyle.Render("Change type for "+issueID+":"), styles.LabelStyle.Render("Change type for "+issueID+":"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("b = bug f = feature t = task e = epic c = chore"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("b = bug f = feature t = task e = epic c = chore"),
lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"), lipgloss.NewStyle().Foreground(styles.FaintText).Render("Esc = cancel"),
) )
typeBoxWidth := min(65, width-4) typeBoxWidth := modalBoxWidth(65, width)
typeBox := styles.ContainerStyle. typeBox := styles.ContainerStyle.
Width(typeBoxWidth). Width(typeBoxWidth).
BorderForeground(styles.PrimaryBorder). BorderForeground(styles.PrimaryBorder).

View File

@@ -14,10 +14,15 @@ type KanbanKeyMap struct {
MoveColumnRight key.Binding MoveColumnRight key.Binding
MoveIssueLeft key.Binding MoveIssueLeft key.Binding
MoveIssueRight key.Binding MoveIssueRight key.Binding
SubmitValidation key.Binding
} }
var defaultKanbanKeyMap = KanbanKeyMap{ var defaultKanbanKeyMap = KanbanKeyMap{
CommonKeyMap: components.DefaultCommonKeyMap(), CommonKeyMap: components.DefaultCommonKeyMap(),
SubmitValidation: key.NewBinding(
key.WithKeys("S"),
key.WithHelp("S", "submit validation"),
),
SwitchToDashboard: key.NewBinding( SwitchToDashboard: key.NewBinding(
key.WithKeys("v"), key.WithKeys("v"),
key.WithHelp("v", "dashboard 1"), key.WithHelp("v", "dashboard 1"),
@@ -44,6 +49,13 @@ func (d *Model) handleKeyMsg(msg tea.KeyMsg) tea.Cmd {
var cmd tea.Cmd var cmd tea.Cmd
switch { switch {
case key.Matches(msg, d.keyMap.SubmitValidation):
if d.submitChan != nil {
select {
case d.submitChan <- struct{}{}:
default:
}
}
case key.Matches(msg, d.keyMap.Help): case key.Matches(msg, d.keyMap.Help):
d.helpBar.ToggleHelp() d.helpBar.ToggleHelp()
case key.Matches(msg, d.keyMap.Quit): case key.Matches(msg, d.keyMap.Quit):

View File

@@ -55,11 +55,12 @@ type Model struct {
typeIssueID string typeIssueID string
feedbackChan chan models.ValidationFeedback feedbackChan chan models.ValidationFeedback
quitChan chan bool quitChan chan bool
submitChan chan<- struct{}
currentFeedback models.ValidationFeedback currentFeedback models.ValidationFeedback
showComplete bool showComplete bool
} }
func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool) *Model { func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, quitChan chan bool, submitChan chan<- struct{}) *Model {
m := &Model{ m := &Model{
header: components.NewHeader("Kanban Board"), header: components.NewHeader("Kanban Board"),
keyMap: defaultKanbanKeyMap, keyMap: defaultKanbanKeyMap,
@@ -70,6 +71,7 @@ func NewDashboard(app *app.App, feedbackChan chan models.ValidationFeedback, qui
focusOnDetail: false, focusOnDetail: false,
feedbackChan: feedbackChan, feedbackChan: feedbackChan,
quitChan: quitChan, quitChan: quitChan,
submitChan: submitChan,
} }
allIssues, _ := app.Issues.SearchIssues(context.Background(), "", models.IssueFilter{}) allIssues, _ := app.Issues.SearchIssues(context.Background(), "", models.IssueFilter{})

View File

@@ -14,6 +14,7 @@ type RootModel struct {
app *app.App app *app.App
feedbackChan chan models.ValidationFeedback feedbackChan chan models.ValidationFeedback
quitChan chan bool quitChan chan bool
submitChan chan<- struct{}
lastSize tea.WindowSizeMsg lastSize tea.WindowSizeMsg
hasSize bool hasSize bool
} }
@@ -25,6 +26,7 @@ func NewRootView(app *app.App, feedbackChan chan models.ValidationFeedback, quit
app: app, app: app,
feedbackChan: feedbackChan, feedbackChan: feedbackChan,
quitChan: quitChan, quitChan: quitChan,
submitChan: submitChan,
} }
} }
@@ -44,7 +46,7 @@ func (r *RootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return r, cmd return r, cmd
case msgs.SwitchToDashboardMsg: case msgs.SwitchToDashboardMsg:
// switch back to dashboard 1 and apply the last known size. // switch back to dashboard 1 and apply the last known size.
r.currentView = dashboard.NewDashboard(r.app, r.feedbackChan, r.quitChan, r.app.SubmitChan) r.currentView = dashboard.NewDashboard(r.app, r.feedbackChan, r.quitChan, r.submitChan)
var cmds []tea.Cmd var cmds []tea.Cmd
if r.hasSize { if r.hasSize {
// check if there is a size, and then update it // check if there is a size, and then update it
@@ -59,7 +61,7 @@ func (r *RootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return r, tea.Batch(cmds...) return r, tea.Batch(cmds...)
case msgs.SwitchToKanbanBoardMsg: case msgs.SwitchToKanbanBoardMsg:
// switch to kanban board and apply the last known size. // switch to kanban board and apply the last known size.
r.currentView = kanban.NewDashboard(r.app, r.feedbackChan, r.quitChan) r.currentView = kanban.NewDashboard(r.app, r.feedbackChan, r.quitChan, r.submitChan)
var cmds []tea.Cmd var cmds []tea.Cmd
if r.hasSize { if r.hasSize {
// check if there is a size, and then update it // check if there is a size, and then update it