diff --git a/frontend/src/components/scripts/ScriptPreview.tsx b/frontend/src/components/scripts/ScriptPreview.tsx new file mode 100644 index 00000000..769c91db --- /dev/null +++ b/frontend/src/components/scripts/ScriptPreview.tsx @@ -0,0 +1,56 @@ +import { useState } from 'react' +import { Copy, Check } from 'lucide-react' +import { useScriptGeneratorStore } from '@/store/scriptGeneratorStore' +import { PowerShellHighlighter } from './PowerShellHighlighter' +import type { ScriptParametersSchema } from '@/types' + +export function ScriptPreview() { + const selectedTemplate = useScriptGeneratorStore(s => s.selectedTemplate) + const paramValues = useScriptGeneratorStore(s => s.paramValues) + const generatedScript = useScriptGeneratorStore(s => s.generatedScript) + const [copied, setCopied] = useState(false) + + if (!selectedTemplate) return null + + // Compute the displayed script + let displayScript: string + if (generatedScript !== null) { + displayScript = generatedScript + } else { + // Draft mode: client-side {{key}} substitution + const schema = selectedTemplate.parameters_schema as ScriptParametersSchema + const parameters = schema?.parameters ?? [] + displayScript = selectedTemplate.script_body + for (const param of parameters) { + const placeholder = `{{${param.key}}}` + const replacement = param.sensitive + ? '****' + : (paramValues[param.key] ?? '') + displayScript = displayScript.replaceAll(placeholder, replacement || placeholder) + } + } + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(displayScript) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } catch { + // silently fail — no error displayed + } + } + + return ( +
+ + +
+ ) +}