fix: corretto funzionamento dei filtri per gli stati aperti dei ticket (ignora lo stato dei ticket)
This commit is contained in:
+25
-15
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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)));
|
||||||
|
|||||||
Reference in New Issue
Block a user