diff --git a/backend/migrations.db b/backend/migrations.db deleted file mode 100644 index 25d54ec9..00000000 Binary files a/backend/migrations.db and /dev/null differ diff --git a/frontend/src/components/DashboardGrid.svelte b/frontend/src/components/DashboardGrid.svelte index 443d5d79..87053982 100644 --- a/frontend/src/components/DashboardGrid.svelte +++ b/frontend/src/components/DashboardGrid.svelte @@ -11,7 +11,6 @@ -
+ { event.preventDefault(); handleSubmit(); }} class="space-y-4"> {#if schema && schema.properties} {#each Object.entries(schema.properties) as [key, prop]}
diff --git a/frontend/src/components/EnvSelector.svelte b/frontend/src/components/EnvSelector.svelte index 10cc9744..5865685c 100644 --- a/frontend/src/components/EnvSelector.svelte +++ b/frontend/src/components/EnvSelector.svelte @@ -10,7 +10,6 @@ @@ -47,7 +45,7 @@ id="env-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={selectedId} - on:change={handleSelect} + onchange={handleSelect} > {#each environments as env} diff --git a/frontend/src/components/MappingTable.svelte b/frontend/src/components/MappingTable.svelte index 736ce3fe..7e109f17 100644 --- a/frontend/src/components/MappingTable.svelte +++ b/frontend/src/components/MappingTable.svelte @@ -10,7 +10,6 @@ @@ -72,7 +69,7 @@
  • @@ -241,7 +244,7 @@ {taskId} {logs} {autoScroll} - on:filterChange={handleFilterChange} + onfilterchange={handleFilterChange} /> {/if}
  • diff --git a/frontend/src/components/TaskRunner.svelte b/frontend/src/components/TaskRunner.svelte index 83dd5f69..c71f279a 100755 --- a/frontend/src/components/TaskRunner.svelte +++ b/frontend/src/components/TaskRunner.svelte @@ -370,12 +370,12 @@
    - + {#if waitingForData && connectionStatus === 'connected'}
    @@ -388,22 +388,22 @@ {/if}
    - { connectionStatus = 'disconnected'; ws.close(); }} -/> - - { showPasswordPrompt = false; }} -/> + { connectionStatus = 'disconnected'; ws.close(); }} +/> + + { showPasswordPrompt = false; }} +/> diff --git a/frontend/src/components/backups/BackupList.svelte b/frontend/src/components/backups/BackupList.svelte index b684793a..89175e55 100644 --- a/frontend/src/components/backups/BackupList.svelte +++ b/frontend/src/components/backups/BackupList.svelte @@ -49,7 +49,7 @@
    diff --git a/frontend/src/components/backups/BackupManager.svelte b/frontend/src/components/backups/BackupManager.svelte index f3accdcc..a6736c5a 100644 --- a/frontend/src/components/backups/BackupManager.svelte +++ b/frontend/src/components/backups/BackupManager.svelte @@ -21,23 +21,27 @@ // [/SECTION] // [SECTION: STATE] - let backups: Backup[] = []; - let environments: any[] = []; - let selectedEnvId = ''; - let loading = true; - let creating = false; - let savingSchedule = false; - let currentPath = 'backups'; + let backups: Backup[] = $state([]); + let environments: any[] = $state([]); + let selectedEnvId = $state(''); + let loading = $state(true); + let creating = $state(false); + let savingSchedule = $state(false); + let currentPath = $state('backups'); // Schedule state for selected environment - let scheduleEnabled = false; - let cronExpression = '0 0 * * *'; + let scheduleEnabled = $state(false); + let cronExpression = $state('0 0 * * *'); + let selectedEnv = $derived( + environments.find((environment) => environment.id === selectedEnvId), + ); - $: selectedEnv = environments.find(e => e.id === selectedEnvId); - $: if (selectedEnv) { + $effect(() => { + if (!selectedEnv) return; scheduleEnabled = selectedEnv.backup_schedule?.enabled ?? false; - cronExpression = selectedEnv.backup_schedule?.cron_expression ?? '0 0 * * *'; - } + cronExpression = + selectedEnv.backup_schedule?.cron_expression ?? '0 0 * * *'; + }); // [/SECTION] // [DEF:loadData:Function] @@ -193,7 +197,7 @@
    {#if activeTaskDetails?.plugin_id === "llm_dashboard_validation"} @@ -719,7 +723,7 @@ {@const taskValidation = resolveLlmValidationStatus(task)}
    - + {/if} -``` diff --git a/frontend/src/lib/components/layout/TopNavbar.svelte b/frontend/src/lib/components/layout/TopNavbar.svelte index 56fc4f67..67809b94 100644 --- a/frontend/src/lib/components/layout/TopNavbar.svelte +++ b/frontend/src/lib/components/layout/TopNavbar.svelte @@ -30,9 +30,9 @@ * @TEST_INVARIANT ui_consistency -> verifies: [logged_in] */ - import { createEventDispatcher, onMount } from "svelte"; + import { onMount } from "svelte"; import { goto } from "$app/navigation"; - import { page } from "$app/stores"; + import { page } from "$app/state"; import { api } from "$lib/api.js"; import { getReports } from "$lib/api/reports.js"; import { activityStore } from "$lib/stores/activity.js"; @@ -55,32 +55,44 @@ setSelectedEnvironment, selectedEnvironmentStore, } from "$lib/stores/environmentContext.js"; + import { fromStore } from "svelte/store"; - const dispatch = createEventDispatcher(); - - let showUserMenu = false; - let isSearchFocused = false; - let searchQuery = ""; - let showSearchDropdown = false; - let isSearchLoading = false; - let groupedSearchResults = []; + let showUserMenu = $state(false); + let isSearchFocused = $state(false); + let searchQuery = $state(""); + let showSearchDropdown = $state(false); + let isSearchLoading = $state(false); + let groupedSearchResults = $state([]); let searchTimer = null; const SEARCH_DEBOUNCE_MS = 250; const SEARCH_MIN_LENGTH = 2; const SEARCH_LIMIT = 5; - $: isExpanded = $sidebarStore?.isExpanded ?? true; - $: activeCount = $activityStore?.activeCount || 0; - $: recentTasks = $activityStore?.recentTasks || []; - $: user = $auth?.user || null; - $: canOpenSettings = hasPermission(user, "admin:settings", "READ"); - $: globalEnvironments = $environmentContextStore?.environments || []; - $: globalSelectedEnvId = $environmentContextStore?.selectedEnvId || ""; - $: globalSelectedEnv = $selectedEnvironmentStore; - $: isProdContext = + const sidebarState = fromStore(sidebarStore); + const activityState = fromStore(activityStore); + const authState = fromStore(auth); + const environmentContextState = fromStore(environmentContextStore); + const selectedEnvironmentState = fromStore(selectedEnvironmentStore); + + let isExpanded = $derived(sidebarState.current?.isExpanded ?? true); + let activeCount = $derived(activityState.current?.activeCount || 0); + let recentTasks = $derived(activityState.current?.recentTasks || []); + let user = $derived(authState.current?.user || null); + let canOpenSettings = $derived( + hasPermission(user, "admin:settings", "READ"), + ); + let globalEnvironments = $derived( + environmentContextState.current?.environments || [], + ); + let globalSelectedEnvId = $derived( + environmentContextState.current?.selectedEnvId || "", + ); + let globalSelectedEnv = $derived(selectedEnvironmentState.current); + let isProdContext = $derived( String(globalSelectedEnv?.stage || "").toUpperCase() === "PROD" || - Boolean(globalSelectedEnv?.is_production); + Boolean(globalSelectedEnv?.is_production), + ); function toggleUserMenu(event) { event.stopPropagation(); @@ -106,7 +118,6 @@ } else { openDrawer(); } - dispatch("activityClick"); } function handleAssistantClick() { @@ -358,7 +369,7 @@ @@ -271,9 +271,9 @@ {env.username} {env.is_default ? $t.common?.yes : $t.common?.no} - - - + + + {/each} @@ -324,11 +324,11 @@
    - {#if editingEnvId} - {/if} diff --git a/frontend/src/routes/+error.svelte b/frontend/src/routes/+error.svelte index 80f3411d..d85aa271 100644 --- a/frontend/src/routes/+error.svelte +++ b/frontend/src/routes/+error.svelte @@ -6,13 +6,13 @@ * @LAYER: UI * @UX_STATE: Error -> Displays error code and message with home link */ - import { page } from "$app/stores"; + import { page } from "$app/state"; - - + + {/each} @@ -197,29 +197,33 @@

    {isEditing ? $t.admin.roles.modal_edit_title : $t.admin.roles.modal_create_title}

    - + { + event.preventDefault(); + handleSaveRole(); + }}>
    - - + +
    - - + +
    - -
    +

    {$t.admin.roles.permissions}

    +
    + {$t.admin.roles.permissions} {#each permissions as perm} {/each} -
    +

    {$t.admin.roles.permissions_hint}

    - +
    diff --git a/frontend/src/routes/admin/settings/+page.svelte b/frontend/src/routes/admin/settings/+page.svelte index 6730725b..d26599b4 100644 --- a/frontend/src/routes/admin/settings/+page.svelte +++ b/frontend/src/routes/admin/settings/+page.svelte @@ -180,7 +180,7 @@

    {$t.admin.settings.title}

    @@ -244,8 +244,9 @@
    - + @@ -285,7 +287,7 @@
    +
    diff --git a/frontend/src/routes/dashboards/+page.svelte b/frontend/src/routes/dashboards/+page.svelte index 7c27f969..42228fe2 100644 --- a/frontend/src/routes/dashboards/+page.svelte +++ b/frontend/src/routes/dashboards/+page.svelte @@ -2392,7 +2392,7 @@ target_db_uuid: t, }))} suggestions={availableDbMappings} - on:update={handleMappingUpdate} + onupdate={handleMappingUpdate} />
    {:else} diff --git a/frontend/src/routes/dashboards/[id]/+page.svelte b/frontend/src/routes/dashboards/[id]/+page.svelte index 3021c673..0645279a 100644 --- a/frontend/src/routes/dashboards/[id]/+page.svelte +++ b/frontend/src/routes/dashboards/[id]/+page.svelte @@ -24,7 +24,7 @@ import { onMount, onDestroy } from "svelte"; import { goto } from "$app/navigation"; - import { page } from "$app/stores"; + import { page } from "$app/state"; import { t } from "$lib/i18n"; import { api } from "$lib/api.js"; import { gitService } from "../../../services/gitService"; @@ -37,43 +37,48 @@ import CommitHistory from "../../../components/git/CommitHistory.svelte"; import GitManager from "../../../components/git/GitManager.svelte"; - $: dashboardRef = $page.params.id; - $: envId = $page.url.searchParams.get("env_id") || ""; - $: gitDashboardRef = dashboard?.slug || dashboardRef || ""; - $: resolvedDashboardId = + let dashboardRef = $derived(page.params.id); + let envId = $derived(page.url.searchParams.get("env_id") || ""); + let gitDashboardRef = $derived(dashboard?.slug || dashboardRef || ""); + let resolvedDashboardId = $derived( dashboard?.id ?? - (/^\d+$/.test(String(dashboardRef || "")) ? Number(dashboardRef) : null); + (/^\d+$/.test(String(dashboardRef || "")) ? Number(dashboardRef) : null), + ); - let dashboard = null; - let isLoading = true; - let error = null; - let taskHistory = []; - let isTaskHistoryLoading = false; - let taskHistoryError = null; - let isStartingBackup = false; - let isStartingValidation = false; - let thumbnailUrl = ""; - let isThumbnailLoading = false; - let thumbnailError = null; - let llmReady = true; - let llmStatusReason = ""; - let gitStatus = null; - let isGitStatusLoading = false; - let gitStatusError = null; - let gitDiffPreview = ""; - let isGitDiffLoading = false; - let isSyncingGit = false; - let isPullingGit = false; - let isPushingGit = false; - let currentBranch = "main"; - let activeTab = "resources"; - let showGitManager = false; - let wasGitManagerOpen = false; - let gitMeta = getGitStatusMeta(); - let gitSyncState = "NO_REPO"; - let changedChartsCount = 0; - let changedDatasetsCount = 0; - let hasChangesToCommit = false; + let dashboard = $state(null); + let isLoading = $state(true); + let error = $state(null); + let taskHistory = $state([]); + let isTaskHistoryLoading = $state(false); + let taskHistoryError = $state(null); + let isStartingBackup = $state(false); + let isStartingValidation = $state(false); + let thumbnailUrl = $state(""); + let isThumbnailLoading = $state(false); + let thumbnailError = $state(null); + let llmReady = $state(true); + let llmStatusReason = $state(""); + let gitStatus = $state(null); + let isGitStatusLoading = $state(false); + let gitStatusError = $state(null); + let gitDiffPreview = $state(""); + let isGitDiffLoading = $state(false); + let isSyncingGit = $state(false); + let isPullingGit = $state(false); + let isPushingGit = $state(false); + let currentBranch = $state("main"); + let activeTab = $state("resources"); + let showGitManager = $state(false); + let wasGitManagerOpen = $state(false); + let gitMeta = $derived(getGitStatusMeta()); + let gitSyncState = $derived(resolveGitSyncState()); + let changedChartsCount = $derived( + countChangedByAnyPath(["/charts/", "charts/"]), + ); + let changedDatasetsCount = $derived( + countChangedByAnyPath(["/datasets/", "datasets/"]), + ); + let hasChangesToCommit = $derived(allChangedFiles().length > 0); onMount(async () => { await loadDashboardPage(); @@ -504,21 +509,15 @@ await loadGitStatus(); } - $: { - gitStatus; - $t; - gitMeta = getGitStatusMeta(); - gitSyncState = resolveGitSyncState(); - changedChartsCount = countChangedByAnyPath(["/charts/", "charts/"]); - changedDatasetsCount = countChangedByAnyPath(["/datasets/", "datasets/"]); - hasChangesToCommit = allChangedFiles().length > 0; - } - $: if (showGitManager) { - wasGitManagerOpen = true; - } else if (wasGitManagerOpen) { + $effect(() => { + if (showGitManager) { + wasGitManagerOpen = true; + return; + } + if (!wasGitManagerOpen) return; wasGitManagerOpen = false; - loadGitStatus(); - } + void loadGitStatus(); + });
    @@ -526,7 +525,7 @@
    {/if} @@ -568,13 +567,13 @@
    @@ -633,7 +632,7 @@ {error} @@ -660,7 +659,7 @@
    @@ -746,7 +745,7 @@
    @@ -891,7 +890,7 @@ {#if chart.dataset_id} diff --git a/frontend/src/routes/datasets/+page.svelte b/frontend/src/routes/datasets/+page.svelte index ade754cb..9d488521 100644 --- a/frontend/src/routes/datasets/+page.svelte +++ b/frontend/src/routes/datasets/+page.svelte @@ -36,6 +36,7 @@ import { onMount } from "svelte"; import { goto } from "$app/navigation"; + import { fromStore } from "svelte/store"; import { t } from "$lib/i18n"; import { openDrawerForTask, @@ -50,38 +51,44 @@ selectedEnvironmentStore, } from "$lib/stores/environmentContext.js"; + const environmentContextState = fromStore(environmentContextStore); + const selectedEnvironmentState = fromStore(selectedEnvironmentStore); + // State - let selectedEnv = null; - let datasets = []; - let isLoading = true; - let error = null; + let selectedEnv = $state(null); + let datasets = $state([]); + let isLoading = $state(true); + let error = $state(null); // Pagination state - let currentPage = 1; - let pageSize = 10; - let totalPages = 1; - let total = 0; + let currentPage = $state(1); + let pageSize = $state(10); + let totalPages = $state(1); + let total = $state(0); // Selection state - let selectedIds = new Set(); - let isAllSelected = false; - let isAllVisibleSelected = false; + let selectedIds = $state(new Set()); + let isAllSelected = $state(false); + let isAllVisibleSelected = $state(false); // Search state - let searchQuery = ""; + let searchQuery = $state(""); // Bulk action modal state - let showMapColumnsModal = false; - let showGenerateDocsModal = false; - let mapSourceType = "postgresql"; - let mapConnectionId = ""; - let mapFileData = null; - let mapFileInput; - let llmProvider = ""; - let llmOptions = {}; + let showMapColumnsModal = $state(false); + let showGenerateDocsModal = $state(false); + let mapSourceType = $state("postgresql"); + let mapConnectionId = $state(""); + let mapFileData = $state(null); + let mapFileInput = $state(null); + let llmProvider = $state(""); + let llmOptions = $state({}); // Environment options - will be loaded from API - let environments = []; + let environments = $derived( + environmentContextState.current?.environments || [], + ); + let activeEnvironment = $derived(selectedEnvironmentState.current || null); // Debounced search function const debouncedSearch = debounce((query) => { @@ -92,8 +99,8 @@ // Load environments and datasets on mount onMount(async () => { await initializeEnvironmentContext(); - if (!selectedEnv && $environmentContextStore?.selectedEnvId) { - selectedEnv = $environmentContextStore.selectedEnvId; + if (!selectedEnv && environmentContextState.current?.selectedEnvId) { + selectedEnv = environmentContextState.current.selectedEnvId; } await loadDatasets(); }); @@ -387,18 +394,15 @@ } } - $: environments = $environmentContextStore?.environments || []; - $: activeEnvironment = $selectedEnvironmentStore; - $: if ( - $environmentContextStore?.selectedEnvId && - selectedEnv !== $environmentContextStore.selectedEnvId - ) { - selectedEnv = $environmentContextStore.selectedEnvId; + $effect(() => { + const nextSelectedEnvId = environmentContextState.current?.selectedEnvId; + if (!nextSelectedEnvId || selectedEnv === nextSelectedEnvId) return; + selectedEnv = nextSelectedEnvId; setSelectedEnvironment(selectedEnv); currentPage = 1; selectedIds.clear(); - loadDatasets(); - } + void loadDatasets(); + });
    @@ -415,7 +419,7 @@ @@ -430,7 +434,7 @@ {error} @@ -482,14 +486,14 @@
    @@ -542,7 +546,7 @@ handleCheckboxChange(dataset, e)} + onchange={(e) => handleCheckboxChange(dataset, e)} />
    @@ -587,11 +591,10 @@
    {#if dataset.lastTask} -
    handleTaskStatusClick(dataset)} - role="button" - tabindex="0" +
    + {:else} - {/if} @@ -617,7 +620,7 @@ {#if dataset.actions.includes("map_columns")} {/each}
    {#if mapSourceType === "postgresql"}
    - + {:else}
    - + {/if}
    - -
    +

    + {$t.datasets?.selected_datasets} +

    +
    {#each Array.from(selectedIds) as id} {#each datasets as d} {#if d.id === id} @@ -830,13 +839,16 @@
    @@ -269,11 +269,10 @@
    {#each dataset.linked_dashboards as dashboard} -
    navigateToDashboard(dashboard)} - role="button" - tabindex="0" + {/each}
    diff --git a/frontend/src/routes/git/+page.svelte b/frontend/src/routes/git/+page.svelte index 83341874..7dc57cba 100644 --- a/frontend/src/routes/git/+page.svelte +++ b/frontend/src/routes/git/+page.svelte @@ -6,6 +6,7 @@ -->
    diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index 39ebaa32..cd4c0e87 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -102,7 +102,7 @@
    {/if} -
    + { event.preventDefault(); handleLogin(); }} class="space-y-4">
    @@ -310,7 +315,7 @@ @@ -480,7 +480,7 @@ {error} @@ -510,7 +510,7 @@ class:hover:text-gray-800={activeTab !== "environments"} class:hover:border-gray-300={activeTab !== "environments"} aria-current={activeTab === "environments" ? "page" : undefined} - on:click={() => handleTabChange("environments")} + onclick={() => handleTabChange("environments")} > {$t.settings?.environments} @@ -523,7 +523,7 @@ class:hover:text-gray-800={activeTab !== "logging"} class:hover:border-gray-300={activeTab !== "logging"} aria-current={activeTab === "logging" ? "page" : undefined} - on:click={() => handleTabChange("logging")} + onclick={() => handleTabChange("logging")} > {$t.settings?.logging} @@ -536,7 +536,7 @@ class:hover:text-gray-800={activeTab !== "connections"} class:hover:border-gray-300={activeTab !== "connections"} aria-current={activeTab === "connections" ? "page" : undefined} - on:click={() => handleTabChange("connections")} + onclick={() => handleTabChange("connections")} > {$t.settings?.connections} @@ -549,7 +549,7 @@ class:hover:text-gray-800={activeTab !== "git"} class:hover:border-gray-300={activeTab !== "git"} aria-current={activeTab === "git" ? "page" : undefined} - on:click={() => handleTabChange("git")} + onclick={() => handleTabChange("git")} > {$t.nav?.settings_git || $t.nav?.git || "Git"} @@ -562,7 +562,7 @@ class:hover:text-gray-800={activeTab !== "llm"} class:hover:border-gray-300={activeTab !== "llm"} aria-current={activeTab === "llm" ? "page" : undefined} - on:click={() => handleTabChange("llm")} + onclick={() => handleTabChange("llm")} > {$t.settings?.llm} @@ -575,7 +575,7 @@ class:hover:text-gray-800={activeTab !== "migration"} class:hover:border-gray-300={activeTab !== "migration"} aria-current={activeTab === "migration" ? "page" : undefined} - on:click={() => handleTabChange("migration")} + onclick={() => handleTabChange("migration")} > {$t.settings?.migration_sync} @@ -588,7 +588,7 @@ class:hover:text-gray-800={activeTab !== "storage"} class:hover:border-gray-300={activeTab !== "storage"} aria-current={activeTab === "storage" ? "page" : undefined} - on:click={() => handleTabChange("storage")} + onclick={() => handleTabChange("storage")} > {$t.settings?.storage} @@ -601,7 +601,7 @@ class:hover:text-gray-800={activeTab !== "automation"} class:hover:border-gray-300={activeTab !== "automation"} aria-current={activeTab === "automation" ? "page" : undefined} - on:click={() => handleTabChange("automation")} + onclick={() => handleTabChange("automation")} > {$t.settings?.automation || "Automation"} @@ -623,7 +623,7 @@
    @@ -957,7 +957,7 @@
    @@ -1242,14 +1242,14 @@