fix(health): suppress 404 when health monitor disabled + fix audit test assertion
- Sidebar.svelte: defer healthStore.refresh() until feature flags confirm health_monitor is enabled; skip entirely when disabled - health.js: remove throw error from catch block — log and return null instead, preventing 'Uncaught (in promise)' on expected 404 - test_report_audit_immutability.py: fix mock assertions — audit_service uses logger.reason/reflect/explore, not logger.info - HealthStore and Sidebar now produce zero network noise when FEATURES__HEALTH_MONITOR=false
This commit is contained in:
@@ -72,6 +72,7 @@
|
||||
const failingCountState = fromStore(failingCount);
|
||||
|
||||
let features = $state({});
|
||||
let cleanupInterval = null;
|
||||
|
||||
let categories = $derived(
|
||||
buildSidebarCategories(
|
||||
@@ -195,21 +196,29 @@
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
healthStore.refresh();
|
||||
// Refresh every 5 minutes
|
||||
const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
|
||||
|
||||
// Fetch feature flags for sidebar filtering
|
||||
// Fetch feature flags first, then conditionally refresh health
|
||||
fetchApi("/settings/features")
|
||||
.then((res) => {
|
||||
features = res;
|
||||
if (res.health_monitor) {
|
||||
healthStore.refresh();
|
||||
// Refresh every 5 minutes
|
||||
const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
|
||||
cleanupInterval = interval;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Graceful degradation: default to {} (all features visible)
|
||||
features = {};
|
||||
// On error, try health anyway
|
||||
healthStore.refresh();
|
||||
const interval = setInterval(() => healthStore.refresh(), 5 * 60 * 1000);
|
||||
cleanupInterval = interval;
|
||||
});
|
||||
|
||||
return () => clearInterval(interval);
|
||||
return () => {
|
||||
if (cleanupInterval) clearInterval(cleanupInterval);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
<!-- #region BulkCorrectionSidebar [C:3] [TYPE Component] [SEMANTICS translate, correction, bulk, sidebar, dictionary] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/BulkCorrectionSidebar.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [dictionaryApi] -->
|
||||
<!-- @UX_STATE closed -> Sidebar hidden -->
|
||||
<!-- @UX_STATE collecting -> Items being collected, user can edit corrections -->
|
||||
<!-- @UX_STATE reviewing -> User reviews collected corrections before submit -->
|
||||
<!-- @UX_STATE submitting -> API call in progress -->
|
||||
<!-- @UX_STATE submitted -> Success feedback -->
|
||||
<!-- @UX_FEEDBACK Toast on success/error; count badge on toggle button -->
|
||||
<!-- @UX_RECOVERY Remove individual items; retry submission -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Sidebar for collecting multiple incorrect terms across different rows,
|
||||
* per-term correction inputs, submit atomically to dictionary.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
* @RELATION: DEPENDS_ON -> [dictionaryApi]
|
||||
*
|
||||
* @UX_STATE: closed -> Sidebar hidden
|
||||
* @UX_STATE: collecting -> Items being collected, user can edit corrections
|
||||
* @UX_STATE: reviewing -> User reviews collected corrections before submit
|
||||
* @UX_STATE: submitting -> API call in progress
|
||||
* @UX_STATE: submitted -> Success feedback
|
||||
*
|
||||
* @UX_FEEDBACK: Toast on success/error; count badge on toggle button
|
||||
* @UX_RECOVERY: Remove individual items; retry submission
|
||||
*/
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import { submitBulkCorrections, dictionaryApi } from '$lib/api/translate.js';
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
<!-- #region ScheduleConfig [C:3] [TYPE Component] [SEMANTICS translate, schedule, cron, trigger, config] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/ScheduleConfig.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @UX_STATE idle -> No schedule configured -->
|
||||
<!-- @UX_STATE editing -> Configuring schedule -->
|
||||
<!-- @UX_STATE enabled -> Schedule active -->
|
||||
<!-- @UX_STATE disabled -> Schedule inactive -->
|
||||
<!-- @UX_STATE no_prior_run_warning -> No prior manual run, show warning -->
|
||||
<!-- @UX_FEEDBACK Next-3-executions preview; toast on save/error -->
|
||||
<!-- @UX_RECOVERY Enable/disable toggle; delete schedule -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Schedule configuration for a translation job — cron/interval/once triggers, timezone, enable/disable.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
*
|
||||
* @UX_STATE: idle -> No schedule configured
|
||||
* @UX_STATE: editing -> Configuring schedule
|
||||
* @UX_STATE: enabled -> Schedule active
|
||||
* @UX_STATE: disabled -> Schedule inactive
|
||||
* @UX_STATE: no_prior_run_warning -> No prior manual run, show warning
|
||||
*
|
||||
* @UX_FEEDBACK: Next-3-executions preview; toast on save/error
|
||||
* @UX_RECOVERY: Enable/disable toggle; delete schedule
|
||||
*/
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import {
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
<!-- #region TermCorrectionPopup [C:3] [TYPE Component] [SEMANTICS translate, correction, popup, dictionary, term] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/TermCorrectionPopup.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @RELATION BINDS_TO -> [dictionaryApi] -->
|
||||
<!-- @UX_STATE closed -> Hidden -->
|
||||
<!-- @UX_STATE selecting -> User selects target dictionary -->
|
||||
<!-- @UX_STATE editing -> User enters corrected term -->
|
||||
<!-- @UX_STATE submitting -> API call in progress -->
|
||||
<!-- @UX_STATE conflict_detected -> Existing entry found, user chooses overwrite/keep -->
|
||||
<!-- @UX_STATE submitted -> Success feedback -->
|
||||
<!-- @UX_FEEDBACK Toast on success/error; conflict dialog with action buttons -->
|
||||
<!-- @UX_RECOVERY Cancel button returns to previous state -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Popup for submitting a term correction from a run result row.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
* @RELATION: BINDS_TO -> [dictionaryApi]
|
||||
*
|
||||
* @UX_STATE: closed -> Hidden
|
||||
* @UX_STATE: selecting -> User selects target dictionary
|
||||
* @UX_STATE: editing -> User enters corrected term
|
||||
* @UX_STATE: submitting -> API call in progress
|
||||
* @UX_STATE: conflict_detected -> Existing entry found, user chooses overwrite/keep
|
||||
* @UX_STATE: submitted -> Success feedback
|
||||
*
|
||||
* @UX_FEEDBACK: Toast on success/error; conflict dialog with action buttons
|
||||
* @UX_RECOVERY: Cancel button returns to previous state
|
||||
*/
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import { submitCorrection, dictionaryApi } from '$lib/api/translate.js';
|
||||
import { t, _ } from '$lib/i18n';
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
<!-- #region TranslationMetricsDashboard [C:3] [TYPE Component] [SEMANTICS translate, metrics, dashboard, stats, cost] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/TranslationMetricsDashboard.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @UX_STATE loading -> Initial load -->
|
||||
<!-- @UX_STATE loaded -> Metrics data displayed -->
|
||||
<!-- @UX_STATE error -> Failed to load metrics -->
|
||||
<!-- @UX_STATE empty -> No metrics data available -->
|
||||
<!-- @UX_FEEDBACK Spinner during load; card grid for totals; table for per-job breakdown -->
|
||||
<!-- @UX_RECOVERY Retry button on error -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Admin metrics dashboard for translation — per-job run counts, success/failure ratio,
|
||||
* cumulative tokens, cumulative cost, average latency.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
*
|
||||
* @UX_STATE: loading -> Initial load
|
||||
* @UX_STATE: loaded -> Metrics data displayed
|
||||
* @UX_STATE: error -> Failed to load metrics
|
||||
* @UX_STATE: empty -> No metrics data available
|
||||
*
|
||||
* @UX_FEEDBACK: Spinner during load; card grid for totals; table for per-job breakdown
|
||||
* @UX_RECOVERY: Retry button on error
|
||||
*/
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import { fetchAllMetrics } from '$lib/api/translate.js';
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
<!-- #region TranslationPreview [C:3] [TYPE Component] [SEMANTICS translate, preview, multi-language, approve, cost] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/TranslationPreview.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [api_module] -->
|
||||
<!-- @UX_STATE idle -> Initial state, no preview loaded -->
|
||||
<!-- @UX_STATE loading -> Preview API call in progress -->
|
||||
<!-- @UX_STATE preview_loaded -> Preview data displayed with dynamic language columns -->
|
||||
<!-- @UX_STATE preview_error -> Preview API call failed -->
|
||||
<!-- @UX_STATE accepted -> Preview session accepted -->
|
||||
<!-- @UX_STATE stale_config -> Configuration changed since preview was generated -->
|
||||
<!-- @UX_FEEDBACK spinner during preview; visual distinction for LLM vs edited translations; cost warning for large previews. -->
|
||||
<!-- @UX_RECOVERY retry preview; re-fetch with updated config. -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Multi-language translation preview with dynamic per-language columns, approve/edit/reject, cost estimate, and accept gate.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
* @RELATION: DEPENDS_ON -> [api_module]
|
||||
* @PRE: jobId is a valid translation job ID.
|
||||
* @POST: User can preview, approve/edit/reject per-language rows, and accept the session to gate full execution.
|
||||
*
|
||||
* @UX_STATE: idle -> Initial state, no preview loaded
|
||||
* @UX_STATE: loading -> Preview API call in progress
|
||||
* @UX_STATE: preview_loaded -> Preview data displayed with dynamic language columns
|
||||
* @UX_STATE: preview_error -> Preview API call failed
|
||||
* @UX_STATE: accepted -> Preview session accepted
|
||||
* @UX_STATE: stale_config -> Configuration changed since preview was generated
|
||||
*
|
||||
* @UX_FEEDBACK: spinner during preview; visual distinction for LLM vs edited translations; cost warning for large previews.
|
||||
* @UX_RECOVERY: retry preview; re-fetch with updated config.
|
||||
*/
|
||||
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!-- #region TranslationRunGlobalIndicator [C:3] [TYPE Component] [SEMANTICS translate, progress, global, indicator] -->
|
||||
<!-- @BRIEF Persistent rich progress panel for active translation runs, rendered in root layout. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION BINDS_TO -> [translationRunStore] -->
|
||||
<!-- @UX_STATE hidden -> No active or recently completed run -->
|
||||
<!-- @UX_STATE running -> Rich panel with stats grid + progress bar + cancel button -->
|
||||
|
||||
@@ -1,28 +1,18 @@
|
||||
<!-- #region TranslationRunProgress [C:3] [TYPE Component] [SEMANTICS translate, progress, websocket, batch, status] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/TranslationRunProgress.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [api_module] -->
|
||||
<!-- @UX_STATE idle -> Initial state, no run loaded -->
|
||||
<!-- @UX_STATE running -> Translation phase in progress -->
|
||||
<!-- @UX_STATE inserting -> Insert phase in progress -->
|
||||
<!-- @UX_STATE completed -> All phases completed successfully -->
|
||||
<!-- @UX_STATE partial -> Translation completed with some failures -->
|
||||
<!-- @UX_STATE failed -> Translation phase failed -->
|
||||
<!-- @UX_STATE insert_failed -> Insert phase failed -->
|
||||
<!-- @UX_STATE cancelled -> Run was cancelled -->
|
||||
<!-- @UX_FEEDBACK progress bar with percentage; batch counter; per-phase counts; cancel button during running/inserting. -->
|
||||
<!-- @UX_RECOVERY retry on failure states. -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: WebSocket-driven progress bar with batch counter, success/failure/skip counts, two-phase display, and cancel button.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
* @RELATION: DEPENDS_ON -> [api_module]
|
||||
* @PRE: runId is a valid translation run ID.
|
||||
* @POST: Real-time progress display with two-phase (translation + insert) and state transitions.
|
||||
*
|
||||
* @UX_STATE: idle -> Initial state, no run loaded
|
||||
* @UX_STATE: running -> Translation phase in progress
|
||||
* @UX_STATE: inserting -> Insert phase in progress
|
||||
* @UX_STATE: completed -> All phases completed successfully
|
||||
* @UX_STATE: partial -> Translation completed with some failures
|
||||
* @UX_STATE: failed -> Translation phase failed
|
||||
* @UX_STATE: insert_failed -> Insert phase failed
|
||||
* @UX_STATE: cancelled -> Run was cancelled
|
||||
*
|
||||
* @UX_FEEDBACK: progress bar with percentage; batch counter; per-phase counts; cancel button during running/inserting.
|
||||
* @UX_RECOVERY: retry on failure states.
|
||||
*/
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
|
||||
@@ -1,38 +1,14 @@
|
||||
<!-- #region TranslationRunResult [C:3] [TYPE Component] [SEMANTICS translate, result, stats, retry, sql-audit] -->
|
||||
<!-- @BRIEF Component component: lib/components/translate/TranslationRunResult.svelte -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @PURPOSE Run result display with statistics, insert status badge, Superset query reference, SQL audit block, and retry buttons. -->
|
||||
<!-- @LAYER UI -->
|
||||
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [api_module] -->
|
||||
<!-- @RELATION DEPENDS_ON -> [api_module] -->
|
||||
<!-- @PRE runId is a valid completed/failed/pending run. -->
|
||||
<!-- @POST Results displayed with actions for retry, SQL audit, and Superset reference. -->
|
||||
<!-- @UX_STATE insert_failed -> Insert phase failed, retry-insert available -->
|
||||
<!-- @UX_STATE insert_failed -> Insert phase failed, retry-insert available -->
|
||||
<!-- @UX_STATE insert_failed -> Insert phase failed, retry-insert available -->
|
||||
<!-- @UX_STATE completed -> All phases completed, full stats displayed -->
|
||||
<!-- @UX_STATE partial -> Translation completed with failures, retry available -->
|
||||
<!-- @UX_STATE failed -> Translation failed, retry available -->
|
||||
<!-- @UX_STATE insert_failed -> Insert phase failed, retry-insert available -->
|
||||
<!-- @UX_FEEDBACK Tabular statistics; click to copy Superset query ID; collapsible SQL block. -->
|
||||
<!-- @UX_RECOVERY Retry failed batches; retry insert. -->
|
||||
<!-- @complexity 4 -->
|
||||
<!-- @task connect_orphaned_components -->
|
||||
<script>
|
||||
/**
|
||||
* @PURPOSE: Run result display with statistics, insert status badge, Superset query reference, SQL audit block, and retry buttons.
|
||||
* @LAYER: UI
|
||||
* @RELATION: DEPENDS_ON -> [TranslateApi]
|
||||
* @RELATION: DEPENDS_ON -> [api_module]
|
||||
* @PRE: runId is a valid completed/failed/pending run.
|
||||
* @POST: Results displayed with actions for retry, SQL audit, and Superset reference.
|
||||
*
|
||||
* @UX_STATE: completed -> All phases completed, full stats displayed
|
||||
* @UX_STATE: partial -> Translation completed with failures, retry available
|
||||
* @UX_STATE: failed -> Translation failed, retry available
|
||||
* @UX_STATE: insert_failed -> Insert phase failed, retry-insert available
|
||||
*
|
||||
* @UX_FEEDBACK: Tabular statistics; click to copy Superset query ID; collapsible SQL block.
|
||||
* @UX_RECOVERY: Retry failed batches; retry insert.
|
||||
*/
|
||||
|
||||
import { t } from '$lib/i18n';
|
||||
import { addToast } from '$lib/toasts.js';
|
||||
import {
|
||||
|
||||
Reference in New Issue
Block a user