diff --git a/src/app/_components/ServerList.tsx b/src/app/_components/ServerList.tsx index 2e9b490..e3aa497 100644 --- a/src/app/_components/ServerList.tsx +++ b/src/app/_components/ServerList.tsx @@ -4,6 +4,7 @@ import { useState } from 'react'; import type { Server, CreateServerData } from '../../types/server'; import { ServerForm } from './ServerForm'; import { Button } from './ui/button'; +import { ConfirmationModal } from './ConfirmationModal'; interface ServerListProps { servers: Server[]; @@ -15,6 +16,14 @@ export function ServerList({ servers, onUpdate, onDelete }: ServerListProps) { const [editingId, setEditingId] = useState(null); const [testingConnections, setTestingConnections] = useState>(new Set()); const [connectionResults, setConnectionResults] = useState>(new Map()); + const [confirmationModal, setConfirmationModal] = useState<{ + isOpen: boolean; + variant: 'danger'; + title: string; + message: string; + confirmText: string; + onConfirm: () => void; + } | null>(null); const handleEdit = (server: Server) => { setEditingId(server.id); @@ -32,9 +41,20 @@ export function ServerList({ servers, onUpdate, onDelete }: ServerListProps) { }; const handleDelete = (id: number) => { - if (window.confirm('Are you sure you want to delete this server configuration?')) { - onDelete(id); - } + const server = servers.find(s => s.id === id); + if (!server) return; + + setConfirmationModal({ + isOpen: true, + variant: 'danger', + title: 'Delete Server', + message: `This will permanently delete the server configuration "${server.name}" (${server.ip}) and all associated installed scripts. This action cannot be undone!`, + confirmText: server.name, + onConfirm: () => { + onDelete(id); + setConfirmationModal(null); + } + }); }; const handleTestConnection = async (server: Server) => { @@ -228,6 +248,21 @@ export function ServerList({ servers, onUpdate, onDelete }: ServerListProps) { )} ))} + + {/* Confirmation Modal */} + {confirmationModal && ( + setConfirmationModal(null)} + onConfirm={confirmationModal.onConfirm} + title={confirmationModal.title} + message={confirmationModal.message} + variant={confirmationModal.variant} + confirmText={confirmationModal.confirmText} + confirmButtonText="Delete Server" + cancelButtonText="Cancel" + /> + )} ); } diff --git a/src/app/api/servers/[id]/route.ts b/src/app/api/servers/[id]/route.ts index d74a1c1..fbd3bc4 100644 --- a/src/app/api/servers/[id]/route.ts +++ b/src/app/api/servers/[id]/route.ts @@ -173,6 +173,9 @@ export async function DELETE( ); } + // Delete all installed scripts associated with this server + db.deleteInstalledScriptsByServer(id); + const result = db.deleteServer(id); return NextResponse.json( diff --git a/src/server/database.js b/src/server/database.js index bca0659..ff6ceb4 100644 --- a/src/server/database.js +++ b/src/server/database.js @@ -90,7 +90,7 @@ class DatabaseService { installation_date DATETIME DEFAULT CURRENT_TIMESTAMP, status TEXT NOT NULL CHECK(status IN ('in_progress', 'success', 'failed')), output_log TEXT, - FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE SET NULL + FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE ) `); @@ -276,6 +276,14 @@ class DatabaseService { return stmt.run(id); } + /** + * @param {number} server_id + */ + deleteInstalledScriptsByServer(server_id) { + const stmt = this.db.prepare('DELETE FROM installed_scripts WHERE server_id = ?'); + return stmt.run(server_id); + } + close() { this.db.close(); }