From 8cadc5b1b37e944d563614b62fef74c8af4d093b Mon Sep 17 00:00:00 2001 From: chihlasm Date: Fri, 13 Mar 2026 02:37:15 -0400 Subject: [PATCH] feat: add ScriptGeneratorPanel with permission gating Co-Authored-By: Claude Sonnet 4.6 --- .../scripts/ScriptGeneratorPanel.tsx | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 frontend/src/components/scripts/ScriptGeneratorPanel.tsx diff --git a/frontend/src/components/scripts/ScriptGeneratorPanel.tsx b/frontend/src/components/scripts/ScriptGeneratorPanel.tsx new file mode 100644 index 00000000..b7122ecd --- /dev/null +++ b/frontend/src/components/scripts/ScriptGeneratorPanel.tsx @@ -0,0 +1,113 @@ +import { Terminal, Download, Loader2, AlertTriangle } from 'lucide-react' +import { useScriptGeneratorStore } from '@/store/scriptGeneratorStore' +import { usePermissions } from '@/hooks/usePermissions' +import { ScriptParameterForm } from './ScriptParameterForm' +import { ScriptPreview } from './ScriptPreview' + +export function ScriptGeneratorPanel() { + const selectedTemplate = useScriptGeneratorStore(s => s.selectedTemplate) + const isLoadingDetail = useScriptGeneratorStore(s => s.isLoadingDetail) + const generatedScript = useScriptGeneratorStore(s => s.generatedScript) + const generationWarnings = useScriptGeneratorStore(s => s.generationWarnings) + const isGenerating = useScriptGeneratorStore(s => s.isGenerating) + const generateError = useScriptGeneratorStore(s => s.generateError) + const generate = useScriptGeneratorStore(s => s.generate) + + const { isEngineer } = usePermissions() + const canGenerate = isEngineer + + // No template selected + if (!selectedTemplate && !isLoadingDetail) { + return ( +
+ +

Select a template to get started

+
+ ) + } + + // Loading template detail + if (isLoadingDetail) { + return ( +
+ +
+ ) + } + + if (!selectedTemplate) return null + + const handleDownload = () => { + if (!generatedScript) return + const blob = new Blob([generatedScript], { type: 'text/plain' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `${selectedTemplate.slug}.ps1` + a.click() + URL.revokeObjectURL(url) + } + + return ( +
+ {/* Header */} +
+

{selectedTemplate.name}

+ {selectedTemplate.description && ( +

{selectedTemplate.description}

+ )} +
+ + {/* Parameter form */} + + + {/* Warnings */} + {generationWarnings.length > 0 && ( +
+
+ + Warnings +
+ {generationWarnings.map((w, i) => ( +

{w}

+ ))} +
+ )} + + {/* Preview */} + + + {/* Action bar */} +
+ + + + + + + +
+ + {/* Generate error */} + {generateError && ( +

{generateError}

+ )} +
+ ) +}