From ec1fb25d4e7dd8724f11d42a21699db0123b05a2 Mon Sep 17 00:00:00 2001 From: Gabriele Cimaschi Date: Wed, 9 Sep 2026 11:21:58 +0200 Subject: [PATCH] fix: corretto tempo di visualizzazione che non considerava la variabile. style: aggiunto pulsante per eliminare precedenti env. --- public/js/app.js | 12 ++++++++- public/js/views/envConfig.js | 48 ++++++++++++++++++++++++++++++++++++ routes/config.js | 39 +++++++++++++++++++++++++++++ routes/lookups.js | 2 +- routes/tickets.js | 4 +-- 5 files changed, 101 insertions(+), 4 deletions(-) diff --git a/public/js/app.js b/public/js/app.js index e3be841..44a1374 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -508,7 +508,13 @@ const App = { /** Ensure lookup data is loaded (cached) */ async ensureLookups(forceRefresh = false) { - if (this.lookupsLoaded && !forceRefresh) return; + if (this.lookupsLoaded && !forceRefresh) { + const freshConfig = await this.api('/api/config').catch(() => null); + if (freshConfig && this.lookups) { + this.lookups.config = freshConfig; + } + return; + } // Check localStorage cache first if not forcing refresh if (!forceRefresh) { @@ -519,6 +525,10 @@ const App = { if (!this.lookups.config || this.lookups.config.autoTimeMinHour === undefined || !this.lookups.customerUsers || !this.lookups.customer_users_version_1) { throw new Error('Outdated config cache (missing autoTimeMinHour or customerUsers)'); } + const freshConfig = await this.api('/api/config').catch(() => null); + if (freshConfig) { + this.lookups.config = freshConfig; + } this.lookupsLoaded = true; return; } catch (e) { diff --git a/public/js/views/envConfig.js b/public/js/views/envConfig.js index 835683d..5f1e641 100644 --- a/public/js/views/envConfig.js +++ b/public/js/views/envConfig.js @@ -125,6 +125,9 @@ const EnvConfigView = {
#${h.id} + ${isCurrentVersion ? `Attuale` : ''}
${formattedDate} @@ -176,6 +179,11 @@ const EnvConfigView = { this.currentContent = content; this.history = res.history || []; + try { + await App.ensureLookups(true); + App.updateDailyTimer(); + } catch (_) {} + // Re-render history panel const historyListDiv = document.getElementById('env-history-list'); if (historyListDiv) { @@ -237,6 +245,11 @@ const EnvConfigView = { this.currentContent = res.content || record.content; this.history = res.history || []; + try { + await App.ensureLookups(true); + App.updateDailyTimer(); + } catch (_) {} + const editorTextarea = document.getElementById('env-editor-content'); if (editorTextarea) { editorTextarea.value = this.currentContent; @@ -254,6 +267,41 @@ const EnvConfigView = { } }); }); + + // Delete buttons + document.querySelectorAll('.env-history-delete-btn').forEach(btn => { + btn.addEventListener('click', async () => { + const id = parseInt(btn.dataset.id, 10); + const record = this.history.find(h => h.id === id); + if (!record) return; + + const confirmed = await App.confirm( + `Eliminazione Versione #${record.id}`, + `Sei sicuro di voler eliminare permanentemente la versione #${record.id} dallo storico?` + ); + + if (!confirmed) return; + + try { + btn.disabled = true; + const res = await App.api(`/api/config/env/history/${id}`, { + method: 'DELETE' + }); + + Toast.success(res.message || `Versione #${id} eliminata dallo storico!`); + this.history = res.history || []; + + const historyListDiv = document.getElementById('env-history-list'); + if (historyListDiv) { + historyListDiv.innerHTML = this.renderHistoryList(); + this.bindHistoryEvents(); + } + } catch (err) { + Toast.error('Errore durante l\'eliminazione dello storico: ' + err.message); + btn.disabled = false; + } + }); + }); }, showPreviewModal(record) { diff --git a/routes/config.js b/routes/config.js index 2a81df7..49f88b7 100644 --- a/routes/config.js +++ b/routes/config.js @@ -67,6 +67,7 @@ router.post('/env', async (req, res) => { // Write updated content to disk fs.writeFileSync(envPath, content, 'utf8'); + try { require('dotenv').config({ path: envPath, override: true }); } catch (_) {} // Save snapshot in history table const info = db.prepare(` @@ -112,6 +113,7 @@ router.post('/env/restore/:history_id', async (req, res) => { // Write snapshot content to disk fs.writeFileSync(envPath, record.content, 'utf8'); + try { require('dotenv').config({ path: envPath, override: true }); } catch (_) {} // Insert new history record documenting the restore operation const restoreNote = `Ripristinato alla versione #${record.id} del ${record.created_at}`; @@ -144,4 +146,41 @@ router.post('/env/restore/:history_id', async (req, res) => { } }); +// DELETE /api/config/env/history/:id — Delete a specific .env history entry +router.delete('/env/history/:id', async (req, res) => { + try { + const { id } = req.params; + const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10); + const agentName = await resolveAgentName(operatorId); + + const record = db.prepare('SELECT * FROM env_history WHERE id = ?').get(id); + if (!record) { + return res.status(404).json({ error: 'Versione di storico non trovata' }); + } + + db.prepare('DELETE FROM env_history WHERE id = ?').run(id); + + logAttivita({ + agente_id: operatorId, + agente_nome: agentName, + titolo_azione: 'Eliminazione Storico .env', + azione: { deleted_history_id: id }, + esito: 'successo', + }); + + const history = db.prepare(` + SELECT * FROM env_history ORDER BY id DESC LIMIT 100 + `).all(); + + res.json({ + success: true, + message: `Versione #${id} dello storico eliminata con successo!`, + history, + }); + } catch (err) { + console.error('Error deleting .env history entry:', err); + res.status(500).json({ error: 'Errore durante l\'eliminazione della versione dello storico', message: err.message }); + } +}); + module.exports = router; diff --git a/routes/lookups.js b/routes/lookups.js index 1be8104..f79b01c 100644 --- a/routes/lookups.js +++ b/routes/lookups.js @@ -147,7 +147,7 @@ router.get('/config', async (req, res) => { res.json({ defaultAgentLogin: process.env.OTRS_API_USER || '', - dailyTargetTime: parseInt(process.env.DAILY_TARGET_TIME, 10) || 480, + dailyTargetTime: parseInt(process.env.DAILY_TARGET_TIME || process.env.daily_target_time || process.env.Daily_Target_Time, 10) || 480, phraseThreshold: parseInt(process.env.PHRASE_THRESHOLD, 10) || 70, autoTimeMinHour: process.env.AUTO_TIME_MIN_HOUR || '18:00', helpdeskEmail: process.env.OTRS_MAIL_BCC || '', diff --git a/routes/tickets.js b/routes/tickets.js index 4f0c504..e5c04ba 100644 --- a/routes/tickets.js +++ b/routes/tickets.js @@ -2140,7 +2140,7 @@ router.get('/time-accounting/summary', async (req, res) => { } }); - const targetMinutes = parseInt(process.env.DAILY_TARGET_TIME, 10) || 480; + const targetMinutes = parseInt(process.env.DAILY_TARGET_TIME || process.env.daily_target_time || process.env.Daily_Target_Time, 10) || 480; const workDaysRaw = process.env.WORK_DAYS || '1,2,3,4,5'; const workDays = workDaysRaw.split(',').map(x => parseInt(x.trim(), 10)).filter(x => !isNaN(x)); @@ -2265,7 +2265,7 @@ router.post('/auto-time', async (req, res) => { await client.query('BEGIN'); // 1. Calculate remaining time - const targetTime = parseInt(process.env.DAILY_TARGET_TIME, 10) || 480; + const targetTime = parseInt(process.env.DAILY_TARGET_TIME || process.env.daily_target_time || process.env.Daily_Target_Time, 10) || 480; const timeTodayRes = await client.query( `SELECT COALESCE(SUM(time_unit), 0) AS total_today FROM time_accounting