Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions src/app/_components/ServerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand All @@ -15,6 +16,14 @@ export function ServerList({ servers, onUpdate, onDelete }: ServerListProps) {
const [editingId, setEditingId] = useState<number | null>(null);
const [testingConnections, setTestingConnections] = useState<Set<number>>(new Set());
const [connectionResults, setConnectionResults] = useState<Map<number, { success: boolean; message: string }>>(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);
Expand All @@ -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) => {
Expand Down Expand Up @@ -228,6 +248,21 @@ export function ServerList({ servers, onUpdate, onDelete }: ServerListProps) {
)}
</div>
))}

{/* Confirmation Modal */}
{confirmationModal && (
<ConfirmationModal
isOpen={confirmationModal.isOpen}
onClose={() => setConfirmationModal(null)}
onConfirm={confirmationModal.onConfirm}
title={confirmationModal.title}
message={confirmationModal.message}
variant={confirmationModal.variant}
confirmText={confirmationModal.confirmText}
confirmButtonText="Delete Server"
cancelButtonText="Cancel"
/>
)}
</div>
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/api/servers/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
10 changes: 9 additions & 1 deletion src/server/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
`);

Expand Down Expand Up @@ -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();
}
Expand Down