refactor(frontend): migrate Svelte stores from .ts to .svelte.ts runes
- Delete legacy .ts stores (auth, activity, assistantChat, datasetReview, environmentContext, health, sidebar, taskDrawer, translationRun) - Create new .svelte.ts runes-based stores using reactive primitives - Migrate i18n: /i18n → /i18n/index.svelte.js - Migrate toasts: /toasts → /toasts.svelte.js - Update all component imports across 180+ files: components, pages, routes, lib - Remove fromStore() wrappers — use store.value directly with Svelte 5 runes - Update test mocks for new import paths - Add @DEPRECATED annotation to legacy alias
This commit is contained in:
@@ -15,11 +15,11 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import type { DashboardMetadata } from "../types/dashboard";
|
||||
import { t } from "../lib/i18n";
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button, Input } from "../lib/ui";
|
||||
import GitManager from "./git/GitManager.svelte";
|
||||
import { api } from "../lib/api";
|
||||
import { addToast as toast } from "../lib/toasts";
|
||||
import { addToast as toast } from "$lib/toasts.svelte.js";
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: PROPS]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { t } from '../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: PROPS]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: PROPS]
|
||||
|
||||
@@ -14,13 +14,16 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { fromStore } from 'svelte/store';
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { LanguageSwitcher } from '$lib/ui';
|
||||
import { auth } from '$lib/auth/store';
|
||||
import { auth } from '$lib/auth/store.svelte.js';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const authState = fromStore(auth);
|
||||
let _authState = $state({ user: null, token: null, isAuthenticated: false, loading: true });
|
||||
$effect(() => {
|
||||
const unsub = auth.subscribe(v => { _authState = v; });
|
||||
return unsub;
|
||||
});
|
||||
|
||||
function handleLogout() {
|
||||
auth.logout();
|
||||
@@ -58,7 +61,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if authState.current?.isAuthenticated && authState.current?.user?.roles?.some(r => r.name === 'Admin')}
|
||||
{#if _authState.isAuthenticated && _authState.user?.roles?.some(r => r.name === 'Admin')}
|
||||
<div class="relative inline-block group">
|
||||
<button class="text-gray-600 hover:text-primary font-medium pb-1 {page.url.pathname.startsWith('/admin') ? 'text-primary border-b-2 border-blue-600' : ''}">
|
||||
{$t.nav.admin}
|
||||
@@ -73,9 +76,9 @@
|
||||
{/if}
|
||||
<LanguageSwitcher />
|
||||
|
||||
{#if authState.current?.isAuthenticated}
|
||||
{#if _authState.isAuthenticated}
|
||||
<div class="flex items-center space-x-2 border-l pl-4 ml-4">
|
||||
<span class="text-sm text-gray-600">{authState.current?.user?.username}</span>
|
||||
<span class="text-sm text-gray-600">{_authState.user?.username}</span>
|
||||
<button
|
||||
onclick={handleLogout}
|
||||
class="text-sm text-red-600 hover:text-red-800 font-medium"
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
// [SECTION: IMPORTS]
|
||||
import { untrack } from "svelte";
|
||||
import type { DashboardMetadata } from "../types/dashboard";
|
||||
import { t } from "../lib/i18n";
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button, Input } from "../lib/ui";
|
||||
import GitManager from "./git/GitManager.svelte";
|
||||
import { gitService } from "../services/gitService";
|
||||
import { addToast } from "../lib/toasts";
|
||||
import { addToast } from "$lib/toasts.svelte.js";
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: PROPS]
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
* @UX_RECOVERY: User can switch to advanced settings or retry save with corrected data.
|
||||
*/
|
||||
import { goto } from "$app/navigation";
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { api } from "$lib/api.js";
|
||||
import { addToast } from "$lib/toasts";
|
||||
import { refreshEnvironmentContext, setSelectedEnvironment } from "$lib/stores/environmentContext.js";
|
||||
import { addToast } from "$lib/toasts.svelte.js";
|
||||
import { refreshEnvironmentContext, setSelectedEnvironment } from "$lib/stores/environmentContext.svelte.js";
|
||||
|
||||
let { open = false, onCreated = async () => {} } = $props();
|
||||
let step = $state("intro");
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { selectedTask } from '../lib/stores.js';
|
||||
import { selectedTask } from '$lib/stores.svelte.js';
|
||||
import { api, getTaskEventsWsUrl } from '../lib/api.js';
|
||||
import { t } from '../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
|
||||
/** @type {string | undefined} — if set, only shows tasks with this plugin_id (e.g. "superset-migration") */
|
||||
let { pluginId = undefined } = $props();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { t } from '../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
|
||||
let {
|
||||
tasks = [],
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getTaskLogs } from "../services/taskService.js";
|
||||
import { t } from "../lib/i18n";
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import TaskLogPanel from "./tasks/TaskLogPanel.svelte";
|
||||
import Icon from "../lib/ui/Icon.svelte";
|
||||
|
||||
|
||||
@@ -12,14 +12,13 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { selectedTask, taskLogs } from '../lib/stores.js';
|
||||
import { selectedTask, taskLogs } from '$lib/stores.svelte.js';
|
||||
import { getWsUrl, api } from '../lib/api.js';
|
||||
import { addToast } from '../lib/toasts';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import MissingMappingModal from './MissingMappingModal.svelte';
|
||||
import PasswordPrompt from './PasswordPrompt.svelte';
|
||||
import TaskLogPanel from './tasks/TaskLogPanel.svelte';
|
||||
import { t } from '../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
// [/SECTION]
|
||||
|
||||
let ws;
|
||||
@@ -48,7 +47,7 @@
|
||||
* @post WebSocket instance created and listeners attached.
|
||||
*/
|
||||
function connect() {
|
||||
const task = get(selectedTask);
|
||||
const task = selectedTask.current;
|
||||
if (!task || connectionStatus === 'completed') return;
|
||||
|
||||
console.log(`[EXT:frontend:TaskRunner][Entry] Connecting to logs for task: ${task.id} (Attempt ${reconnectAttempts + 1}) filters: source=${selectedSource}, level=${selectedLevel}`);
|
||||
@@ -178,7 +177,7 @@
|
||||
* @post targetDatabases array populated with available databases.
|
||||
*/
|
||||
async function fetchTargetDatabases() {
|
||||
const task = get(selectedTask);
|
||||
const task = selectedTask.current;
|
||||
if (!task || !task.params.to_env) return;
|
||||
|
||||
try {
|
||||
@@ -201,7 +200,7 @@
|
||||
* @post Mapping created in backend, task resumed with resolution params.
|
||||
*/
|
||||
async function handleMappingResolve(event) {
|
||||
const task = get(selectedTask);
|
||||
const task = selectedTask.current;
|
||||
const { sourceDbUuid, targetDbUuid, targetDbName } = event.detail;
|
||||
|
||||
try {
|
||||
@@ -237,7 +236,7 @@
|
||||
* @post Task resumed with passwords, connection status restored to connected.
|
||||
*/
|
||||
async function handlePasswordResume(event) {
|
||||
const task = get(selectedTask);
|
||||
const task = selectedTask.current;
|
||||
const { passwords } = event.detail;
|
||||
|
||||
try {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
@UX_FEEDBACK Close button on persistent toasts; auto-dismiss on transient toasts.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { toasts, removeToast } from '../lib/toasts';
|
||||
import { toasts, removeToast } from '$lib/toasts.svelte.js';
|
||||
|
||||
function handleDismiss(id) {
|
||||
removeToast(id);
|
||||
|
||||
@@ -23,7 +23,7 @@ vi.mock('../../services/taskService.js', () => ({
|
||||
|
||||
const getTaskLogsMock = vi.mocked(getTaskLogs);
|
||||
|
||||
vi.mock('../../lib/i18n', () => ({
|
||||
vi.mock('$lib/i18n/index.svelte.js', () => ({
|
||||
t: {
|
||||
subscribe: (fn) => {
|
||||
fn({
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { auth } from "../../lib/auth/store";
|
||||
import { auth } from "../../lib/auth/store.svelte.js";
|
||||
import { api } from "../../lib/api";
|
||||
import { goto } from "$app/navigation";
|
||||
import { hasPermission } from "$lib/auth/permissions.js";
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { t } from '../../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button } from '../../lib/ui';
|
||||
import type { Backup } from '../../types/backup';
|
||||
// [/SECTION]
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { api, requestApi } from '../../lib/api';
|
||||
import { addToast } from '../../lib/toasts';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import { Button, Card, Select, Input } from '../../lib/ui';
|
||||
import BackupList from './BackupList.svelte';
|
||||
import type { Backup } from '../../types/backup';
|
||||
@@ -86,7 +86,7 @@
|
||||
// Pre-fill with active environment from global context
|
||||
if (!selectedEnvId) {
|
||||
const { get } = await import('svelte/store');
|
||||
const envCtx = await import('$lib/stores/environmentContext.js');
|
||||
const envCtx = await import('$lib/stores/environmentContext.svelte.js');
|
||||
const state = get(envCtx.environmentContextStore);
|
||||
if (state.selectedEnvId && environments.some((env) => env.id === state.selectedEnvId)) {
|
||||
selectedEnvId = state.selectedEnvId;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { BranchModel } from '$lib/models/BranchModel.svelte.ts';
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button, Select, Input } from '$lib/ui';
|
||||
|
||||
let {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount } from 'svelte';
|
||||
import { gitService } from '../../services/gitService';
|
||||
import { addToast as toast } from '../../lib/toasts';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { addToast as toast } from '$lib/toasts.svelte.js';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button } from '../../lib/ui';
|
||||
// [/SECTION]
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { CommitModel } from '$lib/models/CommitModel.svelte.ts';
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
|
||||
let { dashboardId, envId = null, show = false } = $props();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { addToast as toast } from "../../lib/toasts";
|
||||
import { addToast as toast } from "$lib/toasts.svelte.js";
|
||||
// [/SECTION]
|
||||
|
||||
// [SECTION: PROPS]
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { DeploymentModel } from '$lib/models/DeploymentModel.svelte.ts';
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
|
||||
let { dashboardId, envId = null, show = $bindable(false), preferredTargetStage = '' } = $props();
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- @UX_STATE Idle -> Config selector, remote URL input, create/init buttons. -->
|
||||
<!-- @UX_STATE Loading -> Buttons disabled, spinner visible. -->
|
||||
<script lang="ts">
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Button, Card, Select, Input, HelpTooltip } from "$lib/ui";
|
||||
|
||||
let {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<!-- @UX_RECOVERY Dismiss error, Retry operation after fixing the issue. -->
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { HelpTooltip } from '$lib/ui';
|
||||
import { stageBadgeClass, resolveDefaultConfig } from '../../services/git-utils.js';
|
||||
import { GitManagerModel } from '$lib/models/GitManagerModel.svelte.ts';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- @UX_STATE Open -> Dialog with merge context, status, and action buttons. -->
|
||||
<!-- @UX_STATE Loading -> Recovery state loading spinner. -->
|
||||
<script lang="ts">
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Button } from "$lib/ui";
|
||||
|
||||
let {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- @BRIEF Git server operations panel: pull, push, and deploy actions. -->
|
||||
<!-- @LAYER UI -->
|
||||
<script lang="ts">
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Button } from "$lib/ui";
|
||||
|
||||
let {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- @UX_STATE Idle -> Pipeline status and promote button. -->
|
||||
<!-- @UX_STATE Advanced -> Expandable branch/reason settings. -->
|
||||
<script lang="ts">
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Button, Input, Select } from "$lib/ui";
|
||||
import { stageBadgeClass } from "../../services/git-utils.js";
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<!-- @UX_STATE Error -> Toast on failure. -->
|
||||
<!-- @UX_RECOVERY Scroll down to load more diff chunks; sentinel triggers lazy render. -->
|
||||
<script lang="ts">
|
||||
import { t } from "$lib/i18n";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Button } from "$lib/ui";
|
||||
import * as Diff2Html from 'diff2html';
|
||||
import 'diff2html/bundles/css/diff2html.min.css';
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { t } from '../../lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
|
||||
/** @type {Object} */
|
||||
let {
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { t } from "../../lib/i18n";
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { requestApi } from "../../lib/api";
|
||||
import { addToast } from "../../lib/toasts";
|
||||
import { addToast } from "$lib/toasts.svelte.js";
|
||||
import HelpTooltip from "$lib/ui/HelpTooltip.svelte";
|
||||
|
||||
let {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- @PURPOSE: Displays the results of an LLM-based dashboard validation task. -->
|
||||
|
||||
<script lang="ts">
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
let {
|
||||
report,
|
||||
} = $props();
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { downloadFile } from '../../services/storageService';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { addToast } from '../../lib/toasts';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
// [/SECTION: IMPORTS]
|
||||
|
||||
let {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { uploadFile } from '../../services/storageService';
|
||||
import { addToast } from '../../lib/toasts';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
// [/SECTION: IMPORTS]
|
||||
|
||||
// #region handleUpload:Function [TYPE Function]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!-- @UX_STATE Empty -> No task selected, placeholder shown. -->
|
||||
<!-- @UX_STATE Loaded -> Task result displayed with status color coding. -->
|
||||
<script lang="ts">
|
||||
import { t } from '$lib/i18n';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
let { task = null } = $props();
|
||||
|
||||
const result = $derived(task?.result || null);
|
||||
|
||||
@@ -10,17 +10,14 @@
|
||||
<script lang="ts">
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount } from 'svelte';
|
||||
import { fromStore } from 'svelte/store';
|
||||
import { api } from '../../lib/api.js';
|
||||
import { runTask, getTaskStatus } from '../../services/toolsService.js';
|
||||
import { selectedTask } from '../../lib/stores.js';
|
||||
import { addToast } from '../../lib/toasts';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { environmentContextStore } from '$lib/stores/environmentContext.js';
|
||||
import { selectedTask } from '$lib/stores.svelte.js';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { environmentContextStore } from '$lib/stores/environmentContext.svelte.js';
|
||||
// [/SECTION]
|
||||
|
||||
const envContextState = fromStore(environmentContextStore);
|
||||
|
||||
let envs = [];
|
||||
let action = 'test-db-api';
|
||||
let selectedEnv = '';
|
||||
@@ -42,7 +39,7 @@
|
||||
try {
|
||||
envs = await api.getEnvironmentsList();
|
||||
// Pre-fill source and single env with active environment, leave target empty
|
||||
const activeEnvId = envContextState.current?.selectedEnvId;
|
||||
const activeEnvId = environmentContextStore.value?.selectedEnvId;
|
||||
if (activeEnvId && envs.some((e) => e.id === activeEnvId)) {
|
||||
sourceEnv = activeEnvId;
|
||||
selectedEnv = activeEnvId;
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { runTask } from '../../services/toolsService.js';
|
||||
import { api } from '../../lib/api';
|
||||
import { selectedTask } from '../../lib/stores.js';
|
||||
import { addToast } from '../../lib/toasts';
|
||||
import { t } from '../../lib/i18n';
|
||||
import { selectedTask } from '$lib/stores.svelte.js';
|
||||
import { addToast } from '$lib/toasts.svelte.js';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button, Card, Select, Input, Icon } from '../../lib/ui';
|
||||
import DocPreview from '../llm/DocPreview.svelte';
|
||||
// [/SECTION]
|
||||
@@ -44,7 +44,7 @@
|
||||
envs = await api.fetchApi('/environments');
|
||||
// Pre-fill with active environment from global context
|
||||
const { get } = await import('svelte/store');
|
||||
const envCtx = await import('$lib/stores/environmentContext.js');
|
||||
const envCtx = await import('$lib/stores/environmentContext.svelte.js');
|
||||
const state = get(envCtx.environmentContextStore);
|
||||
if (state.selectedEnvId && envs.some((e) => e.id === state.selectedEnvId)) {
|
||||
selectedEnv = state.selectedEnvId;
|
||||
|
||||
Reference in New Issue
Block a user