6f18848f8600d3d6309cfd77239c7bba4aec8302
This is placeholder commit and will be replaced by a merge of your virtual branches. Due to GitButler managing multiple virtual branches, you cannot switch back and forth between git branches and virtual branches easily. If you switch to another branch, GitButler will need to be reinitialized. If you commit on this branch, GitButler will throw it away. For more information about what we're doing here, check out our docs: https://docs.gitbutler.com/features/branch-management/integration-branch
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.htmlfür die Hauptansicht mit Tabs,project-plan.htmlfür die Projektplanung/GANTT-Ansicht) plusstyles.cssund den JS-Modulen unterpublic/js/ - einem einfachen Node.js-/Express-Server in
server.js - einem Datenspeicher in einer SQLite-Datenbank (
node:sqlite, benötigt Node ≥ 22.13) untersessions/projektuebersicht.db - einem Docker-Setup (
Docker/Dockerfile+docker-compose.ymlim 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 unterjs/,styles.css, etc.) bereit; statische Assets werden mitCache-Control: no-storeausgeliefert - implementiert Endpunkte:
GET /→ liefertTest.htmlGET /load-all?department=…→ lädt alle Sitzungen plus globale Personenliste einer AbteilungPOST /save-week {department, week, baseUpdatedAt}→ speichert/aktualisiert eine Sitzung; mitbaseUpdatedAt(die vom Client gehaltene Revision =updatedAtausload-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 AbteilungPOST /delete-week {department, label}→ löscht eine SitzungGET /health→ Gesundheitscheck ({ok:true})- Deep Links je Abteilung + Tab, z. B.
GET /HLS/AuslastungoderGET /ELT/Projektübersicht→ liefertTest.html; gültige Tab-Slugs sindProjektübersicht | Auslastung | Projekte | Projektbeteiligte, alles andere ergibt 404 GET /<Dept>/Projektplan(/<ProjName>)?→ liefertproject-plan.html(GANTT-Ansicht); die Identifikation erfolgt über die Query-ParameterweekLabelundprojNr, der Projektname ist nur ein lesbares Pfad-Segment
- validiert Abteilungen gegen
ELT | HLS | ARCH(unbekannte fallen stillschweigend aufELTzurü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
expressundcors
- definiert den Node.js-Startbefehl
-
package-lock.json- wird für reproduzierbare Docker-Builds verwendet (
npm ci)
- wird für reproduzierbare Docker-Builds verwendet (
-
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)
- gemeinsame Helfer:
- 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
currentDepartmentzur Trennung von Abteilungen (ELT,HLS,ARCH) - speichert:
- alle Sitzungen und die globale Personenliste pro Abteilung in
sessions/projektuebersicht.db
- alle Sitzungen und die globale Personenliste pro Abteilung in
- 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)
- Die Client-Logik ist in kleine klassische Script-Dateien aufgeteilt (alle Funktionen global auf
-
Test.html- die Haupt-Benutzeroberfläche der Anwendung (Tabs: Projektboard, Auslastung, Projekte, Projektbeteiligte)
- lädt
styles.cssund die JS-Module ausjs/in fester Reihenfolge (sieheAGENTS.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, danode:sqliteerst ab Node 22.13 ohne Flag stabil verfügbar ist) - kopiert
package.jsonundpackage-lock.json, installiert Produktionsabhängigkeiten mitnpm ci - kopiert
server.jsundpublic/nach/app - legt sicherheitshalber
/app/sessionsan - läuft als nicht-root-User
node - enthält einen
HEALTHCHECKauf/health - startet
node server.js
- Basis-Image:
-
docker-compose.yml(im Projektstamm)- definiert den Service
projektuebersicht - baut das Image mit Build-Kontext
.undDocker/Dockerfile - mappt Port
3003:3003 - bindet das Host-Verzeichnis
./sessionsin den Container nach/app/sessions - setzt
restart: unless-stopped - definiert einen
healthcheck
- definiert den Service
-
.dockerignore- schließt unnötige Dateien aus dem Docker-Build aus:
node_modules/,npm-debug.log,.git,.gitignore,Docker/*(außerDocker/Dockerfile)
- schließt unnötige Dateien aus dem Docker-Build aus:
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) untersessions/projektuebersicht.dbgespeichert. - 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 istsessions/projektuebersicht.db.
Server-API
- Der Server wird in
server.jserstellt und startet auf Port3003oder dem Wert vonprocess.env.PORT. - Das Frontend ruft den Server über
window.location.originan (Fallbackhttp://localhost:3003beifile://-Öffnung).
Wo werden die Daten gespeichert?
- Das Frontend schreibt über den Server in die SQLite-Datenbank.
- In
js/store.jsspeichert die Anwendung nur geänderte Sitzungen (Dirty-Tracking übermarkWeekDirty()/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 alsupdatedAt); 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 migriertmigrateLegacySchema()idempotent ein altes Single-JSON-Dokument-Schema in das relationale Schema; anschließend ergänztmigrateWeeksUpdatedAt()dieupdated_at-Spalte derweeks-Tabelle (idempotent).PRAGMA busy_timeout = 5000verhindert Fehler bei parallelen Schreibzugriffen.
Betrieb
Lokal mit Node.js (Node ≥ 22.13)
npm install
npm start
Danach ist die Anwendung erreichbar unter http://localhost:3003.
Falls der Port belegt ist:
PORT=3004 npm start
Mit Docker
Im Projektstamm ausführen:
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
./sessionsin den Container. Achte darauf, dass der relative Pfad im Kontext korrekt ist, wenn dudocker composeaus einem anderen Verzeichnis startest. js/store.jsundjs/server.jsarbeiten 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.comgeladen — PDF-Export und Passwortprüfung funktionieren ohne Internet nicht.
Languages
JavaScript
76.5%
CSS
17.1%
HTML
5.5%
Shell
0.8%