Group dashboard targets into a collapsible Targets section with Running/Stopped subsections
Wrap running and stopped target lists under a parent Targets group. Fix narrow-screen layout by keeping action buttons inline and hiding metrics below 768px. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -306,23 +306,32 @@ export async function loadDashboard() {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (running.length > 0) {
|
if (targets.length > 0) {
|
||||||
runningIds = running.map(t => t.id);
|
let targetsInner = '';
|
||||||
const stopAllBtn = `<button class="btn btn-sm btn-danger dashboard-stop-all" onclick="event.stopPropagation(); dashboardStopAll()" title="${t('dashboard.stop_all')}">⏹️ ${t('dashboard.stop_all')}</button>`;
|
|
||||||
const runningItems = running.map(target => renderDashboardTarget(target, true, devicesMap)).join('');
|
if (running.length > 0) {
|
||||||
|
runningIds = running.map(t => t.id);
|
||||||
|
const stopAllBtn = `<button class="btn btn-sm btn-danger dashboard-stop-all" onclick="event.stopPropagation(); dashboardStopAll()" title="${t('dashboard.stop_all')}">⏹️ ${t('dashboard.stop_all')}</button>`;
|
||||||
|
const runningItems = running.map(target => renderDashboardTarget(target, true, devicesMap)).join('');
|
||||||
|
|
||||||
|
targetsInner += `<div class="dashboard-subsection">
|
||||||
|
${_sectionHeader('running', t('dashboard.section.running'), running.length, stopAllBtn)}
|
||||||
|
${_sectionContent('running', runningItems)}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopped.length > 0) {
|
||||||
|
const stoppedItems = stopped.map(target => renderDashboardTarget(target, false, devicesMap)).join('');
|
||||||
|
|
||||||
|
targetsInner += `<div class="dashboard-subsection">
|
||||||
|
${_sectionHeader('stopped', t('dashboard.section.stopped'), stopped.length)}
|
||||||
|
${_sectionContent('stopped', stoppedItems)}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
dynamicHtml += `<div class="dashboard-section">
|
dynamicHtml += `<div class="dashboard-section">
|
||||||
${_sectionHeader('running', t('dashboard.section.running'), running.length, stopAllBtn)}
|
${_sectionHeader('targets', t('dashboard.section.targets'), targets.length)}
|
||||||
${_sectionContent('running', runningItems)}
|
${_sectionContent('targets', targetsInner)}
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stopped.length > 0) {
|
|
||||||
const stoppedItems = stopped.map(target => renderDashboardTarget(target, false, devicesMap)).join('');
|
|
||||||
|
|
||||||
dynamicHtml += `<div class="dashboard-section">
|
|
||||||
${_sectionHeader('stopped', t('dashboard.section.stopped'), stopped.length)}
|
|
||||||
${_sectionContent('stopped', stoppedItems)}
|
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -457,6 +457,7 @@
|
|||||||
"overlay.error.start": "Failed to start overlay",
|
"overlay.error.start": "Failed to start overlay",
|
||||||
"overlay.error.stop": "Failed to stop overlay",
|
"overlay.error.stop": "Failed to stop overlay",
|
||||||
"dashboard.title": "📊 Dashboard",
|
"dashboard.title": "📊 Dashboard",
|
||||||
|
"dashboard.section.targets": "Targets",
|
||||||
"dashboard.section.running": "Running",
|
"dashboard.section.running": "Running",
|
||||||
"dashboard.section.stopped": "Stopped",
|
"dashboard.section.stopped": "Stopped",
|
||||||
"dashboard.no_targets": "No targets configured",
|
"dashboard.no_targets": "No targets configured",
|
||||||
|
|||||||
@@ -457,6 +457,7 @@
|
|||||||
"overlay.error.start": "Не удалось запустить наложение",
|
"overlay.error.start": "Не удалось запустить наложение",
|
||||||
"overlay.error.stop": "Не удалось остановить наложение",
|
"overlay.error.stop": "Не удалось остановить наложение",
|
||||||
"dashboard.title": "📊 Обзор",
|
"dashboard.title": "📊 Обзор",
|
||||||
|
"dashboard.section.targets": "Цели",
|
||||||
"dashboard.section.running": "Запущенные",
|
"dashboard.section.running": "Запущенные",
|
||||||
"dashboard.section.stopped": "Остановленные",
|
"dashboard.section.stopped": "Остановленные",
|
||||||
"dashboard.no_targets": "Нет настроенных целей",
|
"dashboard.no_targets": "Нет настроенных целей",
|
||||||
|
|||||||
@@ -3276,6 +3276,14 @@ input:-webkit-autofill:focus {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-subsection {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
.dashboard-subsection .dashboard-section-header {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard-stop-all {
|
.dashboard-stop-all {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
@@ -3454,12 +3462,12 @@ input:-webkit-autofill:focus {
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.dashboard-target {
|
.dashboard-target {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr auto;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-target-actions {
|
.dashboard-target-metrics {
|
||||||
justify-content: flex-end;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user