107 lines
3.5 KiB
TypeScript
107 lines
3.5 KiB
TypeScript
import { Request, Response } from "express";
|
|
import { DashboardUseCases } from "./Dashboard.usecases.js";
|
|
import { QueueSummary } from "#domain/Dashboard.js";
|
|
import { OrderTracking } from "packages/sim-shared/domain/Order.js";
|
|
|
|
export class DashboardController {
|
|
constructor(private readonly useCases: DashboardUseCases) {}
|
|
|
|
public async getQueuesFragment(req: Request, res: Response) {
|
|
const data = await this.useCases.getDashboardData()
|
|
res.send(renderQueuesHtml(data.queues))
|
|
}
|
|
|
|
public async getOrdersFragment(req: Request, res: Response) {
|
|
const data = await this.useCases.getDashboardData()
|
|
res.send(renderOrdersHtml(data.pendingOrders))
|
|
}
|
|
|
|
public async getFullFragment(req: Request, res: Response) {
|
|
const data = await this.useCases.getDashboardData();
|
|
res.send(`
|
|
${renderQueuesHtml(data.queues)}
|
|
${renderOrdersHtml(data.pendingOrders)}
|
|
<p class="updated-at">Actualizado: ${new Date(data.generatedAt).toLocaleTimeString("es-ES")}</p>
|
|
`)
|
|
}
|
|
}
|
|
|
|
function queueBadgeClass(count: number): string {
|
|
if (count === 0 ) return "badge--ok"
|
|
if (count < 10) return "badge--warn"
|
|
return "badge--error"
|
|
}
|
|
|
|
function orderBadgeClass(status: string): string {
|
|
if (status === 'finished' ) return "badge--ok"
|
|
if (status == 'pending') return "badge--warn"
|
|
return "badge--error"
|
|
}
|
|
|
|
function renderQueuesHtml(queues: QueueSummary): string {
|
|
const row = (label: string, q: typeof queues.main) => `
|
|
<tr>
|
|
<td>${label}</td>
|
|
<td>${q.name}</td>
|
|
<td><span class="badge ${queueBadgeClass(q.messages)}">${q.messages}</span></td>
|
|
<td>${q.ready}</td>
|
|
<td>${q.unacked}</td>
|
|
<td>${q.consumers}</td>
|
|
</tr>
|
|
`
|
|
return `
|
|
<section id="queues-section">
|
|
<h2>Estado de las colas</h2>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Tipo</th>
|
|
<th>Cola</th>
|
|
<th>Total</th>
|
|
<th>Ready</th>
|
|
<th>Unacked</th>
|
|
<th>Consumers</th>
|
|
<tr>
|
|
</thead>
|
|
<tbody>
|
|
${row("Principal", queues.main)}
|
|
${row("Reintentos", queues.retry)}
|
|
${row("Fallidos (DLX)", queues.dlx)}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
`
|
|
}
|
|
|
|
function renderOrdersHtml(orders: OrderTracking<unknown>[]): string {
|
|
const rows = orders.map(o => `
|
|
<tr>
|
|
<td>${o.id}</td>
|
|
<td>${o.correlation_id}</td>
|
|
<td>${o.order_type}</td>
|
|
<td><span class="badge ${orderBadgeClass(o.status)}">${o.status}</span></td>
|
|
<td>${o.retry_count ?? 0}</td>
|
|
<td>${new Date(o.start_date).toLocaleString("es-ES")}</td>
|
|
</tr>
|
|
`
|
|
).join("")
|
|
|
|
return `
|
|
<section id="orders-section">
|
|
<h2>Tareas pendientes (${orders.length})</h2>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Correlation ID</th>
|
|
<th>Tipo</th>
|
|
<th>Estado</th>
|
|
<th>Reintentos</th>
|
|
<th>Inicio</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>${rows}</tbody>
|
|
</table>
|
|
</section>
|
|
`
|
|
} |