todo-server/server/ajax/task/task.go

171 lines
3.9 KiB
Go
Executable File

package task
import (
"encoding/json"
"errors"
"fmt"
"local/todo-server/server/ajax/form"
"net/http"
"regexp"
"strings"
"time"
)
type Task struct {
UUID string
Title string
Priority int
Tags StrList
Created time.Time
Edited time.Time
Completed time.Time
Complete bool
Note []string
Due time.Time
}
type StrList []string
func (sl StrList) MarshalJSON() ([]byte, error) {
s := strings.Join(sl, ", ")
return json.Marshal(s)
}
func New(r *http.Request) (*Task, error) {
task := &Task{
UUID: form.NewUUID(),
Title: form.Get(r, "title"),
Priority: form.ToInt(form.Get(r, "prio")),
Tags: StrList(form.ToStrArr(form.Get(r, "tags"))),
Created: time.Now(),
Edited: time.Now(),
Due: form.ToTime(form.Get(r, "duedate")),
}
task.SetNote(form.Get(r, "note"))
return task, task.validate()
}
func (t *Task) MarshalJSON() ([]byte, error) {
// {"total":4,"list":[
// {"id":"3455",
// "title":"redo qvolution",
// "listId":"18",
// "date":"14 Oct 2019 12:56 PM",
// "dateInt":1571079392,
// "dateInline":"14 Oct",
// "dateInlineTitle":"created at 14 Oct 2019 12:56 PM",
// "dateEditedInt":1571079401,
// "dateCompleted":"",
// "dateCompletedInline":"",
// "dateCompletedInlineTitle":"Completed at ",
// "compl":0,
// "prio":"0",
// "note":"",
// "noteText":"",
// "ow":4,
// "tags":"work",
// "tags_ids":"138",
// "duedate":"",
// "dueClass":"",
// "dueStr":"",
// "dueInt":33330000,
// "dueTitle":"Due "}
// ]}
fullFormat := "02 Jan 2006 03:04 PM"
shortFormat := "02 Jan"
compl := 0
if t.Complete {
compl = 1
}
m := map[string]interface{}{
"id": t.UUID,
"title": t.Title,
"listId": "list",
"date": t.Created.Format(fullFormat),
"dateInt": t.Created.Unix(),
"dateInline": t.Created.Format(shortFormat),
"dateInlineTitle": fmt.Sprintf("created at %s", t.Created.Format(fullFormat)),
"dateEditedInt": t.Edited.Unix(),
"dateCompleted": "",
"dateCompletedInline": "",
"dateCompletedInlineTitle": "",
"compl": compl,
"prio": t.Priority,
"note": strings.Join(t.Note, "\n"),
"noteText": strings.Join(t.Note, "\n"),
"ow": 0,
"tags": strings.Join([]string(t.Tags), ", "),
"tags_ids": "",
"duedate": t.Due.Format(fullFormat),
"dueClass": "",
"dueStr": t.Due.Format(shortFormat),
"dueInt": t.Due.Unix(),
"dueTitle": "Due ",
}
if t.Complete {
m["dateCompleted"] = t.Completed.Format(fullFormat)
m["dateCompletedInline"] = t.Completed.Format(shortFormat)
m["dateCompletedInlineTitle"] = "Completed at "
}
return json.Marshal(m)
}
func (t *Task) AppendTags(tags []string) {
t.touch()
t.Tags = append(t.Tags, tags...)
}
func (t *Task) SetComplete(state bool) {
t.touch()
t.Complete = state
if t.Complete {
t.Completed = time.Now()
} else {
t.Completed = time.Time{}
}
}
func (t *Task) SetPrio(prio int) {
t.touch()
t.Priority = prio
}
func (t *Task) SetNote(note string) {
t.touch()
t.Note = strings.Split(note, "\n")
}
func (t *Task) touch() {
t.Edited = time.Now()
}
func (t *Task) validate() error {
if t.Title == "" {
return errors.New("task cannot have nil title")
}
if err := t.smartSyntax(); err != nil {
return err
}
return nil
}
func (t *Task) smartSyntax() error {
re := regexp.MustCompile(`^(/([+-]{0,1}\d+)?/)?(.*?)(\s+/([^/]*)/$)?$|`)
matches := re.FindAllStringSubmatch(t.Title, 1)[0]
if len(matches) != 6 {
return nil
}
if matches[1] != "" {
t.Priority = form.ToInt(matches[1])
}
if matches[3] != "" {
t.Title = matches[3]
}
if matches[5] != "" {
t.Tags = form.ToStrArr(matches[5])
}
return nil
}