feat(profil): eigenes Profilbild hochladen
Jeder setzt sein Bild unter "Mein Konto", Vorgesetzte und Administratoren auch fuer die Benutzer, die sie verwalten. Wo bisher die Initialen standen, steht jetzt das Bild - Seitenleiste, Kopfzeile, Team, Dashboard, Reports, Projekte, Kunden und die Buchungsliste. Ohne Bild bleiben die Initialen. Der Browser verkleinert das Bild vor dem Hochladen auf ein Quadrat von 256 px und schneidet mittig zu (lib/imageCompress.ts): aus einem 4-MB-Foto werden wenige Kilobyte, und der Server muss kein Bild verarbeiten. Gespeichert wird es als Data-URL in pulse_users.avatar (LONGTEXT). Kein Upload-Verzeichnis, das gesichert und beim Deployment am Leben gehalten werden muesste. Geprueft wird serverseitig in lib/avatar.js: nur PNG, JPEG, GIF, WebP und AVIF als Data-URL, hoechstens 2 MB. SVG ist bewusst nicht erlaubt, es kann Skripte tragen. Externe http(s)-Adressen ebenso wenig - sonst laedt jeder Seitenaufruf ein Bild von einem fremden Server und verraet, wer wann mit Pulse arbeitet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2d3d843988
commit
9576d18abc
@@ -77,7 +77,7 @@ export const ReportTable: React.FC<{
|
||||
<td className="py-3 pl-4 pr-3">
|
||||
<div className="flex min-w-0 items-center gap-2.5">
|
||||
{kind === 'users' || kind === 'team' ? (
|
||||
<Avatar id={r.user_id} name={r.name} color={r.color} size={28} external={r.is_external} />
|
||||
<Avatar id={r.user_id} name={r.name} color={r.color} avatar={r.avatar} size={28} external={r.is_external} />
|
||||
) : kind !== 'tasks' ? (
|
||||
<span className="h-2.5 w-2.5 shrink-0 rounded-full" style={{ background: colorFor(r.customer_id ?? r.project_id ?? r.name, r.color) }} />
|
||||
) : null}
|
||||
|
||||
@@ -300,7 +300,7 @@ const UserEntriesDialog: React.FC<{
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-3 pb-4">
|
||||
<Avatar id={row.user_id} name={row.name} color={row.color} size={40} external={row.is_external} />
|
||||
<Avatar id={row.user_id} name={row.name} color={row.color} avatar={row.avatar} size={40} external={row.is_external} />
|
||||
<p className="text-sm font-semibold text-ink-500">
|
||||
{entries.data ? `${entries.data.length} Buchungen` : 'Lade Buchungen…'}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user