[WIP] Task editing
This commit is contained in:
@ -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()
|
||||||
|
|||||||
@ -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(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 ""
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user