fix: corretto funzionamento dei filtri per gli stati aperti dei ticket (ignora lo stato dei ticket)

This commit is contained in:
2026-07-21 08:11:16 +02:00
parent f36788510e
commit 9527998b7a
3 changed files with 46 additions and 24 deletions
+25 -15
View File
@@ -90,17 +90,18 @@ db.exec(`
db.exec(` db.exec(`
CREATE TABLE IF NOT EXISTS dashboard_chart_lines ( CREATE TABLE IF NOT EXISTS dashboard_chart_lines (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
statuses TEXT NOT NULL, statuses TEXT NOT NULL,
types TEXT NOT NULL, types TEXT NOT NULL,
queues TEXT NOT NULL, queues TEXT NOT NULL,
owners TEXT NOT NULL, owners TEXT NOT NULL,
responsibles TEXT NOT NULL, responsibles TEXT NOT NULL,
color TEXT, color TEXT,
is_visible INTEGER NOT NULL DEFAULT 1, is_visible INTEGER NOT NULL DEFAULT 1,
is_default INTEGER NOT NULL DEFAULT 0, is_default INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) bypass_state_filter INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
) )
`); `);
@@ -116,22 +117,31 @@ try {
// Already exists // Already exists
} }
try {
db.exec(`ALTER TABLE dashboard_chart_lines ADD COLUMN bypass_state_filter INTEGER NOT NULL DEFAULT 0`);
} catch (e) {
// Already exists
}
try { try {
const countRow = db.prepare("SELECT COUNT(*) AS count FROM dashboard_chart_lines").get(); const countRow = db.prepare("SELECT COUNT(*) AS count FROM dashboard_chart_lines").get();
if (countRow && countRow.count === 0) { if (countRow && countRow.count === 0) {
db.prepare(` db.prepare(`
INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default) INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default, bypass_state_filter)
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1) VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1, 1)
`).run('Ticket aperti', JSON.stringify([1, 4, 6, 7, 8]), '[]', '[]', '[]', '[]', '#4f46e5'); `).run('Ticket aperti', JSON.stringify([1, 4, 6, 7, 8]), '[]', '[]', '[]', '[]', '#4f46e5');
db.prepare(` db.prepare(`
INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default) INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default, bypass_state_filter)
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1) VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1, 0)
`).run('Ticket chiusi', JSON.stringify([2, 3, 10]), '[]', '[]', '[]', '[]', '#10b981'); `).run('Ticket chiusi', JSON.stringify([2, 3, 10]), '[]', '[]', '[]', '[]', '#10b981');
} else { } else {
// Update default ones color if not set yet // Update default ones color if not set yet
db.prepare(`UPDATE dashboard_chart_lines SET color = '#4f46e5' WHERE name = 'Ticket aperti' AND color IS NULL`).run(); db.prepare(`UPDATE dashboard_chart_lines SET color = '#4f46e5' WHERE name = 'Ticket aperti' AND color IS NULL`).run();
db.prepare(`UPDATE dashboard_chart_lines SET color = '#10b981' WHERE name = 'Ticket chiusi' AND color IS NULL`).run(); db.prepare(`UPDATE dashboard_chart_lines SET color = '#10b981' WHERE name = 'Ticket chiusi' AND color IS NULL`).run();
// Set default Ticket aperti to bypass state filter
db.prepare(`UPDATE dashboard_chart_lines SET bypass_state_filter = 1 WHERE name = 'Ticket aperti'`).run();
} }
} catch (e) { } catch (e) {
console.error("Error seeding default chart lines:", e.message); console.error("Error seeding default chart lines:", e.message);
+11 -1
View File
@@ -311,6 +311,14 @@ const DashboardView = {
<div class="multiselect-list" id="form-select-responsibles"></div> <div class="multiselect-list" id="form-select-responsibles"></div>
</div> </div>
<div style="display:flex; align-items:center; gap:var(--space-sm); margin-top:4px; background:var(--bg-offset); padding: var(--space-sm); border-radius: var(--radius-md); border: 1px dashed var(--border-light);">
<input type="checkbox" id="form-series-bypass-state" style="width:18px; height:18px; cursor:pointer; margin:0;">
<label for="form-series-bypass-state" style="font-weight:500; font-size:0.85rem; cursor:pointer; user-select:none; margin:0; display:flex; flex-direction:column;">
<span>Ignora lo stato dei ticket</span>
<span style="font-size:0.75rem; color:var(--text-tertiary); font-weight:normal;">Se attivo, mostra tutti i ticket creati nel periodo indipendentemente dal loro stato attuale.</span>
</label>
</div>
<div style="display:flex; justify-content:flex-end; gap:var(--space-sm); border-top:1px solid var(--border-subtle); padding-top:var(--space-md); margin-top:var(--space-xs); flex-shrink:0;"> <div style="display:flex; justify-content:flex-end; gap:var(--space-sm); border-top:1px solid var(--border-subtle); padding-top:var(--space-md); margin-top:var(--space-xs); flex-shrink:0;">
<button type="button" class="btn btn-ghost btn-sm" id="btn-series-form-cancel">Annulla</button> <button type="button" class="btn btn-ghost btn-sm" id="btn-series-form-cancel">Annulla</button>
<button type="submit" class="btn btn-primary btn-sm">Salva Serie</button> <button type="submit" class="btn btn-primary btn-sm">Salva Serie</button>
@@ -413,6 +421,7 @@ const DashboardView = {
const queues = this.getSelectedIds('form-select-queues'); const queues = this.getSelectedIds('form-select-queues');
const owners = this.getSelectedIds('form-select-owners'); const owners = this.getSelectedIds('form-select-owners');
const responsibles = this.getSelectedIds('form-select-responsibles'); const responsibles = this.getSelectedIds('form-select-responsibles');
const bypass_state_filter = document.getElementById('form-series-bypass-state').checked ? 1 : 0;
// Preserve current visibility if editing // Preserve current visibility if editing
let is_visible = 1; let is_visible = 1;
@@ -421,7 +430,7 @@ const DashboardView = {
if (existing) is_visible = existing.is_visible; if (existing) is_visible = existing.is_visible;
} }
const payload = { name, statuses, types, queues, owners, responsibles, color, is_visible }; const payload = { name, statuses, types, queues, owners, responsibles, color, is_visible, bypass_state_filter };
try { try {
if (seriesId) { if (seriesId) {
@@ -726,6 +735,7 @@ const DashboardView = {
idInput.value = line ? line.id : ''; idInput.value = line ? line.id : '';
nameInput.value = line ? line.name : ''; nameInput.value = line ? line.name : '';
colorInput.value = line ? line.color : '#4f46e5'; colorInput.value = line ? line.color : '#4f46e5';
document.getElementById('form-series-bypass-state').checked = line ? !!line.bypass_state_filter : false;
this.renderMultiselect('form-select-statuses', App.lookups.states || [], statuses); this.renderMultiselect('form-select-statuses', App.lookups.states || [], statuses);
this.renderMultiselect('form-select-types', App.lookups.types || [], types); this.renderMultiselect('form-select-types', App.lookups.types || [], types);
+10 -8
View File
@@ -257,13 +257,13 @@ router.get('/chart-lines', (req, res) => {
// POST /api/dashboard/chart-lines // POST /api/dashboard/chart-lines
router.post('/chart-lines', (req, res) => { router.post('/chart-lines', (req, res) => {
const { name, statuses, types, queues, owners, responsibles, color, is_visible } = req.body; const { name, statuses, types, queues, owners, responsibles, color, is_visible, bypass_state_filter } = req.body;
if (!name) return res.status(400).json({ error: 'Name is required' }); if (!name) return res.status(400).json({ error: 'Name is required' });
try { try {
const info = db.prepare(` const info = db.prepare(`
INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default) INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default, bypass_state_filter)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, ?)
`).run( `).run(
name, name,
JSON.stringify(statuses || []), JSON.stringify(statuses || []),
@@ -272,7 +272,8 @@ router.post('/chart-lines', (req, res) => {
JSON.stringify(owners || []), JSON.stringify(owners || []),
JSON.stringify(responsibles || []), JSON.stringify(responsibles || []),
color || '#4f46e5', color || '#4f46e5',
is_visible !== undefined ? parseInt(is_visible, 10) : 1 is_visible !== undefined ? parseInt(is_visible, 10) : 1,
bypass_state_filter !== undefined ? parseInt(bypass_state_filter, 10) : 0
); );
res.json({ success: true, id: info.lastInsertRowid }); res.json({ success: true, id: info.lastInsertRowid });
} catch (err) { } catch (err) {
@@ -284,13 +285,13 @@ router.post('/chart-lines', (req, res) => {
// PUT /api/dashboard/chart-lines/:id // PUT /api/dashboard/chart-lines/:id
router.put('/chart-lines/:id', (req, res) => { router.put('/chart-lines/:id', (req, res) => {
const { id } = req.params; const { id } = req.params;
const { name, statuses, types, queues, owners, responsibles, color, is_visible } = req.body; const { name, statuses, types, queues, owners, responsibles, color, is_visible, bypass_state_filter } = req.body;
if (!name) return res.status(400).json({ error: 'Name is required' }); if (!name) return res.status(400).json({ error: 'Name is required' });
try { try {
const info = db.prepare(` const info = db.prepare(`
UPDATE dashboard_chart_lines UPDATE dashboard_chart_lines
SET name = ?, statuses = ?, types = ?, queues = ?, owners = ?, responsibles = ?, color = ?, is_visible = ? SET name = ?, statuses = ?, types = ?, queues = ?, owners = ?, responsibles = ?, color = ?, is_visible = ?, bypass_state_filter = ?
WHERE id = ? WHERE id = ?
`).run( `).run(
name, name,
@@ -301,6 +302,7 @@ router.put('/chart-lines/:id', (req, res) => {
JSON.stringify(responsibles || []), JSON.stringify(responsibles || []),
color || '#4f46e5', color || '#4f46e5',
is_visible !== undefined ? parseInt(is_visible, 10) : 1, is_visible !== undefined ? parseInt(is_visible, 10) : 1,
bypass_state_filter !== undefined ? parseInt(bypass_state_filter, 10) : 0,
id id
); );
if (info.changes === 0) return res.status(404).json({ error: 'Line not found' }); if (info.changes === 0) return res.status(404).json({ error: 'Line not found' });
@@ -362,7 +364,7 @@ router.get('/chart-data', async (req, res) => {
params.push(end_date + ' 23:59:59'); params.push(end_date + ' 23:59:59');
const statuses = JSON.parse(line.statuses || '[]'); const statuses = JSON.parse(line.statuses || '[]');
if (statuses.length > 0) { if (statuses.length > 0 && !line.bypass_state_filter) {
const placeholders = statuses.map(() => `$${paramIdx++}`).join(', '); const placeholders = statuses.map(() => `$${paramIdx++}`).join(', ');
conditions.push(`t.ticket_state_id IN (${placeholders})`); conditions.push(`t.ticket_state_id IN (${placeholders})`);
params.push(...statuses.map(id => parseInt(id))); params.push(...statuses.map(id => parseInt(id)));
@@ -473,7 +475,7 @@ router.get('/export-excel', async (req, res) => {
params.push(end_date + ' 23:59:59'); params.push(end_date + ' 23:59:59');
const statuses = JSON.parse(line.statuses || '[]'); const statuses = JSON.parse(line.statuses || '[]');
if (statuses.length > 0) { if (statuses.length > 0 && !line.bypass_state_filter) {
const placeholders = statuses.map(() => `$${paramIdx++}`).join(', '); const placeholders = statuses.map(() => `$${paramIdx++}`).join(', ');
conditions.push(`t.ticket_state_id IN (${placeholders})`); conditions.push(`t.ticket_state_id IN (${placeholders})`);
params.push(...statuses.map(id => parseInt(id))); params.push(...statuses.map(id => parseInt(id)));