feat: dashboard apps y mejora layout del dashboard Overview

Dashboard fn-registry Apps con 10 cards: KPIs por lenguaje, dominio,
framework, dependencias y catálogo completo. Cards del Overview
ampliadas a grid de 24 columnas con tamaños más legibles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 00:54:18 +01:00
parent 26ffba2c03
commit 95bba767bc
2 changed files with 247 additions and 15 deletions
@@ -19,61 +19,72 @@ METABASE_URL = "http://localhost:3000"
EMAIL = "admin@fnregistry.local"
PASSWORD = "FnRegistry2024!"
# --- Layout ---
# Grid de 24 unidades de ancho (estandar Metabase).
# Fila 0 (h=5): 5 scalars de 4-5 unidades cada uno → fila de KPIs
# Fila 5 (h=8): 3 graficas de 8 unidades → distribucion general
# Fila 13 (h=9): 3 graficas de 8 unidades → analisis profundo
# Fila 22 (h=8): 2 tablas de 12 unidades → cobertura + x lenguaje
# Fila 30 (h=8): 2 tablas de 12 unidades → tipos + recientes
# --- SQL Queries ---
CARDS = [
# ---- Fila 0: KPIs escalares (h=5) ----
{
"name": "Total de Funciones",
"display": "scalar",
"sql": "SELECT COUNT(*) AS total FROM functions;",
"size_x": 4, "size_y": 3, "col": 0, "row": 0,
"size_x": 5, "size_y": 5, "col": 0, "row": 0,
},
{
"name": "Funciones con Tests",
"display": "scalar",
"sql": "SELECT COUNT(*) AS con_tests FROM functions WHERE tested = 1;",
"size_x": 4, "size_y": 3, "col": 4, "row": 0,
"size_x": 5, "size_y": 5, "col": 5, "row": 0,
},
{
"name": "Funciones sin Tests",
"display": "scalar",
"sql": "SELECT COUNT(*) AS sin_tests FROM functions WHERE tested = 0;",
"size_x": 4, "size_y": 3, "col": 8, "row": 0,
"size_x": 4, "size_y": 5, "col": 10, "row": 0,
},
{
"name": "Total de Tipos",
"display": "scalar",
"sql": "SELECT COUNT(*) AS total FROM types;",
"size_x": 3, "size_y": 3, "col": 12, "row": 0,
"size_x": 5, "size_y": 5, "col": 14, "row": 0,
},
{
"name": "Proposals Pendientes",
"display": "scalar",
"sql": "SELECT COUNT(*) AS pendientes FROM proposals WHERE status = 'pending';",
"size_x": 3, "size_y": 3, "col": 15, "row": 0,
"size_x": 5, "size_y": 5, "col": 19, "row": 0,
},
# ---- Fila 5: Distribucion general (h=8) ----
{
"name": "Funciones por Lenguaje",
"display": "bar",
"sql": "SELECT lang, COUNT(*) AS cantidad FROM functions GROUP BY lang ORDER BY cantidad DESC;",
"size_x": 6, "size_y": 5, "col": 0, "row": 3,
"size_x": 8, "size_y": 8, "col": 0, "row": 5,
},
{
"name": "Funciones por Dominio",
"display": "pie",
"sql": "SELECT domain, COUNT(*) AS cantidad FROM functions GROUP BY domain ORDER BY cantidad DESC;",
"size_x": 6, "size_y": 5, "col": 6, "row": 3,
"size_x": 8, "size_y": 8, "col": 8, "row": 5,
},
{
"name": "Funciones por Kind",
"display": "bar",
"sql": "SELECT kind, COUNT(*) AS cantidad FROM functions GROUP BY kind ORDER BY cantidad DESC;",
"size_x": 6, "size_y": 5, "col": 12, "row": 3,
"size_x": 8, "size_y": 8, "col": 16, "row": 5,
},
# ---- Fila 13: Analisis profundo (h=9) ----
{
"name": "Puras vs Impuras",
"display": "pie",
"sql": "SELECT purity, COUNT(*) AS cantidad FROM functions GROUP BY purity ORDER BY cantidad DESC;",
"size_x": 6, "size_y": 5, "col": 0, "row": 8,
"size_x": 8, "size_y": 9, "col": 0, "row": 13,
},
{
"name": "Funciones Mas Usadas por Otras",
@@ -94,7 +105,7 @@ CARDS = [
ORDER BY veces_usada DESC
LIMIT 15;
""",
"size_x": 6, "size_y": 5, "col": 6, "row": 8,
"size_x": 8, "size_y": 9, "col": 8, "row": 13,
},
{
"name": "Funciones Mas Complejas (mas dependencias)",
@@ -111,8 +122,9 @@ CARDS = [
ORDER BY num_dependencias DESC
LIMIT 15;
""",
"size_x": 6, "size_y": 5, "col": 12, "row": 8,
"size_x": 8, "size_y": 9, "col": 16, "row": 13,
},
# ---- Fila 22: Cobertura + cross-table (h=8) ----
{
"name": "Cobertura de Tests por Dominio",
"display": "bar",
@@ -125,7 +137,7 @@ CARDS = [
GROUP BY domain
ORDER BY domain;
""",
"size_x": 9, "size_y": 5, "col": 0, "row": 13,
"size_x": 12, "size_y": 8, "col": 0, "row": 22,
},
{
"name": "Funciones por Lenguaje y Dominio",
@@ -142,8 +154,9 @@ CARDS = [
GROUP BY domain
ORDER BY total DESC;
""",
"size_x": 9, "size_y": 5, "col": 9, "row": 13,
"size_x": 12, "size_y": 8, "col": 12, "row": 22,
},
# ---- Fila 30: Tipos + recientes (h=8) ----
{
"name": "Tipos por Dominio y Algebraic",
"display": "table",
@@ -156,7 +169,7 @@ CARDS = [
GROUP BY domain, algebraic
ORDER BY domain, cantidad DESC;
""",
"size_x": 9, "size_y": 4, "col": 0, "row": 18,
"size_x": 12, "size_y": 8, "col": 0, "row": 30,
},
{
"name": "Funciones Recientes (ultimas 20 indexadas)",
@@ -167,7 +180,7 @@ CARDS = [
ORDER BY created_at DESC
LIMIT 20;
""",
"size_x": 9, "size_y": 4, "col": 9, "row": 18,
"size_x": 12, "size_y": 8, "col": 12, "row": 30,
},
]