diff --git a/backend/Dockerfile b/backend/Dockerfile
index 67a9d42..655af93 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.21.3-alpine
+FROM golang:1.21-alpine
# Set the Current Working Directory inside the container
WORKDIR /app
diff --git a/backend/go.mod b/backend/go.mod
index 660cc3d..3a2ca8b 100644
--- a/backend/go.mod
+++ b/backend/go.mod
@@ -1,6 +1,6 @@
module htwkalender
-go 1.21.3
+go 1.21
require (
github.com/google/uuid v1.3.1
diff --git a/backend/service/fetch/v1/fetchSeminarEventService.go b/backend/service/fetch/v1/fetchSeminarEventService.go
index bc1af4c..6238c44 100644
--- a/backend/service/fetch/v1/fetchSeminarEventService.go
+++ b/backend/service/fetch/v1/fetchSeminarEventService.go
@@ -64,18 +64,22 @@ func GetSeminarGroupsEventsFromHTML(seminarGroupsLabel []string) []model.Seminar
var seminarGroups []model.SeminarGroup
for _, seminarGroupLabel := range seminarGroupsLabel {
- ssUrl := "https://stundenplan.htwk-leipzig.de/" + string("ss") + "/Berichte/Text-Listen;Studenten-Sets;name;" + seminarGroupLabel + "?template=sws_semgrp&weeks=1-65"
- result, getError := fetch.GetHTML(ssUrl)
- if getError == nil {
- seminarGroup := parseSeminarGroup(result)
- seminarGroups = append(seminarGroups, seminarGroup)
+ if (time.Now().Month() >= 3) && (time.Now().Month() <= 10) {
+ ssUrl := "https://stundenplan.htwk-leipzig.de/" + string("ss") + "/Berichte/Text-Listen;Studenten-Sets;name;" + seminarGroupLabel + "?template=sws_semgrp&weeks=1-65"
+ result, getError := fetch.GetHTML(ssUrl)
+ if getError == nil {
+ seminarGroup := parseSeminarGroup(result)
+ seminarGroups = append(seminarGroups, seminarGroup)
+ }
}
- wsUrl := "https://stundenplan.htwk-leipzig.de/" + string("ws") + "/Berichte/Text-Listen;Studenten-Sets;name;" + seminarGroupLabel + "?template=sws_semgrp&weeks=1-65"
- result, getError = fetch.GetHTML(wsUrl)
- if getError == nil {
- seminarGroup := parseSeminarGroup(result)
- seminarGroups = append(seminarGroups, seminarGroup)
+ if (time.Now().Month() >= 9) || (time.Now().Month() <= 4) {
+ wsUrl := "https://stundenplan.htwk-leipzig.de/" + string("ws") + "/Berichte/Text-Listen;Studenten-Sets;name;" + seminarGroupLabel + "?template=sws_semgrp&weeks=1-65"
+ result, getError := fetch.GetHTML(wsUrl)
+ if getError == nil {
+ seminarGroup := parseSeminarGroup(result)
+ seminarGroups = append(seminarGroups, seminarGroup)
+ }
}
}
return seminarGroups
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 153089b..6d84655 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,11 +1,24 @@
+
+
diff --git a/frontend/src/components/CalendarPreview.vue b/frontend/src/components/CalendarPreview.vue
new file mode 100644
index 0000000..c9da149
--- /dev/null
+++ b/frontend/src/components/CalendarPreview.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/ModuleSelection.vue b/frontend/src/components/ModuleSelection.vue
index 9500ca8..7c6f1f8 100644
--- a/frontend/src/components/ModuleSelection.vue
+++ b/frontend/src/components/ModuleSelection.vue
@@ -1,9 +1,10 @@
@@ -61,31 +45,29 @@ function nextStep() {
-
+
{{ $t("moduleSelection.modules") }} -
- {{ selectedModules.length }}
+ {{ store.countModules() }}
-
@@ -106,18 +88,19 @@ function nextStep() {
-
{{ slotProps.data.module.name }}
+
{{ slotProps.data.name }}
diff --git a/frontend/src/components/ModuleTemplateDialog.vue b/frontend/src/components/ModuleTemplateDialog.vue
index 73ab90d..631dafe 100644
--- a/frontend/src/components/ModuleTemplateDialog.vue
+++ b/frontend/src/components/ModuleTemplateDialog.vue
@@ -68,10 +68,4 @@ const placeholders = computed(() => [
-
+
diff --git a/frontend/src/components/RenameModules.vue b/frontend/src/components/RenameModules.vue
index 0e90c17..21220fd 100644
--- a/frontend/src/components/RenameModules.vue
+++ b/frontend/src/components/RenameModules.vue
@@ -9,8 +9,9 @@ import { onlyWhitespace } from "../helpers/strings.ts";
import { useI18n } from "vue-i18n";
const { t } = useI18n({ useScope: "global" });
+const store = moduleStore();
const tableData = ref(
- moduleStore().modules.map((module) => {
+ store.getAllModules().map((module) => {
return {
Course: module.course,
Module: module,
@@ -25,7 +26,7 @@ const columns = computed(() => [
]);
async function finalStep() {
- const token: string = await createIndividualFeed(moduleStore().modules);
+ const token: string = await createIndividualFeed(store.getAllModules());
tokenStore().setToken(token);
await router.push("/calendar-link");
}
@@ -124,10 +125,4 @@ async function finalStep() {
-
+
diff --git a/frontend/src/components/editCalendar/EditModules.vue b/frontend/src/components/editCalendar/EditModules.vue
index bb5c3f6..8f13bbf 100644
--- a/frontend/src/components/editCalendar/EditModules.vue
+++ b/frontend/src/components/editCalendar/EditModules.vue
@@ -11,8 +11,9 @@ import { onlyWhitespace } from "../../helpers/strings.ts";
import { useI18n } from "vue-i18n";
const { t } = useI18n({ useScope: "global" });
+const store = moduleStore();
const tableData = computed(() =>
- moduleStore().modules.map((module: Module) => {
+ store.getAllModules().map((module: Module) => {
return {
Course: module.course,
Module: module,
@@ -45,7 +46,7 @@ fetchedModules().then(
);
async function finalStep() {
- await saveIndividualFeed(tokenStore().token, moduleStore().modules);
+ await saveIndividualFeed(tokenStore().token, store.getAllModules());
await router.push("/calendar-link");
}
@@ -159,10 +160,4 @@ async function finalStep() {
-
+
diff --git a/frontend/src/i18n/translations/de.json b/frontend/src/i18n/translations/de.json
index d059bce..bd84f6e 100644
--- a/frontend/src/i18n/translations/de.json
+++ b/frontend/src/i18n/translations/de.json
@@ -38,7 +38,7 @@
"semester": "Semester",
"module": "Modul",
"day": "Tag",
- "start": "Begin",
+ "start": "Anfang",
"end": "Ende",
"room": "Raum",
"type": "Art",
@@ -57,8 +57,17 @@
"dropDown": "Wähle weitere Module aus",
"module": "Modul",
"modules": "Module",
- "dropDownFooterSelected": "ausgewählt",
- "nextStep": "Weiter"
+ "footerModulesSelected": "{count} Modul ausgewählt | {count} Module ausgewählt",
+ "nextStep": "Weiter",
+ "professor": "Dozent",
+ "course": "Seminargruppe",
+ "info": "Info",
+ "info-long": "Information",
+ "paginator": {
+ "from": "",
+ "to": " bis ",
+ "of": " von insgesamt "
+ }
},
"renameModules": {
"reminder": "Erinnerung",
@@ -90,6 +99,12 @@
"toGoogleCalendar": "Google Kalender",
"toMicrosoftCalendar": "Microsoft Kalender"
},
+ "calendarPreview": {
+ "preview": "Vorschau",
+ "preview-long": "Kalendervorschau",
+ "module": "Modul",
+ "course": "Seminargruppe"
+ },
"faqView": {
"headline": "Fragen und Antworten",
"firstQuestion": "Wie funktioniert das Kalender erstellen mit dem HTWKalender?",
diff --git a/frontend/src/i18n/translations/en.json b/frontend/src/i18n/translations/en.json
index cf7d08a..2e76316 100644
--- a/frontend/src/i18n/translations/en.json
+++ b/frontend/src/i18n/translations/en.json
@@ -53,12 +53,21 @@
"noCalendarFound": "no calendar found"
},
"additionalModules": {
- "subTitle": "Select additional Modules that are not listed in the regular semester for your Course",
+ "subTitle": "Select additional modules that are not listed in the regular semester for your course",
"dropDown": "Select additional modules",
"module": "module",
"modules": "modules",
- "dropDownFooterSelected": "selected",
- "nextStep": "next step"
+ "footerModulesSelected": "{count} module selected | {count} modules selected",
+ "nextStep": "next step",
+ "professor": "professor",
+ "course": "course",
+ "info": "info",
+ "info-long": "information",
+ "paginator": {
+ "from": "",
+ "to": " to ",
+ "of": " of "
+ }
},
"renameModules": {
"reminder": "reminder",
@@ -90,6 +99,12 @@
"toGoogleCalendar": "to Google Calendar",
"toMicrosoftCalendar": "to Microsoft Calendar"
},
+ "calendarPreview": {
+ "preview": "preview",
+ "preview-long": "calendar preview",
+ "module": "module",
+ "course": "course"
+ },
"faqView": {
"headline": "faq",
"firstQuestion": "How does calendar creation work with HTWKalender?",
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index 3c4bc9b..c2b5e96 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -16,6 +16,7 @@ import "primevue/resources/themes/viva-dark/theme.css";
import "primeicons/primeicons.css";
import "primeflex/primeflex.css";
import router from "./router";
+import SpeedDial from "primevue/speeddial";
import TabView from "primevue/tabview";
import TabPanel from "primevue/tabpanel";
import Tag from "primevue/tag";
@@ -30,6 +31,7 @@ import Column from "primevue/column";
import DynamicDialog from "primevue/dynamicdialog";
import DialogService from "primevue/dialogservice";
import ProgressSpinner from "primevue/progressspinner";
+import Checkbox from "primevue/checkbox";
import i18n from "./i18n";
const app = createApp(App);
@@ -52,6 +54,7 @@ app.component("InputSwitch", InputSwitch);
app.component("Card", Card);
app.component("DataView", DataView);
app.component("ToggleButton", ToggleButton);
+app.component("SpeedDial", SpeedDial);
app.component("TabView", TabView);
app.component("TabPanel", TabPanel);
app.component("MultiSelect", MultiSelect);
@@ -63,4 +66,5 @@ app.component("DataTable", DataTable);
app.component("Column", Column);
app.component("DynamicDialog", DynamicDialog);
app.component("ProgressSpinner", ProgressSpinner);
+app.component("Checkbox", Checkbox);
app.mount("#app");
diff --git a/frontend/src/model/module.ts b/frontend/src/model/module.ts
index 01f277d..e08c18b 100644
--- a/frontend/src/model/module.ts
+++ b/frontend/src/model/module.ts
@@ -12,7 +12,7 @@ export class Module {
public events: Event[] = [],
) {}
- isEqual(module: Module): Boolean {
+ isEqual(module: Module): boolean {
return this.name === module.name && this.course === module.course;
}
}
diff --git a/frontend/src/store/moduleStore.ts b/frontend/src/store/moduleStore.ts
index 27f6a2b..281135c 100644
--- a/frontend/src/store/moduleStore.ts
+++ b/frontend/src/store/moduleStore.ts
@@ -3,18 +3,42 @@ import { defineStore } from "pinia";
const moduleStore = defineStore("moduleStore", {
state: () => ({
- modules: [] as Module[],
+ modules: new Map(),
}),
actions: {
addModule(module: Module) {
- this.modules.push(module);
+ this.modules.set(module.uuid, module);
},
removeModule(module: Module) {
- this.modules.splice(this.modules.indexOf(module), 1);
+ this.modules.delete(module.uuid);
+ },
+ hasModule(module: Module): boolean {
+ return (
+ this.modules.has(module.uuid) &&
+ (this.modules.get(module.uuid)?.isEqual(module) ?? false)
+ );
},
removeAllModules() {
- this.modules = [];
+ this.modules.clear();
},
+ overwriteModules(modules: Module[]) {
+ this.modules.clear();
+ modules.forEach((module) => {
+ this.modules.set(module.uuid, module);
+ });
+ },
+ isEmpty(): boolean {
+ return this.modules.size === 0;
+ },
+ countModules(): number {
+ return this.modules.size;
+ },
+ getAllModules(): Module[] {
+ return Array.from(this.modules.values());
+ },
+ containsModule(module: Module): boolean {
+ return this.modules.has(module.uuid);
+ }
},
});
diff --git a/frontend/src/style.css b/frontend/src/style.css
index 4d2c94a..99b676e 100644
--- a/frontend/src/style.css
+++ b/frontend/src/style.css
@@ -1,3 +1,10 @@
body {
font-family: var(--font-family);
}
+
+.small-button.p-button.p-button-icon-only,
+.small-button.p-button.p-button-icon-only.p-button-rounded {
+ width: 2rem;
+ height: 2rem;
+ padding: 0;
+}
diff --git a/frontend/src/view/AdditionalModules.vue b/frontend/src/view/AdditionalModules.vue
index bbb647e..f4f4ed1 100644
--- a/frontend/src/view/AdditionalModules.vue
+++ b/frontend/src/view/AdditionalModules.vue
@@ -1,12 +1,13 @@
@@ -100,56 +92,103 @@ function itemsLabelWithNumber(selectedModules: Module[]): string {
-
+
-
-
-
-
- {{ display(slotProps.option) }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {{ selectedModules ? selectedModules.length : 0 }}
- item{{
- (selectedModules ? selectedModules.length : 0) > 1 ? "s" : ""
- }}
- selected.
+ {{
+ t('additionalModules.footerModulesSelected', { count: store?.countModules() ?? 0 })
+ }}
-
+
-
@@ -170,4 +209,8 @@ function itemsLabelWithNumber(selectedModules: Module[]): string {
height: 2rem;
padding: 0;
}
+
+:deep(.p-filter-column .p-checkbox .p-component) {
+ display: none !important;
+}
diff --git a/frontend/src/view/EditCalendarView.vue b/frontend/src/view/EditCalendarView.vue
index ae80c71..2952cb7 100644
--- a/frontend/src/view/EditCalendarView.vue
+++ b/frontend/src/view/EditCalendarView.vue
@@ -12,7 +12,7 @@ const { t } = useI18n({ useScope: "global" });
const toast = useToast();
const token: Ref = ref("");
-const modules: Ref = ref(moduleStore().modules);
+const modules: Ref