Fix automation badge overflow, dashboard crosslinks, compact numbers, icon grids, OpenRGB brightness

UI fixes:
- Automation card badge moved to flex layout — title truncates, badge stays visible
- Automation condition pills max-width increased to 280px
- Dashboard crosslinks fixed: pass correct sub-tab key (led-targets not led)
- navigateToCard only skips data load when tab already has cards in DOM
- Badge gets white-space:nowrap + flex-shrink:0 to prevent wrapping

New features:
- formatCompact() for large frame/error counters (1.2M, 45.2K) with hover title
- Log filter and log level selects replaced with IconSelect grids
- OpenRGB devices now support software brightness control

OpenRGB improvements:
- Added brightness_control capability (uses software brightness fallback)
- Change-threshold dedup compares raw pixels before brightness scaling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 01:29:17 +03:00
parent 304fa24389
commit 29b43b028d
16 changed files with 143 additions and 35 deletions

View File

@@ -5,7 +5,7 @@
import { apiKey, _dashboardLoading, set_dashboardLoading, dashboardPollInterval, setDashboardPollInterval, colorStripSourcesCache, devicesCache, outputTargetsCache } from '../core/state.js';
import { API_BASE, getHeaders, fetchWithAuth, escapeHtml } from '../core/api.js';
import { t } from '../core/i18n.js';
import { showToast, showConfirm, formatUptime, setTabRefreshing } from '../core/ui.js';
import { showToast, showConfirm, formatUptime, formatCompact, setTabRefreshing } from '../core/ui.js';
import { renderPerfSection, initPerfCharts, startPerfPolling, stopPerfPolling } from './perf-charts.js';
import { startAutoRefresh, updateTabBadge } from './tabs.js';
import {
@@ -189,7 +189,7 @@ function _updateRunningMetrics(enrichedRunning) {
}
const errorsEl = cached?.errors || document.querySelector(`[data-errors-text="${target.id}"]`);
if (errorsEl) errorsEl.innerHTML = `${errors > 0 ? ICON_WARNING : ICON_OK} ${errors}`;
if (errorsEl) { errorsEl.innerHTML = `${errors > 0 ? ICON_WARNING : ICON_OK} ${formatCompact(errors)}`; errorsEl.title = String(errors); }
// Update health dot — prefer streaming reachability when processing
const isLed = target.target_type === 'led' || target.target_type === 'wled';
@@ -542,7 +542,7 @@ function renderDashboardTarget(target, isRunning, devicesMap = {}, cssSourceMap
const isLed = target.target_type === 'led' || target.target_type === 'wled';
const icon = ICON_TARGET;
const typeLabel = isLed ? t('dashboard.type.led') : t('dashboard.type.kc');
const navSubTab = isLed ? 'led' : 'key_colors';
const navSubTab = isLed ? 'led-targets' : 'kc-targets';
const navSection = isLed ? 'led-targets' : 'kc-targets';
const navAttr = isLed ? 'data-target-id' : 'data-kc-target-id';
const navOnclick = `if(!event.target.closest('button')){navigateToCard('targets','${navSubTab}','${navSection}','${navAttr}','${target.id}')}`;
@@ -607,7 +607,7 @@ function renderDashboardTarget(target, isRunning, devicesMap = {}, cssSourceMap
<div class="dashboard-metric-value" data-uptime-text="${target.id}">${ICON_CLOCK} ${uptime}</div>
</div>
<div class="dashboard-metric" title="${t('dashboard.errors')}">
<div class="dashboard-metric-value" data-errors-text="${target.id}">${errors > 0 ? ICON_WARNING : ICON_OK} ${errors}</div>
<div class="dashboard-metric-value" data-errors-text="${target.id}" title="${errors}">${errors > 0 ? ICON_WARNING : ICON_OK} ${formatCompact(errors)}</div>
</div>
</div>
<div class="dashboard-target-actions">