[WIP] Task editing

This commit is contained in:
Martin
2024-05-23 07:15:08 +02:00
parent 14dbfc406d
commit 7712711736
4 changed files with 152 additions and 27 deletions

View File

@ -141,6 +141,9 @@ func (p *ReportPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
p.subpageActive = true p.subpageActive = true
p.common.PushPage(p) p.common.PushPage(p)
return p.subpage, nil return p.subpage, nil
case key.Matches(msg, p.common.Keymap.Ok):
p.common.TW.SetTaskDone(p.selectedTask)
return p, p.getTasks()
case key.Matches(msg, p.common.Keymap.SetProject): case key.Matches(msg, p.common.Keymap.SetProject):
p.subpage = NewProjectPickerPage(p.common, p.activeProject) p.subpage = NewProjectPickerPage(p.common, p.activeProject)
p.subpage.Init() p.subpage.Init()

View File

@ -43,7 +43,12 @@ func NewTaskEditorPage(common *common.Common, task taskwarrior.Task) *TaskEditor
p := &TaskEditorPage{ p := &TaskEditorPage{
common: common, common: common,
task: task, task: task,
mode: ModeInsert, }
if p.task.Uuid == "" {
p.mode = ModeInsert
} else {
p.mode = ModeNormal
} }
if p.task.Priority == "" { if p.task.Priority == "" {
@ -197,7 +202,7 @@ func (p *TaskEditorPage) View() string {
return lipgloss.JoinVertical( return lipgloss.JoinVertical(
lipgloss.Left, lipgloss.Left,
// lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceBackground(p.common.Styles.Warning.GetForeground())), // lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceBackground(p.common.Styles.Warning.GetForeground())),
lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceChars(".")), lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceChars(" . ")),
p.statusline.View(), p.statusline.View(),
) )
} }

View File

