Files
pm/Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md

12 KiB
Raw Blame History

Diplomarbeitsbuch


1. Einleitung

Ausgangssituation

Motivation

Kurzbeschreibung des Projekts

Persönlicher Aufgabenbereich

Abgrenzung der Arbeit

Die Datenbankinfrastruktur war zum Projektstart bereits vorhanden und wurde nicht im Rahmen dieser Arbeit konzipiert. Die Diplomarbeit beschränkt sich auf die Entwicklung der Anwendungsschicht, bestehend aus CMS-Konfiguration, Modul- und Theme-Entwicklung.

Individuelle Themenstellung


3. Projektumfeld & Rahmenbedingungen

Einsatz eines bestehenden CMS (Oqtane)

Teamarbeit

Das Projektteam wurde im Verlauf des Projekts von sechs auf drei Personen reduziert.

Schulisches Umfeld (HTL)

Zeitliche Rahmenbedingungen


4. Technologischer Überblick

4.1 Web-Entwicklung mit ASP.NET & C#

Backend-Logik

API-basierte Kommunikation

Zusammenspiel mit Oqtane

4.2 Oqtane Überblick

Grundidee & Architektur

Modul- & Theme-Konzept

Vorteile für das Projekt

4.3 CMS-Grundkonfiguration

Initiale Einrichtung

Modul-Integration

Rollen & Berechtigungen

Grundlegende Systemeinstellungen


5. System- und Lösungsarchitektur

Gesamtarchitektur des Systems

Einordnung von CMS, Modulen und Theme

Datenfluss

Architekturentscheidungen


6. Entwicklung des Oqtane Themes

Ziel des Themes

Technische Umsetzung

Herausforderungen


7. Umsetzung der Module

7.1 Anmeldetool

Ziel des Moduls

Frontend (Eingabemaske)

Backend-Logik

API-Schnittstelle

Datenauswertung

UX-Überlegungen


7.2 Hall of Fame

Das Hall-of-Fame-Modul ist ein Oqtane-Modul, das ehemalige Absolventinnen und Absolventen der Schule auf der Vereinswebseite präsentiert. Es wurde als eigenständiges, wiederverwendbares Modul innerhalb des Oqtane-Frameworks entwickelt und ermöglicht registrierten Benutzerinnen und Benutzern, sich selbst mit einem persönlichen Profil einzutragen. Die Einträge werden erst nach bewusster Veröffentlichung durch die jeweilige Person auf der öffentlichen Seite angezeigt, können als PDF exportiert werden und unterliegen einem Meldesystem zur Qualitätssicherung.

Datenmodell

Das Modul verwendet zwei Entitäten, die in der Datenbank als Tabellen abgebildet werden. Entität HallOfFame Die zentrale Entität repräsentiert einen einzelnen Absolventeneintrag und wird in der Datenbanktabelle SZUAbsolventenvereinHallOfFame gespeichert.

Spalte Datentyp Beschreibung
HallOfFameId int (PK, Auto-Inkrement) Primärschlüssel
ModuleId int (FK → Module) Fremdschlüssel zur Oqtane-Modulinstanz
Name string Name der Person
Year int Abschlussjahrgang
Description string Beschreibung bzw. Werdegang
Image string Relativer Pfad zum hochgeladenen Foto
Link string Optionaler externer Link
Status string (max. 50) Veröffentlichungsstatus: „Draft" oder „Published"
UserId int ID der Benutzerin bzw. des Benutzers, der den Eintrag erstellt hat
IsReported bool Kennzeichnung, ob der Eintrag gemeldet wurde
ReportReason string (Legacy) Ursprüngliches Feld für Meldegrund, abgelöst durch die Report-Tabelle
CreatedBy string Erstellt von (Audit)
CreatedOn DateTime Erstellzeitpunkt (Audit)
ModifiedBy string Zuletzt geändert von (Audit)
ModifiedOn DateTime Zeitpunkt der letzten Änderung (Audit)
Die Entität implementiert das Oqtane-Interface IAuditable, wodurch die Audit-Felder automatisch vom Framework befüllt werden. Der Fremdschlüssel ModuleId verknüpft jeden Eintrag mit einer bestimmten Modulinstanz und ermöglicht so den Multi-Tenant-Betrieb: Mehrere Hall-of-Fame-Module auf verschiedenen Seiten der Website verwalten jeweils unabhängige Datensätze.
Entität HallOfFameReport
Die zweite Entität bildet einzelne Meldungen zu einem Eintrag ab und wird in der Tabelle SZUAbsolventenvereinHallOfFameReport gespeichert.
Spalte Datentyp Beschreibung
-------- ---------- --------------
HallOfFameReportId int (PK, Auto-Inkrement) Primärschlüssel
HallOfFameId int (FK → SZUAbsolventenvereinHallOfFame) Zugehöriger Eintrag
Reason string Meldegrund
CreatedBy string Erstellt von (Audit)
CreatedOn DateTime Erstellzeitpunkt (Audit)
ModifiedBy string Zuletzt geändert von (Audit)
ModifiedOn DateTime Zeitpunkt der letzten Änderung (Audit)
Der Fremdschlüssel zu SZUAbsolventenvereinHallOfFame ist mit kaskadierendem Löschen konfiguriert, sodass beim Löschen eines Eintrags automatisch alle zugehörigen Meldungen entfernt werden. Zwischen den beiden Entitäten besteht somit eine 1:n-Beziehung: Ein Eintrag kann beliebig viele Meldungen besitzen.

