Skip to content

Commit 684676a

Browse files
committed
Add CSV download for tickets
1 parent db939ce commit 684676a

4 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/hmnurl/urls.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ func BuildTicketsAdminEvent(urlSlug string) string {
151151
return Url(fmt.Sprintf("/tickets/admin/%s", urlSlug), nil)
152152
}
153153

154+
var RegexTicketsAdminEventCSVDownload = regexp.MustCompile("^/tickets/admin/(?P<urlslug>[^/]+)/csv$")
155+
156+
func BuildTicketsAdminEventCSVDownload(urlSlug string) string {
157+
defer CatchPanic()
158+
return Url(fmt.Sprintf("/tickets/admin/%s/csv", urlSlug), nil)
159+
}
160+
154161
var RegexTicketsAdminReserve = regexp.MustCompile("^/tickets/admin/(?P<urlslug>[^/]+)/reserve$")
155162

156163
func BuildTicketsAdminReserve(urlSlug string) string {

src/templates/src/tickets_admin_event.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@
119119
<div class="pa3 flex flex-column g3">
120120
<div>
121121
<div class="f3">Tickets</div>
122-
<a href="{{ .ScannerUrl }}">Scan tickets</a>
122+
<a class="db" href="{{ .ScannerUrl }}">Scan tickets</a>
123+
<a class="db" href="{{ .CSVUrl }}">Download CSV</a>
123124
<div>
124125
<div><b>Total:</b> {{ add .TicketsEvent.Metadata.SoldTickets .TicketsEvent.Metadata.ReservedTickets }}</div>
125126
<div><b>Pending:</b> {{ .TicketsEvent.Metadata.PendingTickets }}</div>

src/website/routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ func NewWebsiteRoutes(conn *pgxpool.Pool, perfCollector *perf.PerfCollector) htt
135135
hmnOnly.GET(hmnurl.RegexTicketsAdmin, adminsOnly(TicketsAdmin))
136136
hmnOnly.GET(hmnurl.RegexTicketsAdminEvent, adminsOnly(TicketsAdminEvent))
137137
hmnOnly.POST(hmnurl.RegexTicketsAdminEvent, adminsOnly(TicketsAdminEventSubmit))
138+
hmnOnly.GET(hmnurl.RegexTicketsAdminEventCSVDownload, adminsOnly(TicketsAdminEventCSVDownload))
138139
hmnOnly.POST(hmnurl.RegexTicketsAdminReserve, adminsOnly(TicketsAdminReserve))
139140
hmnOnly.GET(hmnurl.RegexTicketsAdminScan, adminsOnly(TicketsAdminScan))
140141
hmnOnly.POST(hmnurl.RegexTicketsAdminScan, adminsOnly(csrfMiddleware(TicketsAdminScanSubmit)))

src/website/tickets.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package website
22

33
import (
44
"context"
5+
"encoding/csv"
56
"fmt"
67
"math/rand"
78
"net/http"
@@ -81,6 +82,7 @@ func TicketsAdminEvent(c *RequestContext) ResponseData {
8182
TicketsEvent TicketsAdminEventTemplateData
8283
ReserveActionUrl string
8384
ScannerUrl string
85+
CSVUrl string
8486
}
8587
urlSlug := c.PathParams["urlslug"]
8688

@@ -114,6 +116,7 @@ func TicketsAdminEvent(c *RequestContext) ResponseData {
114116
},
115117
ReserveActionUrl: hmnurl.BuildTicketsAdminReserve(event.UrlSlug),
116118
ScannerUrl: hmnurl.BuildTicketsAdminScan(event.UrlSlug),
119+
CSVUrl: hmnurl.BuildTicketsAdminEventCSVDownload(event.UrlSlug),
117120
}
118121

119122
var res ResponseData
@@ -176,6 +179,42 @@ func TicketsAdminEventSubmit(c *RequestContext) ResponseData {
176179
return c.Redirect(hmnurl.BuildTicketsAdminEvent(eventUrlSlug), http.StatusSeeOther)
177180
}
178181

182+
func TicketsAdminEventCSVDownload(c *RequestContext) ResponseData {
183+
urlSlug := c.PathParams["urlslug"]
184+
event, found := hmndata.FindTicketEventBySlug(urlSlug)
185+
if !found {
186+
return FourOhFour(c)
187+
}
188+
189+
rawTickets, err := hmndata.FetchTickets(c, c.Conn, &event)
190+
if err != nil {
191+
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch tickets"))
192+
}
193+
var tickets []templates.Ticket
194+
for _, t := range rawTickets {
195+
tickets = append(tickets, templates.TicketToTemplate(&t))
196+
}
197+
198+
var res ResponseData
199+
res.Header().Set("Content-Type", "text/csv")
200+
res.Header().Set("Content-Disposition", `attachment; filename="tickets.csv"`)
201+
w := csv.NewWriter(&res)
202+
w.Write([]string{"name", "email", "username", "discord_username", "purchase_date", "notes", "accommodations"})
203+
for _, ticket := range tickets {
204+
w.Write([]string{
205+
ticket.OwnerName,
206+
ticket.OwnerEmail,
207+
ticket.OwnerUsername,
208+
ticket.OwnerDiscordUsername,
209+
ticket.PurchaseDate.String(),
210+
ticket.Notes,
211+
ticket.Accommodations,
212+
})
213+
}
214+
w.Flush()
215+
return res
216+
}
217+
179218
func TicketsAdminReserve(c *RequestContext) ResponseData {
180219
err := c.Req.ParseForm()
181220
if err != nil {

0 commit comments

Comments
 (0)