feat(metabase): expansion cards y documents — export, model, ProseMirror validation, copy nativo
Cards: export_card (CSV/XLSX/JSON), create_model (type=model para fuentes MBQL). Documents: prosemirror_card_embed helper (resizeNode envolviendo cardEmbed), validacion automatica contra whitelist TipTap antes de enviar, copy_document refactorizado al endpoint nativo POST /api/document/:id/copy. Docs: dataset_query legacy vs MBQL5, template-tags, whitelist de nodos. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -354,3 +354,83 @@ def metabase_create_card_raw(client: MetabaseClient, payload: dict) -> dict:
|
||||
>>> print(card["id"]) # ID asignado por Metabase
|
||||
"""
|
||||
return client.request("POST", "/api/card", json=payload)
|
||||
|
||||
|
||||
def metabase_export_card(
|
||||
client: MetabaseClient,
|
||||
card_id: int,
|
||||
format: str = "csv",
|
||||
) -> bytes:
|
||||
"""Exporta los resultados de una card en CSV, XLSX o JSON.
|
||||
|
||||
Endpoint: POST /api/card/:id/query/:format.
|
||||
|
||||
Args:
|
||||
client: Cliente autenticado.
|
||||
card_id: ID de la card.
|
||||
format: Formato de exportación: "csv", "xlsx" o "json".
|
||||
|
||||
Returns:
|
||||
bytes con el contenido del archivo exportado.
|
||||
|
||||
Example:
|
||||
>>> data = metabase_export_card(client, 42, format="csv")
|
||||
>>> with open("export.csv", "wb") as f:
|
||||
... f.write(data)
|
||||
"""
|
||||
resp = client._http.request("POST", f"/api/card/{card_id}/query/{format}")
|
||||
resp.raise_for_status()
|
||||
return resp.content
|
||||
|
||||
|
||||
def metabase_create_model(
|
||||
client: MetabaseClient,
|
||||
name: str,
|
||||
sql: str,
|
||||
database_id: int,
|
||||
collection_id: int = 0,
|
||||
description: str = "",
|
||||
) -> dict:
|
||||
"""Crea un modelo (card tipo model) que otras cards pueden referenciar.
|
||||
|
||||
Un modelo es una card con type="model". Otras cards MBQL pueden usarlo
|
||||
como fuente con source-table: "card__<model_id>".
|
||||
|
||||
Endpoint: POST /api/card con type="model".
|
||||
|
||||
Args:
|
||||
client: Cliente autenticado.
|
||||
name: Nombre del modelo.
|
||||
sql: Query SQL del modelo.
|
||||
database_id: ID de la database en Metabase.
|
||||
collection_id: Coleccion destino. 0 = root.
|
||||
description: Descripcion opcional.
|
||||
|
||||
Returns:
|
||||
Dict con el modelo creado (id, name, type="model").
|
||||
|
||||
Example:
|
||||
>>> model = metabase_create_model(client, "supply_orders_base",
|
||||
... "SELECT * FROM supply_orders WHERE ...", database_id=6)
|
||||
>>> # Usar en otra card MBQL:
|
||||
>>> card = metabase_create_card(client, "Revenue", {
|
||||
... "database": 6, "type": "query",
|
||||
... "query": {"source-table": f"card__{model['id']}"}
|
||||
... })
|
||||
"""
|
||||
body: dict = {
|
||||
"name": name,
|
||||
"type": "model",
|
||||
"dataset_query": {
|
||||
"database": database_id,
|
||||
"type": "native",
|
||||
"native": {"query": sql},
|
||||
},
|
||||
"display": "table",
|
||||
"visualization_settings": {},
|
||||
}
|
||||
if collection_id > 0:
|
||||
body["collection_id"] = collection_id
|
||||
if description:
|
||||
body["description"] = description
|
||||
return client.request("POST", "/api/card", json=body)
|
||||
|
||||
Reference in New Issue
Block a user