diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 1ec4da8..85eb207 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -16,6 +16,7 @@
"@fullcalendar/vue3": "^6.1.11",
"@tanstack/vue-query": "^5.28.9",
"@tanstack/vue-query-devtools": "^5.28.10",
+ "@types/ical": "^0.8.3",
"@vueuse/core": "^10.9.0",
"country-flag-emoji-polyfill": "^0.1.8",
"ical.js": "^1.5.0",
@@ -3081,6 +3082,14 @@
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
+ "node_modules/@types/ical": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@types/ical/-/ical-0.8.3.tgz",
+ "integrity": "sha512-qPejGORaXOstmqyKzp0Qw9nXDPiWiahiJJcx4zMB0zJVg0rLfJ6bDip/naqagEqYTjKl/LI91399hR8zFwRJ5A==",
+ "dependencies": {
+ "rrule": "2.6.4"
+ }
+ },
"node_modules/@types/json-schema": {
"version": "7.0.12",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
@@ -6361,6 +6370,15 @@
"node": ">=10"
}
},
+ "node_modules/luxon": {
+ "version": "1.28.1",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz",
+ "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==",
+ "optional": true,
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
@@ -7200,6 +7218,17 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/rrule": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.4.tgz",
+ "integrity": "sha512-sLdnh4lmjUqq8liFiOUXD5kWp/FcnbDLPwq5YAc/RrN6120XOPb86Ae5zxF7ttBVq8O3LxjjORMEit1baluahA==",
+ "dependencies": {
+ "tslib": "^1.10.0"
+ },
+ "optionalDependencies": {
+ "luxon": "^1.21.3"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -7881,6 +7910,11 @@
"typescript": ">=4.2.0"
}
},
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 27f6925..5dacd9c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -21,6 +21,7 @@
"@fullcalendar/vue3": "^6.1.11",
"@tanstack/vue-query": "^5.28.9",
"@tanstack/vue-query-devtools": "^5.28.10",
+ "@types/ical": "^0.8.3",
"@vueuse/core": "^10.9.0",
"country-flag-emoji-polyfill": "^0.1.8",
"ical.js": "^1.5.0",
diff --git a/frontend/src/api/loadICal.ts b/frontend/src/api/loadICal.ts
new file mode 100644
index 0000000..e835dd9
--- /dev/null
+++ b/frontend/src/api/loadICal.ts
@@ -0,0 +1,23 @@
+//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 .
+
+export async function fetchICalendarEvents() {
+ const response = await fetch("https://cal.htwk-leipzig.de/api/feed?token=rk47mvraeb43t3g");
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+ return response.text();
+}
\ No newline at end of file
diff --git a/frontend/src/components/CalendarViewer.vue b/frontend/src/components/CalendarViewer.vue
index c54b41d..8d36be1 100644
--- a/frontend/src/components/CalendarViewer.vue
+++ b/frontend/src/components/CalendarViewer.vue
@@ -11,12 +11,30 @@ import iCalenderPlugin from "@fullcalendar/icalendar";
import router from "@/router";
import { formatYearMonthDay } from "@/helpers/dates.ts";
import { useI18n } from "vue-i18n";
+import { useQuery } from "@tanstack/vue-query";
+import tokenStore from "@/store/tokenStore.ts";
+import { parseICalData } from "@/helpers/ical.ts";
+import { fetchICalendarEvents } from "@/api/loadICal.ts";
const { t } = useI18n({ useScope: "global" });
const mobilePage = inject("mobilePage") as Ref;
const date: Ref = ref(new Date());
-const feedUrl: Ref = ref("https://cal.htwk-leipzig.de/api/feed?token=rk47mvraeb43t3g");
+
+tokenStore().setToken("3rz8vb3974tr2b")
+
+
+const { data: calendar } = useQuery({
+ queryKey: ["userCalendar", tokenStore().token],
+ queryFn: () =>
+ fetchICalendarEvents(),
+ select: (data) => {
+ return data;
+ },
+ networkMode: "offlineFirst",
+ enabled: () => tokenStore().token !== "",
+ staleTime: 5000000, // 500 seconds
+});
const fullCalendar = ref>();
@@ -88,13 +106,7 @@ const calendarOptions: ComputedRef = computed(() => ({
},
});
},
- events: {
- url: feedUrl.value,
- format: "ics",
- failure: function () {
- alert("There was an error while fetching the calendar events!");
- },
- },
+ events: parseICalData(calendar.value),
}));
watch(mobilePage, () => {
diff --git a/frontend/src/components/MenuBar.vue b/frontend/src/components/MenuBar.vue
index 0de1280..995d208 100644
--- a/frontend/src/components/MenuBar.vue
+++ b/frontend/src/components/MenuBar.vue
@@ -27,14 +27,26 @@ const isDark = ref(true);
const items = computed(() => [
{
- label: t("createCalendar"),
- icon: "pi pi-fw pi-plus",
- route: "/",
- },
- {
- label: t("editCalendar"),
- icon: "pi pi-fw pi-pencil",
- route: "/edit",
+ label: t("calendar"),
+ icon: "pi pi-fw pi-angle-down",
+ info: "calendar",
+ items: [
+ {
+ label: t("createCalendar"),
+ icon: "pi pi-fw pi-plus",
+ route: "/calendar/create",
+ },
+ {
+ label: t("editCalendar"),
+ icon: "pi pi-fw pi-pencil",
+ route: "/calendar/edit",
+ },
+ {
+ label: t("userCalendar"),
+ icon: "pi pi-fw pi-calendar",
+ route: "/calendar/view",
+ },
+ ],
},
{
label: t("rooms"),
@@ -53,11 +65,6 @@ const items = computed(() => [
},
],
},
- {
- label: t("userCalendar"),
- icon: "pi pi-fw pi-calendar",
- route: "/user/calendar",
- },
{
label: t("faq"),
icon: "pi pi-fw pi-book",
diff --git a/frontend/src/helpers/ical.ts b/frontend/src/helpers/ical.ts
index e69de29..7af483a 100644
--- a/frontend/src/helpers/ical.ts
+++ b/frontend/src/helpers/ical.ts
@@ -0,0 +1,24 @@
+import ICAL from 'ical.js';
+import { CalendarComponent } from 'ical';
+
+export function parseICalData(icalData: string | undefined) {
+ if (icalData === undefined || !icalData) {
+ return [];
+ }
+
+ const jCalData = ICAL.parse(icalData);
+ const comp = new ICAL.Component(jCalData);
+ const vEvents = comp.getAllSubcomponents('vevent');
+
+ return vEvents.map((vevent: CalendarComponent) => {
+ const event = new ICAL.Event(vevent);
+
+ return {
+ title: event.summary,
+ start: event.startDate.toJSDate(),
+ end: event.endDate.toJSDate(),
+ allDay: event.startDate.isDate,
+ // Include other properties as needed
+ };
+ });
+}
\ No newline at end of file
diff --git a/frontend/src/i18n/translations/de.json b/frontend/src/i18n/translations/de.json
index 567f440..f6862ad 100644
--- a/frontend/src/i18n/translations/de.json
+++ b/frontend/src/i18n/translations/de.json
@@ -3,6 +3,7 @@
"createCalendar": "Kalender erstellen",
"editCalendar": "Kalender bearbeiten",
"userCalendar": "Dein Kalender",
+ "calendar": "Kalender",
"rooms": "Räume",
"faq": "FAQ",
"imprint": "Impressum",
diff --git a/frontend/src/i18n/translations/en.json b/frontend/src/i18n/translations/en.json
index b1edb9f..e843cef 100644
--- a/frontend/src/i18n/translations/en.json
+++ b/frontend/src/i18n/translations/en.json
@@ -3,6 +3,7 @@
"createCalendar": "create calendar",
"editCalendar": "edit calendar",
"userCalendar": "user calendar",
+ "calendar": "calendar",
"rooms": "rooms",
"faq": "faq",
"imprint": "imprint",
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index a50391a..8e107bd 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -36,7 +36,12 @@ const router = createRouter({
routes: [
{
path: "/",
- name: "course-selection",
+ name: "home",
+ component: CourseSelection,
+ },
+ {
+ path: "/calendar/create",
+ name: "calendar-create",
component: CourseSelection,
},
{
@@ -50,8 +55,8 @@ const router = createRouter({
component: FreeRooms,
},
{
- path: "/user/calendar",
- name: "user-calendar",
+ path: "/calendar/view",
+ name: "calendar-view",
component: CalenderViewer,
},
{
@@ -80,7 +85,7 @@ const router = createRouter({
component: CalendarLink,
},
{
- path: "/edit",
+ path: "/calendar/edit",
name: "edit",
component: EditCalendarView,
},
diff --git a/frontend/src/view/UserCalendar.vue b/frontend/src/view/UserCalendar.vue
index ce1cffa..e7f5e7a 100644
--- a/frontend/src/view/UserCalendar.vue
+++ b/frontend/src/view/UserCalendar.vue
@@ -1,10 +1,25 @@
-
+
+
+
+
+