diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fb9a51a..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec99bcc --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# SQLite-Datenbank (Laufzeitartefakt in sessions/) +sessions/*.db +sessions/*.db-wal +sessions/*.db-shm + +# macOS-Artefakte +.DS_Store diff --git a/AGENTS.md b/AGENTS.md index 093811d..46d0fab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,39 +4,38 @@ Single-page app for tracking engineering projects across weekly sessions ("Sitzungen"). Vanilla JS/HTML/CSS frontend + Node.js/Express server. No build -step, no bundler, no tests. Data is persisted as semicolon-separated CSVs -under `sessions/`. +step, no bundler, no tests. Data is persisted in a SQLite database +(`node:sqlite`, needs Node >= 22.13) at `sessions/projektuebersicht.db`. Two HTML entrypoints, both served statically by Express: - `Test.html` — the main app (tabs: Projektboard, Auslastung, Projekte, Projektbeteiligte). Served at `/`. - `project-plan.html` — per-project Gantt/TODO planning view, opened in a new tab via `openProjectPlan()` in `js/gantt.js`. Loads the shared helper modules - (`globals`, `utils`, `ui`, `date-picker`, `csv`, `server`, `gantt`) plus the + (`globals`, `utils`, `ui`, `date-picker`, `server`, `gantt`) plus the plan modules under `js/plan/` — NOT the full main module set. -All UI strings/comments/CSV content are German. Preserve German in +All UI strings/comments are German. Preserve German in user-facing text. ## File structure ``` . -├── server.js # Express server + CSV API +├── server.js # Express server + SQLite API ├── package.json # deps: express, cors only ├── docker-compose.yml # at repo ROOT; build context ., dockerfile Docker/Dockerfile -├── Docker/Dockerfile # node:20-alpine +├── Docker/Dockerfile # node:22-alpine (nötig für node:sqlite) ├── .dockerignore ├── .vscode/extensions.json ├── public/ │ ├── Test.html # main app (served at /) │ ├── js/ # shared modules (classic scripts, global fns) │ │ ├── globals.js # Konstanten (LPHS, ROLES, LPH-Farben, DEPARTMENTS) + db/currentDepartment -│ │ ├── utils.js # esc, uid, Datum-/Differenz-Helfer, personIdForName, peopleByRole, assignKey, weekSortKey-Quelle +│ │ ├── utils.js # esc, uid, Datum-/Differenz-Helfer, personIdForName, peopleByRole, assignKey, weekSortKey │ │ ├── ui.js # LocalStorage-UI-State, Header-Collapse, Theme │ │ ├── date-picker.js # Datums-/Bereichspicker-Overlays -│ │ ├── csv.js # CSV-Parser/Serializer + weekSortKey, filenameForWeek -│ │ ├── server.js # baseUrl, sendCsvToServer, deleteCsvFromServer, blobToDataUrl +│ │ ├── server.js # baseUrl, sendWeekToServer, sendPeopleToServer, blobToDataUrl │ │ ├── store.js # save/syncAllToServer, switchDepartment, load, seed │ │ ├── weeks.js # Wochen-Auswahl, -Erzeugung, -Klonen, Auto-Lock, -Löschung │ │ ├── gantt.js # GANTT-Diagramm (buildGanttHtml, openProjectPlan), geshared @@ -62,8 +61,8 @@ user-facing text. │ │ └── plan-schedule.js # Kritischer Pfad, Auto-Schedule, Mail-Link │ ├── styles.css │ └── dein_bild.ico -└── sessions/ # data; bind-mounted into Docker container - ├── ELT/ HLS/ ARCH/ # one folder per department +└── sessions/ # SQLite-DB; bind-mounted into Docker container + └── projektuebersicht.db # node:sqlite database (WAL mode) ``` ## Running @@ -93,31 +92,55 @@ docker compose up --build # Docker variant (compose file is at repo root) reads/writes these routes via `applyUrlRoute()`/`updateRouteUrl()` in `js/ui.js` and all static assets in the HTML use **absolute** paths (`/js/...`, `/styles.css`) so they resolve on nested routes. -- `GET /load-all?department=` → `{sessions:[{filename,content}], people}` with - `_people.csv` content in `people`; sessions sorted by filename. -- `POST /save-csv {filename, csv, department}` → writes UTF-8 BOM CSV. -- `POST /delete-csv {filename, department}`. +- `GET /load-all?department=` → `{weeks:[weekObj], people:[personObj]}` with the + global people list in `people`; weeks are full JSON week objects (id, label, + date, locked, people, attendance, projects), sorted by label. +- `POST /save-week {department, week}` → upserts one week (JSON object, keyed by + department + label). Used by `sendWeekToServer()`. +- `POST /save-people {department, people}` → replaces the department's global + people list (JSON array). +- `POST /delete-week {department, label}` → deletes the week; missing label + yields 400, missing week tolerates with `deleted:false`. - Valid departments hard-coded as `ELT|HLS|ARCH` in `server.js` (`VALID_DEPARTMENTS`); anything else silently falls back to `ELT`. Same set in `DEPARTMENTS` in `js/globals.js`. -- `safeName()` strictly validates filenames (path traversal protection); - static assets get `Cache-Control: no-store`. +- Static assets get `Cache-Control: no-store`. - JSON body limit is 2 MB. -## CSV format +## Persistence (SQLite) -- Delimiter `;`, UTF-8 with BOM. Hand-editing is possible but risky; the parser - reconstructs objects from the fixed column layout. -- Week files `