diff --git a/backend/main.go b/backend/main.go index 9d67b7d..caf1ce3 100644 --- a/backend/main.go +++ b/backend/main.go @@ -21,9 +21,7 @@ func main() { // (the isGoRun check is to enable it only during development) Automigrate: isGoRun, }) - service.AddRoutes(app) - service.AddSchedules(app) if err := app.Start(); err != nil { diff --git a/backend/openapi.yml b/backend/openapi.yml index 8488838..ac2dc3d 100644 --- a/backend/openapi.yml +++ b/backend/openapi.yml @@ -187,6 +187,20 @@ paths: responses: '200': description: Successful response + /api/courses/events: + get: + summary: Get Courses that have Events for specific semester + parameters: + - name: semester + in: query + description: semester + required: true + example: "ws" + schema: + type: string + responses: + '200': + description: Successful response /api/collections/feeds/records/{id}: get: summary: Get Modules selected for iCal feed diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index a9fa997..6a2bd28 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -294,8 +294,14 @@ func AddRoutes(app *pocketbase.PocketBase) { Method: http.MethodGet, Path: "/api/courses", Handler: func(c echo.Context) error { - courses := events.GetAllCourses(app) - return c.JSON(200, courses) + semester := c.QueryParam("semester") + if semester == "" { + courses := events.GetAllCourses(app) + return c.JSON(200, courses) + } else { + courses := events.GetAllCoursesForSemester(app, semester) + return c.JSON(200, courses) + } }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), @@ -307,14 +313,21 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) + // api end point to get all courses for a specific semester with courses that have events app.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, - Path: "/api/courses", + Path: "/api/courses/events", Handler: func(c echo.Context) error { semester := c.QueryParam("semester") - courses := events.GetAllCoursesForSemester(app, semester) - return c.JSON(200, courses) + courses, err := events.GetAllCoursesForSemesterWithEvents(app, semester) + + if err != nil { + slog.Error("Failed to get courses for semester with events: %v", err) + return c.JSON(http.StatusBadRequest, "Failed to get courses for semester with events") + } else { + return c.JSON(200, courses) + } }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), diff --git a/backend/service/db/dbGroups.go b/backend/service/db/dbGroups.go index 545b071..81af46b 100644 --- a/backend/service/db/dbGroups.go +++ b/backend/service/db/dbGroups.go @@ -82,13 +82,13 @@ func GetAllCourses(app *pocketbase.PocketBase) []string { return courseArray } -func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) interface{} { +func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []string { var courses []struct { CourseShortcut string `db:"course" json:"course"` } - // get all rooms from event records in the events collection + // get all courses for a specific semester err := app.Dao().DB().Select("course").From("groups").Where(dbx.NewExp("semester = {:semester}", dbx.Params{"semester": semester})).All(&courses) if err != nil { slog.Error("Error while getting groups from database: ", err) @@ -104,3 +104,25 @@ func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) inter return courseArray } + +func GetAllCoursesForSemesterWithEvents(app *pocketbase.PocketBase, semester string) ([]string, error) { + + var courses []struct { + CourseShortcut string `db:"course" json:"course"` + } + + // get all courses from events distinct for a specific semester + err := app.Dao().DB().Select("course").From("events").Where(dbx.NewExp("semester = {:semester}", dbx.Params{"semester": semester})).Distinct(true).All(&courses) + if err != nil { + slog.Error("Error while getting groups from database: ", err) + return nil, err + } + + var courseArray []string + + for _, course := range courses { + courseArray = append(courseArray, course.CourseShortcut) + } + + return courseArray, nil +} diff --git a/backend/service/events/courseService.go b/backend/service/events/courseService.go index 3f9e99c..c20134e 100644 --- a/backend/service/events/courseService.go +++ b/backend/service/events/courseService.go @@ -3,12 +3,35 @@ package events import ( "github.com/pocketbase/pocketbase" "htwkalender/service/db" + "htwkalender/service/functions" ) func GetAllCourses(app *pocketbase.PocketBase) []string { return db.GetAllCourses(app) } -func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) interface{} { +func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []string { return db.GetAllCoursesForSemester(app, semester) } + +func GetAllCoursesForSemesterWithEvents(app *pocketbase.PocketBase, semester string) ([]string, error) { + courses, err := db.GetAllCoursesForSemesterWithEvents(app, semester) + if err != nil { + return nil, err + } else { + // remove empty courses + courses = removeEmptyCourses(courses) + return courses, nil + } +} + +func removeEmptyCourses(courses []string) []string { + var filteredCourses []string + + for index, course := range courses { + if functions.OnlyWhitespace(course) || len(course) == 0 { + filteredCourses = append(courses[:index], courses[index+1:]...) + } + } + return filteredCourses +} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index dc83671..ebc5159 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -12,6 +12,9 @@ const disabledPages = [ "privacy-policy", "edit", "edit-calendar", + "rooms", + "free-rooms", + "room-schedule", ]; const store = moduleStore(); diff --git a/frontend/src/api/createFeed.ts b/frontend/src/api/createFeed.ts index 00a3a04..9c4c4aa 100644 --- a/frontend/src/api/createFeed.ts +++ b/frontend/src/api/createFeed.ts @@ -53,7 +53,6 @@ export async function saveIndividualFeed( return feedResponse; }) .then((response: FeedResponse) => { - console.debug("response", response); token = response.id; }); return token; diff --git a/frontend/src/api/fetchCourse.ts b/frontend/src/api/fetchCourse.ts index e953c7c..933559e 100644 --- a/frontend/src/api/fetchCourse.ts +++ b/frontend/src/api/fetchCourse.ts @@ -24,7 +24,7 @@ export async function fetchCourseBySemester( semester: string, ): Promise { const courses: string[] = []; - await fetch("/api/courses?semester=" + semester) + await fetch("/api/courses/events?semester=" + semester) .then((response) => { //check if response type is json const contentType = response.headers.get("content-type"); @@ -35,7 +35,7 @@ export async function fetchCourseBySemester( } }) .then((coursesResponse) => { - coursesResponse.forEach((course: string) => courses.push(course)); + coursesResponse?.forEach((course: string) => courses.push(course)); }); return courses; } @@ -70,7 +70,7 @@ export async function fetchModulesByCourseAndSemester( } export async function fetchAllModules(): Promise { - let modules: Module[] = []; + const modules: Module[] = []; await fetch("/api/modules") .then((response) => { return response.json() as Promise; diff --git a/frontend/src/api/requestFreeRooms.ts b/frontend/src/api/requestFreeRooms.ts index 76f4037..4baad59 100644 --- a/frontend/src/api/requestFreeRooms.ts +++ b/frontend/src/api/requestFreeRooms.ts @@ -4,7 +4,6 @@ export async function requestFreeRooms( from: string, to: string, ): Promise { - console.debug("requestFreeRooms: from=" + from + ", to=" + to); const rooms: string[] = []; await fetch("/api/rooms/free?from=" + from + "&to=" + to) .then((response) => { diff --git a/frontend/src/components/CalendarLink.vue b/frontend/src/components/CalendarLink.vue index a64a2bf..9678937 100644 --- a/frontend/src/components/CalendarLink.vue +++ b/frontend/src/components/CalendarLink.vue @@ -34,8 +34,7 @@ function rerouteIfTokenIsEmpty() { function copyToClipboard() { // Copy the text inside the text field - navigator.clipboard.writeText(getLink()).then(show, (err) => { - console.error("Could not copy text: ", err); + navigator.clipboard.writeText(getLink()).then(show, () => { toast.add({ severity: "error", summary: t("calendarLink.copyToastError"), diff --git a/frontend/src/components/RoomOccupation.vue b/frontend/src/components/RoomOccupation.vue index 21f61b4..1f13108 100644 --- a/frontend/src/components/RoomOccupation.vue +++ b/frontend/src/components/RoomOccupation.vue @@ -60,7 +60,7 @@ async function getOccupation() { calendar?.refetchEvents(); }) .catch((error) => { - console.log(error); + console.error(error); }); } diff --git a/frontend/src/view/editCalendar/EditModules.vue b/frontend/src/view/editCalendar/EditModules.vue index b55efa6..f883b01 100644 --- a/frontend/src/view/editCalendar/EditModules.vue +++ b/frontend/src/view/editCalendar/EditModules.vue @@ -45,7 +45,6 @@ const fetchedModules = async () => { }; function deleteModule(module: Module) { - console.debug(module); moduleStore().removeModule(module); }