From afb0a04fe600575b00d551da7dce6a08679ef7b8 Mon Sep 17 00:00:00 2001 From: Julian T Date: Sun, 26 May 2024 22:20:40 +0200 Subject: Working task selection --- db.go | 4 +- model.go | 13 ++-- page.go | 61 ++++++++++++---- templates/index.html | 13 +++- templates/parts/entry.html | 37 +++++++--- templates/parts/entryRows.html | 2 +- templates/parts/taskEntry.html | 8 +++ templates/parts/taskRows.html | 17 +++-- tidsreg.go | 160 ++++++++++++++++++++++++++++++++++++----- 9 files changed, 258 insertions(+), 57 deletions(-) create mode 100644 templates/parts/taskEntry.html diff --git a/db.go b/db.go index 363bc93..b37e103 100644 --- a/db.go +++ b/db.go @@ -70,7 +70,7 @@ func (db *InMemDb) StartNewEntry(now time.Time, task *Entry) (*Entry, error) { From: task.From, To: nil, Date: DateFromStd(now), - Tag: task.Tag, + Tasks: task.Tasks, Comment: task.Comment, } @@ -108,8 +108,8 @@ func (db *InMemDb) SaveEntry(entry *Entry) (*Entry, error) { existent := db.entries[entry.Id] existent.Comment = entry.Comment - existent.Tag = entry.Tag existent.From = entry.From + existent.Tasks = entry.Tasks existent.To = entry.To existent.Date = entry.Date return existent, nil diff --git a/model.go b/model.go index 93a988c..6eebd60 100644 --- a/model.go +++ b/model.go @@ -12,7 +12,7 @@ type Entry struct { Date Date From *Time To *Time - Tag *string + Tasks map[int]*time.Duration Comment string } @@ -27,8 +27,13 @@ type Date string type Time string -var timeMatch = regexp.MustCompile("\\d\\d:\\d\\d") -var dateMatch = regexp.MustCompile("\\d\\d\\d\\d-\\d\\d-\\d\\d") +type EntrySubDuration string + +var ( + timeMatch = regexp.MustCompile("[0-9]{2}:[0-9]{2}") + dateMatch = regexp.MustCompile("[0-9]{4}-[0-9]{2}-[0-9]{2}") + subDurationMatch = regexp.MustCompile("[0-9]") +) var ( ErrInvalidTime = errors.New("Invalid time string") @@ -41,7 +46,7 @@ func NewEntry(date Date) *Entry { From: nil, Date: date, To: nil, - Tag: nil, + Tasks: map[int]*time.Duration{}, Comment: "", } diff --git a/page.go b/page.go index 8e2074e..cae7ecb 100644 --- a/page.go +++ b/page.go @@ -1,6 +1,8 @@ package main -import "time" +import ( + "time" +) type Service struct { Db Database @@ -14,10 +16,12 @@ type DateInfo struct { } type EntryPage struct { - Entry *Entry - Detached bool - Tracking *Entry - DateInfo DateInfo + Entry *Entry + Detached bool + Tracking *Entry + DateInfo DateInfo + GroupToTasks map[string]([]*Task) + TaskCount int } type RootPage struct { @@ -25,11 +29,12 @@ type RootPage struct { Entry *EntryPage Entries []*Entry Task *TaskPage - Tasks []*Task + Tasks *TasksPage } type TasksPage struct { - Tasks []*Task + Tasks []*Task + GroupToTasks map[string]([]*Task) } type TaskPage struct { @@ -73,8 +78,26 @@ func (srv *Service) GetTasksPage() (*TasksPage, error) { if err != nil { return nil, err } + + mp := make(map[string]([]*Task)) + + for _, task := range tasks { + key := task.Group + if key == nil { + empty := "" + key = &empty + } + mparr, ok := mp[*key] + if !ok { + mparr = make([]*Task, 0) + } + mparr = append(mparr, task) + mp[*key] = mparr + } + return &TasksPage{ - Tasks: tasks, + Tasks: tasks, + GroupToTasks: mp, }, nil } @@ -83,11 +106,19 @@ func (srv *Service) GetEntryPage(detached *Entry, dt DateInfo) (*EntryPage, erro if err != nil { return nil, err } + + tasksPage, err := srv.GetTasksPage() + if err != nil { + return nil, err + } + page := &EntryPage{ - Entry: tracking, - Detached: false, - Tracking: tracking, - DateInfo: dt, + Entry: tracking, + Detached: false, + Tracking: tracking, + DateInfo: dt, + GroupToTasks: tasksPage.GroupToTasks, + TaskCount: 0, } if detached != nil { @@ -95,6 +126,10 @@ func (srv *Service) GetEntryPage(detached *Entry, dt DateInfo) (*EntryPage, erro page.Detached = true } + if page.Entry != nil { + page.TaskCount = len(page.Entry.Tasks) + } + return page, nil } @@ -115,7 +150,7 @@ func (srv *Service) GetRootPage(date Date) (*RootPage, error) { return nil, err } - tasks, err := srv.Db.GetTasks() + tasks, err := srv.GetTasksPage() if err != nil { return nil, err } diff --git a/templates/index.html b/templates/index.html index 18ca5f0..99bfc31 100644 --- a/templates/index.html +++ b/templates/index.html @@ -8,6 +8,7 @@ + - +
+
-
+
{{template "entry.html" .Entry}}
@@ -120,7 +127,7 @@ {{ template "task.html" .Task }} - {{ template "taskRows.html" . }} + {{ template "taskRows.html" .Tasks }}
diff --git a/templates/parts/entry.html b/templates/parts/entry.html index 52f2eb3..4be2073 100644 --- a/templates/parts/entry.html +++ b/templates/parts/entry.html @@ -16,17 +16,32 @@
- Mærker
-
- + Opgaver
+ + + + {{ if .Entry }} + {{ range $x := taskMapToArr .Entry.Tasks }} + + + + + {{ end }} + {{ end }} + + + + + +
+ +
+ +
Kommentar
diff --git a/templates/parts/entryRows.html b/templates/parts/entryRows.html index 8f10ee3..3749ddb 100644 --- a/templates/parts/entryRows.html +++ b/templates/parts/entryRows.html @@ -4,7 +4,7 @@ {{ $entry.Id }} - {{ if $entry.Tag}}{{ $entry.Tag }}{{end}} + {{ $entry.Comment }} {{ if $entry.To }}{{end}} diff --git a/templates/parts/taskEntry.html b/templates/parts/taskEntry.html new file mode 100644 index 0000000..3c3be3f --- /dev/null +++ b/templates/parts/taskEntry.html @@ -0,0 +1,8 @@ + +{{ range $group, $tasks := index . 0}} + + {{ range $task := $tasks }} + + {{ end }} + +{{ end }} diff --git a/templates/parts/taskRows.html b/templates/parts/taskRows.html index a2a6020..bef2366 100644 --- a/templates/parts/taskRows.html +++ b/templates/parts/taskRows.html @@ -1,11 +1,20 @@ - {{ range $task := .Tasks }} + {{ range $group, $tasks := .GroupToTasks }} - - + + + + {{ range $task := $tasks }} + + + + + + + {{ end }} {{ end }}
Trifork - + {{ $group }}
{{ $task.Text }}{{ if $task.Ident }}{{ $task.Ident }}{{end}}
diff --git a/tidsreg.go b/tidsreg.go index e327f74..b988ad7 100644 --- a/tidsreg.go +++ b/tidsreg.go @@ -18,20 +18,27 @@ type Server struct { srv *Service } +func parseIdInt(str string) (int, error) { + var id int = -1 + if str != "" { + idLong, err := strconv.ParseInt(str, 10, 32) + if err != nil { + return -1, err + } + id = int(idLong) + } + return id, nil +} + func parseTaskFromForm(r *http.Request) (*Task, error) { err := r.ParseForm() if err != nil { return nil, err } - var id int64 - if r.PostFormValue("id") == "" { - id = -1 - } else { - id, err = strconv.ParseInt(r.PostFormValue("id"), 10, 32) - if err != nil { - return nil, err - } + id, err := parseIdInt(r.PostFormValue("id")) + if err != nil { + return nil, err } var group *string @@ -57,12 +64,59 @@ func parseTaskFromForm(r *http.Request) (*Task, error) { }, nil } +func readTaskSelectFromPost(r *http.Request, index string) (int, *time.Duration, bool, error) { + idS := r.PostFormValue(fmt.Sprintf("task-%s-id", index)) + if idS == "" || idS == "-" { + return -1, nil, false, nil + } + id, err := parseIdInt(idS) + if err != nil { + return -1, nil, false, err + } + + durS := r.PostFormValue(fmt.Sprintf("task-%s-part", index)) + if durS == "" { + return id, nil, true, nil + } + dur, err := time.ParseDuration(durS) + if err != nil { + return -1, nil, false, err + } + + return id, &dur, true, nil +} + func parseEntryFromForm(r *http.Request, useToday bool) (*Entry, error) { err := r.ParseForm() if err != nil { return nil, err } + tasks := map[int]*time.Duration{} + taskCount, err := strconv.ParseInt(r.PostFormValue("task-count"), 10, 32) + if err != nil { + return nil, fmt.Errorf("Error reading task-count: %w", err) + } + for i := 0; i < int(taskCount); i++ { + id, dur, ok, err := readTaskSelectFromPost(r, fmt.Sprintf("%d", i)) + if err != nil { + return nil, err + } + if !ok { + continue + } + tasks[id] = dur + } + { + id, dur, ok, err := readTaskSelectFromPost(r, "new") + if err != nil { + return nil, fmt.Errorf("Error reading new task select: %w", err) + } + if ok { + tasks[id] = dur + } + } + var date Date dateP, err := DateFromString(r.PostFormValue("date")) if err != nil { @@ -85,28 +139,51 @@ func parseEntryFromForm(r *http.Request, useToday bool) (*Entry, error) { if err != nil { return nil, err } - var id int64 - if r.PostFormValue("id") == "" { - id = -1 - } else { - id, err = strconv.ParseInt(r.PostFormValue("id"), 10, 32) - if err != nil { - return nil, err - } + id, err := parseIdInt(r.PostFormValue("id")) + if err != nil { + return nil, err } + log.Printf("hej hej %+v\n", tasks) task := &Entry{ Id: int(id), From: from, Date: date, To: to, + Tasks: tasks, Comment: r.PostFormValue("comment"), } return task, nil } func (s *Server) renderTemplate(w http.ResponseWriter, name string, page interface{}) { - tmpl, err := template.ParseFiles("templates/index.html", "templates/parts/entry.html", "templates/parts/entryRows.html", "templates/parts/task.html", "templates/parts/taskRows.html") + tmpl := template.New("").Funcs(template.FuncMap { + "arr": (func (els ...interface{}) []interface{} { + return els + }), + "taskMapToArr": (func (taskMap map[int]*time.Duration) [](struct {Key int; Id int; Sel *string}) { + res := make([](struct {Key int; Id int; Sel *string}), 0, len(taskMap)) + count := 0 + for taskId, sel := range taskMap { + thing := struct {Key int; Id int; Sel *string}{ + Key: count, + Id: taskId, + Sel: nil, + } + if sel != nil { + formatted := sel.String() + thing.Sel = &formatted + } + res = append(res, thing) + + count += 1 + } + + fmt.Printf("Hej, %+v, lul: %+v\n", res, taskMap) + return res + }), + }) + tmpl, err := tmpl.ParseFiles("templates/index.html", "templates/parts/entry.html", "templates/parts/entryRows.html", "templates/parts/task.html", "templates/parts/taskRows.html", "templates/parts/taskEntry.html") if err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return @@ -269,12 +346,11 @@ func (s *Server) getNew(w http.ResponseWriter, r *http.Request) { } func (s *Server) getEdit(w http.ResponseWriter, r *http.Request) { - idLarge, err := strconv.ParseInt(r.URL.Query().Get("id"), 10, 32) + id, err := parseIdInt(r.URL.Query().Get("id")) if err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } - id := int(idLarge) entries, err := s.srv.Db.QueryEntry(&id, nil) if err != nil { @@ -359,6 +435,50 @@ func (s *Server) getTaskEmpty(w http.ResponseWriter, _ *http.Request) { s.renderTemplate(w, "task.html", page) } +func (s *Server) getTaskEdit(w http.ResponseWriter, r *http.Request) { + id, err := parseIdInt(r.URL.Query().Get("id")) + if err != nil { + writeError(w, err.Error(), http.StatusBadRequest) + return + } + + page, err := s.srv.GetTaskPage(&id, nil) + if err != nil { + writeError(w, err.Error(), http.StatusInternalServerError) + return + } + + s.renderTemplate(w, "task.html", page) +} + +func (s *Server) getTaskSelect(w http.ResponseWriter, r *http.Request) { + page, err := s.srv.GetTasksPage() + if err != nil { + writeError(w, err.Error(), http.StatusInternalServerError) + return + } + + var selected int = -1 + { + selectedStr := r.URL.Query().Get("selected") + if selectedStr != "" { + selectedLong, err := strconv.ParseInt(selectedStr, 10, 32) + if err != nil { + writeError(w, err.Error(), http.StatusBadRequest) + return + } + selected = int(selectedLong) + } + } + + args := []interface{}{ + &page.GroupToTasks, + selected, + } + + s.renderTemplate(w, "taskEntry.html", args) +} + func main() { fmt.Println("Hello world!") @@ -378,6 +498,8 @@ func main() { r.HandleFunc("/task/list", s.getTasksList).Methods("GET") r.HandleFunc("/task/save", s.postTaskSave).Methods("POST") r.HandleFunc("/task/empty", s.getTaskEmpty).Methods("GET") + r.HandleFunc("/task/edit", s.getTaskEdit).Methods("GET") + r.HandleFunc("/task/select", s.getTaskSelect).Methods("GET") r.HandleFunc("/", s.rootHandle) http.Handle("/", r) -- cgit v1.2.3