|
|
|
|
@@ -10,7 +10,6 @@ if (container) {
|
|
|
|
|
const labelQueue = container.dataset.labelQueue || 'Queue';
|
|
|
|
|
const labelTickets = container.dataset.labelTickets || 'Tickets';
|
|
|
|
|
const labelCritical = container.dataset.labelCritical || 'Critical (>48h open)';
|
|
|
|
|
const labelWaitTime = container.dataset.labelWaitTime || 'Wait time';
|
|
|
|
|
const ticketBaseUrl = container.dataset.ticketBaseUrl || '';
|
|
|
|
|
const debitorBaseUrl = container.dataset.debitorBaseUrl || '';
|
|
|
|
|
|
|
|
|
|
@@ -39,13 +38,6 @@ if (container) {
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Detect queue entries — Support_User_Name contains 'warteschlange'.
|
|
|
|
|
*/
|
|
|
|
|
function isQueueMember(m) {
|
|
|
|
|
return m.support_user === '' || m.support_user.includes('wartschlang');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initials(name) {
|
|
|
|
|
const parts = name.trim().split(/\s+/);
|
|
|
|
|
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
|
|
|
@@ -306,49 +298,12 @@ if (container) {
|
|
|
|
|
return section;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Build a queue summary with wait time Ø/Min/Max from open ticket ages.
|
|
|
|
|
*/
|
|
|
|
|
function buildQueueWaitSummary(queueMembers) {
|
|
|
|
|
const allAges = queueMembers.flatMap(m => (m.open_ticket_details || []).map(t => t.age_hours));
|
|
|
|
|
if (allAges.length === 0) return null;
|
|
|
|
|
|
|
|
|
|
const stats = computeResolution(allAges);
|
|
|
|
|
const wrap = h('div', 'helpdesk-team-queue-wait');
|
|
|
|
|
wrap.appendChild(h('span', 'helpdesk-team-perf-stat-label', labelWaitTime));
|
|
|
|
|
|
|
|
|
|
const list = h('ol', 'helpdesk-team-perf-ranked helpdesk-team-perf-ranked-plain');
|
|
|
|
|
const items = [
|
|
|
|
|
['Ø', formatResolution(stats.avg)],
|
|
|
|
|
['Min', formatResolution(stats.min)],
|
|
|
|
|
['Max', formatResolution(stats.max)],
|
|
|
|
|
];
|
|
|
|
|
for (const [label, value] of items) {
|
|
|
|
|
const li = h('li');
|
|
|
|
|
li.appendChild(h('span', 'helpdesk-team-perf-ranked-name', label));
|
|
|
|
|
li.appendChild(h('span', 'helpdesk-team-perf-ranked-count', value));
|
|
|
|
|
list.appendChild(li);
|
|
|
|
|
}
|
|
|
|
|
wrap.appendChild(list);
|
|
|
|
|
return wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderCurrentTab(members) {
|
|
|
|
|
if (!elCurrentCards) return;
|
|
|
|
|
elCurrentCards.replaceChildren();
|
|
|
|
|
|
|
|
|
|
const queueMembers = members.filter(m => isQueueMember(m) && m.open_tickets > 0);
|
|
|
|
|
const agents = members.filter(m => !isQueueMember(m) && (m.open_tickets > 0 || m.critical_tickets > 0));
|
|
|
|
|
|
|
|
|
|
// Queue section(s) at top
|
|
|
|
|
for (const q of queueMembers) elCurrentCards.appendChild(buildAgentWidget(q, true));
|
|
|
|
|
|
|
|
|
|
// Wait time summary across all queues
|
|
|
|
|
const waitSummary = buildQueueWaitSummary(queueMembers);
|
|
|
|
|
if (waitSummary) elCurrentCards.appendChild(waitSummary);
|
|
|
|
|
|
|
|
|
|
// Agent cards
|
|
|
|
|
for (const m of agents) elCurrentCards.appendChild(buildAgentWidget(m, false));
|
|
|
|
|
const visible = members.filter(m => m.open_tickets > 0 || m.critical_tickets > 0);
|
|
|
|
|
for (const m of visible) elCurrentCards.appendChild(buildAgentWidget(m, m.support_user === ''));
|
|
|
|
|
|
|
|
|
|
// Legend
|
|
|
|
|
const hasCritical = members.some(m => m.critical_tickets > 0);
|
|
|
|
|
@@ -366,13 +321,15 @@ if (container) {
|
|
|
|
|
if (!elPerformanceCards) return;
|
|
|
|
|
elPerformanceCards.replaceChildren();
|
|
|
|
|
|
|
|
|
|
const queueResolved = members.filter(m => isQueueMember(m) && m.resolved_in_period > 0);
|
|
|
|
|
const agentsResolved = members
|
|
|
|
|
.filter(m => !isQueueMember(m) && m.resolved_in_period > 0)
|
|
|
|
|
.sort((a, b) => b.resolved_in_period - a.resolved_in_period);
|
|
|
|
|
const sorted = [...members]
|
|
|
|
|
.filter(m => m.resolved_in_period > 0)
|
|
|
|
|
.sort((a, b) => {
|
|
|
|
|
if (a.support_user === '') return 1;
|
|
|
|
|
if (b.support_user === '') return -1;
|
|
|
|
|
return b.resolved_in_period - a.resolved_in_period;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (const q of queueResolved) elPerformanceCards.appendChild(buildPerformanceWidget(q));
|
|
|
|
|
for (const m of agentsResolved) elPerformanceCards.appendChild(buildPerformanceWidget(m));
|
|
|
|
|
for (const m of sorted) elPerformanceCards.appendChild(buildPerformanceWidget(m));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchData(refresh = false) {
|
|
|
|
|
|