104 lines
4.3 KiB
JavaScript
104 lines
4.3 KiB
JavaScript
/**
|
|
* Live-Anzeige im Mitarbeiterbereich: neue Tickets erscheinen sofort als Hinweis unten rechts, die Zahl steht im Browser-Tab und die
|
|
* Kennzahlen auf der Übersicht (Elemente mit data-live-count) aktualisieren sich von selbst. Fragt /staff/live_tickets.php ab.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
if (window.__deskhubLive) return;
|
|
window.__deskhubLive = true;
|
|
|
|
var KEY = 'deskhub_live_last_ticket';
|
|
var since = 0;
|
|
try { since = parseInt(sessionStorage.getItem(KEY) || '0', 10) || 0; } catch (e) {}
|
|
var unseen = 0;
|
|
var baseTitle = document.title;
|
|
var stopped = false;
|
|
var box = null;
|
|
|
|
function container() {
|
|
if (box) return box;
|
|
box = document.createElement('div');
|
|
box.setAttribute('aria-live', 'polite');
|
|
box.style.cssText = 'position:fixed;right:18px;bottom:18px;z-index:2147483000;display:flex;flex-direction:column;gap:10px;max-width:360px;font:14px/1.4 "Segoe UI",system-ui,sans-serif';
|
|
document.body.appendChild(box);
|
|
return box;
|
|
}
|
|
|
|
function toast(t) {
|
|
var a = document.createElement('a');
|
|
a.href = '/staff/ticket_view.php?n=' + encodeURIComponent(t.number);
|
|
a.style.cssText = 'display:block;background:#0f172a;color:#fff;text-decoration:none;border-radius:12px;padding:12px 16px;box-shadow:0 10px 30px rgba(0,0,0,.35);border-left:4px solid #2dd4bf;transition:opacity .4s,transform .4s;opacity:0;transform:translateY(10px)';
|
|
var h = document.createElement('div');
|
|
h.style.cssText = 'font-size:.74rem;letter-spacing:.04em;text-transform:uppercase;color:#5eead4;font-weight:700';
|
|
h.textContent = 'Neues Ticket #' + t.number + (t.department ? ' · ' + t.department : '');
|
|
var s = document.createElement('div');
|
|
s.style.cssText = 'font-weight:600;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap';
|
|
s.textContent = t.subject;
|
|
var n = document.createElement('div');
|
|
n.style.cssText = 'color:#94a3b8;font-size:.82rem';
|
|
n.textContent = t.name;
|
|
a.appendChild(h); a.appendChild(s); a.appendChild(n);
|
|
container().appendChild(a);
|
|
requestAnimationFrame(function () { a.style.opacity = '1'; a.style.transform = 'none'; });
|
|
setTimeout(function () { a.style.opacity = '0'; setTimeout(function () { a.remove(); }, 450); }, 14000);
|
|
a.addEventListener('click', function () { a.remove(); });
|
|
}
|
|
|
|
function info(text) {
|
|
var d = document.createElement('div');
|
|
d.style.cssText = 'background:#334155;color:#e2e8f0;border-radius:10px;padding:8px 14px;font-size:.84rem;box-shadow:0 6px 18px rgba(0,0,0,.3)';
|
|
d.textContent = text;
|
|
container().appendChild(d);
|
|
setTimeout(function () { d.remove(); }, 14000);
|
|
}
|
|
|
|
function setCounts(c) {
|
|
document.querySelectorAll('[data-live-count]').forEach(function (el) {
|
|
var v = c[el.getAttribute('data-live-count')];
|
|
if (v === undefined || el.textContent.trim() === String(v)) return;
|
|
el.textContent = v;
|
|
el.style.transition = 'transform .3s';
|
|
el.style.transform = 'scale(1.25)';
|
|
setTimeout(function () { el.style.transform = 'none'; }, 350);
|
|
});
|
|
}
|
|
|
|
function updateTitle() {
|
|
document.title = unseen > 0 ? '(' + unseen + ') ' + baseTitle : baseTitle;
|
|
}
|
|
function seen() {
|
|
if (unseen === 0) return;
|
|
unseen = 0;
|
|
updateTitle();
|
|
}
|
|
document.addEventListener('visibilitychange', function () { if (!document.hidden) seen(); });
|
|
window.addEventListener('focus', seen);
|
|
|
|
function poll() {
|
|
if (stopped) return;
|
|
fetch('/staff/live_tickets.php?since=' + since, { credentials: 'same-origin', cache: 'no-store' })
|
|
.then(function (r) {
|
|
if (r.status === 401 || r.status === 403) { stopped = true; return null; }
|
|
return r.ok ? r.json() : null;
|
|
})
|
|
.then(function (d) {
|
|
if (!d) return;
|
|
setCounts(d.counts || {});
|
|
var list = d.tickets || [];
|
|
list.forEach(toast);
|
|
if (d.more > 0) info('… und ' + d.more + ' weitere neue Tickets');
|
|
if (list.length) {
|
|
unseen += list.length + (d.more || 0);
|
|
if (document.hidden || !document.hasFocus()) updateTitle(); else unseen = 0;
|
|
}
|
|
if (d.latest > since) {
|
|
since = d.latest;
|
|
try { sessionStorage.setItem(KEY, String(since)); } catch (e) {}
|
|
}
|
|
})
|
|
.catch(function () {})
|
|
.then(function () { if (!stopped) setTimeout(poll, document.hidden ? 30000 : 10000); });
|
|
}
|
|
setTimeout(poll, 1500);
|
|
})();
|