99 lines
3.7 KiB
Svelte
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] -->
|