Buttons in sectionHeader (flex-direction: column) streckten sich auf
volle Containerbreite. align-self: flex-start begrenzt die Breite auf
min-width + Textinhalt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- darkenColor() Funktion: extrahierte Logo-Farbe um 30% abdunkeln
(gilt für PDF und DOCX Export) → kräftigerer, druckfreundlicher Ton
- ExpertProfileTab: min-width: 130px für btnPrimary und btnSecondary
→ alle Aktions-Buttons haben einheitliche Mindestbreite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PDF-Export: doc.flushPages() vor doc.end() verhindert leere
Schlussseite (PDFKit bufferPages-Bug nach Footer-Loop)
- ExpertProfileTab: height: 32px für btnPrimary/Secondary/Danger
sowie chipInput- und headerForm-Inputs → einheitliche Höhe
- Primärfarbe #1a56db → #1040bb (dunkler, besser zum Logo passend)
- LoginPage CSS-Fallback-Gradient ebenfalls auf neue Primärfarbe
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PDF-Export: alle Anhänge als zusätzliche Seiten (Bilder als Vorschau, andere mit Hinweis)
- DOCX-Export: Bild-Anhänge als zusätzliche Sections (je eine Seite pro Bild)
- ExpertProfileTab: Skills/Sprachen/Erfahrungen nebeneinander (3 Spalten)
- ExpertProfileTab: Zertifizierungen und Profilanlagen nebeneinander (2 Spalten)
- threeColumnRow CSS-Klasse hinzugefügt (responsive auf 1 Spalte bei <900px)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neue Prisma-Modelle ProfileAccessGroup + ProfileAccessGroupMember mit canView/canExport/canEdit
- Manuelle Migration 20260314_profile_access_groups
- ProfileAccessModule: CRUD-Endpoints für Gruppen und Mitglieder (nur PLATFORM_ADMIN)
- Neue Admin-Endpoints in ExpertProfileService/-Controller für alle Profil-Mutationen
- verifyOwnership mit skipCheck-Parameter für Admin-Bypass
- ExpertProfileTab + alle Section-Komponenten erhalten apiBase-Prop für Wiederverwendung
- AdminProfileAccessPage: Gruppen-Tab (CRUD) + Profile-Tab (alle User mit Aktionen)
- AdminProfileDetailPage: Profil eines beliebigen Users im Admin-Kontext bearbeiten
- Route /admin/profile-access + /admin/profiles/:userId + Nav-Tab Profilzugriff
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neue Funktion blLineAt() auf Modul-Ebene: parst Zeile an Cursor-Position
(Einrueckung, Bullet/Nummeriert, Zahl, Zeileninhalt) ohne Closure-Probleme
- Neuer Toolbar-Button "1. Liste": toggled nummerierte Liste (1./2./3.);
wandelt Bullet→Nummeriert und Nummeriert→Bullet automatisch um
- Tab-Taste: fuegt 2 Leerzeichen am Zeilenanfang ein (Einrueckung)
- Shift+Tab: entfernt bis zu 2 Leerzeichen (Ausrueckung)
- Enter in nummerierter Liste: setzt naechste Zeile mit N+1 fort
- Enter auf leerem Listenelement: beendet die Liste (Bullet + Nummeriert)
- Enter beruecksichtigt Einrueckung bei Bullets
- CSS: bulletToolbarSep (Trennlinie) + bulletToolbarHint (Keyboard-Hinweis)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Neue Felder im Benutzerprofil (analog Microsoft 365 /me):
- Stellenbezeichnung (jobTitle), Abteilung (department)
- Firma (companyName), Standort (officeLocation)
Changes:
- Core: Prisma-Migration + neue Felder in User-Model, UpdateUserDto,
findById/update/updateProfile
- CRM: M365UserProfile-Interface + getM365Profile um neue Felder erweitert;
neue Methode getM365Photo() lädt 96x96 JPEG als Base64 Data-URL;
neuer Endpoint GET /crm/office365/photo
- Frontend: AuthContext User-Interface, M365UserProfile-Typ, office365Api.getM365Photo()
ProfilePage: Neues Formular-Fieldset "Organisation" mit 4 Feldern;
manueller Sync-Button übernimmt auch Profilbild (immer überschreiben);
useO365ProfileSync: Auto-Sync lädt Foto nur wenn noch kein INSIGHT-Avatar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neuer Hook useO365ProfileSync: läuft einmalig pro Browser-Session,
überschreibt INSIGHT-Profil-Felder mit O365-Daten (firstName, lastName,
phone, mobile, city, street, postalCode) — kein UI-Feedback, kein Fehler
bricht die UX auf.
- AppLayout ruft useO365ProfileSync() auf, sodass die Synchronisation
beim Laden der App (nach Login) automatisch startet.
- ProfilePage: "↓ O365 übernehmen"-Button überschreibt jetzt alle Felder
wo O365 Daten hat (nicht mehr nur leere Felder) — konsistent mit dem
Auto-Sync-Verhalten.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neuer "Integrationen"-Tab in ProfilePage mit "Microsoft 365 verbinden"-
Button, OAuth-Callback-Handling (?integration=...&status=...), Trennen-Button
- EmailsTab, CalendarTab, TasksTab fuer ContactDetailPage (via MS Graph Proxy)
- useIntegrations, useDisconnectM365, useContactEmails/Calendar/Tasks Hooks
- integrationsApi + graphApi in crm/api.ts
- M365Email, M365CalendarEvent, M365Task, UserIntegration Types in crm/types.ts
- Tabs nur sichtbar wenn Kontakt eine E-Mail-Adresse hat; ohne Verbindung Connect-Button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Professional CV-style document generation using pdfkit (PDF) and docx (Word).
Two-column layout with avatar, contact info, languages on the left and work
experience timeline on the right. Skills rendered as chips. Accent color
configurable (default teal #009688) for later admin customization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Input fields now appear inline next to the section title, matching the
layout pattern used by Projects, Certifications and Attachments sections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-stack implementation of the Expert Profile tab with 6 sections:
- Skills (tag/chip UI with add/remove)
- Experience (area, years, optional level)
- Languages (language + proficiency level)
- Project History (modal form with dates, role, tasks, company details)
- Certifications (modal form with title, issuer, website, year)
- Attachments (file upload/download as Base64, max 10MB)
Backend: 15 API endpoints, 8 DTOs, full CRUD service with ownership verification.
Frontend: Reusable Modal component (React Portal), ExpertProfileTab orchestrator, 8 section components.
Database: 6 new tables (expert_profiles, expert_experiences, expert_languages, expert_projects, expert_certifications, expert_attachments).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add phone, mobile, street, postalCode, city fields to User model (Prisma + migration)
- Extend UpdateUserDto with validated contact/address fields
- Update UsersService (findById, update, updateProfile) for new fields
- Rename tab "Persönliche Informationen" to "Profil"
- New layout: avatar left column, form right column with fieldset groups
- Move 2FA section from always-visible into "Passwort ändern" tab
- Add orange 2FA warning badge next to page title (clickable → password tab)
- Add responsive CSS for mobile breakpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bug fix: include twoFactorEnabled in login response so ProfilePage
shows correct 2FA status after login (not always "Aktivieren")
- Bug fix: restructure 2FA enable/disable handlers to separate API call
from state updates, preventing false error messages on success
- New: avatar field in User model (Base64 data-URL in PostgreSQL TEXT)
- New: UserAvatar component with initials fallback
- New: client-side image resize to 200x200px before upload
- New: avatar upload/remove on ProfilePage with preview
- New: avatar display + "Zum Profil" hint in sidebar
- Increase JSON body size limit to 1mb for avatar uploads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- POST /auth/2fa/setup - generate TOTP secret + QR code (temp Redis storage)
- POST /auth/2fa/enable - verify TOTP code and activate 2FA
- POST /auth/2fa/disable - deactivate 2FA (requires password)
- PATCH /users/me - update own profile (firstName, lastName)
- POST /users/me/change-password - change own password
Frontend:
- New ProfilePage with 3 sections: personal info, password, 2FA
- QR code display for Authenticator app setup
- Clickable user info in sidebar navigates to /profile
- AuthContext extended with twoFactorEnabled + refreshUser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>