diff --git a/activityDb.js b/activityDb.js index 7117455..a5c7231 100644 --- a/activityDb.js +++ b/activityDb.js @@ -27,6 +27,20 @@ db.exec(` ) `); +db.exec(` + CREATE TABLE IF NOT EXISTS agent_settings ( + agent_id INTEGER PRIMARY KEY, + preview_limit INTEGER NOT NULL DEFAULT 10, + tickets_per_page INTEGER NOT NULL DEFAULT 50 + ) +`); + +try { + db.exec(`ALTER TABLE agent_settings ADD COLUMN tickets_per_page INTEGER NOT NULL DEFAULT 50`); +} catch (e) { + // Column already exists +} + /** * Generate a UUID v7 (time-ordered). */ diff --git a/public/js/views/dashboard.js b/public/js/views/dashboard.js index 3ec46f0..3333ab3 100644 --- a/public/js/views/dashboard.js +++ b/public/js/views/dashboard.js @@ -88,7 +88,19 @@ const DashboardView = {
-
Ticket Recenti
+
+
Ticket Recenti
+
+ Mostra: + +
+
${(stats.recent_tickets || []).length > 0 ? ` @@ -132,6 +144,24 @@ const DashboardView = { }); }); + // Bind preview limit change event + const limitSelect = document.getElementById('dashboard-preview-limit'); + if (limitSelect) { + limitSelect.addEventListener('change', async () => { + const newLimit = parseInt(limitSelect.value, 10); + try { + await App.api('/api/dashboard/settings', { + method: 'POST', + body: JSON.stringify({ preview_limit: newLimit }), + }); + Toast.success(`Limite anteprima aggiornato a ${newLimit} ticket!`); + this.render(); + } catch (err) { + Toast.error('Errore durante il salvataggio dell\'impostazione: ' + err.message); + } + }); + } + // Update open ticket count in sidebar badge const badge = document.getElementById('open-ticket-count'); if (badge) { diff --git a/public/js/views/ticketList.js b/public/js/views/ticketList.js index 0ffed0f..7ad14a0 100644 --- a/public/js/views/ticketList.js +++ b/public/js/views/ticketList.js @@ -19,6 +19,16 @@ const TicketListView = { // Fetch lookups for filter dropdowns await App.ensureLookups(); + // Fetch agent settings for tickets_per_page + try { + const settings = await App.api('/api/dashboard/settings'); + if (settings && settings.tickets_per_page) { + this.perPage = settings.tickets_per_page; + } + } catch (err) { + console.warn('Failed to load agent settings:', err); + } + // Build query params const isMyTickets = window.location.hash.startsWith('#/tickets/my'); Filters.currentMode = isMyTickets ? 'my' : 'general'; @@ -168,6 +178,19 @@ const TicketListView = { renderPagination(page, per_page, total, total_pages, isTop) { const marginStyle = isTop ? 'margin-bottom: var(--space-md); margin-top: 0;' : 'margin-top: var(--space-md); margin-bottom: 0;'; + const limitSelectHtml = ` +
+ Righe: + +
+ `; + if (total_pages > 1) { return `
+ ${limitSelectHtml} ${this.renderPageButtons(page, total_pages)} @@ -187,7 +211,9 @@ const TicketListView = { return ` `; } @@ -400,6 +426,25 @@ const TicketListView = { this.render(); }); }); + + // Page size change + document.querySelectorAll('.ticket-per-page-select').forEach(select => { + select.addEventListener('change', async () => { + const newLimit = parseInt(select.value, 10); + try { + await App.api('/api/dashboard/settings', { + method: 'POST', + body: JSON.stringify({ tickets_per_page: newLimit }), + }); + Toast.success(`Righe per pagina aggiornate a ${newLimit}!`); + this.perPage = newLimit; + this.currentPage = 1; + this.render(); + } catch (err) { + Toast.error('Errore durante il salvataggio dell\'impostazione: ' + err.message); + } + }); + }); }, updateBatchBar() { diff --git a/routes/dashboard.js b/routes/dashboard.js index feaf8f7..a47070a 100644 --- a/routes/dashboard.js +++ b/routes/dashboard.js @@ -74,6 +74,17 @@ seedPhrases(); // GET /api/dashboard/stats — Dashboard statistics router.get('/stats', async (req, res) => { const activeAgentId = parseInt(req.headers['x-agent-id'], 10) || 1; + + let previewLimit = 10; + try { + const row = db.prepare("SELECT preview_limit FROM agent_settings WHERE agent_id = ?").get(activeAgentId); + if (row) { + previewLimit = row.preview_limit; + } + } catch (err) { + console.error('Error reading agent_settings:', err.message); + } + try { // All queries in parallel for speed const [ @@ -138,7 +149,7 @@ router.get('/stats', async (req, res) => { JOIN ticket_state_type tst ON ts.type_id = tst.id WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')` ), - // 10 most recent tickets + // Custom most recent tickets based on agent settings pool.query( `SELECT t.id, t.tn, t.title, ts.name AS state_name, tp.name AS priority_name, tp.color AS priority_color, @@ -148,7 +159,8 @@ router.get('/stats', async (req, res) => { JOIN ticket_priority tp ON t.ticket_priority_id = tp.id JOIN queue q ON t.queue_id = q.id ORDER BY t.create_time DESC - LIMIT 10` + LIMIT $1`, + [previewLimit] ), // Escalated tickets pool.query( @@ -164,7 +176,7 @@ router.get('/stats', async (req, res) => { JOIN ticket_state_type tst ON ts.type_id = tst.id WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto') AND t.user_id = $1`, - [activeAgentId] + [activeAgentId] ), ]); @@ -178,6 +190,7 @@ router.get('/stats', async (req, res) => { recent_tickets: recentTickets.rows, escalated: parseInt(escalated.rows[0].count), total_my_open: parseInt(myOpenCount.rows[0].count), + preview_limit: previewLimit, }); } catch (err) { console.error('Error fetching dashboard stats:', err); @@ -206,4 +219,47 @@ router.get('/phrases', (req, res) => { } }); +// GET /api/dashboard/settings — Retrieve settings for the agent +router.get('/settings', (req, res) => { + const activeAgentId = parseInt(req.headers['x-agent-id'], 10) || 1; + try { + const row = db.prepare("SELECT preview_limit, tickets_per_page FROM agent_settings WHERE agent_id = ?").get(activeAgentId); + if (row) { + res.json(row); + } else { + res.json({ preview_limit: 10, tickets_per_page: 50 }); + } + } catch (err) { + console.error('Error reading agent settings:', err); + res.status(500).json({ error: err.message }); + } +}); + +// POST /api/dashboard/settings — Save settings for the agent +router.post('/settings', (req, res) => { + const activeAgentId = parseInt(req.headers['x-agent-id'], 10) || 1; + const { preview_limit, tickets_per_page } = req.body; + + try { + let currentSettings = { preview_limit: 10, tickets_per_page: 50 }; + const row = db.prepare("SELECT preview_limit, tickets_per_page FROM agent_settings WHERE agent_id = ?").get(activeAgentId); + if (row) { + currentSettings = row; + } + + const newPreviewLimit = preview_limit !== undefined ? parseInt(preview_limit, 10) : currentSettings.preview_limit; + const newTicketsPerPage = tickets_per_page !== undefined ? parseInt(tickets_per_page, 10) : currentSettings.tickets_per_page; + + db.prepare(` + INSERT OR REPLACE INTO agent_settings (agent_id, preview_limit, tickets_per_page) + VALUES (?, ?, ?) + `).run(activeAgentId, newPreviewLimit, newTicketsPerPage); + + res.json({ success: true, preview_limit: newPreviewLimit, tickets_per_page: newTicketsPerPage }); + } catch (err) { + console.error('Error saving agent settings:', err); + res.status(500).json({ error: err.message }); + } +}); + module.exports = router;