Documentation
¶
Overview ¶
Package monitor provides the TUI monitor for td.
Index ¶
- Constants
- Variables
- func ComputeBoardIssueCategories(database *db.DB, issues []models.BoardIssueView, sessionID string)
- func DefaultBoardStatusFilter() map[models.Status]bool
- func OverlayModal(background, modal string, width, height int) string
- func StatusFilterMapToSlice(filter map[models.Status]bool) []models.Status
- type ActivityItem
- type BoardIssuesMsg
- type BoardMode
- type BoardViewMode
- type BoardsDataMsg
- type ClearStatusMsg
- type EditorField
- type EditorFinishedMsg
- type EmbeddedOptions
- type FormMode
- type FormState
- type HandoffsDataMsg
- type IssueDetailsMsg
- type MarkdownRenderedMsg
- type ModalEntry
- type ModalRenderer
- type ModalType
- type Model
- func (m *Model) Close() error
- func (m Model) CurrentContextString() string
- func (m *Model) CurrentModal() *ModalEntry
- func (m Model) HitTestDivider(x, y int) int
- func (m Model) HitTestPanel(x, y int) Panel
- func (m Model) HitTestRow(panel Panel, y int) int
- func (m Model) Init() tea.Cmd
- func (m Model) ModalBreadcrumb() string
- func (m Model) ModalDepth() int
- func (m Model) ModalOpen() bool
- func (m Model) ModalSourcePanel() Panel
- func (m Model) SelectedIssueID(panel Panel) string
- func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)
- func (m Model) View() string
- type PaneHeightsSavedMsg
- type Panel
- type PanelRenderer
- type PanelState
- type RecentHandoff
- type Rect
- type RefreshDataMsg
- type RestoreLastBoardMsg
- type SortMode
- type StatsData
- type StatsDataMsg
- type StatusFilterPreset
- type TaskListCategory
- type TaskListData
- type TaskListMode
- type TaskListRow
- type TickMsg
- type TypeFilterMode
Constants ¶
const ( MinWidth = 40 MinHeight = 15 )
Minimum dimensions for the monitor
Variables ¶
var DimStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("242"))
DimStyle applies a dim gray color to background content behind modals. We strip existing ANSI codes and apply gray because SGR 2 (faint) doesn't reliably combine with existing color codes in most terminals.
Functions ¶
func ComputeBoardIssueCategories ¶ added in v0.10.0
func ComputeBoardIssueCategories(database *db.DB, issues []models.BoardIssueView, sessionID string)
ComputeBoardIssueCategories sets the Category field on each BoardIssueView. This is the single source of truth for issue categorization, considering dependency blocking, rejection status, and reviewability.
func DefaultBoardStatusFilter ¶ added in v0.10.0
DefaultBoardStatusFilter returns the default status filter (closed hidden)
func OverlayModal ¶ added in v0.4.20
OverlayModal composites a modal on top of a dimmed background. The modal is centered, with dimmed background visible on all sides.
Types ¶
type ActivityItem ¶
type ActivityItem struct {
Timestamp time.Time
SessionID string
Type string // "log", "action", "comment"
IssueID string
IssueTitle string // title of the associated issue
Message string
LogType models.LogType // for logs
Action models.ActionType // for actions
}
ActivityItem represents a unified activity item (log, action, or comment)
type BoardIssuesMsg ¶ added in v0.10.0
type BoardIssuesMsg struct {
BoardID string
Issues []models.BoardIssueView
Error error
}
BoardIssuesMsg carries issues for the current board
type BoardMode ¶ added in v0.10.0
type BoardMode struct {
Board *models.Board // Currently active board
Issues []models.BoardIssueView // Issues in the board (for backlog view)
Cursor int // Selected issue index (backlog view)
ScrollOffset int // Scroll offset for long lists (backlog view)
StatusFilter map[models.Status]bool // Status filter (true = visible)
// View mode toggle (swimlanes vs backlog)
ViewMode BoardViewMode // Current view mode
// Swimlanes view state (separate cursor/scroll from backlog)
SwimlaneData TaskListData // Categorized data for swimlanes view
SwimlaneRows []TaskListRow // Flattened rows for swimlanes view
SwimlaneCursor int // Cursor position in swimlanes view
SwimlaneScroll int // Scroll offset in swimlanes view
// Selection restoration after move operations
PendingSelectionID string // Issue ID to select after refresh (cleared after use)
}
BoardMode holds state for board mode view (when Task List is in board mode)
type BoardViewMode ¶ added in v0.10.0
type BoardViewMode int
BoardViewMode represents the display mode within a board
const ( BoardViewSwimlanes BoardViewMode = iota // Default: grouped by status categories BoardViewBacklog // Flat list with position ordering )
func BoardViewModeFromString ¶ added in v0.10.0
func BoardViewModeFromString(s string) BoardViewMode
FromString parses a view mode string (from database)
func (BoardViewMode) String ¶ added in v0.10.0
func (v BoardViewMode) String() string
String returns the display name for the view mode
type BoardsDataMsg ¶ added in v0.10.0
BoardsDataMsg carries fetched boards data
type ClearStatusMsg ¶ added in v0.4.12
type ClearStatusMsg struct{}
ClearStatusMsg clears the status message
type EditorField ¶ added in v0.4.16
type EditorField int
EditorField identifies which form field is being edited externally
const ( EditorFieldDescription EditorField = iota EditorFieldAcceptance )
type EditorFinishedMsg ¶ added in v0.4.16
type EditorFinishedMsg struct {
Field EditorField
Content string
Error error
}
EditorFinishedMsg carries the result from external editor
type EmbeddedOptions ¶ added in v0.11.0
type EmbeddedOptions struct {
BaseDir string // Base directory for database and config
Interval time.Duration // Refresh interval
Version string // Version string for display
PanelRenderer PanelRenderer // Custom panel border renderer (nil = default lipgloss)
ModalRenderer ModalRenderer // Custom modal border renderer (nil = default lipgloss)
}
EmbeddedOptions configures an embedded monitor model.
type FormState ¶ added in v0.4.14
type FormState struct {
Mode FormMode
Form *huh.Form
IssueID string // For edit mode - the issue being edited
ParentID string // For create mode - auto-populated parent epic
// Bound form values (standard fields)
Title string
Type string
Priority string
Description string
Labels string // Comma-separated
// Extended fields (toggled with Tab)
ShowExtended bool
Parent string // Parent epic ID
Points string // String for select options
Acceptance string
Minor bool
Dependencies string // Comma-separated issue IDs
// Button focus: -1 = form fields focused, 0 = submit, 1 = cancel
ButtonFocus int
ButtonHover int // 0 = none, 1 = submit, 2 = cancel
}
FormState holds the state for the issue form modal
func NewFormState ¶ added in v0.4.14
NewFormState creates a new form state for creating an issue
func NewFormStateForEdit ¶ added in v0.4.14
NewFormStateForEdit creates a form state populated with existing issue data
func (*FormState) GetDependencies ¶ added in v0.4.14
GetDependencies returns parsed dependency IDs
func (*FormState) ToggleExtended ¶ added in v0.4.14
func (fs *FormState) ToggleExtended()
ToggleExtended toggles the extended fields visibility and rebuilds the form
type HandoffsDataMsg ¶ added in v0.4.12
HandoffsDataMsg carries fetched handoffs data for the modal
type IssueDetailsMsg ¶
type IssueDetailsMsg struct {
IssueID string
Issue *models.Issue
Handoff *models.Handoff
Logs []models.Log
Comments []models.Comment
BlockedBy []models.Issue // Dependencies (issues blocking this one)
Blocks []models.Issue // Dependents (issues blocked by this one)
EpicTasks []models.Issue // Child tasks (when issue is an epic)
ParentEpic *models.Issue // Parent epic (when issue.ParentID is set)
Error error
}
IssueDetailsMsg carries fetched issue details for the modal
type MarkdownRenderedMsg ¶
MarkdownRenderedMsg carries pre-rendered markdown for the modal
type ModalEntry ¶ added in v0.4.9
type ModalEntry struct {
// Core
IssueID string
SourcePanel Panel // Only meaningful for base entry (depth 1)
// Display
Scroll int
ContentLines int // Cached content line count for scroll clamping
// Async data
Loading bool
Error error
Issue *models.Issue
Handoff *models.Handoff
Logs []models.Log
Comments []models.Comment
BlockedBy []models.Issue
Blocks []models.Issue
DescRender string
AcceptRender string
// Epic-specific (when Issue.Type == "epic")
EpicTasks []models.Issue
EpicTasksCursor int
TaskSectionFocused bool
// Parent epic (when issue has ParentID pointing to an epic)
ParentEpic *models.Issue
ParentEpicFocused bool
// Used when opening issues from within an epic to scope navigation to siblings
NavigationScope []models.Issue
// Blocked-by section (dependencies blocking this issue)
BlockedBySectionFocused bool
BlockedByCursor int
// Blocks section (issues blocked by this one)
BlocksSectionFocused bool
BlocksCursor int
// Line tracking for mouse click support (set during render)
BlockedByStartLine int // Line index where blocked-by section starts
BlockedByEndLine int // Line index where blocked-by section ends
BlocksStartLine int // Line index where blocks section starts
BlocksEndLine int // Line index where blocks section ends
}
ModalEntry represents a single modal in the stack
type ModalRenderer ¶ added in v0.11.0
ModalRenderer renders content in a modal box Used by embedders to inject custom modal styling (e.g., gradient borders)
type ModalType ¶ added in v0.11.0
type ModalType int
ModalType represents the type of modal for styling
type Model ¶
type Model struct {
// Database and session
DB *db.DB
SessionID string
// Window dimensions
Width int
Height int
// Panel data
FocusedIssue *models.Issue
InProgress []models.Issue
Activity []ActivityItem
TaskList TaskListData
RecentHandoffs []RecentHandoff // Handoffs since monitor started
ActiveSessions []string // Sessions with recent activity
// UI state
ActivePanel Panel
ScrollOffset map[Panel]int
Cursor map[Panel]int // Per-panel cursor position (selected row)
SelectedID map[Panel]string // Per-panel selected issue ID (preserved across refresh)
ScrollIndependent map[Panel]bool // True when user scrolled viewport away from cursor
HelpOpen bool // Whether help modal is open
HelpScroll int // Current scroll position in help
HelpTotalLines int // Cached total line count in help
ShowTDQHelp bool // Show TDQ query syntax help (when in search mode)
LastRefresh time.Time
StartedAt time.Time // When monitor started, to track new handoffs
Err error // Last error, if any
Embedded bool // When true, skip footer (embedded in sidecar)
// Flattened rows for selection
TaskListRows []TaskListRow // Flattened task list for selection
CurrentWorkRows []string // Issue IDs for current work panel (focused + in-progress)
// Modal stack for stacking modals (empty = no modal open)
ModalStack []ModalEntry
// Search state
SearchMode bool // Whether search mode is active
SearchQuery string // Current search query
SearchInput textinput.Model // Text input for search (cursor support)
IncludeClosed bool // Whether to include closed tasks
SortMode SortMode // Task list sort order
TypeFilterMode TypeFilterMode // Type filter (epic, task, bug, etc.)
// Confirmation dialog state
ConfirmOpen bool
ConfirmAction string // "delete"
ConfirmIssueID string
ConfirmTitle string
ConfirmButtonFocus int // 0=Yes, 1=No (for delete confirmation)
ConfirmButtonHover int // 0=none, 1=Yes, 2=No
// Close confirmation dialog state
CloseConfirmOpen bool
CloseConfirmIssueID string
CloseConfirmTitle string
CloseConfirmInput textinput.Model
CloseConfirmButtonFocus int // 0=input, 1=Confirm, 2=Cancel
CloseConfirmButtonHover int // 0=none, 1=Confirm, 2=Cancel
// Stats modal state
StatsOpen bool
StatsLoading bool
StatsData *StatsData
StatsScroll int
StatsError error
// Handoffs modal state
HandoffsOpen bool
HandoffsLoading bool
HandoffsData []models.Handoff
HandoffsCursor int
HandoffsScroll int
HandoffsError error
// Form modal state
FormOpen bool
FormState *FormState
// Board picker state
BoardPickerOpen bool
BoardPickerCursor int
BoardPickerHover int // -1=none, 0+=hovered board index
AllBoards []models.Board
// Board mode state
TaskListMode TaskListMode // Whether Task List shows categorized or board view
BoardMode BoardMode // Active board mode state
BoardStatusPreset StatusFilterPreset // Current status filter preset for cycling
// Configuration
RefreshInterval time.Duration
// Keymap registry for keyboard shortcuts
Keymap *keymap.Registry
// Status message (temporary feedback, e.g., "Copied to clipboard")
StatusMessage string
StatusIsError bool // true for error messages, false for success
// Version checking
Version string // Current version
UpdateAvail *version.UpdateAvailableMsg
// Mouse support - panel bounds for hit-testing
PanelBounds map[Panel]Rect
HoverPanel Panel // Panel currently under mouse cursor (-1 for none)
LastClickTime time.Time // For double-click detection
LastClickPanel Panel // Panel of last click
LastClickRow int // Row of last click
// Pane resizing (drag-to-resize)
PaneHeights [3]float64 // Height ratios (sum=1.0)
DividerBounds [2]Rect // Hit regions for the 2 dividers between 3 panes
DraggingDivider int // -1 = not dragging, 0 = first divider, 1 = second
DividerHover int // -1 = none, 0 or 1 = which divider is hovered
DragStartY int // Y position when drag started
DragStartHeights [3]float64 // Pane heights when drag started
BaseDir string // Base directory for config persistence
// Custom renderers (for embedding with custom theming)
PanelRenderer PanelRenderer // Custom panel border renderer (nil = default lipgloss)
ModalRenderer ModalRenderer // Custom modal border renderer (nil = default lipgloss)
}
Model is the main Bubble Tea model for the monitor TUI
func NewEmbedded ¶
NewEmbedded creates a monitor model for embedding in external applications. It opens the database and creates/gets a session automatically. The caller must call Close() when done to release resources.
func NewEmbeddedWithOptions ¶ added in v0.11.0
func NewEmbeddedWithOptions(opts EmbeddedOptions) (*Model, error)
NewEmbeddedWithOptions creates a monitor model with custom options. It opens the database and creates/gets a session automatically. The caller must call Close() when done to release resources.
func NewModel ¶
func NewModel(database *db.DB, sessionID string, interval time.Duration, ver string, baseDir string) Model
NewModel creates a new monitor model
func (*Model) Close ¶
Close releases resources held by an embedded monitor. Only call this if the model was created with NewEmbedded.
func (Model) CurrentContextString ¶ added in v0.4.14
CurrentContextString returns the current keymap context as a sidecar-formatted string. This is used by sidecar's TD plugin to determine which shortcuts to display.
func (*Model) CurrentModal ¶ added in v0.4.9
func (m *Model) CurrentModal() *ModalEntry
CurrentModal returns a pointer to the current (top) modal entry, or nil if none
func (Model) HitTestDivider ¶ added in v0.4.16
HitTestDivider returns which divider (0 or 1) contains the point, or -1 if none
func (Model) HitTestPanel ¶ added in v0.4.14
HitTestPanel returns which panel contains the point (x, y), or -1 if none
func (Model) HitTestRow ¶ added in v0.4.14
HitTestRow returns the row index within a panel for a given y coordinate, or -1 if none. Accounts for scroll indicators, category headers, and separator lines.
func (Model) ModalBreadcrumb ¶ added in v0.4.9
ModalBreadcrumb returns a breadcrumb string for the modal stack
func (Model) ModalDepth ¶ added in v0.4.9
ModalDepth returns the current modal stack depth (0 = no modal)
func (Model) ModalSourcePanel ¶
ModalSourcePanel returns the source panel of the base modal (depth 1)
func (Model) SelectedIssueID ¶
SelectedIssueID returns the issue ID of the currently selected row in a panel
type PaneHeightsSavedMsg ¶ added in v0.4.16
type PaneHeightsSavedMsg struct {
Error error
}
PaneHeightsSavedMsg is sent after pane heights are persisted to config
type PanelRenderer ¶ added in v0.11.0
type PanelRenderer func(content string, width, height int, state PanelState) string
PanelRenderer renders content in a bordered panel Used by embedders to inject custom panel styling (e.g., gradient borders)
type PanelState ¶ added in v0.11.0
type PanelState int
PanelState represents the visual state of a panel for theming
const ( PanelStateNormal PanelState = iota PanelStateActive PanelStateHover PanelStateDividerHover PanelStateDividerActive )
type RecentHandoff ¶
RecentHandoff represents a recent handoff for display
type Rect ¶ added in v0.4.14
type Rect struct {
X, Y, W, H int
}
Rect represents a rectangular region for hit-testing
type RefreshDataMsg ¶
type RefreshDataMsg struct {
FocusedIssue *models.Issue
InProgress []models.Issue
Activity []ActivityItem
TaskList TaskListData
RecentHandoffs []RecentHandoff
ActiveSessions []string
Timestamp time.Time
}
RefreshDataMsg carries refreshed data
type RestoreLastBoardMsg ¶ added in v0.10.0
RestoreLastBoardMsg is sent when restoring the last viewed board on launch
type SortMode ¶ added in v0.4.9
type SortMode int
SortMode represents task list sorting
func (SortMode) ToDBOptions ¶ added in v0.4.9
ToDBOptions returns SortBy and SortDesc for ListIssuesOptions
func (SortMode) ToSortClause ¶ added in v0.4.15
ToSortClause returns the TDQ sort clause string for this mode
type StatsData ¶
type StatsData struct {
ExtendedStats *models.ExtendedStats
Error error
}
StatsData holds statistics for the stats modal
type StatsDataMsg ¶
StatsDataMsg carries fetched stats data
func FetchStats ¶
func FetchStats(database *db.DB) StatsDataMsg
FetchStats retrieves extended statistics for the stats modal
type StatusFilterPreset ¶ added in v0.10.0
type StatusFilterPreset int
StatusFilterPreset represents a status filter preset for cycling
const ( StatusPresetDefault StatusFilterPreset = iota // open/in_progress/blocked/in_review StatusPresetAll // all statuses StatusPresetOpen // only open StatusPresetInProgress // only in_progress StatusPresetBlocked // only blocked StatusPresetInReview // only in_review StatusPresetClosed // only closed )
func (StatusFilterPreset) Name ¶ added in v0.10.0
func (p StatusFilterPreset) Name() string
StatusFilterPresetName returns the display name for a preset
type TaskListCategory ¶
type TaskListCategory string
TaskListCategory represents the category of a task list row
const ( CategoryReviewable TaskListCategory = "REVIEW" CategoryNeedsRework TaskListCategory = "REWORK" CategoryReady TaskListCategory = "READY" CategoryBlocked TaskListCategory = "BLOCKED" CategoryClosed TaskListCategory = "CLOSED" )
type TaskListData ¶
type TaskListData struct {
Ready []models.Issue
Reviewable []models.Issue
NeedsRework []models.Issue
Blocked []models.Issue
Closed []models.Issue
}
TaskListData holds categorized issues for the task list panel
func CategorizeBoardIssues ¶ added in v0.10.0
func CategorizeBoardIssues(database *db.DB, issues []models.BoardIssueView, sessionID string, sortMode SortMode) TaskListData
CategorizeBoardIssues takes board issues and groups them by status category for the swimlanes view. Issues are sorted within each category respecting backlog positions: positioned issues first (by position), then unpositioned (by sortMode). Also sets Category on each BoardIssueView.
type TaskListMode ¶ added in v0.10.0
type TaskListMode int
TaskListMode represents the display mode of the Task List panel
const ( TaskListModeCategorized TaskListMode = iota // Default categorized view (Reviewable, Ready, Blocked, etc.) TaskListModeBoard // Board view with flat list and ordering )
type TaskListRow ¶
type TaskListRow struct {
Issue models.Issue
Category TaskListCategory
}
TaskListRow represents a single selectable row in the task list panel
func BuildSwimlaneRows ¶ added in v0.10.0
func BuildSwimlaneRows(data TaskListData) []TaskListRow
BuildSwimlaneRows flattens categorized TaskListData into TaskListRow slice for cursor navigation in swimlanes view
type TypeFilterMode ¶ added in v0.4.16
type TypeFilterMode int
TypeFilterMode represents type filtering for the task list
const ( TypeFilterNone TypeFilterMode = iota // No type filter TypeFilterEpic // type=epic TypeFilterTask // type=task TypeFilterBug // type=bug TypeFilterFeature // type=feature TypeFilterChore // type=chore )
func (TypeFilterMode) String ¶ added in v0.4.16
func (t TypeFilterMode) String() string
String returns display name for type filter mode
func (TypeFilterMode) ToTypeClause ¶ added in v0.4.16
func (t TypeFilterMode) ToTypeClause() string
ToTypeClause returns the TDQ type clause string for this mode