diff --git a/backend/model/eventModel.go b/backend/model/eventModel.go
index 8a492cf..2debe6d 100644
--- a/backend/model/eventModel.go
+++ b/backend/model/eventModel.go
@@ -57,6 +57,10 @@ type Event struct {
models.BaseModel
}
+type EventType struct {
+ EventType string `db:"EventType" json:"eventType"`
+}
+
func (e *Event) Equals(event Event) bool {
return e.Day == event.Day &&
e.Week == event.Week &&
diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go
index eeb6884..0f131bf 100644
--- a/backend/service/addRoute.go
+++ b/backend/service/addRoute.go
@@ -363,7 +363,31 @@ func AddRoutes(app *pocketbase.PocketBase) {
slog.Error("Failed to get courses for semester with events: ", "error", err)
return c.JSON(http.StatusBadRequest, "Failed to get courses for semester with events")
} else {
- return c.JSON(200, courses)
+ return c.JSON(http.StatusOK, courses)
+ }
+ },
+ Middlewares: []echo.MiddlewareFunc{
+ apis.ActivityLogger(app),
+ },
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+ })
+
+ // API Endpoint to get all eventTypes from the database distinct
+ app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
+ _, err := e.Router.AddRoute(echo.Route{
+ Method: http.MethodGet,
+ Path: "/api/events/types",
+ Handler: func(c echo.Context) error {
+ eventTypes, err := events.GetEventTypes(app)
+ if err != nil {
+ slog.Error("Failed to get event types", "error", err)
+ return c.JSON(http.StatusBadRequest, "Failed to get event types")
+ } else {
+ return c.JSON(http.StatusOK, eventTypes)
}
},
Middlewares: []echo.MiddlewareFunc{
@@ -390,7 +414,7 @@ func AddRoutes(app *pocketbase.PocketBase) {
slog.Error("Failed to delete events: ", "error", err)
return c.JSON(http.StatusBadRequest, "Failed to delete events")
} else {
- return c.JSON(http.StatusBadRequest, "Events deleted")
+ return c.JSON(http.StatusOK, "Events deleted")
}
},
Middlewares: []echo.MiddlewareFunc{
diff --git a/backend/service/db/dbEvents.go b/backend/service/db/dbEvents.go
index 0d1fe04..8db7b64 100644
--- a/backend/service/db/dbEvents.go
+++ b/backend/service/db/dbEvents.go
@@ -367,6 +367,17 @@ func GetEventsThatStartBeforeAndEndBefore(app *pocketbase.PocketBase, from types
return events, nil
}
+func GetAllEventTypes(app *pocketbase.PocketBase) ([]model.EventType, error) {
+ var eventTypes []model.EventType
+
+ err := app.Dao().DB().Select("EventType").From("events").GroupBy("EventType").Distinct(true).All(&eventTypes)
+ if err != nil {
+ return nil, err
+ }
+
+ return eventTypes, nil
+}
+
func GetEventsThatStartAfterAndEndAfter(app *pocketbase.PocketBase, from types.DateTime, to types.DateTime) (model.Events, error) {
var events model.Events
err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Start >= {:startDate} AND End >= {:endDate} AND Start <= {:endDate} AND End >= {:startDate}", dbx.Params{"startDate": from, "endDate": to})).All(&events)
diff --git a/backend/service/events/eventService.go b/backend/service/events/eventService.go
index fedfa51..77b8bb1 100644
--- a/backend/service/events/eventService.go
+++ b/backend/service/events/eventService.go
@@ -198,3 +198,18 @@ func ContainsEvent(events model.Events, event model.Event) bool {
}
return false
}
+
+func GetEventTypes(app *pocketbase.PocketBase) ([]string, error) {
+ dbEventTypes, err := db.GetAllEventTypes(app)
+ if err != nil {
+ return nil, err
+ }
+
+ // Convert the []model.EventType to []string
+ var eventTypes []string
+ for _, eventType := range dbEventTypes {
+ eventTypes = append(eventTypes, eventType.EventType)
+ }
+
+ return eventTypes, nil
+}
diff --git a/frontend/src/api/fetchEvents.ts b/frontend/src/api/fetchEvents.ts
new file mode 100644
index 0000000..7738036
--- /dev/null
+++ b/frontend/src/api/fetchEvents.ts
@@ -0,0 +1,33 @@
+//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
+//Copyright (C) 2024 HTWKalender support@htwkalender.de
+
+//This program is free software: you can redistribute it and/or modify
+//it under the terms of the GNU Affero General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU Affero General Public License for more details.
+
+//You should have received a copy of the GNU Affero General Public License
+//along with this program. If not, see .
+
+// function to fetch course data from the API
+
+export async function fetchEventTypes(): Promise {
+ const eventTypes: string[] = [];
+ await fetch("/api/events/types")
+ .then((response) => {
+ return response.json() as Promise;
+ })
+ .then((responseModules: string[]) => {
+ responseModules.forEach((eventType: string) => {
+ eventTypes.push(
+ eventType,
+ );
+ });
+ });
+ return eventTypes;
+}
\ No newline at end of file
diff --git a/frontend/src/components/AdditionalModuleTable.vue b/frontend/src/components/AdditionalModuleTable.vue
index e62e436..d437567 100644
--- a/frontend/src/components/AdditionalModuleTable.vue
+++ b/frontend/src/components/AdditionalModuleTable.vue
@@ -30,6 +30,7 @@ import { useDialog } from "primevue/usedialog";
import router from "../router";
import { fetchModule } from "../api/fetchModule.ts";
import { useI18n } from "vue-i18n";
+import { fetchEventTypes } from "../api/fetchEvents.ts";
const dialog = useDialog();
const { t } = useI18n({ useScope: "global" });
@@ -39,6 +40,9 @@ if (store.isEmpty()) {
router.replace("/");
}
+const eventTypes: Ref = ref([]);
+
+
const mobilePage = inject("mobilePage") as Ref;
const filters = ref({
course: {
@@ -51,7 +55,7 @@ const filters = ref({
},
eventType: {
value: null,
- matchMode: FilterMatchMode.CONTAINS,
+ matchMode: FilterMatchMode.IN,
},
prof: {
value: null,
@@ -63,7 +67,7 @@ const loadedModules: Ref = ref(new Array(10));
const loadingData = ref(true);
-onMounted(() => {
+onMounted( () => {
fetchAllModules()
.then(
(data) =>
@@ -74,6 +78,10 @@ onMounted(() => {
.finally(() => {
loadingData.value = false;
});
+
+ fetchEventTypes().then((data) => {
+ eventTypes.value = data;
+ });
});
const ModuleInformation = defineAsyncComponent(
@@ -184,16 +192,20 @@ function unselectModule(event: DataTableRowUnselectEvent) {
-
diff --git a/reverseproxy.conf b/reverseproxy.conf
index ff64ab2..0a6d63f 100644
--- a/reverseproxy.conf
+++ b/reverseproxy.conf
@@ -196,6 +196,24 @@ http {
limit_req zone=modules burst=5 nodelay;
}
+ location /api/events/types {
+ proxy_pass http://htwkalender-backend:8090;
+ client_max_body_size 20m;
+ proxy_connect_timeout 600s;
+ proxy_read_timeout 600s;
+ proxy_send_timeout 600s;
+ send_timeout 600s;
+ proxy_cache_bypass 0;
+ proxy_no_cache 0;
+ proxy_cache mcache; # mcache=RAM
+ proxy_cache_valid 200 301 302 10m;
+ proxy_cache_valid 403 404 5m;
+ proxy_cache_lock on;
+ proxy_cache_use_stale timeout updating;
+ add_header X-Proxy-Cache $upstream_cache_status;
+ limit_req zone=modules burst=10 nodelay;
+ }
+
location /api/rooms {
proxy_pass http://htwkalender-backend:8090;
client_max_body_size 20m;