diff --git a/src/components/flow/detail-panel.tsx b/src/components/flow/detail-panel.tsx index 46f5824..e93a1ad 100644 --- a/src/components/flow/detail-panel.tsx +++ b/src/components/flow/detail-panel.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useParams } from "next/navigation"; import { Copy, Trash2, Lock, Info } from "lucide-react"; import { useFlowStore } from "@/stores/flow-store"; @@ -122,6 +122,13 @@ export function DetailPanel() { ? nodes.find((n) => n.id === selectedNodeId) : null; + const storeKey = (selectedNode?.data as { componentKey?: string })?.componentKey ?? ""; + const [displayKey, setDisplayKey] = useState(storeKey); + + useEffect(() => { + setDisplayKey(storeKey); + }, [storeKey]); + const upstream = useMemo( () => selectedNodeId @@ -140,12 +147,21 @@ export function DetailPanel() { ); const handleKeyChange = useCallback( - (key: string) => { + (raw: string) => { if (selectedNodeId) { - updateNodeKey(selectedNodeId, key); + const sanitized = raw + .replace(/\s+/g, "_") + .replace(/[^a-zA-Z0-9_]/g, "") + .replace(/^(\d+)/, "_$1"); + if (sanitized) { + setDisplayKey(raw); + updateNodeKey(selectedNodeId, sanitized); + } else { + setDisplayKey(storeKey); + } } }, - [selectedNodeId, updateNodeKey], + [selectedNodeId, updateNodeKey, storeKey], ); const handleDelete = useCallback(() => { @@ -262,10 +278,13 @@ export function DetailPanel() { handleKeyChange(e.target.value)} disabled={isSystemLocked} /> +
+ Letters, numbers, and underscores only (e.g. traefik_logs) +
{/* Enabled toggle */}