"""Calcula la siguiente fila libre al final de una tab de dashboard.""" from __future__ import annotations from .client import MetabaseClient from .dashboards import metabase_get_dashboard def metabase_dashboard_next_row( client: MetabaseClient, *, dashboard_id: int, tab_id: int = 0, ) -> int: """Retorna la primera fila libre al final de una tab de dashboard. Obtiene el dashboard y filtra las dashcards que pertenecen a la tab indicada. Devuelve max(dc["row"] + dc["size_y"]) entre esas cards, o 0 si no hay ninguna dashcard en la tab. Cuando tab_id == 0 se consideran las dashcards sin dashboard_tab_id (dashboards sin pestanas o pestaƱa raiz). Args: client: Cliente autenticado con sesion activa. dashboard_id: ID del dashboard a consultar. tab_id: ID de la tab cuya fila final se calcula. 0 = dashcards sin tab (dashboard sin pestanas o tab raiz). Returns: Entero con la fila donde colocar la siguiente card (0-indexed). 0 si la tab no tiene dashcards. Example: >>> next_row = metabase_dashboard_next_row(client, dashboard_id=10) >>> new_dashcard = { ... "id": -1, ... "card_id": 99, ... "col": 0, "row": next_row, "size_x": 6, "size_y": 4, ... "parameter_mappings": [], ... "visualization_settings": {}, ... } >>> # Dashboard con tabs >>> next_row = metabase_dashboard_next_row( ... client, dashboard_id=10, tab_id=3 ... ) """ dashboard = metabase_get_dashboard(client, dashboard_id) dashcards: list[dict] = dashboard.get("dashcards") or [] if tab_id == 0: filtered = [dc for dc in dashcards if not dc.get("dashboard_tab_id")] else: filtered = [dc for dc in dashcards if dc.get("dashboard_tab_id") == tab_id] if not filtered: return 0 return max(dc["row"] + dc["size_y"] for dc in filtered)