Rework device type view to group by deviceType tag

- /api/devices now groups hosts by deviceType tag instead of host group;
  hosts without the tag are skipped
- /api/detail device lookup filters by deviceType tag instead of groupid
- getTag() is now case-insensitive on the tag name
- Removed selectHostGroups from fetchKFCData (no longer needed)
- Frontend: hex id and Zabbix deep-link use deviceType instead of groupid
- Smaller hex label (1.2rem) for device type view via hex-item--device class
- Skip DOM re-render on auto-refresh when data is unchanged (lastDataKey diff)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 14:59:17 +02:00
parent 55b9935f5b
commit 101aaa6e32
3 changed files with 32 additions and 21 deletions

View File

@@ -36,6 +36,7 @@ let refreshTimer = null;
let zabbixUrl = '';
let customerTagValue = 'QWE';
let hasRendered = false;
let lastDataKey = null;
const REFRESH_MS = 30_000;
/* ── Boot ────────────────────────────────────────────────────────────────── */
@@ -58,6 +59,7 @@ function initControls() {
btn.classList.add('active');
currentView = btn.dataset.view;
hasRendered = false;
lastDataKey = null;
loadData();
});
});
@@ -87,8 +89,12 @@ async function loadData() {
apiFetch(endpoint),
apiFetch('/api/stats').catch(() => ({})),
]);
renderCountryColumns(items, stats);
updateSummary(items);
const key = JSON.stringify({ items, stats });
if (key !== lastDataKey) {
lastDataKey = key;
renderCountryColumns(items, stats);
updateSummary(items);
}
setLastUpdated(new Date());
hasRendered = true;
} catch (e) {
@@ -195,13 +201,13 @@ function buildHex(item) {
const sev = item.severity;
const info = sevInfo(sev);
const label = item.location || item.name || '—';
const id = item.location || item.groupid || '';
const id = item.location || item.deviceType || '';
const type = item.location ? 'restaurant' : 'device';
const issues = item.problemCount || 0;
const hosts = item.hostCount || 0;
const el = document.createElement('div');
el.className = `hex-item sev-${sev}`;
el.className = `hex-item sev-${sev}${type === 'device' ? ' hex-item--device' : ''}`;
el.style.background = info.color;
el.title = `${label}\n${hosts} host(s) · ${issues} issue(s) · ${info.label}\n\nClick: details Double-click: open in Zabbix`;
@@ -364,10 +370,12 @@ function buildZabbixProblemsUrl(type, id) {
p.push(`tags[1][value]=${encodeURIComponent(id)}`);
p.push(`tags[1][operator]=1`);
} else {
p.push(`groupids[]=${encodeURIComponent(id)}`);
p.push(`tags[0][tag]=customer`);
p.push(`tags[0][value]=${encodeURIComponent(customerTagValue)}`);
p.push(`tags[0][operator]=1`);
p.push(`tags[1][tag]=deviceType`);
p.push(`tags[1][value]=${encodeURIComponent(id)}`);
p.push(`tags[1][operator]=1`);
}
return `${zabbixUrl}/zabbix.php?${p.join('&')}`;

View File

@@ -317,6 +317,11 @@ header {
.hex-item:active { transform: scale(0.97); }
.hex-item--device .hex-label {
font-size: 1.2rem;
font-weight: 700;
}
.hex-label {
font-size: 1.8rem;
font-weight: 800;