Commit Graph
86 Commits
Author SHA1 Message Date
gg 929664453e feat(form): flexContent-Option für Flex-Spalte im Formular-Inhalt
Der scrollbare Inhaltsbereich der Form kann bei Bedarf als Flex-Spalte
gerendert werden, damit Masken-Kinder den verbleibenden Platz füllen und
in sich scrollen können, statt die gesamte Maske scrollbar zu machen.
Wirkt nur zusammen mit stickyButtons (Default true).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-27 10:09:09 +02:00
gg 32afb35840 feat(workflow): Workflow-Buttons in die Standard-Button-Leiste der Form integrieren
Die Workflow-Buttons ("Nächster Kontakt", "Speichern und weiter") standen
bisher in einer eigenen Zeile über der Standard-Leiste (Zurücksetzen,
Abbrechen, Speichern). Das Form-Widget erhält dafür das neue optionale
Attribut extrabuttons, dessen Buttons rechts neben "Speichern" in die
Leiste eingereiht werden — sie profitieren damit auch vom Sticky-Verhalten
der Leiste.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 19:24:50 +02:00
gg 4d8febcc3f fix(select): Anzeige bei asynchron nachgeladenen Optionen nachziehen
Beim oninit war attrs.value teils keiner Option zuzuordnen, weil die
Optionen (z.B. Kundenliste) asynchron geladen werden — das Feld blieb
dauerhaft leer, da lastSyncedValue bereits gesetzt war und der Sync im
view nicht mehr griff. syncPending markiert die offene Synchronisierung
und wiederholt sie im view, bis eine passende Option existiert; Tippen
verwirft das Flag, damit die Nutzereingabe nicht überschrieben wird.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 19:14:16 +02:00
gg 3ba9b0a07f fix(treetable): Sticky-Header der Kopfzeile reparieren
Die schließende Klammer fehlte im calc() der Scroll-Container-Höhe, wodurch
die Höhe auf auto fiel und der Div nie selbst scrollte — Sticky bezog sich
damit auf keinen funktionierenden Scroll-Container. Zusätzlich das
overflow-y am table-Element entfernt (macht die Tabelle selbst zum
Scroll-Container und bricht Sticky) und w3-theme als eigener Hintergrund
auf die th gelegt, damit beim Scrollen keine Zeilen durchscheinen.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 19:02:40 +02:00
gg c96ed6e97d feat(workflow): Tages-Workflow-UI für Telefon-Akquise (Liste + Maske)
Server: neuer Endpunkt /xhr/workflow/list aggregiert pro Kontaktadresse
die letzte Gesprächsnotiz, das effektiv gültige Wiedervorlage-Datum
(jüngste Notiz mit Wert), den Erledigt-Status und eine priorisierte
Sortierung (überfällig → ohne Notizen → Rest). Filter: kunden_id, status
(offen/erledigt), wiedervorlage (heute/3tage/ueberfaellig/woche).
Sichtbarkeit wie kontaktadressen über projekt_users.

CallLog erfasst den Ersteller serverseitig (user_id, Migration _db_V01_14,
kein FK wegen separater Auth-DB); to_dict ergänzt mitarbeiter_name.
calllog_list unterstützt kontaktadresse_id als Filter.

