feat: add 'New from Script' button to ScriptLibraryPage
Opens the ParameterizeAndSavePanel in paste mode, letting users import raw scripts with parameter detection and review before saving to library. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Terminal, Settings, Wand2 } from 'lucide-react'
|
import { Terminal, Settings, Wand2, FileUp } from 'lucide-react'
|
||||||
import { useScriptGeneratorStore } from '@/store/scriptGeneratorStore'
|
import { useScriptGeneratorStore } from '@/store/scriptGeneratorStore'
|
||||||
import { usePermissions } from '@/hooks/usePermissions'
|
import { usePermissions } from '@/hooks/usePermissions'
|
||||||
import { ScriptFilterBar } from '@/components/scripts/ScriptFilterBar'
|
import { ScriptFilterBar } from '@/components/scripts/ScriptFilterBar'
|
||||||
import { ScriptTemplateList } from '@/components/scripts/ScriptTemplateList'
|
import { ScriptTemplateList } from '@/components/scripts/ScriptTemplateList'
|
||||||
import { ScriptConfigurePane } from '@/components/scripts/ScriptConfigurePane'
|
import { ScriptConfigurePane } from '@/components/scripts/ScriptConfigurePane'
|
||||||
import { ScriptPreview } from '@/components/scripts/ScriptPreview'
|
import { ScriptPreview } from '@/components/scripts/ScriptPreview'
|
||||||
|
import { ParameterizeAndSavePanel } from '@/components/scripts/ParameterizeAndSavePanel'
|
||||||
|
import { scriptsApi } from '@/api'
|
||||||
|
import type { ScriptParameter } from '@/types'
|
||||||
|
|
||||||
type LibraryTab = 'mine' | 'team'
|
type LibraryTab = 'mine' | 'team'
|
||||||
|
|
||||||
@@ -23,8 +26,35 @@ export default function ScriptLibraryPage() {
|
|||||||
const clearOutput = useScriptGeneratorStore(s => s.clearOutput)
|
const clearOutput = useScriptGeneratorStore(s => s.clearOutput)
|
||||||
const selectedTemplate = useScriptGeneratorStore(s => s.selectedTemplate)
|
const selectedTemplate = useScriptGeneratorStore(s => s.selectedTemplate)
|
||||||
|
|
||||||
|
const categories = useScriptGeneratorStore(s => s.categories)
|
||||||
|
|
||||||
const { isEngineer } = usePermissions()
|
const { isEngineer } = usePermissions()
|
||||||
const canGenerate = isEngineer
|
const canGenerate = isEngineer
|
||||||
|
const [showImportPanel, setShowImportPanel] = useState(false)
|
||||||
|
|
||||||
|
const handleImportSave = async (payload: {
|
||||||
|
name: string
|
||||||
|
description: string | undefined
|
||||||
|
category_id: string | undefined
|
||||||
|
share_with_team: boolean
|
||||||
|
script_body: string
|
||||||
|
parameters_schema: { parameters: ScriptParameter[] }
|
||||||
|
}) => {
|
||||||
|
const categoryId = payload.category_id || categories[0]?.id
|
||||||
|
if (!categoryId) {
|
||||||
|
throw new Error('No categories available. Please create a category first.')
|
||||||
|
}
|
||||||
|
await scriptsApi.createTemplate({
|
||||||
|
category_id: categoryId,
|
||||||
|
name: payload.name,
|
||||||
|
description: payload.description,
|
||||||
|
script_body: payload.script_body,
|
||||||
|
parameters_schema: payload.parameters_schema,
|
||||||
|
})
|
||||||
|
setShowImportPanel(false)
|
||||||
|
const filters = activeTab === 'mine' ? { mine: true } : { shared: true }
|
||||||
|
loadTemplates(filters)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadCategories().then(() => {
|
loadCategories().then(() => {
|
||||||
@@ -70,13 +100,23 @@ export default function ScriptLibraryPage() {
|
|||||||
Browse PowerShell templates, fill in parameters, and generate ready-to-run scripts.
|
Browse PowerShell templates, fill in parameters, and generate ready-to-run scripts.
|
||||||
</p>
|
</p>
|
||||||
{isEngineer && (
|
{isEngineer && (
|
||||||
<Link
|
<div className="flex items-center gap-2 mt-2">
|
||||||
to="/scripts/manage"
|
<Link
|
||||||
className="inline-flex items-center gap-1.5 text-xs text-primary bg-accent-dim hover:bg-primary/15 px-2.5 py-1 rounded-full transition-colors mt-2 group"
|
to="/scripts/manage"
|
||||||
>
|
className="inline-flex items-center gap-1.5 text-xs text-primary bg-accent-dim hover:bg-primary/15 px-2.5 py-1 rounded-full transition-colors group"
|
||||||
<Settings size={12} className="group-hover:rotate-90 transition-transform duration-300" />
|
>
|
||||||
Manage Templates
|
<Settings size={12} className="group-hover:rotate-90 transition-transform duration-300" />
|
||||||
</Link>
|
Manage Templates
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowImportPanel(true)}
|
||||||
|
className="inline-flex items-center gap-1.5 text-xs text-primary bg-accent-dim hover:bg-primary/15 px-2.5 py-1 rounded-full transition-colors"
|
||||||
|
>
|
||||||
|
<FileUp size={12} />
|
||||||
|
New from Script
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Link
|
<Link
|
||||||
@@ -138,6 +178,14 @@ export default function ScriptLibraryPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Import script panel */}
|
||||||
|
{showImportPanel && (
|
||||||
|
<ParameterizeAndSavePanel
|
||||||
|
onSave={handleImportSave}
|
||||||
|
onClose={() => setShowImportPanel(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user