generated from Dicken/dickendock
round15: manuelle Aenderungen nicht mehr nachfragen, 7-Tage-Schwelle fuer verschwundene Geraete, Icon-Buttons mit Tooltip, fixierte mobile Kopfleiste, Scroll-to-top-Button
This commit is contained in:
@@ -162,12 +162,8 @@ function EditDeviceForm({ device, onDone }: { device: DeviceWithServices; onDone
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="primary" onClick={() => mutation.mutate()} disabled={mutation.isPending}>
|
||||
Speichern
|
||||
</Button>
|
||||
<Button size="sm" variant="ghost" onClick={onDone}>
|
||||
Abbrechen
|
||||
</Button>
|
||||
<Button size="icon" variant="primary" onClick={() => mutation.mutate()} disabled={mutation.isPending} title="Speichern" aria-label="Speichern">💾</Button>
|
||||
<Button size="icon" variant="ghost" onClick={onDone} title="Abbrechen" aria-label="Abbrechen">✕</Button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -203,59 +199,36 @@ function NameChangesReview({
|
||||
|
||||
const fieldLabel = (field: ScanNameChange["field"]) =>
|
||||
field === "displayName" ? "Name" : "Kategorie";
|
||||
const manual = remaining.filter((c) => c.manualOverride);
|
||||
const real = remaining.filter((c) => !c.manualOverride);
|
||||
|
||||
function renderList(list: ScanNameChange[]) {
|
||||
return (
|
||||
return (
|
||||
<div className="mt-2 rounded-xl border border-blue-500/30 bg-blue-500/5 p-3 text-xs">
|
||||
<p className="mb-2 font-medium text-blue-700 dark:text-blue-400">
|
||||
{remaining.length} erkannte Änderung(en) weichen vom gespeicherten Wert ab:
|
||||
</p>
|
||||
<ul className="space-y-1">
|
||||
{list.map((c) => (
|
||||
{remaining.map((c) => (
|
||||
<li key={`${c.serviceId}:${c.field}`} className="flex items-center justify-between gap-2">
|
||||
<span className="text-black/70 dark:text-white/70">
|
||||
{c.serviceHostname}:{c.servicePort} – {fieldLabel(c.field)}: „{c.current ?? "–"}" → „{c.suggested}"
|
||||
</span>
|
||||
<div className="flex gap-1">
|
||||
<Button
|
||||
size="sm"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
onClick={() => setHandled((prev) => new Set(prev).add(`${c.serviceId}:${c.field}`))}
|
||||
>
|
||||
Behalten
|
||||
</Button>
|
||||
title="Behalten (Vorschlag verwerfen)"
|
||||
aria-label="Behalten (Vorschlag verwerfen)"
|
||||
>✕</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
size="icon"
|
||||
variant="primary"
|
||||
onClick={() => applyMutation.mutate(c)}
|
||||
disabled={applyMutation.isPending}
|
||||
>
|
||||
Übernehmen
|
||||
</Button>
|
||||
disabled={applyMutation.isPending} title="Übernehmen" aria-label="Übernehmen">✓</Button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-2 space-y-2">
|
||||
{real.length > 0 ? (
|
||||
<div className="rounded-xl border border-blue-500/30 bg-blue-500/5 p-3 text-xs">
|
||||
<p className="mb-2 font-medium text-blue-700 dark:text-blue-400">
|
||||
{real.length} erkannte Änderung(en) weichen vom gespeicherten Wert ab:
|
||||
</p>
|
||||
{renderList(real)}
|
||||
</div>
|
||||
) : null}
|
||||
{manual.length > 0 ? (
|
||||
<div className="rounded-xl border border-black/10 bg-black/[0.02] p-3 text-xs dark:border-white/10 dark:bg-white/[0.02]">
|
||||
<p className="mb-2 font-medium text-black/60 dark:text-white/60">
|
||||
{manual.length} Abweichung(en), weil du diesen Wert bereits manuell angepasst hast:
|
||||
</p>
|
||||
{renderList(manual)}
|
||||
</div>
|
||||
) : null}
|
||||
<button onClick={onDone} className="text-black/40 underline dark:text-white/40">
|
||||
<button onClick={onDone} className="mt-2 text-black/40 underline dark:text-white/40">
|
||||
Hinweis schließen
|
||||
</button>
|
||||
</div>
|
||||
@@ -288,12 +261,8 @@ function DeviceNameSuggestionBanner({
|
||||
Per Reverse-DNS gefunden: „{suggestion}" als Gerätename?
|
||||
</span>
|
||||
<div className="flex gap-1">
|
||||
<Button size="sm" variant="ghost" onClick={onDone}>
|
||||
Behalten
|
||||
</Button>
|
||||
<Button size="sm" variant="primary" onClick={() => applyMutation.mutate()} disabled={applyMutation.isPending}>
|
||||
Übernehmen
|
||||
</Button>
|
||||
<Button size="icon" variant="ghost" onClick={onDone} title="Behalten (Vorschlag verwerfen)" aria-label="Behalten (Vorschlag verwerfen)">✕</Button>
|
||||
<Button size="icon" variant="primary" onClick={() => applyMutation.mutate()} disabled={applyMutation.isPending} title="Übernehmen" aria-label="Übernehmen">✓</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -327,17 +296,12 @@ function StaleServicesReview({ staleServices, onDone }: { staleServices: Service
|
||||
{s.displayName} ({s.hostname}:{s.port})
|
||||
</span>
|
||||
<div className="flex gap-1">
|
||||
<Button size="sm" variant="ghost" onClick={() => setHandled((prev) => new Set(prev).add(s.id))}>
|
||||
Behalten
|
||||
</Button>
|
||||
<Button size="icon" variant="ghost" onClick={() => setHandled((prev) => new Set(prev).add(s.id))} title="Behalten (Vorschlag verwerfen)" aria-label="Behalten (Vorschlag verwerfen)">✕</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
size="icon"
|
||||
variant="danger"
|
||||
onClick={() => deleteMutation.mutate(s.id)}
|
||||
disabled={deleteMutation.isPending}
|
||||
>
|
||||
Entfernen
|
||||
</Button>
|
||||
disabled={deleteMutation.isPending} title="Entfernen" aria-label="Entfernen">🗑️</Button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
@@ -424,9 +388,7 @@ function DeviceRow({ device }: { device: DeviceWithServices }) {
|
||||
<td className="px-4 py-3 text-black/60 dark:text-white/60">{device.services.length}</td>
|
||||
<td className="px-4 py-3">
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Button size="sm" onClick={() => setEditing(true)}>
|
||||
Bearbeiten
|
||||
</Button>
|
||||
<Button size="icon" onClick={() => setEditing(true)} title="Bearbeiten" aria-label="Bearbeiten">✏️</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
@@ -438,13 +400,10 @@ function DeviceRow({ device }: { device: DeviceWithServices }) {
|
||||
{scanMutation.isPending ? "Scanne …" : "Jetzt scannen"}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
size="icon"
|
||||
variant="danger"
|
||||
onClick={() => deleteMutation.mutate()}
|
||||
disabled={deleteMutation.isPending}
|
||||
>
|
||||
Löschen
|
||||
</Button>
|
||||
disabled={deleteMutation.isPending} title="Löschen" aria-label="Löschen">🗑️</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user