Datenbankmigrationen

Die Datenbankstruktur wird über Entity Framework Core Migrationen versioniert verwaltet. Oqtane verwendet ein eigenes Migrationssystem, das auf der Klasse MultiDatabaseMigration basiert und die Kompatibilität mit verschiedenen Datenbankanbietern sicherstellt.

Migration Versionsnummer Inhalt
InitializeModule 01.00.00.00 Erstellt die Haupttabelle mit allen Grundspalten (Name, Year, Description, Image, Link, Status, UserId) sowie den Audit-Spalten
AddReportingColumns 01.00.00.02 Erweitert die Haupttabelle um die Spalten IsReported und ReportReason
AddReportTable 01.00.00.03 Erstellt die eigenständige Report-Tabelle mit Fremdschlüssel zur Haupttabelle
Jede Migration definiert sowohl eine Aufwärts- als auch eine Abwärtsmethode, sodass ein Rollback möglich ist.

Benutzeroberfläche (Razor-Komponenten)

Das Modul umfasst vier Blazor-Razor-Komponenten. Index.razor Übersichtsseite Die Übersichtsseite zeigt alle veröffentlichten Einträge in einem responsiven Kartenlayout mit drei Spalten auf Desktop-Breite. Die Funktionalität umfasst eine Echtzeit-Textsuche über Name und Beschreibung, eine umschaltbare Sortierung nach Datum, Name oder Jahrgang sowie eine Kartenanzeige mit Bild, Name, Jahrgang und gekürzter Beschreibung. Administratorinnen und Administratoren sehen zusätzlich Warnmeldungen bei gemeldeten Einträgen und einen Lösch-Button. Angemeldete Benutzerinnen und Benutzer können über einen eigenen Button ihren Eintrag erstellen oder bearbeiten. Edit.razor Erstellungs- und Bearbeitungsseite Die Edit-Komponente dient sowohl zum Erstellen als auch zum Bearbeiten eines Eintrags. Sie bietet Formularfelder für Name, Jahrgang, Beschreibung (mit Live-Zeichenzähler), Foto-Upload und Link. Über zwei Speicheroptionen kann zwischen Entwurf und Veröffentlichung gewählt werden. Eine Eigentümerprüfung verhindert das Bearbeiten fremder Einträge, und eine Duplikatprüfung verhindert das Erstellen mehrerer Einträge pro Person. Details.razor Detailseite Die Details-Komponente zeigt einen einzelnen Eintrag in einem zweispaltigen Layout mit unscharfem Bildhintergrund. Administratorinnen und Administratoren sehen bei gemeldeten Einträgen eine Liste aller Meldungen mit Lösch-Button. Ein modaler Dialog ermöglicht die PDF-Vorschau sowie den Download. Die Meldefunktion wird über die zentrale IReportUI-Komponente eingebunden. Settings.razor Moduleinstellungen Die Settings-Komponente bietet eine einfache Oberfläche für Moduleinstellungen über Oqtanes Setting-Service.

Gemeinsame Melde-Komponente (IReportUI)

Die Meldefunktion in der Detailseite ist nicht direkt im Hall-of-Fame-Modul implementiert, sondern wird über eine zentrale Schnittstelle aus dem Interfaces-Paket eingebunden. Das Hall-of-Fame-Modell implementiert das Interface IReportable, das eine Entität als meldbar kennzeichnet. In der Detailseite wird per Dependency Injection eine IReportUI-Implementierung injiziert die konkrete ReportComponent stammt dabei aus dem Admin-Modul und stellt den Melden-Button samt modalem Dialog bereit. Die Komponente wird über Blazors DynamicComponent dynamisch gerendert. Ist keine Implementierung im Container registriert, wird die Meldefunktion schlicht nicht angezeigt. Dieses Konzept ermöglicht es, die Melde-Oberfläche zentral zu pflegen und in beliebig vielen weiteren Modulen wiederzuverwenden, ohne dass die einzelnen Module die Melde-Logik selbst implementieren müssen.

