222 lines
5.2 KiB
Go
222 lines
5.2 KiB
Go
package pages
|
|
|
|
import (
|
|
"tasksquire/common"
|
|
"tasksquire/taskwarrior"
|
|
|
|
"github.com/charmbracelet/bubbles/key"
|
|
"github.com/charmbracelet/bubbles/table"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
type ReportPage struct {
|
|
common *common.Common
|
|
|
|
activeReport *taskwarrior.Report
|
|
activeContext *taskwarrior.Context
|
|
activeProject string
|
|
selectedTask *taskwarrior.Task
|
|
|
|
tasks taskwarrior.Tasks
|
|
|
|
taskTable table.Model
|
|
tableStyle table.Styles
|
|
keymap ReportKeys
|
|
|
|
subpage tea.Model
|
|
subpageActive bool
|
|
}
|
|
|
|
type ReportKeys struct {
|
|
Quit key.Binding
|
|
Up key.Binding
|
|
Down key.Binding
|
|
Select key.Binding
|
|
ToggleFocus key.Binding
|
|
}
|
|
|
|
func NewReportPage(com *common.Common, report *taskwarrior.Report) *ReportPage {
|
|
s := table.DefaultStyles()
|
|
s.Header = s.Header.
|
|
BorderStyle(lipgloss.NormalBorder()).
|
|
BorderForeground(com.Styles.Active.GetForeground()).
|
|
BorderBottom(true).
|
|
Bold(true)
|
|
s.Selected = s.Selected.
|
|
Reverse(true).
|
|
Bold(true)
|
|
|
|
keys := ReportKeys{
|
|
Quit: key.NewBinding(
|
|
key.WithKeys("q", "ctrl+c"),
|
|
key.WithHelp("q, ctrl+c", "Quit"),
|
|
),
|
|
Up: key.NewBinding(
|
|
key.WithKeys("k", "up"),
|
|
key.WithHelp("↑/k", "Up"),
|
|
),
|
|
Down: key.NewBinding(
|
|
key.WithKeys("j", "down"),
|
|
key.WithHelp("↓/j", "Down"),
|
|
),
|
|
Select: key.NewBinding(
|
|
key.WithKeys("enter"),
|
|
key.WithHelp("enter", "Select"),
|
|
),
|
|
ToggleFocus: key.NewBinding(
|
|
key.WithKeys("esc"),
|
|
key.WithHelp("esc", "Toggle focus"),
|
|
),
|
|
}
|
|
|
|
return &ReportPage{
|
|
common: com,
|
|
activeReport: report,
|
|
activeContext: com.TW.GetActiveContext(),
|
|
activeProject: "",
|
|
tableStyle: s,
|
|
keymap: keys,
|
|
}
|
|
}
|
|
|
|
func (p ReportPage) Init() tea.Cmd {
|
|
return p.getTasks()
|
|
}
|
|
|
|
func (p ReportPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
var cmds []tea.Cmd
|
|
switch msg := msg.(type) {
|
|
case tea.WindowSizeMsg:
|
|
p.taskTable.SetWidth(msg.Width - 2)
|
|
p.taskTable.SetHeight(msg.Height - 4)
|
|
case BackMsg:
|
|
p.subpageActive = false
|
|
case TaskMsg:
|
|
p.tasks = taskwarrior.Tasks(msg)
|
|
p.populateTaskTable(p.tasks)
|
|
case UpdateReportMsg:
|
|
p.activeReport = msg
|
|
cmds = append(cmds, p.getTasks())
|
|
case UpdateContextMsg:
|
|
p.activeContext = msg
|
|
p.common.TW.SetContext(msg)
|
|
cmds = append(cmds, p.getTasks())
|
|
case UpdateProjectMsg:
|
|
p.activeProject = string(msg)
|
|
cmds = append(cmds, p.getTasks())
|
|
case AddedTaskMsg:
|
|
cmds = append(cmds, p.getTasks())
|
|
case EditedTaskMsg:
|
|
cmds = append(cmds, p.getTasks())
|
|
case tea.KeyMsg:
|
|
switch {
|
|
case key.Matches(msg, p.common.Keymap.Quit):
|
|
return p, tea.Quit
|
|
case key.Matches(msg, p.common.Keymap.SetReport):
|
|
p.subpage = NewReportPickerPage(p.common, p.activeReport)
|
|
p.subpage.Init()
|
|
p.subpageActive = true
|
|
p.common.PageStack.Push(p)
|
|
return p.subpage, nil
|
|
case key.Matches(msg, p.common.Keymap.SetContext):
|
|
p.subpage = NewContextPickerPage(p.common)
|
|
p.subpage.Init()
|
|
p.subpageActive = true
|
|
p.common.PageStack.Push(p)
|
|
return p.subpage, nil
|
|
case key.Matches(msg, p.common.Keymap.Add):
|
|
p.subpage = NewTaskEditorPage(p.common, taskwarrior.Task{})
|
|
p.subpage.Init()
|
|
p.subpageActive = true
|
|
p.common.PageStack.Push(p)
|
|
return p.subpage, nil
|
|
case key.Matches(msg, p.common.Keymap.Edit):
|
|
p.subpage = NewTaskEditorPage(p.common, *p.selectedTask)
|
|
p.subpage.Init()
|
|
p.subpageActive = true
|
|
p.common.PageStack.Push(p)
|
|
return p.subpage, nil
|
|
case key.Matches(msg, p.common.Keymap.SetProject):
|
|
p.subpage = NewProjectPickerPage(p.common, p.activeProject)
|
|
p.subpage.Init()
|
|
p.subpageActive = true
|
|
p.common.PageStack.Push(p)
|
|
return p.subpage, nil
|
|
}
|
|
}
|
|
|
|
var cmd tea.Cmd
|
|
p.taskTable, cmd = p.taskTable.Update(msg)
|
|
cmds = append(cmds, cmd)
|
|
|
|
if p.tasks != nil {
|
|
p.selectedTask = (*taskwarrior.Task)(p.tasks[p.taskTable.Cursor()])
|
|
}
|
|
|
|
return p, tea.Batch(cmds...)
|
|
}
|
|
|
|
func (p ReportPage) View() string {
|
|
return p.common.Styles.Main.Render(p.taskTable.View()) + "\n"
|
|
}
|
|
|
|
func (p *ReportPage) populateTaskTable(tasks taskwarrior.Tasks) {
|
|
nCols := len(p.activeReport.Columns)
|
|
columns := make([]table.Column, 0)
|
|
columnSizes := make([]int, nCols)
|
|
fullRows := make([]table.Row, len(tasks))
|
|
rows := make([]table.Row, len(tasks))
|
|
|
|
for i, task := range tasks {
|
|
row := table.Row{}
|
|
for i, col := range p.activeReport.Columns {
|
|
field := task.GetString(col)
|
|
columnSizes[i] = max(columnSizes[i], len(field))
|
|
row = append(row, field)
|
|
}
|
|
fullRows[i] = row
|
|
}
|
|
|
|
for i, r := range fullRows {
|
|
row := table.Row{}
|
|
for j, size := range columnSizes {
|
|
if size == 0 {
|
|
continue
|
|
}
|
|
row = append(row, r[j])
|
|
}
|
|
rows[i] = row
|
|
}
|
|
|
|
for i, label := range p.activeReport.Labels {
|
|
if columnSizes[i] == 0 {
|
|
continue
|
|
}
|
|
|
|
columns = append(columns, table.Column{Title: label, Width: max(columnSizes[i], len(label))})
|
|
}
|
|
|
|
p.taskTable = table.New(
|
|
table.WithColumns(columns),
|
|
table.WithRows(rows),
|
|
table.WithFocused(true),
|
|
// table.WithHeight(7),
|
|
// table.WithWidth(100),
|
|
)
|
|
p.taskTable.SetStyles(p.tableStyle)
|
|
}
|
|
|
|
func (p *ReportPage) getTasks() tea.Cmd {
|
|
return func() tea.Msg {
|
|
filters := []string{}
|
|
if p.activeProject != "" {
|
|
filters = append(filters, "project:"+p.activeProject)
|
|
}
|
|
tasks := p.common.TW.GetTasks(p.activeReport, filters...)
|
|
return TaskMsg(tasks)
|
|
}
|
|
}
|
|
|
|
type TaskMsg taskwarrior.Tasks
|