This PR breaks the large web and player bootstrap files into smaller modules with clearer ownership.
Web changes: Split shared helpers, bootstrap logic, route groups, and upload-sync behavior out of web.js. Kept web.js focused on wiring and server startup. Fixed screen playlist reassignment so changing a screen’s playlist now triggers a refresh. Fixed single-slide playlist refresh behavior so updates do not get stuck behind the current slide. Player changes: Split websocket/runtime handling into runtime.js. Split playlist assembly and revision hashing into playlist.js. Split onboarding and player HTTP routes into dedicated modules. Split render utilities and template loading into render-helpers.js. Kept player.js mostly as startup/orchestration. Validation: Rebuilt both services with Docker Compose. Smoke-checked web and player routes after the refactor. Verified get_errors was clean on the touched modules.
This commit is contained in:
@@ -69,6 +69,45 @@
|
||||
return table._sortableState;
|
||||
}
|
||||
|
||||
function ensureSortableHeaderIndicator(headerCell) {
|
||||
var indicator = headerCell.querySelector && headerCell.querySelector('.table-sort-indicator');
|
||||
if (indicator) {
|
||||
return indicator;
|
||||
}
|
||||
|
||||
indicator = document.createElement('i');
|
||||
indicator.className = 'table-sort-indicator bi bi-arrow-down-up ms-1';
|
||||
indicator.setAttribute('aria-hidden', 'true');
|
||||
headerCell.appendChild(indicator);
|
||||
return indicator;
|
||||
}
|
||||
|
||||
function updateSortableHeaderIndicator(headerCell, isSortable, isActive, direction) {
|
||||
if (!isSortable) {
|
||||
var hiddenIndicator = headerCell.querySelector && headerCell.querySelector('.table-sort-indicator');
|
||||
if (hiddenIndicator) {
|
||||
hiddenIndicator.style.display = 'none';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var indicator = ensureSortableHeaderIndicator(headerCell);
|
||||
indicator.style.display = '';
|
||||
indicator.className = 'table-sort-indicator bi ms-1';
|
||||
|
||||
if (isActive && direction === 'desc') {
|
||||
indicator.classList.add('bi-caret-down-fill');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isActive && direction === 'asc') {
|
||||
indicator.classList.add('bi-caret-up-fill');
|
||||
return;
|
||||
}
|
||||
|
||||
indicator.classList.add('bi-arrow-down-up');
|
||||
}
|
||||
|
||||
function isSortableTableColumn(table, columnIndex) {
|
||||
var headerCell = table.tHead && table.tHead.rows && table.tHead.rows.length ? table.tHead.rows[0].cells[columnIndex] : null;
|
||||
if (!headerCell) {
|
||||
@@ -100,13 +139,15 @@
|
||||
if (!headerCell) {
|
||||
return;
|
||||
}
|
||||
var sortable = isSortableTableColumn(table, index);
|
||||
headerCell.classList.remove('sort-asc', 'sort-desc', 'sortable', 'unsortable');
|
||||
headerCell.removeAttribute('aria-sort');
|
||||
headerCell.removeAttribute('role');
|
||||
headerCell.removeAttribute('tabindex');
|
||||
|
||||
if (isSortableTableColumn(table, index)) {
|
||||
if (sortable) {
|
||||
headerCell.classList.add('sortable');
|
||||
updateSortableHeaderIndicator(headerCell, true, state.columnIndex === index, state.direction);
|
||||
headerCell.setAttribute('role', 'button');
|
||||
headerCell.setAttribute('tabindex', '0');
|
||||
if (state.columnIndex === index) {
|
||||
@@ -117,6 +158,7 @@
|
||||
}
|
||||
} else {
|
||||
headerCell.classList.add('unsortable');
|
||||
updateSortableHeaderIndicator(headerCell, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -168,6 +210,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
ensureSortableHeaderIndicator(headerCell);
|
||||
|
||||
headerCell.addEventListener('click', function () {
|
||||
var state = getSortableTableState(table);
|
||||
var nextDirection = state.columnIndex === index && state.direction === 'asc' ? 'desc' : 'asc';
|
||||
|
||||
Reference in New Issue
Block a user