Files
dashboard-infra/index.html
T
kvilches1410 d7f7339fde Muchos cambios
2026-04-06 18:59:47 -03:00

311 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard LABS — Story Points</title>
<link rel="stylesheet" href="./css/styles.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>
<script type="module" src="./js/app.js" defer></script>
</head>
<body>
<!-- Loading overlay -->
<div class="loading-overlay" id="loadingOverlay">
<div class="spinner"></div>
<p>Consultando Jira en tiempo real…</p>
</div>
<!-- Error banner -->
<div class="error-banner" id="errorBanner"></div>
<div class="error-banner" id="limitBanner" style="background:#fff7d6; color:#a15900; border-color:#ffab00;"></div>
<!-- Header Principal -->
<header>
<div>
<h1>📊 Dashboard LABS — Story Points</h1>
<div style="font-size:13px;opacity:.7;margin-top:4px;">
Proyecto: <strong>LABS</strong> · invera.atlassian.net
</div>
</div>
<div class="header-meta">
<span id="lastUpdatedLabel">—</span>
<span class="cache-badge" id="cacheBadge"></span>
<label style="font-size:12px;opacity:0.8;color:white;margin-right:-6px;">Rango:</label>
<select id="timeRangeFilter" style="padding:4px 8px; font-size:12px; border-radius:4px; max-width:120px;">
<option value="1d">Hoy</option>
<option value="7d">Últimos 7 días</option>
<option value="30d">Último mes</option>
<option value="90d" selected>Últimos 3 meses</option>
<option value="365d">Último año</option>
<option value="all">Histórico completo</option>
</select>
<button class="refresh-btn" id="refreshBtn">↻ Actualizar</button>
</div>
</header>
<!-- ── SECCIÓN 1: Carga de Trabajo (Pendientes) ── -->
<div class="section-header current">
<div class="dot" style="background:#0065ff;"></div>
<h2>Carga de Trabajo Actual</h2>
<span id="currentTicketsLabel" style="font-size:12px;color:#5e6c84;margin-left:8px;">Tickets pendientes en el tablero</span>
<div class="filter-group">
<label>Filtrar por Dev:</label>
<select id="devFilter"><option value="all">Cargando...</option></select>
</div>
</div>
<div class="main">
<div class="section-block">
<div class="kpi-row">
<div class="kpi progress" title="Suma de Story Points (SP) de todos los tickets actualmente en la columna En Progreso"><div class="kpi-value" id="kpi-ip">—</div><div class="kpi-label">SP En Progreso</div><div class="kpi-sub">Trabajo en curso</div></div>
<div class="kpi todo" title="Suma de Story Points de tickets pendientes que aún no comenzaron"><div class="kpi-value" id="kpi-todo">—</div><div class="kpi-label">SP Por Hacer</div><div class="kpi-sub">Backlog del periodo</div></div>
<div class="kpi members" title="Cantidad de personas con carga de trabajo (tickets) asignados en este momento"><div class="kpi-value" id="kpi-members">—</div><div class="kpi-label">Devs con Carga</div><div class="kpi-sub">Con tickets pendientes</div></div>
</div>
<div class="charts-grid">
<div class="chart-card">
<h3>🔵 Pendientes por Desarrollador</h3>
<div class="sub">Story Points con trabajo pendiente</div>
<div style="position:relative;height:260px"><canvas id="chartCurrentState"></canvas></div>
</div>
<div class="chart-card">
<h3>📢 Alertas de Salud</h3>
<div class="sub">Tickets estancados o sin estimación</div>
<div id="warningsSection" style="display:none; overflow-y:auto; max-height:230px; margin-top:10px;">
<ul class="warning-list" id="warningsList" style="padding:0; margin:0;"></ul>
</div>
<div id="noWarningsMsg" style="text-align:center; color:#36b37e; padding:40px 0; display:none;">
✅ No hay alertas pendientes
</div>
</div>
</div>
<div class="table-card">
<h3>Detalle de Carga de Trabajo</h3>
<table>
<thead><tr><th>Desarrollador</th><th>🔵 En Progreso</th><th>⏳ Por Hacer</th><th>Total Pendiente</th><th>Carga Visual</th></tr></thead>
<tbody id="tableCurrentState"></tbody>
</table>
</div>
</div>
</div>
<!-- ── SECCIÓN 2: Rendimiento & Resultados ── -->
<div class="section-header history">
<div class="dot" style="background:#36b37e;"></div>
<h2>Resultados del Período</h2>
<span style="font-size:12px;color:#5e6c84;margin-left:8px;">Story Points finalizados y velocidad</span>
<span class="badge" id="filterBadge" style="display:none;"></span>
</div>
<div class="main">
<div class="section-block">
<div class="kpi-row-3">
<div class="kpi done" title="Suma total de Story Points entregados y completados en el período de tiempo seleccionado"><div class="kpi-value" id="kpi-done-period">—</div><div class="kpi-label">SP Completados</div><div class="kpi-sub">en el período</div></div>
<div class="kpi members" title="Cantidad de desarrolladores que han cerrado al menos 1 Story Point en este período"><div class="kpi-value" id="kpi-devs-period">—</div><div class="kpi-label">Desarrolladores</div><div class="kpi-sub">que completaron SP</div></div>
<div class="kpi progress" title="Promedio simple: Total de SP completados dividido por la cantidad de desarrolladores"><div class="kpi-value" id="kpi-avg-period">—</div><div class="kpi-label">SP promedio / dev</div><div class="kpi-sub">en el período</div></div>
</div>
<div class="kpi-row-3" style="margin-top:-8px;">
<div class="kpi" style="border-color:#36b37e;" title="Lead Time: Tiempo total promedio que vive un ticket desde su creación hasta que es cerrado"><div class="kpi-value" id="kpi-lead-time">—</div><div class="kpi-label">Promedio Lead Time</div><div class="kpi-sub">Días (Creación a Fin)</div></div>
<div class="kpi" style="border-color:#00b8d9;" title="Cycle Time: Velocidad de desarrollo neto. Promedio en días desde que un developer mueve el ticket 'En Curso' hasta cerrarse"><div class="kpi-value" id="kpi-cycle-time">—</div><div class="kpi-label">Promedio Cycle Time</div><div class="kpi-sub">Días (En Curso a Fin)</div></div>
<div class="kpi warning" title="Variación entre el Story Point estimado al sprint vs el final real; un número en (+) indica Scope Creep (inflación de puntos)"><div class="kpi-value" id="kpi-sp-deviation">—</div><div class="kpi-label">Desviación SP</div><div class="kpi-sub" id="kpi-sp-deviation-sub">Original vs Final</div></div>
</div>
<div class="charts-grid">
<div class="chart-card">
<h3>✅ SP Completados — por Desarrollador</h3>
<div class="sub">Período seleccionado</div>
<div style="position:relative;height:260px"><canvas id="chartDoneDev"></canvas></div>
</div>
<div class="chart-card">
<h3>📈 Velocidad Histórica</h3>
<div class="sub">SP completados mes a mes</div>
<div style="position:relative;height:260px"><canvas id="chartVelocity"></canvas></div>
</div>
</div>
<div class="table-card">
<h3>SP Completados — Tabla Resumen</h3>
<table>
<thead><tr><th>Desarrollador</th><th>✅ SP Completados</th><th>🎟️ Tickets</th><th>% del impacto total</th></tr></thead>
<tbody id="tableHistory"></tbody>
</table>
</div>
</div>
</div>
<!-- ── SECCIÓN: Revisión de Código (Code Review) ── -->
<div class="section-header" style="border-color:#00b8d9;">
<div class="dot" style="background:#00b8d9;"></div>
<h2>Revisión de Código (Code Review)</h2>
<span style="font-size:12px;color:#5e6c84;margin-left:8px;">Métricas de revisión entre pares antes de QA</span>
</div>
<div class="main">
<div class="section-block">
<!-- Colas Actuales -->
<div class="kpi-row" style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #dfe1e6;">
<div class="kpi warning" style="border-color:#ff8b00;" title="Tickets que se encuentran en este preciso instante en la columna Code Review esperando o siendo revisados">
<div class="kpi-value" id="kpi-cr-queue-now">—</div>
<div class="kpi-label">En Cola Actual CR</div>
<div class="kpi-sub" id="kpi-cr-queue-sp">— SP en espera</div>
</div>
<div class="kpi warning" title="Tickets que se encuentran actualmente y desde hace más de 2 días atascados solos en la columna de revisión">
<div class="kpi-value" id="kpi-cr-stalled">—</div>
<div class="kpi-label">Tickets Atascados CR</div>
<div class="kpi-sub">Demorados actualmente (más de 2 días)</div>
</div>
</div>
<!-- Historial del período -->
<h3 style="font-size:14px; margin-bottom:12px; color:#172b4d;">Métricas del período seleccionado</h3>
<div class="kpi-row">
<div class="kpi" style="border-color:#00b8d9;" title="Cantidad de tickets que registraron actividad en la fase de Code Review">
<div class="kpi-value" id="kpi-cr-tickets">—</div>
<div class="kpi-label">Tickets en CR</div>
<div class="kpi-sub">Procesados en el período</div>
</div>
<div class="kpi" style="border-color:#00b8d9;">
<div class="kpi-value" id="kpi-cr-p50">—</div>
<div class="kpi-label">
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempo P50 CR
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
<div class="pop-item" style="font-size:12px;"><strong>Percentil 50 (Mediana)</strong><br>El 50% de las revisiones de código se completan en esta cantidad de horas o menos.<br><br>A diferencia del promedio tradicional, el P50 muestra un valor "habitual" sin ser distorsionado por tickets que queden atascados durante meses.</div>
</div>
</div>
</div>
<div class="kpi-sub">Horas (Mediana)</div>
</div>
<div class="kpi" style="border-color:#ff8b00;">
<div class="kpi-value" id="kpi-cr-p90">—</div>
<div class="kpi-label">
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempos P90 y P99
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
<div class="pop-item" style="font-size:12px;"><strong>Métricas de Cuello de Botella</strong><br>Muestran los "peores escenarios" posibles.<br><br><strong>P90:</strong> El 90% de los tickets logra pasar en este tiempo. El 10% restante demoró aún más.<br><strong>P99:</strong> El 99% pasa en este tiempo. Ideal para medir los bloqueos máximos.</div>
</div>
</div>
</div>
<div class="kpi-sub" id="kpi-cr-p99-sub">P99: — hs</div>
</div>
</div>
<div class="charts-grid">
<div class="chart-card full">
<h3>📈 Tiempo Promedio en Code Review — Mes a Mes</h3>
<div class="sub">Evolución de la velocidad de revisión de pares (horas)</div>
<div style="position:relative;height:240px"><canvas id="chartCrMonthly"></canvas></div>
</div>
</div>
</div>
</div>
<!-- ── SECCIÓN 3: Control de Calidad (QA) ── -->
<div class="section-header qa">
<div class="dot qa"></div>
<h2>Control de Calidad (QA)</h2>
<span style="font-size:12px;color:#5e6c84;margin-left:8px;">Métricas del proceso de QA · Tiempos, colas y devoluciones</span>
</div>
<div class="main">
<div class="section-block">
<!-- Colas Actuales -->
<div class="kpi-row" style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #dfe1e6;">
<div class="kpi qa-queue" style="border-color:#ff8b00;" title="Tickets que se encuentran en este preciso instante en la columna Ready to QA">
<div class="kpi-value" id="kpi-qa-queue-now">—</div>
<div class="kpi-label">En Cola Actual RTQA</div>
<div class="kpi-sub" id="kpi-qa-queue-now-sp">— SP esperando</div>
</div>
<div class="kpi qa" style="border-color:#0065ff;" title="Tickets que se encuentran en este preciso instante siendo probados en la columna QA">
<div class="kpi-value" id="kpi-qa-active-now">—</div>
<div class="kpi-label">En Cola Actual QA</div>
<div class="kpi-sub" id="kpi-qa-active-now-sp">— SP en prueba</div>
</div>
</div>
<!-- KPIs del período -->
<h3 style="font-size:14px; margin-bottom:12px; color:#172b4d;">Métricas del período seleccionado</h3>
<div class="kpi-row">
<div class="kpi qa" title="Total de tickets que han pasado por QA">
<div class="kpi-value" id="kpi-qa-tickets">—</div>
<div class="kpi-label">Tickets QA</div>
<div class="kpi-sub">Procesados en el período</div>
</div>
<div class="kpi qa-time" title="Horas dedicadas a revisar un ticket (Tiempo neto en la columna QA)">
<div class="kpi-value" id="kpi-qa-avg">—</div>
<div class="kpi-label">Tiempo Prom. QA</div>
<div class="kpi-sub">Horas promedio por ticket</div>
</div>
<div class="kpi qa-queue" title="Tiempo pasivo promedio esperando ser tomado (Cola 'Ready to QA')">
<div class="kpi-value" id="kpi-qa-rtqa">—</div>
<div class="kpi-label">Tiempo Prom. en Cola</div>
<div class="kpi-sub">Horas esperando READY TO QA</div>
</div>
<div class="kpi returned" title="Tickets que rebotaron en QA y el desarrollador tuvo que retomar ('Reaperturas' o regresos al ciclo En Curso)">
<div class="kpi-value" id="kpi-qa-returned">—</div>
<div class="kpi-label">Tickets Devueltos</div>
<div class="kpi-sub" id="kpi-qa-returned-pct">Volvieron a En Curso</div>
</div>
</div>
<!-- Gráficos fila 1 -->
<div class="charts-grid">
<div class="chart-card">
<h3>📊 Distribución de Tiempos en QA</h3>
<div class="sub">Rangos: &lt;30min · 30min–2hs · 2–8hs · &gt;8hs</div>
<div style="position:relative;height:240px"><canvas id="chartQaDist"></canvas></div>
</div>
<div class="chart-card">
<h3>🔄 Devueltos vs. Aprobados</h3>
<div class="sub">Tickets que volvieron a En Curso al menos una vez</div>
<div style="position:relative;height:240px"><canvas id="chartQaReturned"></canvas></div>
</div>
</div>
<!-- Gráficos fila 2 -->
<div class="charts-grid">
<div class="chart-card">
<h3>📈 Tiempo Promedio en QA — Mes a Mes</h3>
<div class="sub">Evolución de la velocidad de revisión (horas)</div>
<div style="position:relative;height:240px"><canvas id="chartQaMonthly"></canvas></div>
</div>
<div class="chart-card">
<h3>⏳ Tiempo en Cola RTQA — Mes a Mes</h3>
<div class="sub">Horas promedio esperando ser tomado por QA</div>
<div style="position:relative;height:240px"><canvas id="chartRtqaMonthly"></canvas></div>
</div>
</div>
<!-- Tabla de tickets QA -->
<div class="table-card">
<h3>🔍 Detalle de Tickets — QA</h3>
<table>
<thead>
<tr>
<th>Ticket</th>
<th>Resumen</th>
<th>⏱️ Tiempo en QA (hs)</th>
<th>⏳ Cola RTQA (hs)</th>
<th>🔄 Veces devuelto</th>
<th>Estado</th>
</tr>
</thead>
<tbody id="tableQA"></tbody>
</table>
</div>
</div>
</div>
<footer>
Dashboard en tiempo real · Arquitectura Modular Serverless · Realizado para Vercel & Jira
</footer>
</body>
</html>