Skip to content

Commit 9b9f052

Browse files
add event categories functionality
1 parent eb8a0c7 commit 9b9f052

13 files changed

+202
-80
lines changed

api/admin_delete_event.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package api
22

33
import (
4-
"fmt"
54
"net/http"
65

76
"github.com/gin-gonic/gin"
87
"github.com/sndcds/grains/grains_api"
8+
"github.com/sndcds/uranus/app"
99
)
1010

1111
func (h *ApiHandler) AdminDeleteEvent(gc *gin.Context) {
@@ -26,8 +26,7 @@ func (h *ApiHandler) AdminDeleteEvent(gc *gin.Context) {
2626
}
2727
apiRequest.SetMeta("event_id", eventId)
2828

29-
query := fmt.Sprintf(`DELETE FROM %s.event WHERE id = $1`, h.DbSchema)
30-
cmdTag, err := h.DbPool.Exec(ctx, query, eventId)
29+
cmdTag, err := h.DbPool.Exec(ctx, app.UranusInstance.SqlAdminGetEvent, eventId)
3130
if err != nil {
3231
apiRequest.Error(http.StatusInternalServerError, "failed to delete event")
3332
return

api/admin_todo.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@ func (h *ApiHandler) AdminUpsertTodo(gc *gin.Context) {
191191

192192
args = append(args, userId, payload.Id)
193193

194-
res, err := h.DbPool.Exec(ctx, query, args...)
194+
cmdTag, err := h.DbPool.Exec(ctx, query, args...)
195195
if err != nil {
196196
gc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
197197
return
198198
}
199199

200-
if res.RowsAffected() == 0 {
200+
if cmdTag.RowsAffected() == 0 {
201201
gc.JSON(http.StatusNotFound, gin.H{"error": "todo not found"})
202202
return
203203
}
@@ -219,13 +219,13 @@ func (h *ApiHandler) AdminDeleteTodo(gc *gin.Context) {
219219
}
220220

221221
query := fmt.Sprintf(`DELETE FROM %s.todo WHERE user_id = $1 AND id = $2`, h.DbSchema)
222-
res, err := h.DbPool.Exec(ctx, query, userId, todoId)
222+
cmdTag, err := h.DbPool.Exec(ctx, query, userId, todoId)
223223
if err != nil {
224224
gc.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("delete failed: %v", err)})
225225
return
226226
}
227227

228-
if res.RowsAffected() == 0 {
228+
if cmdTag.RowsAffected() == 0 {
229229
gc.JSON(http.StatusNotFound, gin.H{"error": "todo not found"})
230230
return
231231
}

api/admin_update_event_description.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ func (h *ApiHandler) AdminUpdateEventDescription(gc *gin.Context) {
3030
txErr := WithTransaction(ctx, h.DbPool, func(tx pgx.Tx) *ApiTxError {
3131
query := fmt.Sprintf(`UPDATE %s.event SET description = $2 WHERE id = $1`, h.DbSchema)
3232

33-
res, err := h.DbPool.Exec(ctx, query, eventId, req.Description)
33+
cmdTag, err := h.DbPool.Exec(ctx, query, eventId, req.Description)
3434
if err != nil {
3535
return &ApiTxError{
3636
Code: http.StatusInternalServerError,
3737
Err: fmt.Errorf("failed to update event: %v", err),
3838
}
3939
}
4040

41-
rowsAffected := res.RowsAffected()
41+
rowsAffected := cmdTag.RowsAffected()
4242
if rowsAffected == 0 {
4343
return &ApiTxError{
4444
Code: http.StatusNotFound,

api/admin_update_event_fields.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func (h *ApiHandler) UpdateEventFields(gc *gin.Context) {
2626
ReleaseStatus NullableField[string] `json:"release_status"`
2727
ReleaseDate NullableField[string] `json:"release_date"`
2828
ContentLanguage NullableField[string] `json:"content_language"`
29+
Categories NullableField[[]int] `json:"categories"`
2930
Title NullableField[string] `json:"title"`
3031
Subtitle NullableField[string] `json:"subtitle"`
3132
Description NullableField[string] `json:"description"`
@@ -64,6 +65,7 @@ func (h *ApiHandler) UpdateEventFields(gc *gin.Context) {
6465
argPos = addUpdateClauseNullable("release_status", payload.ReleaseStatus, &setClauses, &args, argPos)
6566
argPos = addUpdateClauseNullable("release_date", payload.ReleaseDate, &setClauses, &args, argPos)
6667
argPos = addUpdateClauseNullable("content_iso_639_1", payload.ContentLanguage, &setClauses, &args, argPos)
68+
argPos = addUpdateClauseNullable("categories", payload.Categories, &setClauses, &args, argPos)
6769
argPos = addUpdateClauseNullable("title", payload.Title, &setClauses, &args, argPos)
6870
argPos = addUpdateClauseNullable("subtitle", payload.Subtitle, &setClauses, &args, argPos)
6971
argPos = addUpdateClauseNullable("description", payload.Description, &setClauses, &args, argPos)

api/get_event.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ func (h *ApiHandler) GetEventByDateId(gc *gin.Context) {
180180
if edd.Id == dateId {
181181
tmp := edd
182182
selectedDate = &tmp
183-
} else {
184-
furtherDates = append(furtherDates, edd)
185183
}
184+
185+
furtherDates = append(furtherDates, edd)
186186
}
187187

188188
event.Date = selectedDate

api/get_events.go

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,44 @@ type eventType struct {
2121

2222
// eventResponse is the JSON structure for each event
2323
type eventResponse struct {
24-
EventDateId int `json:"event_date_id"`
25-
Id int `json:"id"` // event_id
26-
Title string `json:"title"`
27-
Subtitle *string `json:"subtitle"`
28-
StartDate string `json:"start_date"`
29-
StartTime string `json:"start_time,omitempty"`
30-
EndDate *string `json:"end_date,omitempty"`
31-
EndTime *string `json:"end_time,omitempty"`
32-
EntryTime *string `json:"entry_time,omitempty"`
33-
Duration *int `json:"duration,omitempty"`
34-
AllDay *bool `json:"all_day,omitempty"`
35-
TicketLink *string `json:"ticket_link,omitempty"`
36-
SpaceId *int `json:"space_id,omitempty"`
37-
SpaceName *string `json:"space_name,omitempty"`
38-
SpaceAccessibilityFlags *string `json:"space_accessibility_flags,omitempty"`
39-
VenueId *int `json:"venue_id,omitempty"`
40-
VenueName *string `json:"venue_name,omitempty"`
41-
VenueCity *string `json:"venue_city,omitempty"`
42-
VenueStreet *string `json:"venue_street,omitempty"`
43-
VenueHouse *string `json:"venue_house_number,omitempty"`
44-
VenuePostal *string `json:"venue_postal_code,omitempty"`
45-
VenueState *string `json:"venue_state,omitempty"`
46-
VenueCountry *string `json:"venue_country,omitempty"`
47-
VenueLat *float64 `json:"venue_lat,omitempty"`
48-
VenueLon *float64 `json:"venue_lon,omitempty"`
49-
ImageId *int `json:"image_id,omitempty"`
50-
ImagePath *string `json:"image_path,omitempty"`
51-
OrganizationId int `json:"organization_id"`
52-
OrganizationName string `json:"organization_name"`
53-
EventTypes []eventType `json:"event_types,omitempty"`
54-
Languages []string `json:"languages"`
55-
Tags []string `json:"tags"`
56-
MinAge *int `json:"min_age"`
57-
MaxAge *int `json:"max_age"`
58-
VisitorInfoFlags *string `json:"visitor_info_flags,omitempty"`
59-
ReleaseStatus *string `json:"release_status,omitempty"`
24+
EventDateId int `json:"event_date_id"`
25+
Id int `json:"id"` // event_id
26+
Title string `json:"title"`
27+
Subtitle *string `json:"subtitle"`
28+
StartDate string `json:"start_date"`
29+
StartTime string `json:"start_time,omitempty"`
30+
EndDate *string `json:"end_date,omitempty"`
31+
EndTime *string `json:"end_time,omitempty"`
32+
EntryTime *string `json:"entry_time,omitempty"`
33+
Duration *int `json:"duration,omitempty"`
34+
AllDay *bool `json:"all_day,omitempty"`
35+
TicketLink *string `json:"ticket_link,omitempty"`
36+
SpaceId *int `json:"space_id,omitempty"`
37+
SpaceName *string `json:"space_name,omitempty"`
38+
SpaceAccessibilityFlags *string `json:"space_accessibility_flags,omitempty"`
39+
VenueId *int `json:"venue_id,omitempty"`
40+
VenueName *string `json:"venue_name,omitempty"`
41+
VenueCity *string `json:"venue_city,omitempty"`
42+
VenueStreet *string `json:"venue_street,omitempty"`
43+
VenueHouse *string `json:"venue_house_number,omitempty"`
44+
VenuePostal *string `json:"venue_postal_code,omitempty"`
45+
VenueState *string `json:"venue_state,omitempty"`
46+
VenueCountry *string `json:"venue_country,omitempty"`
47+
VenueLat *float64 `json:"venue_lat,omitempty"`
48+
VenueLon *float64 `json:"venue_lon,omitempty"`
49+
ImageId *int `json:"image_id,omitempty"`
50+
ImagePath *string `json:"image_path,omitempty"`
51+
OrganizationId int `json:"organization_id"`
52+
OrganizationName string `json:"organization_name"`
53+
Categories []int `json:"categories,omitempty"`
54+
SecondaryEventCategoryId *int `json:"secondary_event_category_id,omitempty"`
55+
EventTypes []eventType `json:"event_types,omitempty"`
56+
Languages []string `json:"languages"`
57+
Tags []string `json:"tags"`
58+
MinAge *int `json:"min_age"`
59+
MaxAge *int `json:"max_age"`
60+
VisitorInfoFlags *string `json:"visitor_info_flags,omitempty"`
61+
ReleaseStatus *string `json:"release_status,omitempty"`
6062
}
6163

6264
// buildEventFilters parses all query parameters from the context
@@ -76,11 +78,11 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
7678
) {
7779

7880
allowed := map[string]struct{}{
79-
"past": {}, "start": {}, "end": {}, "time": {}, "search": {},
81+
"category": {}, "past": {}, "start": {}, "end": {}, "time": {}, "search": {},
8082
"events": {}, "venues": {}, "spaces": {}, "space_types": {},
8183
"organizations": {}, "countries": {}, "postal_code": {},
8284
"title": {}, "city": {}, "event_types": {}, "tags": {},
83-
"accessibility": {}, "visitor_infos": {}, "age": {},
85+
"accessibility": {}, "visitor_infos": {}, "age": {}, "price": {},
8486
"lon": {}, "lat": {}, "radius": {}, "offset": {}, "limit": {},
8587
"last_event_start_at": {}, "last_event_date_id": {},
8688
"language": {},
@@ -96,6 +98,7 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
9698

9799
_, hasPast := GetContextParam(gc, "past")
98100
// languagesStr, _ := GetContextParam(gc, "language") // TODO: Implement language support!
101+
categoryStr, hasCategory := GetContextParam(gc, "category")
99102
startStr, _ := GetContextParam(gc, "start")
100103
endStr, _ := GetContextParam(gc, "end")
101104
lastEventStartAt, _ := GetContextParam(gc, "last_event_start_at")
@@ -116,12 +119,23 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
116119
accessibilityFlagsStr, _ := GetContextParam(gc, "accessibility")
117120
visitorInfosStr, _ := GetContextParam(gc, "visitor_infos")
118121
ageStr, _ := GetContextParam(gc, "age")
122+
priceStr, _ := GetContextParam(gc, "price")
119123
lonStr, _ := GetContextParam(gc, "lon")
120124
latStr, _ := GetContextParam(gc, "lat")
121125
radiusStr, _ := GetContextParam(gc, "radius")
122126
offsetStr, _ := GetContextParam(gc, "offset")
123127
limitStr, _ := GetContextParam(gc, "limit")
124128

129+
var errBuild error
130+
131+
if hasCategory {
132+
argIndex, errBuild = sql_utils.BuildColumnArrayOverlapCondition(
133+
categoryStr, "ep.categories", argIndex, &conditions, &args)
134+
if errBuild != nil {
135+
return "", "", "", nil, 0, errBuild
136+
}
137+
}
138+
125139
// Date conditions
126140
dateConditionCount := 0
127141
if app.IsValidDateStr(startStr) {
@@ -157,7 +171,6 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
157171
}
158172

159173
// Other conditions
160-
var errBuild error
161174
argIndex, errBuild = sql_utils.BuildTimeCondition(
162175
timeStr, "edp.start_time", "time", argIndex, &conditions, &args)
163176
if errBuild != nil {
@@ -207,6 +220,7 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
207220
if errBuild != nil {
208221
return "", "", "", nil, 0, errBuild
209222
}
223+
210224
if eventIdsStr != "" {
211225
argIndex, errBuild = sql_utils.BuildColumnInIntCondition(
212226
eventIdsStr, "edp.event_id", argIndex, &conditions, &args)
@@ -264,6 +278,13 @@ func (h *ApiHandler) buildEventFilters(gc *gin.Context) (
264278
return "", "", "", nil, 0, errBuild
265279
}
266280

281+
argIndex, errBuild = sql_utils.BuildPriceCondition(
282+
priceStr, "ep.price_type", "ep.currency", "ep.min_price", "ep.max_price", "price", argIndex, &conditions, &args)
283+
debugf("priceStr: %s", priceStr)
284+
if errBuild != nil {
285+
return "", "", "", nil, 0, errBuild
286+
}
287+
267288
argIndex, errBuild = sql_utils.BuildBitmaskCondition(
268289
accessibilityFlagsStr, "edp.space_accessibility_flags", "accessibility", argIndex, &conditions, &args)
269290
if errBuild != nil {
@@ -331,13 +352,13 @@ func (h *ApiHandler) GetEvents(gc *gin.Context) {
331352
query = strings.Replace(query, "{{conditions}}", conditionsStr, 1)
332353
query = strings.Replace(query, "{{limit}}", limitClause, 1)
333354

334-
/*
355+
if true {
335356
fmt.Println(query)
336357
fmt.Printf("ARGS (%d):\n", len(args))
337358
for i, arg := range args {
338359
fmt.Printf(" $%d = %#v (type %T)\n", i+1, arg, arg)
339360
}
340-
*/
361+
}
341362

342363
rows, err := h.DbPool.Query(ctx, query, args...)
343364
if err != nil {
@@ -368,6 +389,7 @@ func (h *ApiHandler) GetEvents(gc *gin.Context) {
368389
&e.TicketLink,
369390
&e.Title,
370391
&e.Subtitle,
392+
&e.Categories,
371393
&typesJSON,
372394
&e.Languages,
373395
&e.Tags,
@@ -420,7 +442,11 @@ func (h *ApiHandler) GetEvents(gc *gin.Context) {
420442
}
421443

422444
if len(events) == 0 {
423-
gc.JSON(http.StatusNotFound, gin.H{"events": events})
445+
gc.JSON(http.StatusOK, gin.H{
446+
"events": []eventResponse{},
447+
"last_event_start_at": nil,
448+
"last_event_date_id": nil,
449+
})
424450
return
425451
}
426452

api/refresh_event_projections.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func initProjectionSql() {
194194
eventProjectionUpsertSql = fmt.Sprintf(`
195195
INSERT INTO %[1]s.event_projection (
196196
event_id, organization_id, venue_id, space_id, release_status,
197-
title, subtitle, description, summary, image_id, languages, tags, types,
197+
title, subtitle, description, summary, image_id, languages, tags, categories, types,
198198
source_url, online_link, occasion_type_id, max_attendees, min_age, max_age,
199199
participation_info, meeting_point, ticket_flags,
200200
price_type, currency, min_price, max_price, visitor_info_flags,
@@ -220,6 +220,7 @@ SELECT DISTINCT ON (e.id)
220220
main_image.pluto_image_id AS image_id, -- << refactored here
221221
e.languages,
222222
e.tags,
223+
e.categories,
223224
COALESCE(
224225
(SELECT jsonb_agg(jsonb_build_array(type_id, genre_id))
225226
FROM %[1]s.event_type_link etl WHERE etl.event_id = e.id),
@@ -297,6 +298,7 @@ ON CONFLICT (event_id) DO UPDATE SET
297298
image_id = EXCLUDED.image_id,
298299
languages = EXCLUDED.languages,
299300
tags = EXCLUDED.tags,
301+
categories = EXCLUDED.categories,
300302
types = EXCLUDED.types,
301303
source_url = EXCLUDED.source_url,
302304
online_link = EXCLUDED.online_link,

app/uranus.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type Uranus struct {
5252
SqlAdminGetEventDates string
5353
SqlAdminInsertEventDate string
5454
SqlAdminUpdateEventDate string
55+
SqlAdminDeleteEvent string
5556
SqlTypeGenreLookup string
5657
SqlChoosableOrganizationVenues string
5758
SqlChoosableVenueSpaces string
@@ -289,6 +290,7 @@ func (app *Uranus) PrepareSql() error {
289290
{"sql/admin-get-event-images.sql", &app.SqlAdminGetEventImages, nil},
290291
{"sql/admin-get-event-links.sql", &app.SqlAdminGetEventLinks, nil},
291292
{"sql/admin-get-event-dates.sql", &app.SqlAdminGetEventDates, nil},
293+
{"sql/admin-delete-event.sql", &app.SqlAdminDeleteEvent, nil},
292294

293295
{"sql/admin-update-event-date.sql", &app.SqlAdminUpdateEventDate, nil},
294296
{"sql/admin-insert-event-date.sql", &app.SqlAdminInsertEventDate, nil},

0 commit comments

Comments
 (0)