feat(migration): implement interactive mapping resolution workflow
- Add SQLite database integration for environments and mappings - Update TaskManager to support pausing tasks (AWAITING_MAPPING) - Modify MigrationPlugin to detect missing mappings and wait for resolution - Add frontend UI for handling missing mappings interactively - Create dedicated migration routes and API endpoints - Update .gitignore and project documentation
This commit is contained in:
132
frontend/src/routes/migration/+page.svelte
Normal file
132
frontend/src/routes/migration/+page.svelte
Normal file
@@ -0,0 +1,132 @@
|
||||
<!-- [DEF:MigrationDashboard:Component] -->
|
||||
<!--
|
||||
@SEMANTICS: migration, dashboard, environment, selection, database-replacement
|
||||
@PURPOSE: Main dashboard for configuring and starting migrations.
|
||||
@LAYER: Page
|
||||
@RELATION: USES -> EnvSelector
|
||||
|
||||
@INVARIANT: Migration cannot start without source and target environments.
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount } from 'svelte';
|
||||
import EnvSelector from '../../components/EnvSelector.svelte';
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: STATE]
|
||||
let environments = [];
|
||||
let sourceEnvId = "";
|
||||
let targetEnvId = "";
|
||||
let dashboardRegex = ".*";
|
||||
let replaceDb = false;
|
||||
let loading = true;
|
||||
let error = "";
|
||||
// [/SECTION]
|
||||
|
||||
// [DEF:fetchEnvironments:Function]
|
||||
/**
|
||||
* @purpose Fetches the list of environments from the API.
|
||||
* @post environments state is updated.
|
||||
*/
|
||||
async function fetchEnvironments() {
|
||||
try {
|
||||
const response = await fetch('/api/environments');
|
||||
if (!response.ok) throw new Error('Failed to fetch environments');
|
||||
environments = await response.json();
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
// [/DEF:fetchEnvironments]
|
||||
|
||||
onMount(fetchEnvironments);
|
||||
|
||||
// [DEF:startMigration:Function]
|
||||
/**
|
||||
* @purpose Starts the migration process.
|
||||
* @pre sourceEnvId and targetEnvId must be set and different.
|
||||
*/
|
||||
async function startMigration() {
|
||||
if (!sourceEnvId || !targetEnvId) {
|
||||
error = "Please select both source and target environments.";
|
||||
return;
|
||||
}
|
||||
if (sourceEnvId === targetEnvId) {
|
||||
error = "Source and target environments must be different.";
|
||||
return;
|
||||
}
|
||||
|
||||
error = "";
|
||||
console.log(`[MigrationDashboard][Action] Starting migration from ${sourceEnvId} to ${targetEnvId} (Replace DB: ${replaceDb})`);
|
||||
// TODO: Implement actual migration trigger in US3
|
||||
}
|
||||
// [/DEF:startMigration]
|
||||
</script>
|
||||
|
||||
<!-- [SECTION: TEMPLATE] -->
|
||||
<div class="max-w-4xl mx-auto p-6">
|
||||
<h1 class="text-2xl font-bold mb-6">Migration Dashboard</h1>
|
||||
|
||||
{#if loading}
|
||||
<p>Loading environments...</p>
|
||||
{:else if error}
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
|
||||
{error}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||||
<EnvSelector
|
||||
label="Source Environment"
|
||||
bind:selectedId={sourceEnvId}
|
||||
{environments}
|
||||
/>
|
||||
<EnvSelector
|
||||
label="Target Environment"
|
||||
bind:selectedId={targetEnvId}
|
||||
{environments}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-8">
|
||||
<label for="dashboard-regex" class="block text-sm font-medium text-gray-700 mb-1">Dashboard Regex</label>
|
||||
<input
|
||||
id="dashboard-regex"
|
||||
type="text"
|
||||
bind:value={dashboardRegex}
|
||||
placeholder="e.g. ^Finance Dashboard$"
|
||||
class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
|
||||
/>
|
||||
<p class="mt-1 text-sm text-gray-500">Regular expression to filter dashboards to migrate.</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-8">
|
||||
<input
|
||||
id="replace-db"
|
||||
type="checkbox"
|
||||
bind:checked={replaceDb}
|
||||
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"
|
||||
/>
|
||||
<label for="replace-db" class="ml-2 block text-sm text-gray-900">
|
||||
Replace Database (Apply Mappings)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button
|
||||
on:click={startMigration}
|
||||
disabled={!sourceEnvId || !targetEnvId || sourceEnvId === targetEnvId}
|
||||
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-400"
|
||||
>
|
||||
Start Migration
|
||||
</button>
|
||||
</div>
|
||||
<!-- [/SECTION] -->
|
||||
|
||||
<style>
|
||||
/* Page specific styles */
|
||||
</style>
|
||||
|
||||
<!-- [/DEF:MigrationDashboard] -->
|
||||
Reference in New Issue
Block a user