Files
fn_registry/python/functions/metabase/metabase_dashboard_append_row.py
egutierrez 20f72edb5a feat(metabase): auto-commit con 17 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 18:40:22 +02:00

125 lines
4.5 KiB
Python

"""Añade N cards como fila horizontal al final de una tab de dashboard."""
from __future__ import annotations
from .client import MetabaseClient
from .metabase_dashboard_next_row import metabase_dashboard_next_row
from .metabase_copy_dashcard_mappings import metabase_copy_dashcard_mappings
from .metabase_update_dashboard_safe import metabase_update_dashboard_safe
def metabase_dashboard_append_row(
client: MetabaseClient,
*,
dashboard_id: int,
tab_id: int,
card_ids: list[int],
height: int = 4,
donor_card_id: int = 0,
grid_width: int = 24,
) -> dict:
"""Añade N cards como fila horizontal al final de una tab de dashboard.
Calcula la primera fila libre de la tab indicada, distribuye las cards
horizontalmente con ancho uniforme (``grid_width // len(card_ids)``) y
opcionalmente copia los ``parameter_mappings`` de una card donante a cada
nueva card. Internamente delega en ``metabase_dashboard_next_row``,
``metabase_copy_dashcard_mappings`` y ``metabase_update_dashboard_safe``.
Args:
client: MetabaseClient autenticado con sesion activa.
dashboard_id: ID del dashboard donde se añaden las cards.
tab_id: ID de la tab donde se insertan las cards. Usar ``0`` para
dashboards sin tabs o para la tab raiz.
card_ids: Lista de IDs de cards a colocar como fila. El orden de
la lista determina el orden de izquierda a derecha.
height: Altura en filas del grid para cada card. Default ``4``.
donor_card_id: Si distinto de ``0``, copia los ``parameter_mappings``
de esa card (que debe existir ya en el dashboard) a cada nueva
card. Util para replicar los 18 filtros de dashboard sin configurar
manualmente cada mapping. Default ``0`` (sin mappings).
grid_width: Anchura total del grid de Metabase. Default ``24``
(estandar de Metabase). Cada card recibe
``grid_width // len(card_ids)`` columnas.
Returns:
Dict con el resumen de la operacion devuelto por
``metabase_update_dashboard_safe``::
{
"added": [lista de IDs negativos asignados],
"updated": int, # dashcards existentes conservados
"removed": int, # dashcards eliminados (0 en este caso)
"response": dict, # respuesta raw de PUT /api/dashboard/:id
}
Raises:
ValueError: Si ``card_ids`` esta vacio, o si ``donor_card_id != 0``
y esa card no existe en el dashboard.
httpx.HTTPStatusError: Si la API de Metabase devuelve 4xx/5xx.
Example:
>>> # Añadir 4 KPIs al final de la tab 7, copiando filtros de card 42
>>> result = metabase_dashboard_append_row(
... client,
... dashboard_id=10,
... tab_id=7,
... card_ids=[101, 102, 103, 104],
... height=4,
... donor_card_id=42,
... )
>>> print(result["added"]) # [-1, -2, -3, -4]
>>> # Sin filtros, 2 cards en dashboard sin tabs
>>> result = metabase_dashboard_append_row(
... client,
... dashboard_id=10,
... tab_id=0,
... card_ids=[200, 201],
... height=6,
... )
"""
if not card_ids:
raise ValueError("card_ids no puede estar vacio")
# 1. Calcular siguiente fila libre
next_row = metabase_dashboard_next_row(
client, dashboard_id=dashboard_id, tab_id=tab_id
)
# 2. Ancho de cada card
size_x = grid_width // len(card_ids)
# 3. Construir dashcards
new_dashcards: list[dict] = []
for i, cid in enumerate(card_ids):
# Copiar mappings del donor si se especifico
if donor_card_id != 0:
mappings = metabase_copy_dashcard_mappings(
client,
dashboard_id=dashboard_id,
source_card_id=donor_card_id,
dest_card_id=cid,
)
else:
mappings = []
dashcard: dict = {
"card_id": cid,
"dashboard_tab_id": tab_id,
"row": next_row,
"col": i * size_x,
"size_x": size_x,
"size_y": height,
"parameter_mappings": mappings,
"visualization_settings": {},
}
new_dashcards.append(dashcard)
# 4. Actualizar el dashboard
return metabase_update_dashboard_safe(
client,
dashboard_id,
dashcards_add=new_dashcards,
)