'use client'; import { useState } from 'react'; import { api } from '~/trpc/react'; import { Terminal } from './Terminal'; import { StatusBadge } from './Badge'; import { Button } from './ui/button'; import { ScriptInstallationCard } from './ScriptInstallationCard'; interface InstalledScript { id: number; script_name: string; script_path: string; container_id: string | null; server_id: number | null; server_name: string | null; server_ip: string | null; server_user: string | null; server_password: string | null; installation_date: string; status: 'in_progress' | 'success' | 'failed'; output_log: string | null; } export function InstalledScriptsTab() { const [searchTerm, setSearchTerm] = useState(''); const [statusFilter, setStatusFilter] = useState<'all' | 'success' | 'failed' | 'in_progress'>('all'); const [serverFilter, setServerFilter] = useState('all'); const [updatingScript, setUpdatingScript] = useState<{ id: number; containerId: string; server?: any } | null>(null); const [editingScriptId, setEditingScriptId] = useState(null); const [editFormData, setEditFormData] = useState<{ script_name: string; container_id: string }>({ script_name: '', container_id: '' }); const [showAddForm, setShowAddForm] = useState(false); const [addFormData, setAddFormData] = useState<{ script_name: string; container_id: string; server_id: string }>({ script_name: '', container_id: '', server_id: 'local' }); // Fetch installed scripts const { data: scriptsData, refetch: refetchScripts, isLoading } = api.installedScripts.getAllInstalledScripts.useQuery(); const { data: statsData } = api.installedScripts.getInstallationStats.useQuery(); const { data: serversData } = api.servers.getAllServers.useQuery(); // Delete script mutation const deleteScriptMutation = api.installedScripts.deleteInstalledScript.useMutation({ onSuccess: () => { void refetchScripts(); } }); // Update script mutation const updateScriptMutation = api.installedScripts.updateInstalledScript.useMutation({ onSuccess: () => { void refetchScripts(); setEditingScriptId(null); setEditFormData({ script_name: '', container_id: '' }); }, onError: (error) => { alert(`Error updating script: ${error.message}`); } }); // Create script mutation const createScriptMutation = api.installedScripts.createInstalledScript.useMutation({ onSuccess: () => { void refetchScripts(); setShowAddForm(false); setAddFormData({ script_name: '', container_id: '', server_id: 'local' }); }, onError: (error) => { alert(`Error creating script: ${error.message}`); } }); const scripts: InstalledScript[] = (scriptsData?.scripts as InstalledScript[]) ?? []; const stats = statsData?.stats; // Filter scripts based on search and filters const filteredScripts = scripts.filter((script: InstalledScript) => { const matchesSearch = script.script_name.toLowerCase().includes(searchTerm.toLowerCase()) || (script.container_id?.includes(searchTerm) ?? false) || (script.server_name?.toLowerCase().includes(searchTerm.toLowerCase()) ?? false); const matchesStatus = statusFilter === 'all' || script.status === statusFilter; const matchesServer = serverFilter === 'all' || (serverFilter === 'local' && !script.server_name) || (script.server_name === serverFilter); return matchesSearch && matchesStatus && matchesServer; }); // Get unique servers for filter const uniqueServers: string[] = []; const seen = new Set(); for (const script of scripts) { if (script.server_name && !seen.has(String(script.server_name))) { uniqueServers.push(String(script.server_name)); seen.add(String(script.server_name)); } } const handleDeleteScript = (id: number) => { if (confirm('Are you sure you want to delete this installation record?')) { void deleteScriptMutation.mutate({ id }); } }; const handleUpdateScript = (script: InstalledScript) => { if (!script.container_id) { alert('No Container ID available for this script'); return; } if (confirm(`Are you sure you want to update ${script.script_name}?`)) { // Get server info if it's SSH mode let server = null; if (script.server_id && script.server_user && script.server_password) { server = { id: script.server_id, name: script.server_name, ip: script.server_ip, user: script.server_user, password: script.server_password }; } setUpdatingScript({ id: script.id, containerId: script.container_id, server: server }); } }; const handleCloseUpdateTerminal = () => { setUpdatingScript(null); }; const handleEditScript = (script: InstalledScript) => { setEditingScriptId(script.id); setEditFormData({ script_name: script.script_name, container_id: script.container_id ?? '' }); }; const handleCancelEdit = () => { setEditingScriptId(null); setEditFormData({ script_name: '', container_id: '' }); }; const handleSaveEdit = () => { if (!editFormData.script_name.trim()) { alert('Script name is required'); return; } if (editingScriptId) { updateScriptMutation.mutate({ id: editingScriptId, script_name: editFormData.script_name.trim(), container_id: editFormData.container_id.trim() || undefined, }); } }; const handleInputChange = (field: 'script_name' | 'container_id', value: string) => { setEditFormData(prev => ({ ...prev, [field]: value })); }; const handleAddFormChange = (field: 'script_name' | 'container_id' | 'server_id', value: string) => { setAddFormData(prev => ({ ...prev, [field]: value })); }; const handleAddScript = () => { if (!addFormData.script_name.trim()) { alert('Script name is required'); return; } createScriptMutation.mutate({ script_name: addFormData.script_name.trim(), script_path: `manual/${addFormData.script_name.trim()}`, container_id: addFormData.container_id.trim() || undefined, server_id: addFormData.server_id === 'local' ? undefined : Number(addFormData.server_id), execution_mode: addFormData.server_id === 'local' ? 'local' : 'ssh', status: 'success' }); }; const handleCancelAdd = () => { setShowAddForm(false); setAddFormData({ script_name: '', container_id: '', server_id: 'local' }); }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleString(); }; if (isLoading) { return (
Loading installed scripts...
); } return (
{/* Update Terminal */} {updatingScript && (
)} {/* Header with Stats */}

Installed Scripts

{stats && (
{stats.total}
Total Installations
{stats.byStatus.success}
Successful
{stats.byStatus.failed}
Failed
{stats.byStatus.in_progress}
In Progress
)} {/* Add Script Button */}
{/* Add Script Form */} {showAddForm && (

Add Manual Script Entry

handleAddFormChange('script_name', e.target.value)} className="w-full px-3 py-2 border border-input rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring" placeholder="Enter script name" />
handleAddFormChange('container_id', e.target.value)} className="w-full px-3 py-2 border border-input rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring" placeholder="Enter container ID" />
)} {/* Filters */}
{/* Search Input - Full Width on Mobile */}
setSearchTerm(e.target.value)} className="w-full px-3 py-2 border border-border rounded-md bg-card text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring" />
{/* Filter Dropdowns - Responsive Grid */}
{/* Scripts Display - Mobile Cards / Desktop Table */}
{filteredScripts.length === 0 ? (
{scripts.length === 0 ? 'No installed scripts found.' : 'No scripts match your filters.'}
) : ( <> {/* Mobile Card Layout */}
{filteredScripts.map((script) => ( handleEditScript(script)} onSave={handleSaveEdit} onCancel={handleCancelEdit} onUpdate={() => handleUpdateScript(script)} onDelete={() => handleDeleteScript(Number(script.id))} isUpdating={updateScriptMutation.isPending} isDeleting={deleteScriptMutation.isPending} /> ))}
{/* Desktop Table Layout */}
{filteredScripts.map((script) => ( ))}
Script Name Container ID Server Status Installation Date Actions
{editingScriptId === script.id ? (
handleInputChange('script_name', e.target.value)} className="w-full px-2 py-1 text-sm border border-border rounded bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Script name" />
{script.script_path}
) : (
{script.script_name}
{script.script_path}
)}
{editingScriptId === script.id ? ( handleInputChange('container_id', e.target.value)} className="w-full px-2 py-1 text-sm font-mono border border-border rounded bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Container ID" /> ) : ( script.container_id ? ( {String(script.container_id)} ) : ( - ) )} {script.server_name ?? 'Local'} {script.status.replace('_', ' ').toUpperCase()} {formatDate(String(script.installation_date))}
{editingScriptId === script.id ? ( <> ) : ( <> {script.container_id && ( )} )}
)}
); }