From f6cbca2214fb52221dd3ff76a36383c8ec8ea577 Mon Sep 17 00:00:00 2001 From: busya Date: Thu, 4 Jun 2026 16:17:14 +0300 Subject: [PATCH] feat(frontend): update translate components + BackupManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translate components: - BulkReplaceModal: add dictionary selection dropdown to save replacements directly to a dictionary after applying bulk find-replace - CorrectionCell: improve inline edit UX with better state handling - TermCorrectionPopup: enhanced popup for term corrections - ConfigTabForm: update form field bindings - RunTabContent: minor layout adjustments - ScheduleConfig: improved schedule configuration UI - TranslationPreview, TranslationRunGlobalIndicator, TranslationRunProgress: UX polish and state management improvements BackupManager: - Add AbortSignal.timeout(30s) to prevent infinite loading state - Add onDestroy AbortController cleanup to prevent stale state - Add error toasts for failure states (was missing — state hung forever) - Import API_REQUEST_TIMEOUT from api.ts --- .../components/backups/BackupManager.svelte | 47 ++++++++++-- .../translate/BulkReplaceModal.svelte | 73 ++++++++++++++----- .../components/translate/ConfigTabForm.svelte | 9 ++- .../translate/CorrectionCell.svelte | 32 +++++--- .../components/translate/RunTabContent.svelte | 2 +- .../translate/ScheduleConfig.svelte | 10 ++- .../translate/TermCorrectionPopup.svelte | 32 ++++---- .../translate/TranslationPreview.svelte | 9 ++- .../TranslationRunGlobalIndicator.svelte | 2 +- .../translate/TranslationRunProgress.svelte | 4 +- 10 files changed, 158 insertions(+), 62 deletions(-) diff --git a/frontend/src/lib/components/backups/BackupManager.svelte b/frontend/src/lib/components/backups/BackupManager.svelte index d77cabef..c3ebec60 100644 --- a/frontend/src/lib/components/backups/BackupManager.svelte +++ b/frontend/src/lib/components/backups/BackupManager.svelte @@ -9,13 +9,23 @@ @RELATION USES -> [EXT:frontend:api] @INVARIANT: Only one backup task can be triggered at a time from the UI. +@UX_FEEDBACK Error toast on backup creation failure (was missing — caught state hung forever). +@UX_FEEDBACK Error toast on data load failure (was missing — loading spinner stayed forever). +@UX_FEEDBACK Error toast on schedule update failure (was missing). +@UX_RECOVERY Request timeout (30s) via AbortSignal.timeout — prevents infinite spinner when backend is unreachable. +@UX_RECOVERY In-flight requests cancelled via AbortController onDestroy — prevents stale state after navigation. +@RATIONALE Fetch API has no default timeout. Without timeout, loadData() and handleCreateBackup() hang + indefinitely when backend is unreachable, leaving loading/creating=true forever. Added 30s + timeout via AbortSignal.timeout() + onDestroy cleanup + user-facing error toasts. +@REJECTED AbortController without timeout rejected — timeout is essential; abort-on-destroy alone + doesn't protect against backend that never responds. --> {#if show} +
e.key === 'Escape' && handleClose()} + role="presentation" >
e.stopPropagation()} + onkeydown={(e) => e.key === 'Escape' && handleClose()} role="dialog" aria-modal="true" aria-label={_t.translate?.bulk_replace?.title} + tabindex="-1" >
@@ -173,10 +196,11 @@ {#if uxState === 'configuring' || uxState === 'previewing' || uxState === 'preview_error'}
- +
- +
- + +
+ + + +
{/if}
@@ -339,7 +378,7 @@ {#if uxState === 'applying'}
-
+
{_t.translate?.bulk_replace?.applying}
{/if} diff --git a/frontend/src/lib/components/translate/ConfigTabForm.svelte b/frontend/src/lib/components/translate/ConfigTabForm.svelte index c7c354f5..f86a8762 100644 --- a/frontend/src/lib/components/translate/ConfigTabForm.svelte +++ b/frontend/src/lib/components/translate/ConfigTabForm.svelte @@ -207,7 +207,7 @@ rows="2" class="w-full px-3 py-2 border border-border-strong rounded-lg text-sm focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring" placeholder={_t.translate?.config?.description_placeholder} - /> + >
@@ -275,15 +275,15 @@
{#if isColumnsLoading} -
+
{/if} {#if columnList.length > 0}
-