Show backend error details in toast notifications

Use error.detail from API responses instead of generic i18n messages
so users see specific reasons for failures (e.g. "Device is referenced
by target(s): ...").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 22:11:24 +03:00
parent 9b2ccde8a7
commit 493d96d604
5 changed files with 10 additions and 14 deletions

View File

@@ -735,7 +735,7 @@ export async function dashboardStartTarget(targetId) {
loadDashboard(); loadDashboard();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('dashboard.error.start_failed'), 'error'); showToast(error.detail || t('dashboard.error.start_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;
@@ -753,7 +753,7 @@ export async function dashboardStopTarget(targetId) {
loadDashboard(); loadDashboard();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('dashboard.error.stop_failed'), 'error'); showToast(error.detail || t('dashboard.error.stop_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;
@@ -772,7 +772,7 @@ export async function dashboardToggleAutoStart(targetId, enable) {
loadDashboard(); loadDashboard();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('dashboard.error.autostart_toggle_failed'), 'error'); showToast(error.detail || t('dashboard.error.autostart_toggle_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;

View File

@@ -150,7 +150,7 @@ export async function removeDevice(deviceId) {
window.loadDevices(); window.loadDevices();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('device.error.remove_failed'), 'error'); showToast(error.detail || t('device.error.remove_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;

View File

@@ -611,7 +611,7 @@ export async function deleteKCTarget(targetId) {
if (typeof window.loadTargetsTab === 'function') window.loadTargetsTab(); if (typeof window.loadTargetsTab === 'function') window.loadTargetsTab();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('kc_target.error.delete_failed'), 'error'); showToast(error.detail || t('kc_target.error.delete_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;

View File

@@ -210,16 +210,12 @@ export async function deletePatternTemplate(templateId) {
const response = await fetchWithAuth(`/pattern-templates/${templateId}`, { const response = await fetchWithAuth(`/pattern-templates/${templateId}`, {
method: 'DELETE', method: 'DELETE',
}); });
if (response.status === 409) {
showToast(t('pattern.delete.referenced'), 'error');
return;
}
if (response.ok) { if (response.ok) {
showToast(t('pattern.deleted'), 'success'); showToast(t('pattern.deleted'), 'success');
if (typeof window.loadTargetsTab === 'function') window.loadTargetsTab(); if (typeof window.loadTargetsTab === 'function') window.loadTargetsTab();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('pattern.error.delete_failed'), 'error'); showToast(error.detail || t('pattern.error.delete_failed'), 'error');
} }
} catch (error) { } catch (error) {
if (error.isAuth) return; if (error.isAuth) return;

View File

@@ -964,7 +964,7 @@ export async function startTargetProcessing(targetId) {
showToast(t('device.started'), 'success'); showToast(t('device.started'), 'success');
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('target.error.start_failed'), 'error'); showToast(error.detail || t('target.error.start_failed'), 'error');
} }
}); });
} }
@@ -978,7 +978,7 @@ export async function stopTargetProcessing(targetId) {
showToast(t('device.stopped'), 'success'); showToast(t('device.stopped'), 'success');
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('target.error.stop_failed'), 'error'); showToast(error.detail || t('target.error.stop_failed'), 'error');
} }
}); });
} }
@@ -1034,7 +1034,7 @@ export async function toggleTargetAutoStart(targetId, enable) {
loadTargetsTab(); loadTargetsTab();
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('target.error.autostart_toggle_failed'), 'error'); showToast(error.detail || t('target.error.autostart_toggle_failed'), 'error');
} }
} catch (error) { } catch (error) {
console.error('Failed to toggle auto-start:', error); console.error('Failed to toggle auto-start:', error);
@@ -1054,7 +1054,7 @@ export async function deleteTarget(targetId) {
showToast(t('targets.deleted'), 'success'); showToast(t('targets.deleted'), 'success');
} else { } else {
const error = await response.json(); const error = await response.json();
showToast(t('target.error.delete_failed'), 'error'); showToast(error.detail || t('target.error.delete_failed'), 'error');
} }
}); });
} }