88 lines
3.1 KiB
Svelte
88 lines
3.1 KiB
Svelte
<!-- [DEF:ConnectionList:Component] -->
|
|
<!--
|
|
@SEMANTICS: connection, list, settings
|
|
@PURPOSE: UI component for listing and deleting saved database connection configurations.
|
|
@LAYER: UI
|
|
@RELATION: USES -> frontend/src/services/connectionService.js
|
|
-->
|
|
<script>
|
|
// [SECTION: IMPORTS]
|
|
import { onMount, createEventDispatcher } from 'svelte';
|
|
import { getConnections, deleteConnection } from '../../services/connectionService.js';
|
|
import { addToast } from '../../lib/toasts.js';
|
|
import { t } from '../../lib/i18n';
|
|
import { Button, Card } from '../../lib/ui';
|
|
// [/SECTION]
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
let connections = [];
|
|
let isLoading = true;
|
|
|
|
// [DEF:fetchConnections:Function]
|
|
// @PURPOSE: Fetches the list of connections from the backend.
|
|
// @PRE: None.
|
|
// @POST: connections array is populated.
|
|
async function fetchConnections() {
|
|
isLoading = true;
|
|
try {
|
|
connections = await getConnections();
|
|
} catch (e) {
|
|
addToast('Failed to fetch connections', 'error');
|
|
} finally {
|
|
isLoading = false;
|
|
}
|
|
}
|
|
// [/DEF:fetchConnections:Function]
|
|
|
|
// [DEF:handleDelete:Function]
|
|
// @PURPOSE: Deletes a connection configuration.
|
|
// @PRE: id is provided and user confirms deletion.
|
|
// @POST: Connection is deleted from backend and list is reloaded.
|
|
async function handleDelete(id) {
|
|
if (!confirm('Are you sure you want to delete this connection?')) return;
|
|
|
|
try {
|
|
await deleteConnection(id);
|
|
addToast('Connection deleted', 'success');
|
|
await fetchConnections();
|
|
} catch (e) {
|
|
addToast(e.message, 'error');
|
|
}
|
|
}
|
|
// [/DEF:handleDelete:Function]
|
|
|
|
onMount(fetchConnections);
|
|
|
|
// Expose fetchConnections to parent
|
|
export { fetchConnections };
|
|
</script>
|
|
|
|
<!-- [SECTION: TEMPLATE] -->
|
|
<Card title={$t.connections?.saved || "Saved Connections"} padding="none">
|
|
<ul class="divide-y divide-gray-100">
|
|
{#if isLoading}
|
|
<li class="p-6 text-center text-gray-500">{$t.common.loading}</li>
|
|
{:else if connections.length === 0}
|
|
<li class="p-12 text-center text-gray-500 italic">{$t.connections?.no_saved || "No connections saved yet."}</li>
|
|
{:else}
|
|
{#each connections as conn}
|
|
<li class="p-6 flex items-center justify-between hover:bg-gray-50 transition-colors">
|
|
<div>
|
|
<div class="text-sm font-medium text-blue-600 truncate">{conn.name}</div>
|
|
<div class="text-xs text-gray-400 mt-1 font-mono">{conn.type}://{conn.username}@{conn.host}:{conn.port}/{conn.database}</div>
|
|
</div>
|
|
<Button
|
|
variant="danger"
|
|
size="sm"
|
|
on:click={() => handleDelete(conn.id)}
|
|
>
|
|
{$t.connections?.delete || "Delete"}
|
|
</Button>
|
|
</li>
|
|
{/each}
|
|
{/if}
|
|
</ul>
|
|
</Card>
|
|
<!-- [/SECTION] -->
|
|
<!-- [/DEF:ConnectionList:Component] --> |