feat: funzione per l'invio della posta elettronica da otrs-turbo. fix: corretta consuntivazione automatica. feat: aggiunto link apri in otrs anche nel numero del ticket in cima

This commit is contained in:
Gabriele Cimaschi
2026-07-08 21:46:11 +02:00
parent 9a91c3d9f5
commit 5b914eb198
15 changed files with 1358 additions and 9 deletions
+76 -2
View File
@@ -14,6 +14,10 @@ const App = {
demotivationalPhrases: [],
motivationalPhrases: [],
get currentAgentId() {
return parseInt(localStorage.getItem('activeAgentId') || '1', 10);
},
/** Initialize the application */
init() {
this.initTheme();
@@ -143,6 +147,11 @@ const App = {
titleEl.textContent = 'Storico Attività';
ActivityLogView.render();
} else if (hash === '#/signatures') {
document.getElementById('nav-signatures')?.classList.add('active');
titleEl.textContent = 'Firme Email';
SignaturesView.render();
} else if (hash.match(/^#\/tickets\/(\d+)$/)) {
const id = hash.match(/^#\/tickets\/(\d+)$/)[1];
document.getElementById('nav-tickets')?.classList.add('active');
@@ -465,15 +474,18 @@ const App = {
const triggerAction = async (e) => {
e.preventDefault();
e.stopPropagation();
const confirmed = confirm(`Sei sicuro di voler effettuare la consuntivazione automatica di ${remaining} minuti rimanenti di oggi? Verrà creato un ticket chiuso a tuo carico.`);
const confirmed = await this.confirm(
'Consuntivazione Automatica',
`Sei sicuro di voler effettuare la consuntivazione automatica di ${remaining} minuti rimanenti di oggi? Verrà creato un ticket chiuso a tuo carico.`
);
if (!confirmed) return;
try {
Toast.success('Consuntivazione in corso...');
const res = await this.api('/api/tickets/auto-time', { method: 'POST' });
Toast.success(res.message || 'Consuntivazione completata!');
this.updateDailyTimer();
this.route();
await this.alert('Consuntivazione Completata', res.message || 'La consuntivazione automatica è stata completata con successo.');
} catch (err) {
Toast.error('Errore consuntivazione automatica: ' + err.message);
}
@@ -647,6 +659,68 @@ const App = {
});
});
},
/** Custom alert dialog in the center of the screen */
alert(title, message, options = {}) {
return new Promise((resolve) => {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100vw';
overlay.style.height = '100vh';
overlay.style.background = 'rgba(0, 0, 0, 0.6)';
overlay.style.backdropFilter = 'blur(4px)';
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.zIndex = '99999';
overlay.style.opacity = '0';
overlay.style.transition = 'opacity 0.2s ease';
const card = document.createElement('div');
card.style.background = 'var(--bg-card, #1e1e2e)';
card.style.border = '1px solid var(--border-subtle, #313244)';
card.style.borderRadius = 'var(--radius-lg, 12px)';
card.style.padding = 'var(--space-lg, 24px)';
card.style.width = '100%';
card.style.maxWidth = '400px';
card.style.boxShadow = 'var(--shadow-lg, 0 10px 30px rgba(0,0,0,0.5))';
card.style.transform = 'scale(0.9)';
card.style.transition = 'transform 0.2s ease';
card.className = 'alert-dialog-card';
card.innerHTML = `
<h3 style="margin-top: 0; margin-bottom: var(--space-xs, 8px); color: var(--text-primary, #cdd6f4); font-size: 1.2rem; font-weight: 600;">${title}</h3>
<p style="margin-bottom: var(--space-lg, 24px); color: var(--text-muted, #a6adc8); font-size: 0.95rem; line-height: 1.5;">${message}</p>
<div style="display: flex; justify-content: flex-end;">
<button id="alert-btn-ok" class="btn btn-primary" style="height: 36px; font-size: 0.9rem; padding: 0 20px; border-radius: var(--radius-md, 6px); font-weight: 500; cursor: pointer;">${options.okText || 'OK'}</button>
</div>
`;
overlay.appendChild(card);
document.body.appendChild(overlay);
requestAnimationFrame(() => {
overlay.style.opacity = '1';
card.style.transform = 'scale(1)';
});
const cleanUp = () => {
overlay.style.opacity = '0';
card.style.transform = 'scale(0.9)';
setTimeout(() => {
overlay.remove();
resolve();
}, 200);
};
card.querySelector('#alert-btn-ok').addEventListener('click', cleanUp);
overlay.addEventListener('click', (e) => {
if (e.target === overlay) cleanUp();
});
});
},
};
// Start the app when DOM is ready