@ -9,26 +9,36 @@ import (
"time" "time"
) )
type Annotation struct {
Entry string `json:"entry,omitempty"`
Description string `json:"description,omitempty"`
}
func (a Annotation) String() string {
return fmt.Sprintf("%s %s", a.Entry, a.Description)
}
type Task struct { type Task struct {
Id int64 `json:"id,omitempty"` Id int64 `json:"id,omitempty"`
Uuid string `json:"uuid,omitempty"` Uuid string `json:"uuid,omitempty"`
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
Project string `json:"project,omitempty"` Project string `json:"project,omitempty"`
Priority string `json:"priority,omitempty"` Priority string `json:"priority,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags,omitempty"`
Depends []string `json:"depends,omitempty"` Depends []string `json:"depends,omitempty"`
Urgency float32 `json:"urgency,omitempty"` Urgency float32 `json:"urgency,omitempty"`
Parent string `json:"parent,omitempty"` Parent string `json:"parent,omitempty"`
Due string `json:"due,omitempty"` Due string `json:"due,omitempty"`
Wait string `json:"wait,omitempty"` Wait string `json:"wait,omitempty"`
Scheduled string `json:"scheduled,omitempty"` Scheduled string `json:"scheduled,omitempty"`
Until string `json:"until,omitempty"` Until string `json:"until,omitempty"`
Start string `json:"start,omitempty"` Start string `json:"start,omitempty"`
End string `json:"end,omitempty"` End string `json:"end,omitempty"`
Entry string `json:"entry,omitempty"` Entry string `json:"entry,omitempty"`
Modified string `json:"modified,omitempty"` Modified string `json:"modified,omitempty"`
Recur string `json:"recur,omitempty"` Recur string `json:"recur,omitempty"`
Annotations []Annotation `json:"annotations,omitempty"`
} }
func (t *Task) GetString(fieldWFormat string) string { func (t *Task) GetString(fieldWFormat string) string {
@ -37,41 +47,136 @@ func (t *Task) GetString(fieldWFormat string) string {
switch field { switch field {
case "id": case "id":
return strconv.FormatInt(t.Id, 10) return strconv.FormatInt(t.Id, 10)
case "uuid": case "uuid":
if format == "short" {
return t.Uuid[:8]
}
return t.Uuid return t.Uuid
case "description": case "description":
return t.Description switch format {
case "desc":
return t.Description
case "oneline":
if len(t.Annotations) == 0 {
return t.Description
} else {
var annotations []string
for _, a := range t.Annotations {
annotations = append(annotations, a.String())
}
return fmt.Sprintf("%s %s", t.Description, strings.Join(annotations, " "))
}
case "truncated":
if len(t.Description) > 20 {
return t.Description[:20] + "..."
} else {
return t.Description
}
case "count":
return fmt.Sprintf("%s [%d]", t.Description, len(t.Annotations))
case "truncated_count":
if len(t.Description) > 20 {
return fmt.Sprintf("%s... [%d]", t.Description[:20], len(t.Annotations))
} else {
return fmt.Sprintf("%s [%d]", t.Description, len(t.Annotations))
}
}
if len(t.Annotations) == 0 {
return t.Description
} else {
var annotations []string
for _, a := range t.Annotations {
annotations = append(annotations, a.String())
}
// TODO support for multiline?
return fmt.Sprintf("%s %s", t.Description, strings.Join(annotations, " "))
}
case "project": case "project":
switch format {
case "parent":
parent, _, _ := strings.Cut(t.Project, ".")
return parent
case "indented":
return fmt.Sprintf(" %s", t.Project)
}
return t.Project return t.Project
case "priority": case "priority":
return t.Priority return t.Priority
case "status": case "status":
return t.Status return t.Status
case "tags": case "tags":
return strings.Join(t.Tags, ", ") switch format {
case "count":
return strconv.Itoa(len(t.Tags))
case "indicator":
if len(t.Tags) > 0 {
return "+"
} else {
return ""
}
}
return strings.Join(t.Tags, " ")
case "parent":
if format == "short" {
return t.Parent[:8]
}
return t.Parent
case "urgency": case "urgency":
if format == "integer" {
return strconv.Itoa(int(t.Urgency))
}
return fmt.Sprintf("%.2f", t.Urgency) return fmt.Sprintf("%.2f", t.Urgency)
case "due": case "due":
return formatDate(t.Due, format) return formatDate(t.Due, format)
case "wait": case "wait":
return t.Wait return formatDate(t.Wait, format)
case "scheduled": case "scheduled":
return formatDate(t.Scheduled, format) return formatDate(t.Scheduled, format)
case "end": case "end":
return t.End return formatDate(t.End, format)
case "entry": case "entry":
return formatDate(t.Entry, format) return formatDate(t.Entry, format)
case "modified": case "modified":
return t.Modified return formatDate(t.Modified, format)
case "start": case "start":
return formatDate(t.Start, format) return formatDate(t.Start, format)
case "until": case "until":
return formatDate(t.Until, format) return formatDate(t.Until, format)
// TODO: implement these fields
case "depends": case "depends":
switch format {
case "count":
return strconv.Itoa(len(t.Depends))
case "indicator":
if len(t.Depends) > 0 {
return "D"
} else {
return ""
}
}
// TODO: get Ids from UUIDs
return strings.Join(t.Depends, ", ") return strings.Join(t.Depends, ", ")
case "recur": case "recur":
return t.Recur return t.Recur
default: default:
slog.Error(fmt.Sprintf("Field not implemented: %s", field)) slog.Error(fmt.Sprintf("Field not implemented: %s", field))
return "" return ""

View File

@ -89,6 +89,7 @@ type TaskWarrior interface {
GetTasks(report *Report, filter ...string) Tasks GetTasks(report *Report, filter ...string) Tasks
AddTask(task *Task) error AddTask(task *Task) error
ImportTask(task *Task) ImportTask(task *Task)
SetTaskDone(task *Task)
} }
type TaskSquire struct { type TaskSquire struct {
@ -343,6 +344,17 @@ func (ts *TaskSquire) ImportTask(task *Task) {
} }
} }
func (ts *TaskSquire) SetTaskDone(task *Task) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"done", task.Uuid}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed setting task done:", err)
}
}
func (ts *TaskSquire) extractConfig() *TWConfig { func (ts *TaskSquire) extractConfig() *TWConfig {
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_show"}...)...) cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_show"}...)...)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()