diff --git a/plugins/caldav/routes.go b/plugins/caldav/routes.go
index cb8aa2a..d7c31f7 100644
--- a/plugins/caldav/routes.go
+++ b/plugins/caldav/routes.go
@@ -18,9 +18,16 @@ import (
type CalendarRenderData struct {
alps.BaseRenderData
Time time.Time
+ Now time.Time
+ Dates [7 * 6]time.Time
Calendar *caldav.Calendar
Events []CalendarObject
PrevPage, NextPage string
+ PrevTime, NextTime time.Time
+
+ EventsForDate func(time.Time) []CalendarObject
+ DaySuffix func(n int) string
+ Sub func(a, b int) int
}
type EventRenderData struct {
@@ -96,13 +103,66 @@ func registerRoutes(p *alps.GoPlugin, u *url.URL) {
return fmt.Errorf("failed to query calendar: %v", err)
}
+ // TODO: Time zones are hard
+ var dates [7 * 6]time.Time
+ initialDate := start.UTC()
+ initialDate = initialDate.AddDate(0, 0, -int(initialDate.Weekday()))
+ for i := 0; i < len(dates); i += 1 {
+ dates[i] = initialDate
+ initialDate = initialDate.AddDate(0, 0, 1)
+ }
+
+ eventMap := make(map[time.Time][]CalendarObject)
+ for _, ev := range events {
+ ev := ev // make a copy
+ // TODO: include event on each date for which it is active
+ co := ev.Data.Events()[0]
+ startTime, _ := co.DateTimeStart(nil)
+ startTime = startTime.UTC().Truncate(time.Hour * 24)
+ eventMap[startTime] = append(eventMap[startTime], CalendarObject{&ev})
+ }
+
return ctx.Render(http.StatusOK, "calendar.html", &CalendarRenderData{
BaseRenderData: *alps.NewBaseRenderData(ctx),
Time: start,
+ Now: time.Now(), // TODO: Use client time zone
Calendar: calendar,
+ Dates: dates,
Events: newCalendarObjectList(events),
PrevPage: start.AddDate(0, -1, 0).Format(monthPageLayout),
NextPage: start.AddDate(0, 1, 0).Format(monthPageLayout),
+ PrevTime: start.AddDate(0, -1, 0),
+ NextTime: start.AddDate(0, 1, 0),
+
+ EventsForDate: func(when time.Time) []CalendarObject {
+ if events, ok := eventMap[when.Truncate(time.Hour * 24)]; ok {
+ return events
+ }
+ return nil
+ },
+
+ DaySuffix: func(n int) string {
+ if n % 100 >= 11 && n % 100 <= 13 {
+ return "th"
+ }
+ return map[int]string{
+ 0: "th",
+ 1: "st",
+ 2: "nd",
+ 3: "rd",
+ 4: "th",
+ 5: "th",
+ 6: "th",
+ 7: "th",
+ 8: "th",
+ 9: "th",
+ }[n % 10]
+ },
+
+ Sub: func (a, b int) int {
+ // Why isn't this built-in, come on Go
+ return a - b
+ },
})
})
diff --git a/themes/alps/assets/style.css b/themes/alps/assets/style.css
index c62fbbc..8ce6549 100644
--- a/themes/alps/assets/style.css
+++ b/themes/alps/assets/style.css
@@ -261,6 +261,11 @@ main.new-contact .actions > *:not(:last-child) {
margin-right: 1rem;
}
+.actions h3 {
+ align-self: center;
+ margin: 0 1.3rem 0 1rem;
+}
+
.message-list-subject a { color: #77c; }
.message-list-unread.message-list-sender,
@@ -370,7 +375,7 @@ main table tfoot {
padding: 0.3rem 0.5rem;
}
-.actions-pagination .button-link:first-child:not(:last-child) {
+.actions-pagination .button-link:not(:last-child) {
margin-right: 0.3rem;
}
@@ -444,6 +449,100 @@ main table tfoot {
margin-top: 1rem;
}
+main.calendar .dates {
+ flex-grow: 1;
+ padding: 0.3rem;
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
+ grid-template-rows: auto 1fr 1fr 1fr 1fr 1fr 1fr auto;
+ grid-template-areas:
+ "sunday-top monday-top wednesday-top tuesday-top thursday-top friday-top saturday-top"
+ "dates dates dates dates dates dates dates"
+ "dates dates dates dates dates dates dates"
+ "dates dates dates dates dates dates dates"
+ "dates dates dates dates dates dates dates"
+ "dates dates dates dates dates dates dates"
+ "dates dates dates dates dates dates dates"
+ "sunday-bottom monday-bottom wednesday-bottom tuesday-bottom thursday-bottom friday-bottom saturday-bottom";
+ grid-gap: 0.3rem;
+}
+
+main.calendar .dates .weekday {
+ text-align: center;
+ font-size: 1.1rem;
+ font-weight: normal;
+}
+
+main.calendar .dates .sunday-top { grid-area: sunday-top; }
+main.calendar .dates .monday-top { grid-area: monday-top; }
+main.calendar .dates .tuesday-top { grid-area: tuesday-top; }
+main.calendar .dates .wednesday-top { grid-area: wednesday-top; }
+main.calendar .dates .thursday-top { grid-area: thursday-top; }
+main.calendar .dates .friday-top { grid-area: friday-top; }
+main.calendar .dates .saturday-top { grid-area: saturday-top; }
+main.calendar .dates .sunday-bottom { grid-area: sunday-bottom; }
+main.calendar .dates .monday-bottom { grid-area: monday-bottom; }
+main.calendar .dates .tuesday-bottom { grid-area: tuesday-bottom; }
+main.calendar .dates .wednesday-bottom { grid-area: wednesday-bottom; }
+main.calendar .dates .thursday-bottom { grid-area: thursday-bottom; }
+main.calendar .dates .friday-bottom { grid-area: friday-bottom; }
+main.calendar .dates .saturday-bottom { grid-area: saturday-bottom; }
+
+main.calendar .date {
+ border: 1px solid #eee;
+ padding: 0.3rem;
+ background: white;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+}
+
+main.calendar .date.active {
+ background-color: #f6fff6;
+ border: 1px solid #afa;
+}
+
+main.calendar .date .date-link {
+ position: absolute;
+ top: 0; right: 0; bottom: 0; left: 0;
+}
+
+main.calendar .date.extra {
+ background: transparent;
+ border: none;
+}
+
+main.calendar .date ul {
+ list-style: none;
+ margin: 0;
+ padding-left: 0.3rem;
+}
+
+main.calendar .date .events {
+ flex-grow: 1;
+}
+
+main.calendar .date.extra .events {
+ visibility: hidden;
+}
+
+main.calendar .events .start-time {
+ color: #444;
+}
+
+main.calendar .events .overflow {
+ color: #444;
+ text-align: right;
+}
+
+main.calendar .date h4 {
+ font-weight: normal;
+ text-align: right;
+ color: #666;
+}
+
+main.calendar .date h4 .da { font-size: 1.2rem; }
+
input[type="submit"],
.button,
button,
diff --git a/themes/alps/calendar-header.html b/themes/alps/calendar-header.html
new file mode 100644
index 0000000..d902806
--- /dev/null
+++ b/themes/alps/calendar-header.html
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/themes/alps/calendar.html b/themes/alps/calendar.html
new file mode 100644
index 0000000..5bdd6eb
--- /dev/null
+++ b/themes/alps/calendar.html
@@ -0,0 +1,84 @@
+{{template "head.html" .}}
+{{template "nav.html" .}}
+
+
+
+
+
+
+
+ {{ template "calendar-header.html" . }}
+
+
+
+ Sunday
+ Monday
+ Tuesday
+ Wednesday
+ Thursday
+ Friday
+ Saturday
+
+ {{$base := .}}
+ {{range .Dates}}
+
+ {{if eq $base.Time.Month .Month}}
+
+ {{end}}
+
+ {{$events := (call $base.EventsForDate .)}}
+ {{if $events}}
+
+ {{$overflow := 0}}
+ {{if gt (len $events) 3}}
+ {{$overflow = call $base.Sub (len $events) 3}}
+ {{$events = slice $events 0 3}}
+ {{end}}
+
+ {{range $events}}
+ {{$event := index .Data.Events 0}}
+ -
+
+ {{($event.DateTimeStart nil).Format "15:04"}}
+
+ {{$event.Props.Text "SUMMARY"}}
+
+ {{end}}
+ {{if ne $overflow 0}}
+ - ...and {{$overflow}} more
+ {{end}}
+
+ {{end}}
+
+
+ {{.Format "Jan"}}
+ {{.Format "2"}}{{call $base.DaySuffix .Day}}
+
+
+ {{end}}
+
+ Sunday
+ Monday
+ Tuesday
+ Wednesday
+ Thursday
+ Friday
+ Saturday
+
+
+
+ {{ template "calendar-header.html" . }}
+
+
+
+
+
+{{template "foot.html"}}