feat(nextcloud-status): Kundenname voll ausgeschrieben, Kachel-Knoepfe in die Fusszeile
Tessera CI/CD / Lint & Type Check (push) Successful in 57s
Tessera CI/CD / Tests (push) Successful in 1m45s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 21s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m47s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-08 15:57:02 +02:00
parent ff4938fa97
commit 83b842b72c
2 changed files with 64 additions and 63 deletions
@@ -98,9 +98,69 @@ export function CloudTile({
)}
</div>
<div className="min-w-0 flex-1">
<div className="truncate font-semibold leading-tight" title={instance.customerName}>
{instance.customerName}
</div>
<div className="break-words font-semibold leading-tight">{instance.customerName}</div>
</div>
</div>
{/* Adresse in voller Laenge auf eigener Zeile — bricht notfalls um statt abgeschnitten zu werden. */}
<a
href={instance.baseUrl}
target="_blank"
rel="noopener noreferrer"
className="block break-all text-xs text-muted-foreground underline-offset-2 hover:underline"
title={t('card.openCloud')}
>
{instance.baseUrl}
</a>
<div className="flex flex-wrap items-center justify-between gap-x-2 gap-y-1">
<span
data-testid="rating-pill"
className={`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${style.pill}`}
>
<span aria-hidden="true" className={`h-1.5 w-1.5 rounded-full ${style.fill}`} />
{reason}
</span>
<span className="text-xs text-muted-foreground">
{t('card.version')}:{' '}
<span className="font-medium tabular-nums text-foreground">
{instance.status.versionString ?? t('card.versionUnknown')}
</span>
</span>
</div>
{hintText && (
<p
data-testid="error-hint"
className="break-words text-xs text-muted-foreground"
title={hintRaw}
>
{hintText}
</p>
)}
{instance.status.pendingRetry === true && (
<p
data-testid="pending-retry"
className="flex items-center gap-1.5 text-xs text-muted-foreground"
>
<span aria-hidden="true" className="h-1.5 w-1.5 shrink-0 rounded-full bg-status-warn" />
{t('card.pendingRetry')}
</p>
)}
{/* Fusszeile: Pruefzeitpunkt links, Knoepfe rechts — der Kopf bleibt dem vollen Kundennamen. */}
<div className="mt-auto flex items-center justify-between gap-2">
<div
data-testid="last-check"
className="min-w-0 text-xs text-muted-foreground"
title={
instance.status.checkedAt
? new Date(instance.status.checkedAt).toLocaleString(locale)
: undefined
}
>
{checkedAge ? t('card.lastCheck', { age: checkedAge }) : t('card.neverChecked')}
</div>
<div className="flex shrink-0 items-center gap-1">
<button
@@ -183,65 +243,6 @@ export function CloudTile({
)}
</div>
</div>
{/* Adresse in voller Laenge auf eigener Zeile — bricht notfalls um statt abgeschnitten zu werden. */}
<a
href={instance.baseUrl}
target="_blank"
rel="noopener noreferrer"
className="block break-all text-xs text-muted-foreground underline-offset-2 hover:underline"
title={t('card.openCloud')}
>
{instance.baseUrl}
</a>
<div className="flex flex-wrap items-center justify-between gap-x-2 gap-y-1">
<span
data-testid="rating-pill"
className={`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${style.pill}`}
>
<span aria-hidden="true" className={`h-1.5 w-1.5 rounded-full ${style.fill}`} />
{reason}
</span>
<span className="text-xs text-muted-foreground">
{t('card.version')}:{' '}
<span className="font-medium tabular-nums text-foreground">
{instance.status.versionString ?? t('card.versionUnknown')}
</span>
</span>
</div>
{hintText && (
<p
data-testid="error-hint"
className="break-words text-xs text-muted-foreground"
title={hintRaw}
>
{hintText}
</p>
)}
{instance.status.pendingRetry === true && (
<p
data-testid="pending-retry"
className="flex items-center gap-1.5 text-xs text-muted-foreground"
>
<span aria-hidden="true" className="h-1.5 w-1.5 shrink-0 rounded-full bg-status-warn" />
{t('card.pendingRetry')}
</p>
)}
<div
data-testid="last-check"
className="mt-auto text-xs text-muted-foreground"
title={
instance.status.checkedAt
? new Date(instance.status.checkedAt).toLocaleString(locale)
: undefined
}
>
{checkedAge ? t('card.lastCheck', { age: checkedAge }) : t('card.neverChecked')}
</div>
</div>
</article>
);