Add manual ping/health check button to device cards

Adds a refresh icon button on each device card that triggers an immediate
health check via POST /devices/{id}/ping, showing online status with
latency or offline result as a toast notification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 12:51:40 +03:00
parent 27884282a7
commit 6a22757755
8 changed files with 76 additions and 2 deletions

View File

@@ -31,7 +31,7 @@ import {
import {
showSettings, closeDeviceSettingsModal, forceCloseDeviceSettingsModal,
saveDeviceSettings, updateBrightnessLabel, saveCardBrightness,
turnOffDevice, removeDevice, loadDevices,
turnOffDevice, pingDevice, removeDevice, loadDevices,
updateSettingsBaudFpsHint, copyWsUrl,
} from './features/devices.js';
import {
@@ -211,6 +211,7 @@ Object.assign(window, {
updateBrightnessLabel,
saveCardBrightness,
turnOffDevice,
pingDevice,
removeDevice,
loadDevices,
updateSettingsBaudFpsHint,

View File

@@ -11,7 +11,7 @@ import { _fetchOpenrgbZones, _getCheckedZones, _splitOpenrgbZone, _getZoneMode }
import { t } from '../core/i18n.js';
import { showToast, showConfirm } from '../core/ui.js';
import { Modal } from '../core/modal.js';
import { ICON_SETTINGS, ICON_STOP_PLAIN, ICON_LED, ICON_WEB, ICON_PLUG } from '../core/icons.js';
import { ICON_SETTINGS, ICON_STOP_PLAIN, ICON_LED, ICON_WEB, ICON_PLUG, ICON_REFRESH } from '../core/icons.js';
import { wrapCard } from '../core/card-colors.js';
import { TagInput, renderTagChips } from '../core/tag-input.js';
@@ -133,6 +133,9 @@ export function createDeviceCard(device) {
</div>` : ''}
${renderTagChips(device.tags)}`,
actions: `
<button class="btn btn-icon btn-secondary card-ping-btn" onclick="event.stopPropagation(); pingDevice('${device.id}')" title="${t('device.button.ping')}">
${ICON_REFRESH}
</button>
<button class="btn btn-icon btn-secondary" onclick="showSettings('${device.id}')" title="${t('device.button.settings')}">
${ICON_SETTINGS}
</button>`,
@@ -157,6 +160,32 @@ export async function turnOffDevice(deviceId) {
}
}
export async function pingDevice(deviceId) {
const btn = document.querySelector(`[data-device-id="${deviceId}"] .card-ping-btn`);
if (btn) btn.classList.add('spinning');
try {
const resp = await fetchWithAuth(`/devices/${deviceId}/ping`, { method: 'POST' });
if (resp.ok) {
const data = await resp.json();
const ms = data.device_latency_ms != null ? data.device_latency_ms.toFixed(0) : '?';
showToast(data.device_online
? t('device.ping.online', { ms })
: t('device.ping.offline'), data.device_online ? 'success' : 'error');
// Refresh device cards to update health dot
devicesCache.invalidate();
await window.loadDevices();
} else {
const err = await resp.json();
showToast(err.detail || 'Ping failed', 'error');
}
} catch (error) {
if (error.isAuth) return;
showToast(t('device.ping.error'), 'error');
} finally {
if (btn) btn.classList.remove('spinning');
}
}
export function attachDeviceListeners(deviceId) {
// Add any specific event listeners here if needed
}