PDF-Export mit QuestPDF

Für die Generierung der PDF-Dokumente wird die Open-Source-Bibliothek QuestPDF in der Community-Edition eingesetzt. Im Server-Projekt wurde ein benutzerdefiniertes MSBuild-Target erstellt, das nach jedem Build automatisch die QuestPDF-DLL sowie die plattformspezifischen nativen Bibliotheken in das bin-Verzeichnis des Oqtane-Servers kopiert. Dies ist notwendig, weil Oqtane Module zur Laufzeit dynamisch lädt und QuestPDF native Abhängigkeiten (unter anderem die SkiaSharp-Rendering-Engine) benötigt. Das PDF-Design folgt einem Glasmorphismus-Ansatz. Jede Seite hat das Format DIN A4 ohne Ränder. Über die Layers-API von QuestPDF wird das Hintergrundbild von der Inhaltsebene getrennt. Der Name wird in 36 Punkt ExtraBold mit Großbuchstaben und Zeichenabstand dargestellt, der Jahrgang in 15 Punkt mit erhöhtem Zeichenabstand und die Beschreibung in 11 Punkt mit 1,5-fachem Zeilenabstand. Der Glaseffekt wird durch halbtransparente dunkle Hintergründe mit mehrschichtigen Rahmen unterschiedlicher Transparenz erzeugt.

Implementierungsdetails und Problemlösungen

Während der Entwicklung traten mehrere technische Herausforderungen auf, die im Folgenden zusammen mit ihren Lösungen beschrieben werden. Bild-Upload-System In der ursprünglichen Version des Moduls mussten Benutzerinnen und Benutzer eine Bild-URL manuell in ein Textfeld eingeben. Das implementierte Bild-Upload-System ersetzt dies durch eine Blazor-InputFile-Komponente mit Live-Vorschau, Fortschrittsanzeige und Lösch-Button. Die Upload-Methode prüft die Dateigröße (maximal 5 MB), öffnet die Datei als Stream und übermittelt sie als MultipartFormDataContent an den Server, der den Dateityp serverseitig validiert, einen UUID-Dateinamen generiert und die Datei speichert. Das System unterstützt beide Blazor-Rendering-Modi. Concurrency Exception beim Löschen Beim Löschen von Einträgen mit vorhandenen Meldungen trat eine DbUpdateConcurrencyException auf, verursacht durch Konflikte im Entity Framework Change Tracker. Die Lösung bestand in der Aufteilung der Löschoperation in zwei separate Transaktionen mit jeweils eigenem DbContext: zuerst werden alle zugehörigen Meldungen gelöscht, danach der Haupteintrag. Kartendesign-Optimierung Karten hatten ursprünglich unterschiedliche Höhen durch variierende Beschreibungslängen. Die Lösung kombiniert CSS-Flexbox auf dem Kartenelement mit einer Maximalhöhe von 150 Pixeln und overflow: hidden auf dem Beschreibungscontainer, sodass alle Karten einer Zeile dieselbe Höhe aufweisen. Sortier-Toggle Die ursprünglich fest codierten Sortierrichtungen wurden durch einen Toggle-Button neben dem Sortier-Dropdown ersetzt, der mit einem dynamischen Pfeil-Icon zwischen aufsteigender und absteigender Sortierung umschaltet. Die Sortierlogik ist in einer berechneten Eigenschaft gekapselt, die Suche und Sortierung kombiniert.

8. Projektorganisation & Teamarbeit

8.1 Planung & Meilensteine

Meilensteine

Soll-/Ist-Vergleich

Zeitverzug

8.2 Teamverkleinerung

Downsizing von 6 auf 3 Personen

Neue Aufgabenverteilung

Auswirkungen auf Theme-Entwicklung, Module und Zeitplanung


9. Übergangslösung, Probleme & Learnings

9.1 Übergangslösung (Sommer 2025)

Gründe & Technische Umsetzung

Differenzen zur finalen Lösung

9.2 Probleme

Technische Probleme

Organisatorische Probleme

9.3 Learnings

Technisch

Methodisch

Persönlich


10. Testen & Qualitätssicherung

Funktionstests der Module

Theme-Tests

Usability-Tests

Bekannte Einschränkungen


11. Fazit & Ausblick

Zielerreichung & Zusammenfassung

Persönliche Reflexion

Erweiterungsmöglichkeiten