1
0
Fork 0

add due date to tasks, columns

This commit is contained in:
Sean Sube 2018-05-21 23:32:20 -05:00
parent d23a0c9ae7
commit 1393b0a334
12 changed files with 76 additions and 18 deletions

View File

@ -13,6 +13,10 @@ go-deps:
go-test:
go test ${BUILD_OPTS} -cover ./...
git-push:
git push github
git push gitlab
docker-build:
docker build -T ${IMAGE_NAME} .

View File

@ -203,6 +203,7 @@ Features:
- [x] add task labels
- [x] config defaults
- [x] columns & sort on root
- [x] add due date column
- [ ] list project names
- [ ] list label names
- [ ] test coverage
@ -214,4 +215,4 @@ Features:
togo was written by [ssube](https://github.com/ssube) and is not created by, affiliated with, or supported by Doist.
Source, documentation, and everything else in this repository is distributed under the included MIT license.
Source, documentation, and everything else in this repository is distributed under the included MIT license.

View File

@ -10,6 +10,7 @@ import (
"strconv"
"strings"
"text/tabwriter"
"time"
"github.com/ssube/togo/config"
"gopkg.in/resty.v1"
@ -39,8 +40,27 @@ func CreateTable(f *os.File, cols []string) *tabwriter.Writer {
return w
}
func FormatDate(d DueDate, dateFmt string) (string, error) {
// if no timezone is provided, this is a simple date (day)
if d.Timezone == "" {
return d.Date, nil
}
zone, err := time.LoadLocation(d.Timezone)
if err != nil {
return d.DateTime, err
}
local, err := time.ParseInLocation(time.RFC3339, d.DateTime, zone)
if err != nil {
return d.DateTime, err
}
return local.Format(dateFmt), nil
}
// GetFields from a column list using reflection
func GetFields(val interface{}, cols []string) []string {
func GetFields(val interface{}, cols []string, dateFmt string) []string {
out := make([]string, len(cols))
rv := reflect.ValueOf(val).Elem()
@ -59,6 +79,18 @@ func GetFields(val interface{}, cols []string) []string {
out[i] = strconv.FormatInt(field.Int(), 10)
case reflect.String:
out[i] = field.String()
case reflect.Struct:
val := field.Interface()
switch val.(type) {
case DueDate:
fmt, err := FormatDate(val.(DueDate), dateFmt)
if err != nil {
log.Fatalf("unable to format date: %s", err.Error)
}
out[i] = fmt
default:
log.Printf("unknown struct for column %s: %v", c, val)
}
case reflect.Slice:
fallthrough
default:

View File

@ -26,12 +26,12 @@ func ParseLabels(data []byte) ([]Label, error) {
}
// PrintLabels after sorting, with column headers
func PrintLabels(f *os.File, labels []Label, cols []string, sortCol string) {
func PrintLabels(f *os.File, labels []Label, cols []string, sortCol string, dateFmt string) {
w := CreateTable(f, cols)
SortByField(labels, sortCol)
for _, l := range labels {
fields := GetFields(&l, cols)
fields := GetFields(&l, cols, dateFmt)
fmt.Fprintln(w, Tabulate(fields)...)
}

View File

@ -27,13 +27,13 @@ func ParseProjects(data []byte) ([]Project, error) {
}
// PrintProjects after sorting, with column headers
func PrintProjects(f *os.File, projects []Project, cols []string, sortCol string) {
func PrintProjects(f *os.File, projects []Project, cols []string, sortCol string, dateFmt string) {
w := CreateTable(f, cols)
SortByField(projects, sortCol)
// prepare a slice for cols and tabs
for _, p := range projects {
fields := GetFields(&p, cols)
fields := GetFields(&p, cols, dateFmt)
fmt.Fprintln(w, Tabulate(fields)...)
}

View File

@ -13,25 +13,32 @@ import (
"gopkg.in/yaml.v2"
)
type DueDate struct {
Date string `json:"date" yaml:"date"`
DateTime string `json:"datetime" yaml:"datetime"`
Timezone string `json:"timezone" yaml:"timezone"`
}
// Task model
// https://developer.todoist.com/rest/v8/#tasks
type Task struct {
Content string `json:"content" yaml:"content"`
ID int `json:"id" yaml:"id,omitempty"`
Labels []int `json:"label_ids" yaml:"label_ids"`
Order int `json:"order" yaml:"order,omitempty"`
Priority int `json:"priority" yaml:"priority,omitempty"`
Project int `json:"project_id" yaml:"project_id"`
Content string `json:"content" yaml:"content"`
Due DueDate `json:"due" yaml:"due"`
ID int `json:"id" yaml:"id,omitempty"`
Labels []int `json:"label_ids" yaml:"label_ids"`
Order int `json:"order" yaml:"order,omitempty"`
Priority int `json:"priority" yaml:"priority,omitempty"`
Project int `json:"project_id" yaml:"project_id"`
}
// PrintTasks in a table
func PrintTasks(f *os.File, tasks []Task, cols []string, sortCol string) {
func PrintTasks(f *os.File, tasks []Task, cols []string, sortCol string, dateFmt string) {
w := CreateTable(f, cols)
SortByField(tasks, sortCol)
// prepare a slice for cols and tabs
for _, t := range tasks {
fields := GetFields(&t, cols)
fields := GetFields(&t, cols, dateFmt)
fmt.Fprintln(w, Tabulate(fields)...)
}

View File

@ -53,6 +53,7 @@ func init() {
"ID",
"Content",
}
date := rootConfig.Default.Date
done := false
labels := rootConfig.Default.Tasks.Labels
project := rootConfig.Default.Tasks.Project
@ -76,8 +77,9 @@ func init() {
}
columns := rootClient.Columns(columns, rootColumns, rootClient.Config().Default.Projects.Columns)
date := rootClient.Sort(date, rootDate, rootClient.Config().Default.Date)
sort := rootClient.Sort(sort, rootSort, rootClient.Config().Default.Projects.Sort)
client.PrintTasks(os.Stdout, tasks, columns, sort)
client.PrintTasks(os.Stdout, tasks, columns, sort, date)
if done {
// this should be a single item
for _, t := range tasks {

View File

@ -3,6 +3,7 @@ package cmd
import (
"log"
"os"
"time"
"github.com/spf13/cobra"
"github.com/ssube/togo/client"
@ -13,6 +14,7 @@ func init() {
"ID",
"Name",
}
date := time.RFC3339
sort := "Name"
labelsCmd := &cobra.Command{
@ -25,8 +27,9 @@ func init() {
}
columns := rootClient.Columns(columns, rootColumns, rootClient.Config().Default.Labels.Columns)
date := rootClient.Sort(date, rootDate, rootClient.Config().Default.Date)
sort := rootClient.Sort(sort, rootSort, rootClient.Config().Default.Labels.Sort)
client.PrintLabels(os.Stdout, labels, columns, sort)
client.PrintLabels(os.Stdout, labels, columns, sort, date)
},
}

View File

@ -4,6 +4,7 @@ import (
"log"
"os"
"strings"
"time"
"github.com/spf13/cobra"
"github.com/ssube/togo/client"
@ -14,6 +15,7 @@ func init() {
"ID",
"Content",
}
date := time.RFC3339
labels := rootConfig.Default.Tasks.Labels
project := rootConfig.Default.Tasks.Project
sort := "ID"
@ -38,8 +40,9 @@ func init() {
}
columns := rootClient.Columns(columns, rootColumns, rootClient.Config().Default.Tasks.Columns)
date := rootClient.Sort(date, rootDate, rootClient.Config().Default.Date)
sort := rootClient.Sort(sort, rootSort, rootClient.Config().Default.Tasks.Sort)
client.PrintTasks(os.Stdout, tasks, columns, sort)
client.PrintTasks(os.Stdout, tasks, columns, sort, date)
},
}

View File

@ -3,6 +3,7 @@ package cmd
import (
"log"
"os"
"time"
"github.com/spf13/cobra"
"github.com/ssube/togo/client"
@ -13,6 +14,7 @@ func init() {
"ID",
"Name",
}
date := time.RFC3339
sort := "Name"
projectsCmd := &cobra.Command{
@ -25,8 +27,9 @@ func init() {
}
columns := rootClient.Columns(columns, rootColumns, rootClient.Config().Default.Projects.Columns)
date := rootClient.Sort(date, rootDate, rootClient.Config().Default.Date)
sort := rootClient.Sort(sort, rootSort, rootClient.Config().Default.Projects.Sort)
client.PrintProjects(os.Stdout, projects, columns, sort)
client.PrintProjects(os.Stdout, projects, columns, sort, date)
},
}

View File

@ -16,6 +16,7 @@ var rootConfig = &config.Config{}
// persistent flags
var rootColumns = []string{}
var rootDate = ""
var rootSort = ""
// flags
@ -46,6 +47,7 @@ func Execute(client *client.Client) {
func init() {
rootCmd.PersistentFlags().StringSliceVarP(&rootColumns, "columns", "c", []string{}, "display columns")
rootCmd.PersistentFlags().StringVarP(&rootDate, "date", "d", "", "date format")
rootCmd.PersistentFlags().StringVarP(&rootSort, "sort", "s", "", "sort column")
// root-only flags

View File

@ -11,6 +11,7 @@ import (
type Config struct {
Default struct {
Date string
Labels struct {
Columns []string
Sort string