# Projektübersicht — README ## Übersicht Dieses Projekt ist eine lokale Weboberfläche zur Verwaltung von TGA-Projekten (Elektro, HLS, Architektur) über wöchentliche Sitzungen. Die Anwendung besteht aus: - einem Frontend aus zwei HTML-Einstiegen (`Test.html` für die Hauptansicht mit Tabs, `project-plan.html` für die Projektplanung/GANTT-Ansicht) plus `styles.css` und den JS-Modulen unter `public/js/` - einem einfachen Node.js-/Express-Server in `server.js` - einem Datenspeicher in einer SQLite-Datenbank (`node:sqlite`, benötigt Node ≥ 22.13) unter `sessions/projektuebersicht.db` - einem Docker-Setup (`Docker/Dockerfile` + `docker-compose.yml` im Projektstamm) ## Datei- und Komponentenübersicht ### Wichtige Laufzeit-Dateien - `server.js` - Node.js/Express-Server - dient als API für das Frontend - stellt statische Dateien (`Test.html`, `project-plan.html`, die Module unter `js/`, `styles.css`, etc.) bereit; statische Assets werden mit `Cache-Control: no-store` ausgeliefert - implementiert Endpunkte: - `GET /` → liefert `Test.html` - `GET /load-all?department=…` → lädt alle Sitzungen plus globale Personenliste einer Abteilung - `POST /save-week {department, week, baseUpdatedAt}` → speichert/aktualisiert eine Sitzung; mit `baseUpdatedAt` (die vom Client gehaltene Revision = `updatedAt` aus `load-all`) erkennt der Server veraltete Speicherungen und antwortet dann mit HTTP 409 `{ok:false, conflict:true, …}`; auch gelöschte Sitzungen werden mit nicht-leerer Basis nicht wiederbelebt (409). Erfolgreiche Saves antworten `{ok:true, updatedAt}` (neue Revision) - `POST /save-people {department, people}` → ersetzt die globale Personenliste einer Abteilung - `POST /delete-week {department, label}` → löscht eine Sitzung - `GET /health` → Gesundheitscheck (`{ok:true}`) - Deep Links je Abteilung + Tab, z. B. `GET /HLS/Auslastung` oder `GET /ELT/Projektübersicht` → liefert `Test.html`; gültige Tab-Slugs sind `Projektübersicht | Auslastung | Projekte | Projektbeteiligte`, alles andere ergibt 404 - `GET //Projektplan(/)?` → liefert `project-plan.html` (GANTT-Ansicht); die Identifikation erfolgt über die Query-Parameter `weekLabel` und `projNr`, der Projektname ist nur ein lesbares Pfad-Segment - validiert Abteilungen gegen `ELT | HLS | ARCH` (unbekannte fallen stillschweigend auf `ELT` zurück) - legt das `sessions`-Verzeichnis beim Start an, falls es nicht existiert - JSON-Body-Limit von 2 MB - beendet sich mit aussagekräftiger Fehlermeldung, wenn der Port belegt ist - `package.json` - definiert den Node.js-Startbefehl `npm start` - enthält Produktionsabhängigkeiten `express` und `cors` - `package-lock.json` - wird für reproduzierbare Docker-Builds verwendet (`npm ci`) - `public/js/` (Module) - Die Client-Logik ist in kleine klassische Script-Dateien aufgeteilt (alle Funktionen global auf `window`, kein Bundler): - gemeinsame Helfer: `globals.js`, `utils.js`, `ui.js`, `date-picker.js`, `server.js`, `store.js`, `weeks.js`, `gantt.js`, `showmode.js`, `tabs-auth.js`, `pdf.js`, `init.js` - tab-spezifisch in eigenen Ordnern: `board/board.js` (Projektboard), `people/people.js` (Projektbeteiligte), `projects/projects.js` (Projekte), `load/load.js` (Auslastung) - Planungs-Module unter `js/plan/` (`plan-state`, `plan-build-gantt`, `plan-gantt`, `plan-drag`, `plan-modals`, `plan-schedule`) - rendert das Projektboard, die Projekt- und Personenverwaltung sowie die Auslastungsansicht - lädt Daten über den Server und speichert Änderungen als JSON-Objekte in die SQLite-Datenbank zurück - verwendet `currentDepartment` zur Trennung von Abteilungen (`ELT`, `HLS`, `ARCH`) - speichert: - alle Sitzungen und die globale Personenliste pro Abteilung in `sessions/projektuebersicht.db` - sortiert Sitzungen nach Kalenderwoche, nicht alphabetisch - sperrt historische Sitzungen automatisch (bis auf die chronologisch letzte) - Personen sind global pro Abteilung verwaltet; historische Sitzungen behalten ihre lokalen Personenkopien - speichert keine Daten in `localStorage` (dort liegt nur UI-Zustand wie Abteilung, Theme und Header-Collapse) - `Test.html` - die Haupt-Benutzeroberfläche der Anwendung (Tabs: Projektboard, Auslastung, Projekte, Projektbeteiligte) - lädt `styles.css` und die JS-Module aus `js/` in fester Reihenfolge (siehe `AGENTS.md`) - enthält die Abteilungsauswahl, Sitzungsnavigation, Tab-Navigation, das Passwort-Modal sowie PDF-Export - lädt CryptoJS (Passwortprüfung) und pdfmake (PDF-Export) von `cdnjs.cloudflare.com` — diese Funktionen benötigen daher Internetzugang - `project-plan.html` - die Planungsansicht (GANTT/TODOs/Meilensteine) pro Projekt - öffnet sich in einem neuen Tab über `openProjectPlan()` (`js/gantt.js`) - lädt nur die gemeinsamen Helfermodule plus `js/plan/*` und window-übergreifend abgestimmte Pfade - `styles.css` - Layout und Styling der Oberfläche ### Docker-bezogene Dateien - `Docker/Dockerfile` - Basis-Image: `node:22-alpine` (nötig, da `node:sqlite` erst ab Node 22.13 ohne Flag stabil verfügbar ist) - kopiert `package.json` und `package-lock.json`, installiert Produktionsabhängigkeiten mit `npm ci` - kopiert `server.js` und `public/` nach `/app` - legt sicherheitshalber `/app/sessions` an - läuft als nicht-root-User `node` - enthält einen `HEALTHCHECK` auf `/health` - startet `node server.js` - `docker-compose.yml` (im Projektstamm) - definiert den Service `projektuebersicht` - baut das Image mit Build-Kontext `.` und `Docker/Dockerfile` - mappt Port `3003:3003` - bindet das Host-Verzeichnis `./sessions` in den Container nach `/app/sessions` - setzt `restart: unless-stopped` - definiert einen `healthcheck` - `.dockerignore` - schließt unnötige Dateien aus dem Docker-Build aus: `node_modules/`, `npm-debug.log`, `.git`, `.gitignore`, `Docker/*` (außer `Docker/Dockerfile`) ### Sonstige Dateien - `dein_bild.ico` - optionales Icon, wird vom Server statisch ausgeliefert, wenn angefragt - `AGENTS.md` - Projektnotizen / Dokumentation, aber nicht Teil des Anwendungslaufs ## Persistenz und Datenfluss ### Speicherung - Alle persistierten Daten werden in einer SQLite-Datenbank (`node:sqlite`, `DatabaseSync`, WAL-Modus, `PRAGMA foreign_keys = ON`) unter `sessions/projektuebersicht.db` gespeichert. - Das Schema ist vollständig relational (19 Tabellen): `weeks`, `week_people` (+ `week_people_roles`), `attendance`, `projects`, `project_lph`, `project_assign`, `project_aufwand`, `project_aktuelle_lp`, `project_plan`, `plan_people`, `plan_todos` (+ `plan_todo_assignees`, `plan_todo_deps`), `plan_milestones` (+ `plan_milestone_deps`), `people` (+ `person_roles`, `person_absences`). Projekt-/Personen-IDs bleiben dadurch über Neustarts stabil. - Der Datenbankpfad ist über die Umgebungsvariable `DB_PATH` übersteuerbar (für Tests/Backups), Standard ist `sessions/projektuebersicht.db`. ### Server-API - Der Server wird in `server.js` erstellt und startet auf Port `3003` oder dem Wert von `process.env.PORT`. - Das Frontend ruft den Server über `window.location.origin` an (Fallback `http://localhost:3003` bei `file://`-Öffnung). ### Wo werden die Daten gespeichert? - Das Frontend schreibt über den Server in die SQLite-Datenbank. - In `js/store.js` speichert die Anwendung nur **geänderte** Sitzungen (Dirty-Tracking über `markWeekDirty()`/`markPeopleDirty()`) via `/save-week` (Sitzungen) bzw. `/save-people` (globale Personen); ein In-Flight-Guard verhindert Doppel-Speicherungen. Jede Sitzung führt einen Revisions-Zeitstempel (`updated_at`, übertragen als `updatedAt`); speichert ein Client mit veralteter Revision (`baseUpdatedAt`), antwortet der Server mit HTTP 409 und der Client lädt nur diese eine Sitzung neu (andere ungespeicherte Änderungen bleiben erhalten). - Der Server zerlegt die JSON-Objekte in die relationalen Tabellen (`serializeWeek()`/`loadWeeks()`) in einer Transaktion pro Sitzung. Beim Start migriert `migrateLegacySchema()` idempotent ein altes Single-JSON-Dokument-Schema in das relationale Schema; anschließend ergänzt `migrateWeeksUpdatedAt()` die `updated_at`-Spalte der `weeks`-Tabelle (idempotent). `PRAGMA busy_timeout = 5000` verhindert Fehler bei parallelen Schreibzugriffen. ## Betrieb ### Lokal mit Node.js (Node ≥ 22.13) ```bash npm install npm start ``` Danach ist die Anwendung erreichbar unter `http://localhost:3003`. Falls der Port belegt ist: ```bash PORT=3004 npm start ``` ### Mit Docker Im Projektstamm ausführen: ```bash docker compose up --build ``` Danach ist die Anwendung erreichbar unter: ``` http://localhost:3003 ``` ## Wichtige Hinweise - Der Server benötigt Lese-/Schreibzugriff auf `sessions/` (für die SQLite-Datenbank und das Docker-Bind-Mount). - Die Docker-Compose-Konfiguration liegt im Projektstamm und mountet `./sessions` in den Container. Achte darauf, dass der relative Pfad im Kontext korrekt ist, wenn du `docker compose` aus einem anderen Verzeichnis startest. - `js/store.js` und `js/server.js` arbeiten mit Abteilungsparametern und speichern Daten abteilungsweise getrennt. - Die Passwortfunktion (Tabs „Projekte“/„Projektbeteiligte“, Sitzungslöschung, Entsperren) ist nur ein einfacher Client-Mechanismus im Frontend (SHA256-Vergleich) und kein echter Sicherheitsmechanismus. - Globale Personen werden pro Abteilung in der Datenbank verwaltet. Wird eine Person global gelöscht, bleibt sie in bereits existierenden Sitzungen sichtbar (Wochen-Personenkopien). - CryptoJS und pdfmake werden von `cdnjs.cloudflare.com` geladen — PDF-Export und Passwortprüfung funktionieren ohne Internet nicht.