Client: TagesWorkflowListe (Route /tagesworkflow, Filterleiste) und
TagesWorkflowMaske (Route /tagesworkflowkontakt, lesende Historie,
Notiz-Formular mit "Speichern und weiter"), Routes + Menüpunkt erster
Eintrag. berechneWiedervorlageDatum aus der Call_Log-Maske nach
models/tag.ts ausgelagert (gemeinsame Nutzung).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 18:56:23 +02:00
gg 981b28df03 feat(treetable): optionale Kopfzeile und abschaltbare Expand-Buttons
Neues Attribut header rendert eine sticky Spaltenüberschriftenzeile.
showExpandButtons=false blendet die Ein-/Ausklappen-Buttons aus; die
Topbar entfällt dann ganz, wenn auch keine Children oder Filter vorhanden
sind — der scrollbare Bereich nutzt in dem Fall die volle Höhe.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 18:54:42 +02:00
gg 3a6732e36b feat(select): Öffnen-Button für ungefilterte Liste und Sync externer value-Änderungen
Der neue Öffnen-Button blendet die Optionsliste ungefiltert ein, ohne das
Feld zu leeren. Der Anzeigetext wird zudem im view nachgezogen, wenn der
Eltern-View den value ändert (z.B. Zurücksetzen eines Filters).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-24 18:53:44 +02:00
gg 977b64292c feat(calllog): kontaktadresse_id als Pflicht-FK + is_erledigt()-Methoden
- Migration V01_13: Spalte kontaktadresse_id auf call_logs mit Backfill
  über die erste Kontaktadresse des Projekts; Commit vor dem
  Systeminfo-Update (Muster wie V01_08) gegen 'database is locked'.
- CallLog gehört zu genau einer Kontaktadresse (FK, Pflichtfeld);
  create/update validieren Existenz und Projekt-Zugehörigkeit.
- is_erledigt() auf Kontaktadresse (mind. ein erledigend-Tag reicht)
  und Projekt (False ohne Kontakte, sonst alle erledigt); beide in
  to_dict() serialisiert.
- Client: kontaktadresse_id in Notizmaske/Submit (required), Interfaces
  um is_erledigt erweitert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-22 20:12:02 +02:00
gg 24b492c5c1 feat(runserver): Selbst-supervidierenden Dev-Server, -D-Parameter funktional
- Supervisor-Modus im Dev-Betrieb: Der Server läuft als Subprozess und
  wird nach einem Abbruch neu gestartet. Der Werkzeug-Reloader beendet
  sich sonst komplett, wenn der App-Prozess beim Start crasht — als
  Hauptprozess des Containers würde damit der gesamte Dev-Container
  stoppen. Der Supervisor importiert die App nicht und überlebt so
  jeden Anwendungsfehler.
- -D-Parameter ist jetzt funktional: Dev-Start direkt von der
  Befehlszeile ohne Devcontainer/Env-Variable. Debug-Entscheidung:
  -D ODER APP_DEBUG.
- approot.py: init_app(debug) reicht die Debug-Entscheidung durch,
  damit Server-Typ und JS-Bundle-Auswahl (.js/.min.js) konsistent
  bleiben. wsgi.py (init_app() ohne Argument) unverändert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-22 19:12:27 +02:00
gg 4e721e9a47 feat(call-log): Wiedervorlage-Auto-Berechnung und Kunde/Projekt-Select
- Wiedervorlage-Datum wird automatisch aus ausgewählten Tags berechnet
  (Minimum von wiedervorlage_abstand_tage aller Tags mit
  loest_wiedervorlage_aus)
- Kunde/Projekt: Conditional Rendering — vorbelegt als Read-Only,
  nicht vorbelegt als abhängige Select-Widgets
