// Connected client route registration and dashboard wiring. module.exports = function registerClientsRoutes(app, deps) { const pool = deps.pool; const common = deps.common; const pages = deps.pages; const buildDashboardState = deps.buildDashboardState; const { buildPagination } = require('../../../lib/pagination'); const { compareSortValues, createSearchMatcher, getComparableSortValue } = require('../../../lib/list-query'); const requirePermission = deps.requirePermission; const LIST_PAGE_SIZE = 25; function sortClients(clients, sortKey, sortDirection) { const normalizedSortKey = String(sortKey || '').trim(); const normalizedDirection = String(sortDirection || '').trim().toLowerCase() === 'desc' ? 'desc' : 'asc'; const accessors = { client: function (client) { return String(client && (client.client_name || client.name || client.clientId) || '').trim(); }, screen: function (client) { return String(client && (client.screen_name || client.screen_slug) || '').trim(); }, slide: function (client) { return String(client && client.currentSlideTitle || '').trim(); }, viewport: function (client) { const viewport = client && client.viewport; if (!viewport || !viewport.width || !viewport.height) { return ''; } return `${Number(viewport.width) || 0}x${Number(viewport.height) || 0}`; }, connected: function (client) { return String(client && (client.connectedAt || client.lastSeenAt) || '').trim(); } }; function compareValues(leftValue, rightValue) { return compareSortValues(getComparableSortValue(leftValue), getComparableSortValue(rightValue)); } const sortKeys = accessors[normalizedSortKey] ? [normalizedSortKey] : ['client']; return (Array.isArray(clients) ? clients.slice() : []).sort(function (leftClient, rightClient) { for (let index = 0; index < sortKeys.length; index += 1) { const sortKeyName = sortKeys[index]; const comparison = compareValues(accessors[sortKeyName](leftClient), accessors[sortKeyName](rightClient)); if (comparison !== 0) { return index === 0 && normalizedDirection === 'desc' ? comparison * -1 : comparison; } } return 0; }); } app.get('/clients', requirePermission('clients.read'), async function (req, res, next) { try { const data = await buildDashboardState(pool); const page = Math.max(1, Math.floor(Number(req.query.page) || 1)); const search = common.getSearchQuery(req); const sort = common.getSortQuery(req); const direction = common.getSortDirectionQuery(req); const matchesSearch = createSearchMatcher(search, [ 'name', 'client_name', 'clientId', 'deviceId', 'slug', 'screen_slug', 'status' ]); const filteredClients = (data.clients || []).filter(matchesSearch); const sortedClients = sortClients(filteredClients, sort, direction); const startIndex = (page - 1) * LIST_PAGE_SIZE; const clients = sortedClients.slice(startIndex, startIndex + LIST_PAGE_SIZE); res.send(pages.renderConnectedClientsPage({ screens: data.screens || [], clients: clients, pagination: buildPagination(sortedClients.length, page, 'page', { search: search, sort: sort, direction: direction }, LIST_PAGE_SIZE, 'clients', 'Client pages') }, req.query.message ? String(req.query.message) : '', req.currentUser)); } catch (error) { next(error); } }); };