From 5eee217f500732ea93e9c7e000d12aca0929a1a8 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 23 Dec 2025 17:34:32 +0000 Subject: [PATCH] Add sort dropdown and consistent button widths to devices page - Add sort dropdown: Extension, Name, Category, Status (Online first), Transport - Consistent width for action selects (95px) and buttons (65px) - Extract renderDevices() function for re-sorting without API calls - Store statusCache globally for sort comparisons --- easy-asterisk-v0.10.0.sh | 100 ++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/easy-asterisk-v0.10.0.sh b/easy-asterisk-v0.10.0.sh index c890bdc..25bbd9b 100644 --- a/easy-asterisk-v0.10.0.sh +++ b/easy-asterisk-v0.10.0.sh @@ -4399,6 +4399,11 @@ HTML_TEMPLATE = ''' .btn-primary { background: var(--primary); color: white; } .btn-danger { background: var(--danger); color: white; } .btn-sm { padding: 4px 10px; font-size: 0.8rem; } + .action-select { width: 95px; padding: 5px 4px; font-size: 12px; border: 1px solid #ccc; border-radius: 4px; } + .action-btn { width: 65px; padding: 5px 4px; font-size: 12px; } + .sort-control { display: flex; align-items: center; gap: 8px; } + .sort-control label { font-size: 13px; color: #666; } + .sort-control select { padding: 5px 8px; font-size: 13px; border: 1px solid #ccc; border-radius: 4px; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: 500; } .form-control { @@ -4482,7 +4487,17 @@ HTML_TEMPLATE = '''

Registered Devices

-
+
+
+ + +
@@ -4692,6 +4707,8 @@ HTML_TEMPLATE = ''' let roomsCache = []; let categoriesCache = []; let devicesCache = []; + let statusCache = {}; + let currentSort = 'extension'; // Tab switching document.querySelectorAll('.tab').forEach(tab => { @@ -4723,6 +4740,59 @@ HTML_TEMPLATE = ''' ).join(''); } + function sortDevices(sortBy) { + currentSort = sortBy; + renderDevices(); + } + + function getSortedDevices() { + const devices = [...devicesCache]; + switch (currentSort) { + case 'extension': + return devices.sort((a, b) => parseInt(a.extension) - parseInt(b.extension)); + case 'name': + return devices.sort((a, b) => a.name.localeCompare(b.name)); + case 'category': + return devices.sort((a, b) => a.category.localeCompare(b.category)); + case 'status': + return devices.sort((a, b) => { + const aOnline = statusCache[a.extension] === 'online' ? 0 : 1; + const bOnline = statusCache[b.extension] === 'online' ? 0 : 1; + return aOnline - bOnline || parseInt(a.extension) - parseInt(b.extension); + }); + case 'transport': + return devices.sort((a, b) => a.transport.localeCompare(b.transport)); + default: + return devices; + } + } + + function renderDevices() { + const devices = getSortedDevices(); + const tbody = document.getElementById('devices-table'); + tbody.innerHTML = devices.map(d => ` + + ${d.extension} + ${d.name} + ${d.category} + ${d.transport.toUpperCase()} + ${statusCache[d.extension] || 'offline'} + + + + + + + + `).join(''); + } + async function loadDevices() { try { const [devicesRes, statusRes, roomsRes, catRes] = await Promise.all([ @@ -4732,36 +4802,12 @@ HTML_TEMPLATE = ''' fetch(API_BASE + '/categories') ]); const devices = await devicesRes.json(); - const status = await statusRes.json(); + statusCache = await statusRes.json(); roomsCache = await roomsRes.json(); categoriesCache = await catRes.json(); - // Sort by extension - devices.sort((a, b) => parseInt(a.extension) - parseInt(b.extension)); devicesCache = devices; - - const tbody = document.getElementById('devices-table'); - tbody.innerHTML = devices.map(d => ` - - ${d.extension} - ${d.name} - ${d.category} - ${d.transport.toUpperCase()} - ${status[d.extension] || 'offline'} - - - - - - - - `).join(''); + renderDevices(); // Update category select in add device form document.getElementById('category-select').innerHTML = categoriesCache.map(c =>