Skip to content

Commit df4b2cb

Browse files
authored
Merge pull request #292 from simar-rekhi/develop
Addresses #249 with some testing already done
2 parents 864a5f1 + 6558097 commit df4b2cb

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

api/controllers/events.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/gin-gonic/gin"
1414

1515
"go.mongodb.org/mongo-driver/bson"
16+
"go.mongodb.org/mongo-driver/bson/primitive"
1617
"go.mongodb.org/mongo-driver/mongo"
1718
)
1819

@@ -97,3 +98,135 @@ func EventsByBuilding(c *gin.Context) {
9798

9899
respond(c, http.StatusOK, "success", eventsByBuilding)
99100
}
101+
102+
// @Id eventsByRoom
103+
// @Router /events/{date}/{building}/{room} [get]
104+
// @Description "Returns all sections with meetings on the specified date in the specified building and room"
105+
// @Produce json
106+
// @Param date path string true "ISO date of the set of events to get"
107+
// @Param building path string true "building abbreviation of the event location"
108+
// @Param room path string true "room number"
109+
// @Success 200 {object} schema.APIResponse[[]schema.SectionWithTime] "All sections with meetings on the specified date in the specified building and room"
110+
// @Failure 500 {object} schema.APIResponse[string] "A string describing the error"
111+
// @Failure 404 {object} schema.APIResponse[string] "A string describing the error"
112+
func EventsByRoom(c *gin.Context) {
113+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
114+
defer cancel()
115+
116+
date := c.Param("date")
117+
building := c.Param("building")
118+
room := c.Param("room")
119+
120+
var events schema.MultiBuildingEvents[schema.SectionWithTime]
121+
var foundSections []schema.SectionWithTime
122+
123+
// find and parse matching date
124+
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
125+
if err != nil {
126+
respondWithInternalError(c, err)
127+
return
128+
}
129+
130+
// filter for the specified building and room
131+
for _, b := range events.Buildings {
132+
if b.Building == building {
133+
for _, r := range b.Rooms {
134+
if r.Room == room {
135+
foundSections = r.Events
136+
break
137+
}
138+
}
139+
break
140+
}
141+
}
142+
143+
if len(foundSections) == 0 {
144+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
145+
Status: http.StatusNotFound,
146+
Message: "error",
147+
Data: "No events found for the specified building and room",
148+
})
149+
return
150+
}
151+
152+
respond(c, http.StatusOK, "success", foundSections)
153+
}
154+
155+
// @Id sectionsByRoomDetailed
156+
// @Router /events/{date}/{building}/{room}/sections [get]
157+
// @Description "Returns full section objects with meetings on the specified date in the specified building and room"
158+
// @Produce json
159+
// @Param date path string true "ISO date of the set of events to get"
160+
// @Param building path string true "building abbreviation of the event location"
161+
// @Param room path string true "room number"
162+
// @Success 200 {object} schema.APIResponse[[]schema.Section] "Full section objects with meetings on the specified date in the specified building and room"
163+
// @Failure 500 {object} schema.APIResponse[string] "A string describing the error"
164+
// @Failure 404 {object} schema.APIResponse[string] "A string describing the error"
165+
func SectionsByRoomDetailed(c *gin.Context) {
166+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
167+
defer cancel()
168+
169+
date := c.Param("date")
170+
building := c.Param("building")
171+
room := c.Param("room")
172+
173+
var events schema.MultiBuildingEvents[schema.SectionWithTime]
174+
175+
// Step 1: Find events for the specified date
176+
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
177+
if err != nil {
178+
respondWithInternalError(c, err)
179+
return
180+
}
181+
182+
// Step 2: Extract section IDs for the specified building and room
183+
var sectionIDs []primitive.ObjectID
184+
for _, b := range events.Buildings {
185+
if b.Building == building {
186+
for _, r := range b.Rooms {
187+
if r.Room == room {
188+
for _, event := range r.Events {
189+
sectionIDs = append(sectionIDs, event.Section)
190+
}
191+
break
192+
}
193+
}
194+
break
195+
}
196+
}
197+
198+
if len(sectionIDs) == 0 {
199+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
200+
Status: http.StatusNotFound,
201+
Message: "error",
202+
Data: "No sections found for the specified building and room",
203+
})
204+
return
205+
}
206+
207+
// Step 3: Fetch full section objects from the sections collection
208+
sectionsCollection := configs.GetCollection("sections")
209+
cursor, err := sectionsCollection.Find(ctx, bson.M{"_id": bson.M{"$in": sectionIDs}})
210+
if err != nil {
211+
respondWithInternalError(c, err)
212+
return
213+
}
214+
defer cursor.Close(ctx)
215+
216+
var sections []schema.Section
217+
if err = cursor.All(ctx, &sections); err != nil {
218+
respondWithInternalError(c, err)
219+
return
220+
}
221+
222+
if len(sections) == 0 {
223+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
224+
Status: http.StatusNotFound,
225+
Message: "error",
226+
Data: "No section details found",
227+
})
228+
return
229+
}
230+
231+
respond(c, http.StatusOK, "success", sections)
232+
}

api/routes/events.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ func EventsRoute(router *gin.Engine) {
1313
eventsGroup.OPTIONS("", controllers.Preflight)
1414
eventsGroup.GET(":date", controllers.Events)
1515
eventsGroup.GET(":date/:building", controllers.EventsByBuilding)
16+
eventsGroup.GET(":date/:building/:room", controllers.EventsByRoom)
17+
eventsGroup.GET(":date/:building/:room/sections", controllers.SectionsByRoomDetailed)
1618
}

api/server.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/gin-gonic/gin"
1212
swaggerFiles "github.com/swaggo/files"
1313
ginSwagger "github.com/swaggo/gin-swagger"
14+
15+
"github.com/UTDNebula/nebula-api/api/controllers"
1416
)
1517

1618
// Unauthenticated placeholder endpoint for the built-in ginSwagger swagger documentation endpoint
@@ -109,3 +111,13 @@ func LogRequest(c *gin.Context) {
109111
log.Printf("%s %s %s", c.Request.Method, c.Request.URL.Path, c.Request.Host)
110112
c.Next()
111113
}
114+
115+
func EventsRoute(router *gin.Engine) {
116+
eventsGroup := router.Group("/events")
117+
{
118+
eventsGroup.GET("/:date", controllers.Events)
119+
eventsGroup.GET("/:date/:building", controllers.EventsByBuilding)
120+
eventsGroup.GET("/:date/:building/:room/sections", controllers.EventsByRoom)
121+
eventsGroup.GET("/:date/:building/:room/sections", controllers.SectionsByRoomDetailed)
122+
}
123+
}

0 commit comments

Comments
 (0)