From 918dbad88f50c38c2e064feb3d3f7c603efd1f5b Mon Sep 17 00:00:00 2001
From: Broque Thomas <26755000+Nezreka@users.noreply.github.com>
Date: Sat, 7 Mar 2026 11:27:53 -0800
Subject: [PATCH] reorganize automations page.
---
webui/static/script.js | 58 ++++++++++++++++++++++++++++++-----
webui/static/style.css | 68 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 117 insertions(+), 9 deletions(-)
diff --git a/webui/static/script.js b/webui/static/script.js
index 9e964ab4..3619b1c1 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -43332,10 +43332,42 @@ const _autoIcons = {
clear_quarantine: '\uD83D\uDDD1\uFE0F', cleanup_wishlist: '\uD83E\uDDF9',
update_discovery_pool: '\uD83E\uDDED', start_quality_scan: '\uD83D\uDCCA',
backup_database: '\uD83D\uDCBE',
+ refresh_beatport_cache: '\uD83C\uDFB5',
+ clean_search_history: '\uD83D\uDDD1\uFE0F',
+ clean_completed_downloads: '\u2705',
};
// --- Load & Render List ---
+function _buildAutomationSection(id, label, automations, useGrid) {
+ const section = document.createElement('div');
+ section.className = 'automations-section';
+ section.id = id;
+ const collapsed = localStorage.getItem('auto_section_' + id) === '1';
+ if (collapsed) section.classList.add('collapsed');
+ const header = document.createElement('div');
+ header.className = 'automations-section-header';
+ header.innerHTML = `
+ ▼
+ ${label}
+ ${automations.length}
+
+ `;
+ header.onclick = () => {
+ section.classList.toggle('collapsed');
+ localStorage.setItem('auto_section_' + id, section.classList.contains('collapsed') ? '1' : '0');
+ };
+ const body = document.createElement('div');
+ body.className = 'automations-section-body';
+ const container = document.createElement('div');
+ container.className = useGrid ? 'automations-grid' : 'automations-user-list';
+ automations.forEach(a => container.appendChild(renderAutomationCard(a)));
+ body.appendChild(container);
+ section.appendChild(header);
+ section.appendChild(body);
+ return section;
+}
+
async function loadAutomations() {
const list = document.getElementById('automations-list');
const empty = document.getElementById('automations-empty');
@@ -43352,18 +43384,27 @@ async function loadAutomations() {
}
empty.style.display = 'none';
list.innerHTML = '';
- automations.forEach(a => list.appendChild(renderAutomationCard(a)));
+
+ const systemAutos = automations.filter(a => a.is_system);
+ const userAutos = automations.filter(a => !a.is_system);
+
+ if (systemAutos.length) {
+ list.appendChild(_buildAutomationSection('auto-section-system', 'System', systemAutos, true));
+ }
+ if (userAutos.length) {
+ list.appendChild(_buildAutomationSection('auto-section-custom', 'My Automations', userAutos, false));
+ }
+
// Stats summary bar
if (statsBar) {
const total = automations.length;
const active = automations.filter(a => a.enabled).length;
- const scheduled = automations.filter(a => a.enabled && a.trigger_type === 'schedule').length;
- const eventBased = automations.filter(a => a.enabled && a.trigger_type !== 'schedule').length;
+ const sys = systemAutos.length;
+ const custom = userAutos.length;
statsBar.innerHTML = `
- ${total} Total
${active} Active
- ${scheduled} Scheduled
- ${eventBased} Event-Based
+ ${sys} System
+ ${custom} Custom
`;
}
// Catch up on current automation progress
@@ -43389,7 +43430,6 @@ function renderAutomationCard(a) {
const thenItems = a.then_actions || [];
const actionDelay = a.action_config && a.action_config.delay ? a.action_config.delay : 0;
const metaParts = [];
- if (a.is_system) metaParts.push('System');
if (a.last_run) metaParts.push('Last: ' + _autoTimeAgo(a.last_run));
const _timerTriggers = ['schedule', 'daily_time', 'weekly_time'];
if (a.next_run && a.enabled && _timerTriggers.includes(a.trigger_type)) metaParts.push('Next: ' + _autoTimeUntil(a.next_run));
@@ -43463,7 +43503,9 @@ function _autoFormatAction(type) {
start_database_update: 'Update Database', run_duplicate_cleaner: 'Run Duplicate Cleaner',
clear_quarantine: 'Clear Quarantine', cleanup_wishlist: 'Clean Up Wishlist',
update_discovery_pool: 'Update Discovery', start_quality_scan: 'Run Quality Scan',
- backup_database: 'Backup Database' };
+ backup_database: 'Backup Database',
+ refresh_beatport_cache: 'Refresh Beatport Cache', clean_search_history: 'Clean Search History',
+ clean_completed_downloads: 'Clean Completed Downloads' };
return labels[type] || type || 'Unknown';
}
function _autoFormatNotify(type) {
diff --git a/webui/static/style.css b/webui/static/style.css
index e257f3cf..32f34b9f 100644
--- a/webui/static/style.css
+++ b/webui/static/style.css
@@ -28820,6 +28820,72 @@ body {
.automations-container { padding: 20px 24px; }
.automations-list { display: flex; flex-direction: column; gap: 0; }
+/* --- Section Headers (System / My Automations) --- */
+.automations-section {
+ margin-bottom: 8px;
+}
+.automations-section:last-child { margin-bottom: 0; }
+.automations-section-header {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 8px 2px 10px;
+ cursor: pointer;
+ user-select: none;
+ -webkit-user-select: none;
+}
+.automations-section-header:hover .section-label { color: rgba(255,255,255,0.85); }
+.section-chevron {
+ font-size: 11px;
+ color: rgba(255,255,255,0.3);
+ transition: transform 0.25s ease;
+ width: 14px;
+ text-align: center;
+ flex-shrink: 0;
+}
+.automations-section.collapsed .section-chevron { transform: rotate(-90deg); }
+.section-label {
+ font-size: 11px;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: rgba(255,255,255,0.4);
+ transition: color 0.2s ease;
+}
+.section-count {
+ font-size: 10px;
+ color: rgba(255,255,255,0.25);
+ padding: 1px 8px;
+ border-radius: 8px;
+ background: rgba(255,255,255,0.04);
+ border: 1px solid rgba(255,255,255,0.06);
+}
+.section-line {
+ flex: 1;
+ height: 1px;
+ background: rgba(255,255,255,0.06);
+}
+.automations-section-body {
+ overflow: hidden;
+ transition: max-height 0.3s ease, opacity 0.25s ease;
+ max-height: 2000px;
+ opacity: 1;
+}
+.automations-section.collapsed .automations-section-body {
+ max-height: 0;
+ opacity: 0;
+}
+
+/* --- System Automations 2-Column Grid --- */
+.automations-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 6px;
+}
+@media (max-width: 800px) {
+ .automations-grid { grid-template-columns: 1fr; }
+}
+
/* --- New Automation Button --- */
.auto-new-btn {
background: linear-gradient(135deg, rgb(var(--accent-rgb)) 0%, rgb(var(--accent-light-rgb)) 100%);
@@ -28892,7 +28958,7 @@ body {
.automation-card.disabled { opacity: 0.55; }
.automation-card.disabled:hover { opacity: 0.75; }
.automation-card.disabled .automation-name { color: rgba(255,255,255,0.5); }
-.automation-card.system { border-left: 3px solid var(--accent, #6366f1); }
+.automation-card.system { border-left: none; padding: 8px 12px; }
.system-badge { display: inline-block; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; padding: 1px 5px; border-radius: 6px; background: rgba(99,102,241,0.2); color: #818cf8; vertical-align: middle; }
.automation-status { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }