feat(translation): "Test connection" button — on-demand Interpreter health check (#143)
CI / lint (push) Successful in 4s
CI / frontend-build (push) Successful in 21s
CI / backend-lint-and-test (push) Successful in 32s
CI / integration (push) Successful in 3m43s

New POST /api/settings/translation/test pings /v1/health for a GIVEN base URL (not
the saved one), so the operator can verify a URL before enabling it. TranslationCard
gains a Test-connection button that reports reachable/unreachable inline and
updates the status dot. Endpoint test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CDgx8bQS5YrGRK76v8HUnM
This commit is contained in:
2026-07-07 13:00:37 -04:00
parent af5aa21e45
commit 6a255482ea
3 changed files with 57 additions and 1 deletions
@@ -28,9 +28,17 @@
@change="onSave"
/>
<div class="d-flex align-center mb-3" style="gap: 8px;">
<div class="d-flex align-center flex-wrap mb-3" style="gap: 8px;">
<v-icon size="12" :color="statusColor">mdi-circle</v-icon>
<span class="fc-muted text-body-2">{{ statusText }}</span>
<v-btn
size="x-small" variant="tonal" rounded="pill" class="ml-2"
:loading="testing" :disabled="!baseUrl" @click="onTest"
>Test connection</v-btn>
<span
v-if="testResult !== null" class="text-caption"
:class="testResult ? 'text-success' : 'text-error'"
>{{ testResult ? ' reachable' : ' unreachable' }}</span>
</div>
<div class="d-flex align-center flex-wrap" style="gap: 10px;">
@@ -67,6 +75,8 @@ const baseUrl = ref('')
const targetLang = ref('en')
const busy = ref(false)
const running = ref(false)
const testing = ref(false)
const testResult = ref(null) // null = not tested this session; true/false = last result
const status = ref(null)
const err = ref(null)
@@ -86,6 +96,25 @@ async function loadStatus() {
catch { status.value = null }
}
async function onTest() {
// Ping /v1/health for the CURRENTLY-typed URL (not the saved one), so a new
// URL can be verified before enabling. Also reflects in the status dot.
testing.value = true
err.value = null
testResult.value = null
try {
const r = await api.post('/api/settings/translation/test', {
body: { base_url: baseUrl.value.trim() },
})
testResult.value = !!r.healthy
if (status.value) status.value.healthy = !!r.healthy
} catch (e) {
err.value = e.message
} finally {
testing.value = false
}
}
onMounted(async () => {
try {
await store.loadSettings()