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 @@
+
+
+ {
+ if (e.target === e.currentTarget) oncancel();
+ }}
+>
+
+
{title}
+ {#if message}
{message}
{/if}
+
+
+
+
+
+
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 @@
+
+
+ {
+ if (e.target === e.currentTarget) oncancel();
+ }}
+>
+
+
{title}
+ {#if label}
+
+ {/if}
+
+
{
+ if (e.key === 'Enter') onsubmit(text.trim());
+ }}
+ />
+
+
+
+
+
+
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}