KPI-Monitor zeigt Agenten/Online-Kacheln wieder an
Die KPI-Kacheln "Agenten" (registrierte Agenten) und "Online" (davon in den letzten 10 Minuten aktiv, siehe AgentRepository::isPresent()) wurden auf der Monitor-Wand nie angezeigt. Statt eine eigene Meldepflicht dafuer einzufuehren, leitet buildAgentCountKpis() beide Werte direkt aus der ohnehin geladenen Agentenliste ab und stellt sie den ueber /api/v1/kpis gemeldeten Kennzahlen voran. Schliesst #39
This commit is contained in:
parent
5471940389
commit
042a535c78
4 changed files with 57 additions and 4 deletions
|
|
@ -245,8 +245,10 @@ externe Datenbankserver (nur PHP/Python-Standardbibliothek) auskommen, um die
|
||||||
Klick-Modals. ✅ erledigt: Events/Systeme/KPIs kommen live von der API, ein neuer
|
Klick-Modals. ✅ erledigt: Events/Systeme/KPIs kommen live von der API, ein neuer
|
||||||
SSE-Endpoint (`GET /api/v1/stream`, F13) stoesst Frontend-Updates an (Polling-Fallback in
|
SSE-Endpoint (`GET /api/v1/stream`, F13) stoesst Frontend-Updates an (Polling-Fallback in
|
||||||
`office-realtime.js`), KPI-Monitor zeichnet eine eigene SVG-Sparkline (F10, kein Chart-Lib)
|
`office-realtime.js`), KPI-Monitor zeichnet eine eigene SVG-Sparkline (F10, kein Chart-Lib)
|
||||||
sobald KPIs gemeldet wurden - vorher weiterhin der Platzhalter aus Phase 2 (F7 ist
|
sobald KPIs gemeldet wurden. "Agenten" (registrierte Agenten) und "Online" (davon
|
||||||
inhaltlich weiterhin offen).
|
praesent, isAgentPresent()) sind als erste zwei KPI-Kacheln immer sichtbar, direkt aus der
|
||||||
|
Agentenliste abgeleitet statt gemeldet (Issue #39) - darueber hinaus ist F7 inhaltlich
|
||||||
|
weiterhin offen, ohne gemeldete KPIs zeigt die Wand nur diese beiden Kacheln.
|
||||||
6. **Phase 5 – Agenten & Animation**: Zustandsmaschine, Laufwege, Tipp-/Lese-/Kaffee-Animation,
|
6. **Phase 5 – Agenten & Animation**: Zustandsmaschine, Laufwege, Tipp-/Lese-/Kaffee-Animation,
|
||||||
Reaktion auf neue Ticket-/Event-/Systemstatus-Meldungen. ✅ erledigt: `resolveAgentVisualState`
|
Reaktion auf neue Ticket-/Event-/Systemstatus-Meldungen. ✅ erledigt: `resolveAgentVisualState`
|
||||||
bildet die von der API gemeldeten Zustaende auf Ort/Pose ab, Agenten-Avatare sind eine
|
bildet die von der API gemeldeten Zustaende auf Ort/Pose ab, Agenten-Avatare sind eine
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
buildSystemModalContent,
|
buildSystemModalContent,
|
||||||
buildKpiTiles,
|
buildKpiTiles,
|
||||||
buildKpiModalContent,
|
buildKpiModalContent,
|
||||||
|
buildAgentCountKpis,
|
||||||
mapAgentsToDesks,
|
mapAgentsToDesks,
|
||||||
normalizeAgentForDisplay,
|
normalizeAgentForDisplay,
|
||||||
resolveAgentVisualState,
|
resolveAgentVisualState,
|
||||||
|
|
@ -1401,6 +1402,11 @@ export function renderOfficeScene(container, data = {}) {
|
||||||
// is_present-Feld wie registrierte Agenten (Issue #19).
|
// is_present-Feld wie registrierte Agenten (Issue #19).
|
||||||
poIsLive = isLive;
|
poIsLive = isLive;
|
||||||
|
|
||||||
|
// "Agenten"/"Online" (Issue #39) stehen vor den gemeldeten KPIs (F7), damit sie auf der
|
||||||
|
// Wandkachel (MAX_KPI_TILES) immer sichtbar sind, statt von gemeldeten Kennzahlen verdraengt
|
||||||
|
// zu werden.
|
||||||
|
const displayKpis = [...buildAgentCountKpis(agents), ...kpis];
|
||||||
|
|
||||||
const groupedTickets = groupTicketsByColumn(tickets);
|
const groupedTickets = groupTicketsByColumn(tickets);
|
||||||
|
|
||||||
const boardGroup = renderBoard(ticketCounts, groupedTickets, (columnKey) => {
|
const boardGroup = renderBoard(ticketCounts, groupedTickets, (columnKey) => {
|
||||||
|
|
@ -1417,10 +1423,10 @@ export function renderOfficeScene(container, data = {}) {
|
||||||
svg.insertBefore(boardGroup, svg.querySelector(".agents-layer"));
|
svg.insertBefore(boardGroup, svg.querySelector(".agents-layer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallGroup = renderMonitorWall(systems, events, kpis, {
|
const wallGroup = renderMonitorWall(systems, events, displayKpis, {
|
||||||
onEventsClick: () => openModal(buildEventModalContent(events), renderEventModalBody),
|
onEventsClick: () => openModal(buildEventModalContent(events), renderEventModalBody),
|
||||||
onSystemsClick: () => openModal(buildSystemModalContent(systems), renderSystemModalBody),
|
onSystemsClick: () => openModal(buildSystemModalContent(systems), renderSystemModalBody),
|
||||||
onKpiClick: () => openModal(buildKpiModalContent(kpis), renderKpiModalBody),
|
onKpiClick: () => openModal(buildKpiModalContent(displayKpis), renderKpiModalBody),
|
||||||
});
|
});
|
||||||
const existingWall = svg.querySelector(".monitor-wall");
|
const existingWall = svg.querySelector(".monitor-wall");
|
||||||
if (existingWall) {
|
if (existingWall) {
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,27 @@ export function isAgentPresent(agent) {
|
||||||
return Boolean(agent.is_present);
|
return Boolean(agent.is_present);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die beiden im KPI-Monitor erwarteten Kennzahlen "Agenten" (registrierte Agenten) und
|
||||||
|
* "Online" (davon innerhalb der letzten 10 Minuten aktiv, siehe isAgentPresent()) werden
|
||||||
|
* anders als die per POST /api/v1/kpis/{key} gemeldeten Kennzahlen (F7, weiterhin offen)
|
||||||
|
* direkt aus der ohnehin geladenen Agentenliste abgeleitet statt separat gemeldet.
|
||||||
|
* Gibt KPI-foermige Eintraege zurueck (gleiche Form wie GET /api/v1/kpis), damit sie sich
|
||||||
|
* mit den gemeldeten KPIs vor buildKpiTiles()/buildKpiModalContent() zusammenfuehren lassen.
|
||||||
|
*
|
||||||
|
* @param {Array<object|null>} agents - z.B. leere Schreibtisch-Plaetze der Demo-Daten sind null.
|
||||||
|
* @returns {Array<object>}
|
||||||
|
*/
|
||||||
|
export function buildAgentCountKpis(agents = []) {
|
||||||
|
const registered = agents.filter(Boolean);
|
||||||
|
const online = registered.filter(isAgentPresent).length;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ key: "agents_total", label: "Agenten", unit: "", current_value: registered.length, history: [] },
|
||||||
|
{ key: "agents_online", label: "Online", unit: "", current_value: online, history: [] },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ordnet eine rohe Agentenliste (GET /api/v1/agents) den Schreibtischen zu - anders als
|
* Ordnet eine rohe Agentenliste (GET /api/v1/agents) den Schreibtischen zu - anders als
|
||||||
* buildDeskLayout()/Demo-Daten steht der Sitzplatz hier nicht in der Array-Reihenfolge,
|
* buildDeskLayout()/Demo-Daten steht der Sitzplatz hier nicht in der Array-Reihenfolge,
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {
|
||||||
buildKpiSparklinePoints,
|
buildKpiSparklinePoints,
|
||||||
buildKpiTiles,
|
buildKpiTiles,
|
||||||
buildKpiModalContent,
|
buildKpiModalContent,
|
||||||
|
buildAgentCountKpis,
|
||||||
MAX_KPI_TILES,
|
MAX_KPI_TILES,
|
||||||
AGENT_LOCATIONS,
|
AGENT_LOCATIONS,
|
||||||
resolveAgentVisualState,
|
resolveAgentVisualState,
|
||||||
|
|
@ -331,6 +332,29 @@ test("buildKpiModalContent zeigt alle KPIs (kein Limit) inkl. Historie", () => {
|
||||||
assert.equal(content.items[0].label, "Offene Tickets");
|
assert.equal(content.items[0].label, "Offene Tickets");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("buildAgentCountKpis liefert Anzahl registrierter und online-Agenten (Issue #39)", () => {
|
||||||
|
const kpis = buildAgentCountKpis([
|
||||||
|
{ id: 1, is_present: true },
|
||||||
|
{ id: 2, is_present: false },
|
||||||
|
{ id: 3, is_present: true },
|
||||||
|
]);
|
||||||
|
assert.equal(kpis.length, 2);
|
||||||
|
assert.deepEqual(kpis[0], { key: "agents_total", label: "Agenten", unit: "", current_value: 3, history: [] });
|
||||||
|
assert.deepEqual(kpis[1], { key: "agents_online", label: "Online", unit: "", current_value: 2, history: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("buildAgentCountKpis ignoriert leere Schreibtisch-Plaetze (null) und faellt ohne is_present auf anwesend zurueck", () => {
|
||||||
|
const kpis = buildAgentCountKpis([{ id: 1 }, null, { id: 2 }, null]);
|
||||||
|
assert.equal(kpis[0].current_value, 2);
|
||||||
|
assert.equal(kpis[1].current_value, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("buildAgentCountKpis liefert 0/0 ohne Agenten", () => {
|
||||||
|
const kpis = buildAgentCountKpis([]);
|
||||||
|
assert.equal(kpis[0].current_value, 0);
|
||||||
|
assert.equal(kpis[1].current_value, 0);
|
||||||
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
// Phase 5 - Agenten-Zustandsmaschine & Animation
|
// Phase 5 - Agenten-Zustandsmaschine & Animation
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue