diff --git a/go.mod b/go.mod index c0c2992..378aa71 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b github.com/emersion/go-smtp v0.12.1 github.com/emersion/go-vcard v0.0.0-20191221110513-5f81fa0d3cc7 - github.com/emersion/go-webdav v0.2.1-0.20200205170548-baf63fb1b759 + github.com/emersion/go-webdav v0.2.1-0.20200205173846-1d93353e3dee github.com/gorilla/css v1.0.0 // indirect github.com/labstack/echo/v4 v4.1.15-0.20200203180927-504f39abaf32 github.com/labstack/gommon v0.3.0 diff --git a/go.sum b/go.sum index 40f9393..c489df1 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,8 @@ github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0 github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= github.com/emersion/go-vcard v0.0.0-20191221110513-5f81fa0d3cc7 h1:SE+tcd+0kn0cT4MqTo66gmkjqWHF1Z+Yha5/rhLs/H8= github.com/emersion/go-vcard v0.0.0-20191221110513-5f81fa0d3cc7/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM= -github.com/emersion/go-webdav v0.2.1-0.20200205170548-baf63fb1b759 h1:8joXUXgdaV935H/AUKhnyvUf754VcjmQAenNsakT4pA= -github.com/emersion/go-webdav v0.2.1-0.20200205170548-baf63fb1b759/go.mod h1:dfzmdPRkPLLUQU00fDfwPJomgFmdblZpMoh3CaUsGCc= +github.com/emersion/go-webdav v0.2.1-0.20200205173846-1d93353e3dee h1:xuiEbeyM/8jUYzsucpmvoQOi6j4XVRv0n8NxKHw9UGg= +github.com/emersion/go-webdav v0.2.1-0.20200205173846-1d93353e3dee/go.mod h1:dfzmdPRkPLLUQU00fDfwPJomgFmdblZpMoh3CaUsGCc= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/labstack/echo/v4 v4.1.15-0.20200203180927-504f39abaf32 h1:UiIEDYxPPmjl6mMIY4QPDguD/QAtK+gR4IRMSrjWmeA= diff --git a/plugins/caldav/routes.go b/plugins/caldav/routes.go index acc879f..7ff831d 100644 --- a/plugins/caldav/routes.go +++ b/plugins/caldav/routes.go @@ -16,6 +16,12 @@ type CalendarRenderData struct { Events []caldav.CalendarObject } +type EventRenderData struct { + koushin.BaseRenderData + Calendar *caldav.Calendar + Event *caldav.CalendarObject +} + func registerRoutes(p *koushin.GoPlugin, u *url.URL) { p.GET("/calendar", func(ctx *koushin.Context) error { // TODO: multi-calendar support @@ -63,4 +69,55 @@ func registerRoutes(p *koushin.GoPlugin, u *url.URL) { Events: events, }) }) + + p.GET("/calendar/:uid", func(ctx *koushin.Context) error { + uid := ctx.Param("uid") + + c, calendar, err := getCalendar(u, ctx.Session) + if err != nil { + return err + } + + query := caldav.CalendarQuery{ + CompRequest: caldav.CalendarCompRequest{ + Name: "VCALENDAR", + Props: []string{"VERSION"}, + Comps: []caldav.CalendarCompRequest{{ + Name: "VEVENT", + Props: []string{ + "SUMMARY", + "DESCRIPTION", + "UID", + "DTSTART", + "DTEND", + "DURATION", + }, + }}, + }, + CompFilter: caldav.CompFilter{ + Name: "VCALENDAR", + Comps: []caldav.CompFilter{{ + Name: "VEVENT", + Props: []caldav.PropFilter{{ + Name: "UID", + TextMatch: &caldav.TextMatch{Text: uid}, + }}, + }}, + }, + } + events, err := c.QueryCalendar(calendar.Path, &query) + if err != nil { + return fmt.Errorf("failed to query calendar: %v", err) + } + if len(events) != 1 { + return fmt.Errorf("expected exactly one calendar object with UID %q, got %v", uid, len(events)) + } + event := &events[0] + + return ctx.Render(http.StatusOK, "event.html", &EventRenderData{ + BaseRenderData: *koushin.NewBaseRenderData(ctx), + Calendar: calendar, + Event: event, + }) + }) }