Files
ss-tools/frontend/src/components/MappingTable.svelte
2026-01-18 21:29:54 +03:00

99 lines
3.7 KiB
Svelte

<!-- [DEF:MappingTable:Component] -->
<!--
@SEMANTICS: mapping, table, database, editor
@PURPOSE: Displays and allows editing of database mappings.
@LAYER: Feature
@RELATION: BINDS_TO -> mappings state
@INVARIANT: Each source database can be mapped to one target database.
-->
<script lang="ts">
// [SECTION: IMPORTS]
import { createEventDispatcher } from 'svelte';
// [/SECTION]
// [SECTION: PROPS]
export let sourceDatabases: Array<{uuid: string, database_name: string}> = [];
export let targetDatabases: Array<{uuid: string, database_name: string}> = [];
export let mappings: Array<{source_db_uuid: string, target_db_uuid: string}> = [];
export let suggestions: Array<{source_db_uuid: string, target_db_uuid: string, confidence: number}> = [];
// [/SECTION]
const dispatch = createEventDispatcher();
// [DEF:updateMapping:Function]
/**
* @purpose Updates a mapping for a specific source database.
* @pre sourceUuid and targetUuid are provided.
* @post 'update' event is dispatched.
*/
function updateMapping(sourceUuid: string, targetUuid: string) {
dispatch('update', { sourceUuid, targetUuid });
}
// [/DEF:updateMapping:Function]
// [DEF:getSuggestion:Function]
/**
* @purpose Finds a suggestion for a source database.
* @pre sourceUuid is provided.
* @post Returns matching suggestion object or undefined.
*/
function getSuggestion(sourceUuid: string) {
return suggestions.find(s => s.source_db_uuid === sourceUuid);
}
// [/DEF:getSuggestion:Function]
</script>
<!-- [SECTION: TEMPLATE] -->
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Source Database</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Target Database</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
{#each sourceDatabases as sDb}
{@const mapping = mappings.find(m => m.source_db_uuid === sDb.uuid)}
{@const suggestion = getSuggestion(sDb.uuid)}
<tr class={suggestion && !mapping ? 'bg-green-50' : ''}>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{sDb.database_name}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<select
class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
value={mapping?.target_db_uuid || suggestion?.target_db_uuid || ""}
on:change={(e) => updateMapping(sDb.uuid, (e.target as HTMLSelectElement).value)}
>
<option value="">-- Select Target --</option>
{#each targetDatabases as tDb}
<option value={tDb.uuid}>{tDb.database_name}</option>
{/each}
</select>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{#if mapping}
<span class="text-blue-600 font-semibold">Saved</span>
{:else if suggestion}
<span class="text-green-600 font-semibold">Suggested ({Math.round(suggestion.confidence * 100)}%)</span>
{:else}
<span class="text-red-600">Unmapped</span>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<!-- [/SECTION] -->
<style>
/* Component specific styles */
</style>
<!-- [/DEF:MappingTable:Component] -->