From 484b5f96fab108b03c2c2027a84f9ff3fc5408b5 Mon Sep 17 00:00:00 2001 From: Eduard Wisch Date: Tue, 19 May 2026 22:52:23 +0200 Subject: [PATCH] =?UTF-8?q?Ger=C3=A4te=20als=20Favoriten=20markieren=20und?= =?UTF-8?q?=20benennen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Favoriten-Stern je Gerät; favorisierte Geräte werden in der Liste oben einsortiert. Favorit + eigener Name bleiben im Protokoll erhalten, auch ohne gespeicherten Scan-Snapshot - Gerät umbenennen (customName) über neuen TextPromptDialog - toggleFavorite / renameDevice in protocols.ts - TextPromptDialog + ConfirmDialog: schlanke Modal-Komponenten als Ersatz für die verbotenen Browser-prompt()/confirm(); melden sich als Overlay an (Hardware-Backbutton schließt sie) - Protokoll-Löschen nutzt jetzt ConfirmDialog statt confirm() Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/components/ConfirmDialog.svelte | 56 +++++++++++++++++ src/lib/components/TextPromptDialog.svelte | 73 ++++++++++++++++++++++ src/lib/protocols.ts | 12 ++++ src/routes/protokoll/[id]/+page.svelte | 61 ++++++++++++++++-- 4 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 src/lib/components/ConfirmDialog.svelte create mode 100644 src/lib/components/TextPromptDialog.svelte diff --git a/src/lib/components/ConfirmDialog.svelte b/src/lib/components/ConfirmDialog.svelte new file mode 100644 index 0000000..5834553 --- /dev/null +++ b/src/lib/components/ConfirmDialog.svelte @@ -0,0 +1,56 @@ + + + diff --git a/src/lib/components/TextPromptDialog.svelte b/src/lib/components/TextPromptDialog.svelte new file mode 100644 index 0000000..b7dfec3 --- /dev/null +++ b/src/lib/components/TextPromptDialog.svelte @@ -0,0 +1,73 @@ + + + diff --git a/src/lib/protocols.ts b/src/lib/protocols.ts index 40828d1..a5946ee 100644 --- a/src/lib/protocols.ts +++ b/src/lib/protocols.ts @@ -61,6 +61,18 @@ export function upsertDevice( return created; } +/** Favoriten-Markierung eines Geräts umschalten */ +export function toggleFavorite(protocol: Protocol, clientId: string): void { + const d = protocol.devices.find((x) => x.clientId === clientId); + if (d) d.isFavorite = !d.isFavorite; +} + +/** Einem Gerät einen eigenen Namen geben (leerer Name = zurücksetzen) */ +export function renameDevice(protocol: Protocol, clientId: string, name: string): void { + const d = protocol.devices.find((x) => x.clientId === clientId); + if (d) d.customName = name.trim() || undefined; +} + /** Messung zum Protokoll hinzufügen */ export function addMeasurement( protocol: Protocol, diff --git a/src/routes/protokoll/[id]/+page.svelte b/src/routes/protokoll/[id]/+page.svelte index d388f0a..ce3c4c6 100644 --- a/src/routes/protokoll/[id]/+page.svelte +++ b/src/routes/protokoll/[id]/+page.svelte @@ -8,8 +8,10 @@ import ToolDialog from '$lib/components/ToolDialog.svelte'; import MeasurementResult from '$lib/components/MeasurementResult.svelte'; import DeviceCard from '$lib/components/DeviceCard.svelte'; + import TextPromptDialog from '$lib/components/TextPromptDialog.svelte'; + import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import { getProtocol, saveProtocol, deleteProtocol } from '$lib/db'; - import { addMeasurement, upsertDevice } from '$lib/protocols'; + import { addMeasurement, upsertDevice, toggleFavorite, renameDevice } from '$lib/protocols'; import { sync } from '$lib/sync.svelte'; import { toast } from '$lib/toast.svelte'; import { pushOverlay } from '$lib/overlay.svelte'; @@ -22,12 +24,21 @@ let activeTool = $state(null); let activeDevice = $state(undefined); let saving = $state(false); + let renameTarget = $state(null); + let confirmDelete = $state(false); let appStateListener: PluginListenerHandle | null = null; const protocolTools = TOOLS.filter((t) => t.scope === 'protocol'); const deviceTools = TOOLS.filter((t) => t.scope === 'device'); + /** Geräte mit Favoriten zuerst */ + const sortedDevices = $derived( + [...(protocol?.devices ?? [])].sort( + (a, b) => Number(b.isFavorite ?? false) - Number(a.isFavorite ?? false), + ), + ); + const ampel = ['ampel-ok', 'ampel-warn', 'ampel-fail']; const ampelDot = ['bg-emerald-500', 'bg-amber-400', 'bg-red-500']; @@ -127,9 +138,25 @@ ); } - async function removeProtocol() { + /** Favoriten-Stern eines Geräts umschalten */ + function doToggleFav(device: Device) { + if (!protocol) return; + toggleFavorite(protocol, device.clientId); + void persist(); + } + + /** Gerät umbenennen (aus dem Namens-Dialog) */ + function doRename(name: string) { + if (protocol && renameTarget) { + renameDevice(protocol, renameTarget.clientId, name); + void persist(); + } + renameTarget = null; + } + + async function doDelete() { + confirmDelete = false; if (!protocol) return; - if (!confirm('Dieses Protokoll wirklich löschen?')) return; await deleteProtocol(protocol.clientUuid); await sync.refreshPending(); goto('/auftraege/'); @@ -227,18 +254,20 @@ Noch keine Geräte — IP-Scanner ausführen, um das Netz zu erfassen.

{/if} - {#each protocol.devices as device (device.clientId)} + {#each sortedDevices as device (device.clientId)} openTool(tool, device)} + onfavorite={() => doToggleFav(device)} + onrename={() => (renameTarget = device)} /> {/each}
-
@@ -264,6 +293,28 @@ onrun={runTool} /> {/if} + + {#if renameTarget} + (renameTarget = null)} + /> + {/if} + + {#if confirmDelete} + (confirmDelete = false)} + /> + {/if} {:else}
Lädt …
{/if}