summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Jørgensen <julian@jtle.dk>2024-05-24 23:33:49 +0200
committerJulian Jørgensen <julian@jtle.dk>2024-05-24 23:33:49 +0200
commit6cdd02af0684500b5376d4d4a08feb796fdaf889 (patch)
tree7ffb2ded2251fef175f2c0ce6dfbea978152e063
parenteabd0e769c2bfef7a7aa748d794675d3ff7a920b (diff)
Add date stuff
-rw-r--r--db.go31
-rw-r--r--model.go23
-rw-r--r--page.go46
-rw-r--r--templates/index.html6
-rw-r--r--templates/parts/entry.html6
-rw-r--r--templates/parts/entryRows.html2
-rw-r--r--tidsreg.go100
7 files changed, 156 insertions, 58 deletions
diff --git a/db.go b/db.go
index a1b0c33..45296d6 100644
--- a/db.go
+++ b/db.go
@@ -8,7 +8,7 @@ import (
type Database interface {
GetTracking() (*Entry, error)
GetEntries() ([]*Entry, error)
- QueryEntry(id *int) ([]*Entry, error)
+ QueryEntry(id *int, date *Date) ([]*Entry, error)
StartNewEntry(now time.Time, task *Entry) (*Entry, error)
StopEntry(now time.Time) error
SaveEntry(task *Entry) (*Entry, error)
@@ -49,12 +49,16 @@ func (db *InMemDb) GetEntries() ([]*Entry, error) {
return res, nil
}
-func (db *InMemDb) QueryEntry(id *int) ([]*Entry, error) {
+func (db *InMemDb) QueryEntry(id *int, date *Date) ([]*Entry, error) {
res := make([]*Entry, 0, 1)
for _, entry := range db.entries {
- if id != nil && entry.Id == *id {
- res = append(res, entry)
+ if id != nil && entry.Id != *id {
+ continue
+ }
+ if date != nil && entry.Date != *date {
+ continue
}
+ res = append(res, entry)
}
return res, nil
@@ -65,6 +69,7 @@ func (db *InMemDb) StartNewEntry(now time.Time, task *Entry) (*Entry, error) {
Id: len(db.entries),
From: task.From,
To: nil,
+ Date: DateFromStd(now),
Tag: task.Tag,
Comment: task.Comment,
}
@@ -77,6 +82,7 @@ func (db *InMemDb) StartNewEntry(now time.Time, task *Entry) (*Entry, error) {
db.entries = append(db.entries, newTask)
db.StopEntry(now)
db.current = newTask
+
return newTask, nil
}
@@ -91,20 +97,21 @@ func (db *InMemDb) StopEntry(now time.Time) error {
return nil
}
-func (db *InMemDb) SaveEntry(task *Entry) (*Entry, error) {
- if task.Id < 0 || task.Id >= len(db.entries) {
- copyTask := *task
+func (db *InMemDb) SaveEntry(entry *Entry) (*Entry, error) {
+ if entry.Id < 0 || entry.Id >= len(db.entries) {
+ copyTask := *entry
copyTask.Id = len(db.entries)
db.entries = append(db.entries, &copyTask)
return &copyTask, nil
}
- existent := db.entries[task.Id]
- existent.Comment = task.Comment
- existent.Tag = task.Tag
- existent.From = task.From
- existent.To = task.To
+ existent := db.entries[entry.Id]
+ existent.Comment = entry.Comment
+ existent.Tag = entry.Tag
+ existent.From = entry.From
+ existent.To = entry.To
+ existent.Date = entry.Date
return existent, nil
}
diff --git a/model.go b/model.go
index 96be9e4..b8d174c 100644
--- a/model.go
+++ b/model.go
@@ -2,13 +2,14 @@ package main
import (
"errors"
+ "log"
"regexp"
"time"
)
type Entry struct {
Id int
- Date time.Time
+ Date Date
From *Time
To *Time
Tag *string
@@ -34,6 +35,18 @@ var (
ErrInvalidDate = errors.New("Invalid date string")
)
+func NewEntry(date Date) *Entry {
+ return &Entry{
+ Id: -1,
+ From: nil,
+ Date: date,
+ To: nil,
+ Tag: nil,
+ Comment: "",
+ }
+
+}
+
func TimeFromStd(time time.Time) Time {
return Time(time.Format("15:04"))
}
@@ -67,3 +80,11 @@ func DateFromString(str string) (*Date, error) {
date := Date(str)
return &date, nil
}
+
+func (d Date) ToStd() time.Time {
+ t, err := time.Parse("2006-01-02", string(d))
+ if err != nil {
+ log.Fatal(err)
+ }
+ return t
+}
diff --git a/page.go b/page.go
index bae3e7c..b58436d 100644
--- a/page.go
+++ b/page.go
@@ -1,24 +1,29 @@
package main
+import "time"
+
type Service struct {
Db Database
}
type DateInfo struct {
- Date string
- Tomorrow string
- Yesterday string
+ Date Date
+ Tomorrow Date
+ Yesterday Date
+ IsToday bool
}
type EntryPage struct {
Entry *Entry
Detached bool
Tracking *Entry
+ DateInfo DateInfo
}
type RootPage struct {
- Entry *EntryPage
- Entries []*Entry
+ DateInfo DateInfo
+ Entry *EntryPage
+ Entries []*Entry
}
type TasksPage struct {
@@ -31,6 +36,15 @@ func NewService(db Database) *Service {
}
}
+func NewDateInfo(t time.Time) DateInfo {
+ return DateInfo{
+ Date: DateFromStd(t),
+ Tomorrow: DateFromStd(t.Add(24 * time.Hour)),
+ Yesterday: DateFromStd(t.Add(-24 * time.Hour)),
+ IsToday: DateFromStd(time.Now()) == DateFromStd(t),
+ }
+}
+
func (srv *Service) GetTasksPage() (*TasksPage, error) {
tasks, err := srv.Db.GetTasks()
if err != nil {
@@ -40,16 +54,16 @@ func (srv *Service) GetTasksPage() (*TasksPage, error) {
Tasks: tasks,
}, nil
}
-func (srv *Service) GetEntryPage(detached *Entry) (*EntryPage, error) {
+func (srv *Service) GetEntryPage(detached *Entry, dt DateInfo) (*EntryPage, error) {
tracking, err := srv.Db.GetTracking()
if err != nil {
return nil, err
}
-
page := &EntryPage{
Entry: tracking,
Detached: false,
Tracking: tracking,
+ DateInfo: dt,
}
if detached != nil {
@@ -60,18 +74,26 @@ func (srv *Service) GetEntryPage(detached *Entry) (*EntryPage, error) {
return page, nil
}
-func (srv *Service) GetRootPage() (*RootPage, error) {
- entry, err := srv.GetEntryPage(nil)
+func (srv *Service) GetRootPage(date Date) (*RootPage, error) {
+ var entry *Entry = nil
+
+ if string(date) != time.Now().Format("2006-01-02") {
+ // If not today detach
+ entry = NewEntry(date)
+ }
+
+ entryPage, err := srv.GetEntryPage(entry, NewDateInfo(date.ToStd()))
if err != nil {
return nil, err
}
- entries, err := srv.Db.GetEntries()
+ entries, err := srv.Db.QueryEntry(nil, &date)
if err != nil {
return nil, err
}
return &RootPage{
- Entry: entry,
- Entries: entries,
+ DateInfo: entryPage.DateInfo,
+ Entry: entryPage,
+ Entries: entries,
}, nil
}
diff --git a/templates/index.html b/templates/index.html
index eecf879..b2dc6b0 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -55,9 +55,9 @@
</head>
<body>
<div id="controls-bar">
- <button>I går</button>
- <input type="date" />
- <button>I morgen</button>
+ <button hx-get="/" hx-replace-url="true" hx-params="date" hx-vals='{"date": "{{.DateInfo.Yesterday}}"}' hx-target="body">I går</button>
+ <input type="date" hx-get="/" hx-replace-url="true" hx-params="date" hx-vals='js:{date: event.target.value}' autocomplete="off" hx-target="body" hx-trigger="change" value="{{.DateInfo.Date}}" />
+ <button hx-get="/" hx-replace-url="true" hx-params="date" hx-vals='{"date": "{{.DateInfo.Tomorrow}}"}' hx-target="body">I morgen</button>
</div>
<div class="flex">
<div>
diff --git a/templates/parts/entry.html b/templates/parts/entry.html
index 9f05ffa..300f543 100644
--- a/templates/parts/entry.html
+++ b/templates/parts/entry.html
@@ -48,13 +48,15 @@
>Gem
</button>
{{end}}
- {{ if .Detached }}
+ {{ if .Detached}}
+ {{ if .DateInfo.IsToday }}
<button
hx-get="/tracking"
hx-trigger="click"
hx-target="#entry-bar"
hx-swap="outerHTML"
>Tilbage</button>
+ {{ end }}
{{ else }}
{{ if .Entry }}
<button
@@ -77,5 +79,5 @@
hx-target="#entry-bar"
hx-swap="outerHTML"
>Manuel</button>
- {{ end }}
+ {{ end }}<input readonly type="text" name="date" {{if .Entry}}value="{{ .Entry.Date }}"{{end}} />
</form>
diff --git a/templates/parts/entryRows.html b/templates/parts/entryRows.html
index fd14608..9e9c0eb 100644
--- a/templates/parts/entryRows.html
+++ b/templates/parts/entryRows.html
@@ -1,4 +1,4 @@
-<tbody hx-swap="outerHTML" hx-trigger="changedEntries from:body" hx-get="/entryRows">
+<tbody hx-swap="outerHTML" hx-trigger="changedEntries from:body" hx-get="/entryRows" hx-params="date" hx-vals='{"date": "{{.DateInfo.Date}}"}'>
{{ range $entry := .Entries }}
<tr>
<td>{{ $entry.Id }}</td>
diff --git a/tidsreg.go b/tidsreg.go
index 987a40f..43e4adb 100644
--- a/tidsreg.go
+++ b/tidsreg.go
@@ -1,9 +1,11 @@
package main
import (
+ "errors"
"fmt"
"log"
"net/http"
+ "net/url"
"strconv"
"text/template"
"time"
@@ -13,15 +15,29 @@ import (
type Server struct {
template *template.Template
- srv *Service
+ srv *Service
}
-func parseTaskFromForm(r *http.Request) (*Entry, error) {
+func parseTaskFromForm(r *http.Request, useToday bool) (*Entry, error) {
err := r.ParseForm()
if err != nil {
return nil, err
}
+ var date Date
+ dateP, err := DateFromString(r.PostFormValue("date"))
+ if err != nil {
+ return nil, err
+ }
+ if dateP != nil {
+ date = *dateP
+ } else {
+ if useToday {
+ date = DateFromStd(time.Now())
+ } else {
+ return nil, errors.New("date missing from post")
+ }
+ }
from, err := TimeFromString(r.PostFormValue("from"))
if err != nil {
return nil, err
@@ -40,10 +56,11 @@ func parseTaskFromForm(r *http.Request) (*Entry, error) {
}
}
- task := &Entry {
- Id: int(id),
- From: from,
- To: to,
+ task := &Entry{
+ Id: int(id),
+ From: from,
+ Date: date,
+ To: to,
Comment: r.PostFormValue("comment"),
}
return task, nil
@@ -69,6 +86,22 @@ func writeError(w http.ResponseWriter, err string, code int) {
return
}
+func parseDateFromUrl(url *url.URL, allowToday bool) (Date, error) {
+ date, err := DateFromString(url.Query().Get("date"))
+ if err != nil {
+ return "", nil
+ }
+ if date == nil {
+ if allowToday {
+ return DateFromStd(time.Now()), nil
+ } else {
+ return "", errors.New("date query param empty")
+ }
+ }
+
+ return *date, nil
+}
+
func (s *Server) rootHandle(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound)
@@ -76,7 +109,13 @@ func (s *Server) rootHandle(w http.ResponseWriter, r *http.Request) {
return
}
- page, err := s.srv.GetRootPage()
+ date, err := parseDateFromUrl(r.URL, true)
+ if err != nil {
+ writeError(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ page, err := s.srv.GetRootPage(date)
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -85,11 +124,10 @@ func (s *Server) rootHandle(w http.ResponseWriter, r *http.Request) {
s.renderTemplate(w, "index.html", page)
}
-
func (s *Server) postStart(w http.ResponseWriter, r *http.Request) {
now := time.Now()
- task, err := parseTaskFromForm(r)
+ task, err := parseTaskFromForm(r, true)
if err != nil {
writeError(w, err.Error(), http.StatusBadRequest)
return
@@ -100,7 +138,7 @@ func (s *Server) postStart(w http.ResponseWriter, r *http.Request) {
writeError(w, err.Error(), http.StatusInternalServerError)
return
}
- page, err := s.srv.GetEntryPage(nil)
+ page, err := s.srv.GetEntryPage(nil, NewDateInfo(now))
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -112,7 +150,7 @@ func (s *Server) postStart(w http.ResponseWriter, r *http.Request) {
func (s *Server) postStop(w http.ResponseWriter, r *http.Request) {
now := time.Now()
- task, err := parseTaskFromForm(r)
+ task, err := parseTaskFromForm(r, true)
if err != nil {
writeError(w, err.Error(), http.StatusBadRequest)
return
@@ -134,7 +172,8 @@ func (s *Server) postStop(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) getTracking(w http.ResponseWriter, _ *http.Request) {
- page, err := s.srv.GetEntryPage(nil)
+ nowDt := NewDateInfo(time.Now())
+ page, err := s.srv.GetEntryPage(nil, nowDt)
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -144,7 +183,7 @@ func (s *Server) getTracking(w http.ResponseWriter, _ *http.Request) {
}
func (s *Server) putSave(w http.ResponseWriter, r *http.Request) {
- task, err := parseTaskFromForm(r)
+ task, err := parseTaskFromForm(r, false)
if err != nil {
writeError(w, err.Error(), http.StatusBadRequest)
return
@@ -161,7 +200,7 @@ func (s *Server) putSave(w http.ResponseWriter, r *http.Request) {
detached = task
}
- page, err := s.srv.GetEntryPage(detached)
+ page, err := s.srv.GetEntryPage(detached, NewDateInfo(task.Date.ToStd()))
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -172,16 +211,16 @@ func (s *Server) putSave(w http.ResponseWriter, r *http.Request) {
s.renderTemplate(w, "entry.html", page)
}
-func (s *Server) getNew(w http.ResponseWriter, _ *http.Request) {
- task := &Entry {
- Id: -1,
- From: nil,
- To: nil,
- Tag: nil,
- Comment: "",
+func (s *Server) getNew(w http.ResponseWriter, r *http.Request) {
+ date, err := parseDateFromUrl(r.URL, true)
+ if err != nil {
+ writeError(w, err.Error(), http.StatusBadRequest)
+ return
}
- page, err := s.srv.GetEntryPage(task)
+ task := NewEntry(date)
+
+ page, err := s.srv.GetEntryPage(task, NewDateInfo(date.ToStd()))
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -198,7 +237,7 @@ func (s *Server) getEdit(w http.ResponseWriter, r *http.Request) {
}
id := int(idLarge)
- entries, err := s.srv.Db.QueryEntry(&id)
+ entries, err := s.srv.Db.QueryEntry(&id, nil)
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -208,7 +247,8 @@ func (s *Server) getEdit(w http.ResponseWriter, r *http.Request) {
return
}
- page, err := s.srv.GetEntryPage(entries[0])
+ page, err := s.srv.GetEntryPage(entries[0],
+ NewDateInfo(entries[0].Date.ToStd()))
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -217,8 +257,14 @@ func (s *Server) getEdit(w http.ResponseWriter, r *http.Request) {
s.renderTemplate(w, "entry.html", page)
}
-func (s *Server) getEntries(w http.ResponseWriter, _ *http.Request) {
- page, err := s.srv.GetRootPage()
+func (s *Server) getEntries(w http.ResponseWriter, r *http.Request) {
+ date, err := parseDateFromUrl(r.URL, true)
+ if err != nil {
+ writeError(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ page, err := s.srv.GetRootPage(date)
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)
return
@@ -242,7 +288,7 @@ func main() {
s := Server{
template: nil,
- srv: NewService(NewInMemDb()),
+ srv: NewService(NewInMemDb()),
}
r := mux.NewRouter()