diff --git a/modules/helpdesk/i18n/default_de.json b/modules/helpdesk/i18n/default_de.json index 0954e39..49a885a 100644 --- a/modules/helpdesk/i18n/default_de.json +++ b/modules/helpdesk/i18n/default_de.json @@ -294,5 +294,7 @@ "Resolved in period": "Gelöst im Zeitraum", "Not assigned": "Nicht zugewiesen", "Could not load team dashboard.": "Team-Dashboard konnte nicht geladen werden.", - "No team data available.": "Keine Team-Daten verfügbar." + "No team data available.": "Keine Team-Daten verfügbar.", + "Current": "Aktuell", + "Performance": "Leistung" } diff --git a/modules/helpdesk/i18n/default_en.json b/modules/helpdesk/i18n/default_en.json index 1ef6c84..48010d6 100644 --- a/modules/helpdesk/i18n/default_en.json +++ b/modules/helpdesk/i18n/default_en.json @@ -294,5 +294,7 @@ "Resolved in period": "Resolved in period", "Not assigned": "Not assigned", "Could not load team dashboard.": "Could not load team dashboard.", - "No team data available.": "No team data available." + "No team data available.": "No team data available.", + "Current": "Current", + "Performance": "Performance" } diff --git a/modules/helpdesk/pages/helpdesk/team/index(default).phtml b/modules/helpdesk/pages/helpdesk/team/index(default).phtml index 1c73047..6b291b4 100644 --- a/modules/helpdesk/pages/helpdesk/team/index(default).phtml +++ b/modules/helpdesk/pages/helpdesk/team/index(default).phtml @@ -2,6 +2,8 @@ /** * Team workload dashboard — shows support agent metrics aggregated from BC tickets. + * Tab 1 "Current": snapshot of open tickets per agent (no period filter). + * Tab 2 "Performance": resolved tickets per agent in a selectable period. */ $periods = [30, 90, 180, 365]; @@ -38,75 +40,98 @@ $periodLabels = [ ?>
-
- - checked> - - -
- -
-
+
+
+ +
+
+
+
+ +
-
-
-
+
+
+
+
+
- -
-
-
-
-
-
-
- -
- - - - -
diff --git a/modules/helpdesk/web/js/helpdesk-team.js b/modules/helpdesk/web/js/helpdesk-team.js index 02e6663..3627608 100644 --- a/modules/helpdesk/web/js/helpdesk-team.js +++ b/modules/helpdesk/web/js/helpdesk-team.js @@ -1,5 +1,7 @@ /** * Team workload dashboard — fetches and renders team metrics. + * Tab "Current": snapshot of open tickets per agent. + * Tab "Performance": resolved tickets per agent in a selectable period. */ const container = document.querySelector('.app-details-container[data-team-workload-url]'); @@ -11,11 +13,13 @@ if (container) { const elError = document.getElementById('team-error'); const elEmpty = document.getElementById('team-empty'); const elContent = document.getElementById('team-content'); - const elBody = document.getElementById('team-table-body'); + const elCurrentBody = document.getElementById('team-table-current'); + const elPerformanceBody = document.getElementById('team-table-performance'); const elRefresh = container.querySelector('button[name="team-refresh"]'); const periodSelector = document.getElementById('team-period-selector'); let currentPeriod = 90; + let lastData = null; function showState(state) { if (elLoading) elLoading.hidden = state !== 'loading'; @@ -30,45 +34,70 @@ if (container) { if (el) el.textContent = value; } - function renderKpis(kpis) { - setText('team-kpi-open', kpis.open_tickets ?? 0); - setText('team-kpi-unassigned', kpis.unassigned ?? 0); - setText('team-kpi-avg-age', kpis.avg_age_hours ?? 0); - setText('team-kpi-resolved', kpis.resolved_in_period ?? 0); - } - function createCell(text) { const td = document.createElement('td'); td.textContent = text; return td; } - function renderTable(members) { - if (!elBody) return; - elBody.replaceChildren(); + function agentName(m) { + return m.support_user === '' ? labelNotAssigned : m.display_name; + } + + function renderCurrentTab(kpis, members) { + setText('team-kpi-open', kpis.open_tickets ?? 0); + setText('team-kpi-unassigned', kpis.unassigned ?? 0); + setText('team-kpi-avg-age', kpis.avg_age_hours ?? 0); + + if (!elCurrentBody) return; + elCurrentBody.replaceChildren(); for (const m of members) { const tr = document.createElement('tr'); - const isUnassigned = m.support_user === ''; - const name = isUnassigned ? labelNotAssigned : m.display_name; - - const nameCell = document.createElement('td'); - nameCell.textContent = name; - - tr.appendChild(nameCell); + tr.appendChild(createCell(agentName(m))); tr.appendChild(createCell(String(m.open_tickets))); tr.appendChild(createCell(String(m.critical_tickets))); tr.appendChild(createCell(String(m.avg_age_hours))); - tr.appendChild(createCell(String(m.resolved_in_period))); - if (isUnassigned) { + if (m.support_user === '') { tr.classList.add('helpdesk-team-row-unassigned'); } - elBody.appendChild(tr); + elCurrentBody.appendChild(tr); } } + function renderPerformanceTab(kpis, members) { + setText('team-kpi-resolved', kpis.resolved_in_period ?? 0); + + if (!elPerformanceBody) return; + elPerformanceBody.replaceChildren(); + + const sorted = [...members].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 m of sorted) { + const tr = document.createElement('tr'); + tr.appendChild(createCell(agentName(m))); + tr.appendChild(createCell(String(m.resolved_in_period))); + + if (m.support_user === '') { + tr.classList.add('helpdesk-team-row-unassigned'); + } + + elPerformanceBody.appendChild(tr); + } + } + + function renderAll(data) { + lastData = data; + renderCurrentTab(data.kpis, data.members); + renderPerformanceTab(data.kpis, data.members); + } + async function fetchData(refresh = false) { showState('loading'); @@ -89,8 +118,7 @@ if (container) { return; } - renderKpis(json.kpis); - renderTable(json.members); + renderAll(json); showState('success'); } catch { showState('error');