- Live-Binding für datum und wiedervorlage_datum via oninput, um
  Mithril-Redraw-Override durch FormData-Auslesung zu verhindern

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-22 16:42:36 +02:00
gg 5a39c64880 docs(ai-context): Konzept für Telefon-Akquise-Workflow hinzugefügt
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-20 20:21:40 +02:00
gg 6f86bc9808 feat(tag): Workflow-Felder für Telefon-Akquise (is_erledigend, Wiedervorlage)
Tag-Modell um is_erledigend, loest_wiedervorlage_aus und
wiedervorlage_abstand_tage erweitert. Migration V01_12 idempotent
angelegt, Geschäftslogik mit Validierung, Client-Maske mit Controls
und Workflow-Badges. Farb-Default Grau bei fehlender Farbe, parent_id
im onchange direkt in currentTag übernehmen.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-20 20:20:52 +02:00
gg 1d8201f46a fix: Entferne Kommentar aus .gitignore für App_Server/data 2026-09-19 19:02:59 +02:00
gg d7e5c014a8 Merge branch 'main' of https://git.everdc.eu/chmln-app-dev/kbcrm 2026-09-19 18:59:14 +02:00
gg a67921ec74 feat(isdirty): Navigations-Guard gegen ungespeichertes Verlassen von Bearbeitungsmasken
Zentraler DirtyGuard (dirtyguard.ts) mit DirtyMaskHelper-Klasse und
3-Button-Bestätigungs-Modal (Speichern/Verwerden/Abbrechen). Form meldet
Dirty-State via onDirtyChange nach oben; input-Event ergänzt change für
frühzeitiges Dirty-Marking. Alle App-Navigationen (Breadcrumb, Menü,
In-Masken-Buttons, Abbrechen) laufen über guardedNavigate. Auto-Redraw
bei dirty per e.redraw=false unterbunden, damit DOM-Eingaben erhalten
bleiben (Input-Widget hat kein Live-Binding).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 18:21:58 +02:00
gg fd30049a32 feat(nav): Breadcrumb-Navigation für Hierarchie-Aufrufkette
Neue BreadcrumbBar-Widget-Komponente (breadcrumb.ts) zeigt die
Aufrufkette als anklickbare Leiste. Der Route-Param bc (JSON-String)
transportiert die Vorgänger-Ansichten durch alle Listen und Masken.
Jede Ansicht hängt beim Weiternavigieren ihren eigenen Crumb an die
Kette an; Masken reichen bc beim Speichern/Abbrechen zurück.
Erfasst: kunde, projekt, kontaktadresse, call_log, kontakt.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 16:16:49 +02:00
gg f1e5938ae1 fix: Rückkehr-Kontext für Gesprächsnotizenliste erhalten
Die Bearbeitungsmaske kehrt beim Speichern/Abbrechen nicht mehr mit dem
Projekt der bearbeiteten Notiz zurück, sondern mit dem Filter der Liste,
aus der sie geöffnet wurde. Liste reicht from_liste/return_projekt_id an
die Maske durch; Maske wertet diesen Kontext in goBack() aus.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 15:38:23 +02:00
gg d30adf1579 feat(calllog): Tags einer Gesprächsnotiz zuordnen (n:m)
Backend:
- Neues CallLogTag-Model (Tabelle call_logs_tags) mit Relationship
  auf CallLog (cascade delete-orphan); to_dict liefert 'tags'.
- Migration _db_V01_11 (idempotent via create_all).
- _set_call_log_tags in create/update_call_log: ersetzt
  Tag-Zuordnungen, filtert is_parent-Tags, eliminiert Duplikate.
- _parse_date wandelt ISO-Strings in date-Objekte (fixt autoflush-
  Crash bei Date-Spalten).

Frontend:
- iCallLog um tags (Lesen) und tag_ids (Schreiben) ergänzt.
- Neues generisches MultiSelect-Widget (widgets/select.ts):
  Badges + Edit-Button, inline Modal mit Suchfeld, Checkbox-Liste,
  OK-Button; konfigurierbare Texte (placeholder, modalTitle,
  editTooltip).
- Call_Log-Formular: Tag-Auswahl via MultiSelect, Submit via
  FormData.getAll; Tag-Badges in der Listenansicht hinter dem Betreff.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 15:12:36 +02:00
gg 5abcb2d96c feat(tags): Backend mit REST-API und Client-Anbindung fuer hierarchische Tags
- SQLAlchemy-Modell Tag mit Selbst-Referenz (parent_id), is_parent-Flag
- DB-Migration V01.10 (idempotent via create_all)
- Geschaeftslogik tag.py: CRUD, Hierarchie-Aufbau, kaskadierendes Loeschen,
  Zirkelbezug-Pruefung
