revert(helpdesk): remove queue separation from team dashboard
Revert queue detection, wait time summary, and visual separation. All members are treated equally again — queue appears as a normal agent entry sorted by the existing criteria. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -301,6 +301,5 @@
|
|||||||
"Current": "Aktuell",
|
"Current": "Aktuell",
|
||||||
"Performance": "Leistung",
|
"Performance": "Leistung",
|
||||||
"Historical": "Historisch",
|
"Historical": "Historisch",
|
||||||
"Queue": "Warteschlange",
|
"Queue": "Warteschlange"
|
||||||
"Wait time": "Wartezeit"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,6 +301,5 @@
|
|||||||
"Current": "Current",
|
"Current": "Current",
|
||||||
"Performance": "Performance",
|
"Performance": "Performance",
|
||||||
"Historical": "Historical",
|
"Historical": "Historical",
|
||||||
"Queue": "Queue",
|
"Queue": "Queue"
|
||||||
"Wait time": "Wait time"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ $periodLabels = [
|
|||||||
data-label-resolution-time="<?php e(t('Resolution time')); ?>"
|
data-label-resolution-time="<?php e(t('Resolution time')); ?>"
|
||||||
data-label-top-customers="<?php e(t('Top customers')); ?>"
|
data-label-top-customers="<?php e(t('Top customers')); ?>"
|
||||||
data-label-top-categories="<?php e(t('Top categories')); ?>"
|
data-label-top-categories="<?php e(t('Top categories')); ?>"
|
||||||
data-label-wait-time="<?php e(t('Wait time')); ?>"
|
|
||||||
>
|
>
|
||||||
<section>
|
<section>
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
@@ -220,15 +220,6 @@
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Team workload — queue wait time summary */
|
|
||||||
.helpdesk-team-queue-wait {
|
|
||||||
padding: calc(var(--app-spacing) * 0.5) calc(var(--app-spacing) * 0.75);
|
|
||||||
margin-bottom: calc(var(--app-spacing) * 0.5);
|
|
||||||
border: 1px dashed var(--app-muted-border-color);
|
|
||||||
border-radius: var(--app-radius, 0.375rem);
|
|
||||||
background: color-mix(in srgb, var(--app-muted-border-color) 10%, transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Team workload — inline avatar for section titles */
|
/* Team workload — inline avatar for section titles */
|
||||||
.helpdesk-team-avatar-inline {
|
.helpdesk-team-avatar-inline {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ if (container) {
|
|||||||
const labelQueue = container.dataset.labelQueue || 'Queue';
|
const labelQueue = container.dataset.labelQueue || 'Queue';
|
||||||
const labelTickets = container.dataset.labelTickets || 'Tickets';
|
const labelTickets = container.dataset.labelTickets || 'Tickets';
|
||||||
const labelCritical = container.dataset.labelCritical || 'Critical (>48h open)';
|
const labelCritical = container.dataset.labelCritical || 'Critical (>48h open)';
|
||||||
const labelWaitTime = container.dataset.labelWaitTime || 'Wait time';
|
|
||||||
const ticketBaseUrl = container.dataset.ticketBaseUrl || '';
|
const ticketBaseUrl = container.dataset.ticketBaseUrl || '';
|
||||||
const debitorBaseUrl = container.dataset.debitorBaseUrl || '';
|
const debitorBaseUrl = container.dataset.debitorBaseUrl || '';
|
||||||
|
|
||||||
@@ -39,13 +38,6 @@ if (container) {
|
|||||||
return e;
|
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) {
|
function initials(name) {
|
||||||
const parts = name.trim().split(/\s+/);
|
const parts = name.trim().split(/\s+/);
|
||||||
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
||||||
@@ -306,49 +298,12 @@ if (container) {
|
|||||||
return section;
|
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) {
|
function renderCurrentTab(members) {
|
||||||
if (!elCurrentCards) return;
|
if (!elCurrentCards) return;
|
||||||
elCurrentCards.replaceChildren();
|
elCurrentCards.replaceChildren();
|
||||||
|
|
||||||
const queueMembers = members.filter(m => isQueueMember(m) && m.open_tickets > 0);
|
const visible = members.filter(m => m.open_tickets > 0 || m.critical_tickets > 0);
|
||||||
const agents = members.filter(m => !isQueueMember(m) && (m.open_tickets > 0 || m.critical_tickets > 0));
|
for (const m of visible) elCurrentCards.appendChild(buildAgentWidget(m, m.support_user === ''));
|
||||||
|
|
||||||
// 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));
|
|
||||||
|
|
||||||
// Legend
|
// Legend
|
||||||
const hasCritical = members.some(m => m.critical_tickets > 0);
|
const hasCritical = members.some(m => m.critical_tickets > 0);
|
||||||
@@ -366,13 +321,15 @@ if (container) {
|
|||||||
if (!elPerformanceCards) return;
|
if (!elPerformanceCards) return;
|
||||||
elPerformanceCards.replaceChildren();
|
elPerformanceCards.replaceChildren();
|
||||||
|
|
||||||
const queueResolved = members.filter(m => isQueueMember(m) && m.resolved_in_period > 0);
|
const sorted = [...members]
|
||||||
const agentsResolved = members
|
.filter(m => m.resolved_in_period > 0)
|
||||||
.filter(m => !isQueueMember(m) && m.resolved_in_period > 0)
|
.sort((a, b) => {
|
||||||
.sort((a, b) => b.resolved_in_period - a.resolved_in_period);
|
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 sorted) elPerformanceCards.appendChild(buildPerformanceWidget(m));
|
||||||
for (const m of agentsResolved) elPerformanceCards.appendChild(buildPerformanceWidget(m));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchData(refresh = false) {
|
async function fetchData(refresh = false) {
|
||||||
|
|||||||
Reference in New Issue
Block a user