all repos — homestead @ 610418737cec7dcd954f0080da40417b54f2e937

Code for my website

show per-day times for multi-day events

Alan Pearce
commit

610418737cec7dcd954f0080da40417b54f2e937

parent

6d30cc9ad4727ebb35c3c899358121255ee34caa

3 files changed, 60 insertions(+), 20 deletions(-)

changed files
M internal/calendar/calendar.gointernal/calendar/calendar.go
@@ -21,7 +21,8 @@ const Filename = "calendar.ics"
const Refresh = 30 * time.Minute type Options struct { - URL config.URL + URL config.URL + Timezone config.Timezone } type Calendar struct {
@@ -188,7 +189,7 @@ 0,
0, 0, 0, - now.Location(), + c.opts.Timezone.Location, ) days := count*7 + weekday + 1 dates := make([]Date, 0, days)
@@ -209,7 +210,7 @@ c.log.Debug("processing date", "date", date.DateOnly())
cd := &CalendarDate{Date: date} - evs, err := c.EventsBetween(date.Time, date.NextDay().Time) + evs, err := c.EventsBetween(date.Add(1*time.Second), date.EndOfDay().Time) if err != nil { return nil, errors.WithMessage(err, "could not get events") }
@@ -227,7 +228,7 @@ return cds, nil
} func (d Date) Between(lower, upper Date) bool { - return d.After(lower.Time) && d.Before(upper.Time) + return d.After(lower) && d.Before(upper) } func (d Date) Key() int {
@@ -251,6 +252,21 @@ ),
} } +func (d Date) EndOfDay() Date { + return Date{ + Time: time.Date( + d.Year(), + d.Month(), + d.Day(), + 23, + 59, + 59, + 999999999, + d.Location(), + ), + } +} + func (d Date) DateOnly() string { return d.Format(time.DateOnly) }
@@ -264,3 +280,11 @@
func (d Date) IsToday() bool { return d.Key() == Date{time.Now()}.Key() } + +func (d Date) Before(other Date) bool { + return d.Time.Before(other.Time) +} + +func (d Date) After(other Date) bool { + return d.Time.After(other.Time) +}
M internal/website/website.gointernal/website/website.go
@@ -119,15 +119,6 @@ CSPHeader.ScriptSrc = slices.Insert(CSPHeader.ScriptSrc, 0, "'unsafe-inline'")
CSPHeader.ConnectSrc = slices.Insert(CSPHeader.ConnectSrc, 0, "'self'") } - website.calendar = calendar.New(&calendar.Options{ - URL: opts.CalendarURL, - }, log.Named("calendar")) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - if err := website.calendar.FetchIfNeeded(ctx); err != nil { - log.Error("could not fetch calendar", "error", err) - } - cancel() - firstUpdate := make(chan bool) go func() { updated := sync.OnceFunc(func() {
@@ -149,6 +140,16 @@ Timezone: cfg.Timezone,
Menu: cfg.Menu, InjectLiveReload: opts.Development, } + + website.calendar = calendar.New(&calendar.Options{ + URL: opts.CalendarURL, + Timezone: cfg.Timezone, + }, log.Named("calendar")) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + if err := website.calendar.FetchIfNeeded(ctx); err != nil { + log.Error("could not fetch calendar", "error", err) + } + cancel() if opts.GoatcounterToken == "" { if !opts.Development {
M templates/calendar.gotemplates/calendar.go
@@ -1,6 +1,7 @@
package templates import ( + "fmt" "time" g "go.alanpearce.eu/gomponents"
@@ -42,20 +43,27 @@ "today": date.IsToday(),
}, H3( Time( - DateTime(date.UTC().Format(time.DateOnly)), + DateTime(date.Format(time.DateOnly)), g.Text(date.Format("Mon _2"))), ), g.Map(date.Events, func(e *calendar.Event) g.Node { return Div( Class("event"), - Time( - DateTime(e.StartTime.UTC().Format(time.DateOnly)), - g.Text(e.StartTime.Format("15:04")), + TitleAttr( + fmt.Sprintf( + "%s–%s", + e.StartTime.Format(time.RFC1123), + e.EndTime.Format(time.RFC1123), + ), + ), + g.If(e.StartTime.Before(date.BeginningOfDay()), + CTime(date.BeginningOfDay()), + CTime(e.StartTime), ), g.Text("–"), - Time( - DateTime(e.EndTime.UTC().Format(time.DateOnly)), - g.Text(e.EndTime.Format("15:04")), + g.If(e.EndTime.After(date.EndOfDay()), + CTime(date.EndOfDay()), + CTime(e.EndTime), ), ) }),
@@ -67,3 +75,10 @@ P(g.Textf("Timezone is %s", site.Timezone.String())),
), ) } + +func CTime(date calendar.Date) g.Node { + return Time( + DateTime(date.Format(time.RFC3339)), + g.Text(date.Format("15:04")), + ) +}