- REST-Endpunkte /xhr/tag/*: Lesen fuer Mitarbeiter, Schreiben fuer AppAdmin
- Client-Modell tag.ts mit REST-Funktionen
- Frontend tags.ts auf REST-API umgestellt, hartcodierte Daten entfernt,
  Loesch-Dialog mit kaskadierender Bestaetigung

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 14:08:34 +02:00
gg 675d7775c1 feat: oninput-Callback zum Input-Widget hinzugefügt
Ermöglicht ein Live-Binding der Eingabewerte, damit Eingaben bei einem
Redraw (z.B. durch interaktive Elemente außerhalb des Inputs) nicht
verloren gehen.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 14:07:30 +02:00
gg b44ea806ef feat(tags): is_parent-Flag zur Unterscheidung von Gruppierungs-Tags und zuordenbaren Tags
Parent-Tags (is_parent=true) dienen als Gruppierungsknoten und können nicht
Gesprächsnotizen zugeordnet werden. Echte Tags (is_parent=false) sind
zuordenbar. Die Bearbeitungsmaske bietet eine Checkbox für das Flag, die
Eltern-Auswahl ist auf Parent-Tags beschränkt. Die Tag-Liste zeigt
Parent-Tags mit Folder-Icon, echte Tags mit Label-Icon. Die Suche filtert
den gesamten Teilbaum — nur Knoten mit Self-Match oder einem matchenden
Nachfahren werden angezeigt.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 10:40:39 +02:00
ggandMistral Vibe 3361ef16dd feat: Treetable filter auf Kind-Knoten anwenden
Der filter-Callback wird jetzt auch auf Kind-Knoten angewendet, nicht nur auf Top-Level-Nodes. Dadurch lässt sich bei hierarchischen Daten (z.B. Tag-Baum) die Suche auf den gesamten Teilbaum verfeinern — nur Knoten, die selbst matchen oder einen matchenden Nachfahren haben, werden gerendert.

Abwärtskompatibel: Aufrufer ohne filter-Attribut sind unaffected.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-19 10:39:11 +02:00
br 947f299543 ignore ergänzt, continue (vscode ai plugin) hat noch eine context erhalten. 2026-09-17 14:16:38 +02:00
gg 44c411e5d7 fix(crm): DB-Migrationen idempotent machen für Neuinstallationen
Bei Neuinstallation erzeugt create_all bereits das gesamte Schema,
so dass nachfolgende ALTER-Table-Migrationen fehlschlagen ("duplicate
column name"). V01_04 prüft nun die Spalten-Existenz per PRAGMA
table_info. checkupdates läuft wieder sequentiell ohne Überspringen.
Konvention in AGENTS.md dokumentiert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-15 17:36:52 +02:00
gg efef212544 feat(deploy): Image-Promotion, deploy.env, Health-Check-Fix und Anleitungen
- Deploy-Scripts: Image-Promotion statt Rebuild (docker tag + up -d),
  deploy.env fuer Server-Konfiguration, -p fuer Projekt-Namen,
  Health-Check mit Host-Header und /xhr/health-check
- docker-compose.prod.yaml: name-Feld entfernt (Projekt-Name per -p)
- deploy.env.example als Vorlage hinzugefuegt
- .vibe/skills/client-build/SKILL.md aus Git-Index entfernt (gitignore)
- Deployment-Anleitung: Zugangsdaten, deploy.env, Image-Promotion,
  prod ohne eigenes Repo, git-clone-Hinweis, Log-Befehle mit -p
- Deploy-lokal-testen.md: neue Anleitung fuer lokales Testen

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-15 17:10:18 +02:00
gg e824b545bb docs(agents): Begründung für user_id-Parameter ergänzt und Formulierungen korrigiert
Ergänzt eine kurze Begründung, warum user_id als Parameter an Modell-Funktionen
übergeben wird statt current_user direkt im Modell zu lesen. Zudem kleinere
Korrekturen an Tippfehlern, Pfadangaben und Formulierungen in den
TypeScript/Mithril-Vorgaben.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-14 10:06:11 +02:00
gg bde45871f6 Merge feature/auto-deploy: automatisches Deployment und Start-Meldungen 2026-09-13 20:08:24 +02:00
gg 4015f83ba0 chore(runserver): Start-Meldungen fuer Server-Typ ergaenzt
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 20:08:12 +02:00
gg fffa9d4a28 docs(deploy): Multi-Stage-Build korrekt beschrieben, SSL-Variablen-Hinweis ergaenzt
Die Deploy-Anleitung sagte irrefuehrend "gesamter Code (Python + TypeScript)" im Image. Korrigiert auf den tatsaechlichen Multi-Stage-Build: nur das fertige JS-Bundle landet im NGINX-Image, nicht der TS-Quellcode. Zussaetzlich Hinweis in env-sample und Deployment-Anleitung, dass NGINX_CERTS/CERT/CERT_KEY auch bei SSL=false nicht geloescht werden duerfen, da docker-compose.base.yaml sie immer als Volume/Env bindet.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 19:47:42 +02:00
gg b268b301c1 docs(deploy): COMPOSE_FILE-Beschreibung um BUILD_ENVIRONMENT-Bezug ergaenzt
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 19:30:09 +02:00
gg 40ad0e1ba9 refactor(deploy): Image-Versionen fest in Dockerfiles verankern
ARG-Variablen durch feste Werte in FROM ersetzt — nicht per .env
ueberschreibbar. PYTHON_VERSION, NODE_VERSION, NPM_VERSION,
NGINX_VERSION aus .env, env-sample und Compose-Dateien entfernt.
Deployment-Anleitung erstellt und entsprechend angepasst.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 19:12:14 +02:00
gg 3b3e2893e5 feat(deploy): Multi-Stage-Docker-Build fuer automatisches Deployment
- App_Server/Dockerfile: Build-Context auf Repo-Root, COPY-Pfade
  angepasst, ENTRYPOINT aktiviert, dev-Stage mit inittypescriptdev.sh
- NGINX_Server/Dockerfile: Multi-Stage mit frontend-Stage (Node.js baut
  TypeScript), statische Dateien und Config-Templates ins Image kopiert
- docker-compose.base.yaml: Context auf '.', python-venv Volume entfernt,
  NGINX_STATIC_DIR/CONFIG_TEMPLATE_DIR bind-mounts in Dev verschoben
- docker-compose.dev.yaml: python-venv-dev Volume, APP_DEBUG=true,
  nginx-proxy mit bind-mounts fuer statische Dateien und Templates
- docker-compose.prod.yaml: Code-bind-mount entfernt, nginx-proxy extends
- approot.py: absolute Pfade, Debug-Modus via APP_DEBUG Umgebungsvariable
- init.sh: vereinfacht (kein cd/pip, absolute Pfade)
- inireader.mjs: absoluter Pfad fuer config.ini
- package.json: scripts.build (tsc + rollup) ergaenzt
- .dockerignore, deploy-kbcrm-test.sh, deploy-kbcrm-prod.sh erstellt
- docker-compose.save.yaml geloescht
- env-sample: BUILD_ENVIRONMENT nach oben, Dev-only Variablen markiert

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 18:40:55 +02:00
gg 31ef206bd8 docs(env): Kommentare in env-sample verdeutlichen
NGINX_USE_SSL: Inline-Kommentar durch Block-Kommentar ersetzt,
der Port-Abhaengigkeit bei SSL-Deaktivierung erlaeutert.
COMPOSE_FILE: Einzeiligen Kommentar durch Block-Kommentar ersetzt,
der Bedeutung und Anwendung von COMPOSE_FILE erklaert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-12 15:48:13 +02:00
gg b1795e2f41 Merge origin/main: revert 96c9cea und c1c92d1, behalte bdb4329 (OIDC/Email-Settings)
- 96c9cea (deploy-Prozess-Aenderungen) vollstaendig revertiert:
  lokale Versionen von .gitignore, NGINX_Server/Dockerfile,
  docker-compose.base.yaml, docker-compose.dev.yaml beibehalten,
  App_Server/Dockerfile auf Stand vor 96c9cea zurueckgesetzt.
- c1c92d1 (env-raus) revertiert: lokale env-sample als Basis,
  .env aus Tracking entfernt (bereits in .gitignore).
- bdb4329 behalten: OIDC/Email-Block an lokale env-sample angehaengt.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-12 15:30:09 +02:00
gg 9ee0433c4d feat(auth): Logout-Meldung 1 Sekunde anzeigen vor Weiterleitung
Dedizierte loggedout-Komponente für die Abmeldebestätigung und
Redirect um 1 Sekunde verzögert, damit die Meldung sichtbar bleibt.
Default-Route auf /kundenliste korrigiert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-11 16:53:54 +02:00
gg 55d03ddeb3 chore: env-sample als Konfigurationsvorlage hinzufügen und .env ignorieren
.env-Dateien mit echten credentials ab sofort über .gitignore ausgeschlossen;
env-sample als kopierbare Vorlage für NGINX-, Python- und Dev-Parameter eingecheckt.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-11 16:40:06 +02:00
gg b6268f7d22 chore(dev): Vibe-Code-Setup in Devcontainer, docker-compose und .gitignore integrieren
- .devcontainer: mistralai.mistral-vibe-code Extension hinzugefügt
- docker-compose.dev: VIBE_HOME auf /usr/opt/pythonapp/.vibe-global gesetzt
- .gitignore: .vibe/ und .vibe-global/ ignoriert, Pfad-Slashes normalisiert

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-11 16:33:08 +02:00
br bdb4329240 oidc sample
compose stack files in .env
2026-09-11 15:15:44 +02:00
br 96c9ceafc1 kleinigkeiten für deploy prozess... 2026-09-11 15:01:51 +02:00
gg ef563bad2f NGINX: Dynamische SSL-Konfiguration über Umgebungsvariable
- Aufteilung des NGINX-Templates in kbp_crm.nossl.conf.template (ohne SSL)
  und kbp_crm.ssl.conf.template (mit SSL)
- Neues Skript 10-select-ssl.sh wählt Template zur Laufzeit basierend auf
  NGINX_USE_SSL (true/false)
- Dockerfile: Vorbereitung für dynamische Template-Auswahl
- docker-compose: Template-Verzeichnis auf /etc/nginx/configtemplates geändert,
  NGINX_USE_SSL als Umgebungsvariable hinzugefügt
- .env: NGINX_USE_SSL=true standardmäßig aktiviert

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-11 14:52:08 +02:00
gg a6876fcc55 oidc-test Verzeichnis zu .gitignore hinzugefuegt
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-11 13:48:08 +02:00
br c1c92d1169 env-raus 2026-09-11 12:14:23 +02:00
gg 9ed5e88e01 Menü Projekt-Berechtigungen, Übersichtssichten und AppAdmin-Erkennung
- Menü: Dropdown "Projekt-Berechtigungen" unter Optionen mit
  Unterpunkten "Projekt-Zugriffe" und "Nutzer-Zugriffe" (nur SysAdmin/AppAdmin)
- AppAdmin-Erkennung: Server liefert isAppAdmin-Flag im Login- und
  getusers-Response (applikationsspezifisch via has_permission)
- Login: CurrentUserIsAppAdmin in sessionStorage speichern/entfernen
- Projekt-Zugriffe: geschachtelter Treetable (Projekt → Nutzer) als
  reine Anzeige, Detail-Sicht aus Projekt-Maske mit Bearbeitung
- Nutzer-Zugriffe: neue Komponente user_projektliste.ts, geschachtelter
  Treetable (Nutzer → Projekte), reine Anzeige
- Server: neuer Endpunkt GET /xhr/projektuser/listall (nur AppAdmin/SysAdmin)
- Server: get_all_projekt_users() mit Batch-Query für Projekte und User
- Treetable-Widget: Platzhalter-Pfeil bei kinderlosen Nodes nur wenn
  Geschwister mit Kindern existieren (hasSiblingsWithChildren)
- Datei projekt_user.ts umbenannt in projekt_userliste.ts (konsistent
  mit user_projektliste.ts)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-07 16:04:06 +02:00
gg 505177b5e2 ProjektUser-Modal: Mehrfachauswahl, Filterung und Fehlermeldungs-Verbesserung
- Modal von Einzelauswahl (Select) auf Mehrfachauswahl mit Checkboxen umgestellt
- Nutzerliste sortiert nach username, scrollbar (eine Zeile pro Nutzer)
- SysAdmin und AppAdmin aus der Auswahlliste ausgeblendet (immer Zugriff)
- Bereits zugeordnete Nutzer ausgeblendet
- Fehleranzeige bei fehlender Rolle: closeModal im catch entfernt,
  sodass showServerError nicht sofort überschrieben wird
- AutorisationError: Meldung "Erforderliche Rollen" nur bei nicht-leerer
  allowed_roles-Liste (entfällt bei @authorisation_required([]))

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-05 16:14:13 +02:00
gg 4cb0084066 Projekt-Sichtbarkeit: Nutzer-Zuordnung, projektbezogene Filterung und Schreibschutz
- Neues Modell ProjektUser (projekt_users) für projektbezogene Sichtbarkeit
- Migration V01_09 legt Tabelle an (keine Initial-Befüllung)
- CRUD-Logik für Projekt-User-Zuordnungen mit Cross-DB-User-Auflösung
- Serverseitige Sichtbarkeits-Filterung: Projekt-Liste/Get filtert nach
  projekt_users-Zuordnung für Nicht-SysAdmin/Nicht-AppAdmin
- Auto-Assignment: Ersteller wird bei Projektanlage automatisch zugeordnet
- Sichtbarkeits-Filterung auf CallLog und Kontaktadresse erweitert
  (Liste und Einzelabruf)
- Schreibschutz: Alle Schreib-Endpunkte (update/delete) für Projekt,
  Kontaktadresse und CallLog prüfen Projekt-Zuordnung vor der Ausführung
- Hilfsfunktionen _get_visible_user_id() und _require_projekt_access()
  zur Kapselung der wiederkehrenden Prüfungen
- REST-Endpunkte /xhr/projektuser/{list,add,remove};
  Schreib-Endpunkte mit @authorisation_required([]) als Erweiterungspunkt
- Client: Neues Modell projekt_user.ts, Listen-Komponente mit Modal
  (Select-Widget), Button in Projekt-Maske, Route registriert
- Build aktualisiert (tsc + rollup)
- AGENTS.md: Vorgaben für projektbezogene Sichtbarkeit dokumentiert

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-05 15:45:32 +02:00
gg b2f8684afb Fehlerbehandlung für REST-Aufrufe in allen CRM-Komponenten und Konvention in AGENTS.md
Alle m.request-Aufrufe in den CRM-Komponenten (kunde, kontakt, projekt,
kontaktadresse, call_log) erhalten .catch(showServerError), sodass
Serverfehler wie 401 (fehlende Autorisierung) dem Nutzer als Modal
angezeigt werden. Die Navigation bleibt im .then-Zweig, damit sie bei
Fehler nicht ausgeführt wird. AGENTS.md erhält die entsprechende
Konvention für zukünftige REST-Aufrufe.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-05 14:29:23 +02:00
gg 461953a7e9 Datumsspalten auf Date-Typ umgestellt und Normalisierungsmigration
Modelle: startdatum (Projekt), datum und wiedervorlage_datum (CallLog)
von String(20) auf Date umgestellt. columns2dict serialisiert diese nun
über isoformat() als yyyy-MM-dd. Die String-Normalisierung in
columns2dict wurde entfernt, da sie nicht mehr benötigt wird.

Migration V01.08: Normalisiert bestehende String-Datumswerte (z.B.
'2026-08-3') auf ISO-Format yyyy-MM-dd mittels printf/substr, da
SQLite's date() einstellige Komponenten nicht erkennt. Leere Strings
werden zu NULL. V01.07 ist Platzhalter für die fehlgeschlagene V01.06.

Client: toDateInputValue normalisiert ebenfalls String-Datumswerte
als Fallback für Route-Params (Neuanlage).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-04 16:57:17 +02:00
gg 93827dde0f Serverseitige Filterung für Listen-Endpunkte und Einzelabrufe in Listen-Komponenten
Server: Die list-Endpunkte für Kontakt, Projekt, Kontaktadresse und CallLog
akzeptieren nun einen optionalen Query-Parameter (kunden_id bzw. projekt_id)
und filtern im ORM-Query. Neue Migration V01.05 legt Indizes auf den
FK-Spalten an.

Client: Die fetch-Funktionen erhalten einen optionalen Parent-ID-Parameter.
Die Listen-Komponenten übergeben die Parent-ID aus den Route-Params an den
Server und laden nur noch benötigte Daten. Statt kompletter Eltern-Listen
wird per fetchXxxById ein einzelner Datensatz für die Namensauflösung geladen.
Die CallLog-Bearbeitungsmaske behält ihre ungesfilterten Dropdown-Abrufe.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-04 15:43:43 +02:00
gg e9a2f48ede Kontaktadresse: Neues Feld Position, Filter-Funktionen null-sicher, Projektnamen-Spalte entfernt
- Server: Neue Spalte position in Kontaktadresse-Modell (String(200), nullable)
- Server: Migration V01_04 (ALTER TABLE kontaktadressen ADD COLUMN position)
- Server: position in Geschäftslogik create/update aufgenommen
- Server: CLI-Musterdaten um Position ergänzt (Geschäftsführer, IT-Leiter etc.)
- Client: position in iKontaktadresse-Interface, View nach Firma, Columnmapper, Filter
- Client: Projektnamen-Spalte aus Kontaktadressenliste entfernt (steht in Überschrift)
- Client: Filter-Funktionen in allen Listen null-sicher (kunde, kontakt, projekt, kontaktadresse, call_log)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-04 14:58:52 +02:00
gg b510c50497 Server+Client: REST-API für Kontaktadresse und CallLog, In-Memory vollständig entfernt, CLI-Musterdaten, Route-Param-Fix
- Server: ORM-Modelle Kontaktadresse (kontaktadressen) und CallLog (call_logs) mit FK projekt_id
- Server: Geschäftslogik kontaktadresse.py und call_log.py (get/create/update/delete)
- Server: DB-Migration V01_03 (kontaktadressen + call_logs Tabellen)
- Server: REST-Endpunkte /xhr/kontaktadresse/* und /xhr/calllog/* mit Autorisierung
- Server: CLI init-db legt Muster-Kontaktadressen (1-3/Projekt) und Muster-Gesprächsnotizen (2-5/Projekt) an
- Client: kontaktadresse.ts auf REST umgestellt, snake_case, In-Memory entfernt
- Client: call_log.ts auf REST umgestellt, snake_case, In-Memory entfernt, Submit-Handler implementiert
- Client: projekt.ts In-Memory vollständig entfernt (keine weiteren Verbraucher)
- Client: Route-Params projektId → projekt_id korrigiert (3 Stellen in projekt.ts)
- Client: addCallLog in projekt.ts Route-Params auf snake_case angepasst
- AGENTS.md: Erinnerung client-build-Skill nach .ts-Änderungen hinzugefügt

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-04 12:35:07 +02:00