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:
@@ -43,7 +43,58 @@ card = metabase_create_card(client, "Revenue", {
|
||||
}, display="scalar")
|
||||
```
|
||||
|
||||
## Ejemplo con template-tags (filtros)
|
||||
|
||||
```python
|
||||
card = metabase_create_card(client, "Revenue filtrable", {
|
||||
"database": 6, "type": "native",
|
||||
"native": {
|
||||
"query": "SELECT * FROM orders WHERE 1=1 [[AND date >= {{fecha_desde}}]]",
|
||||
"template-tags": {
|
||||
"fecha_desde": {
|
||||
"name": "fecha_desde",
|
||||
"display-name": "Fecha desde",
|
||||
"id": "fecha_desde_tag",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
}, display="table")
|
||||
```
|
||||
|
||||
## Formato dataset_query — IMPORTANTE
|
||||
|
||||
Hay DOS formatos y hay que saber cuál usar:
|
||||
|
||||
**Para CREAR cards (POST /api/card) — formato legacy:**
|
||||
```python
|
||||
{"database": id, "type": "native", "native": {"query": "SELECT ..."}}
|
||||
```
|
||||
|
||||
**Lo que DEVUELVE Metabase al LEER cards (GET /api/card/:id) — formato MBQL5:**
|
||||
```python
|
||||
{"lib/type": "mbql/query", "database": id,
|
||||
"stages": [{"lib/type": "mbql.stage/native", "native": "SELECT ..."}]}
|
||||
```
|
||||
|
||||
Son representaciones distintas de lo mismo. Al leer una card existente y querer extraer el SQL:
|
||||
```python
|
||||
card = metabase_get_card(client, 42)
|
||||
ds = card["dataset_query"]
|
||||
|
||||
# Formato MBQL5 (Metabase reciente)
|
||||
stages = ds.get("stages", [])
|
||||
if stages:
|
||||
sql = stages[0].get("native", "")
|
||||
|
||||
# Formato legacy
|
||||
else:
|
||||
sql = ds.get("native", {}).get("query", "")
|
||||
```
|
||||
|
||||
Al crear/actualizar cards, usar SIEMPRE el formato legacy — Metabase lo acepta y lo convierte internamente.
|
||||
|
||||
## Notas
|
||||
|
||||
dataset_query SQL nativo: `{"database": id, "type": "native", "native": {"query": "..."}}`
|
||||
dataset_query MBQL: `{"database": id, "type": "query", "query": {"source-table": id, ...}}`
|
||||
- `display` válidos: scalar, table, line, bar, pie, area, row, funnel, combo, pivot, map, scatter, waterfall, gauge, progress, smartscalar, sankey.
|
||||
- Para queries que se repiten como base de otras cards, considerar crear un "model" (type="model") y referenciar desde otras cards con `source-table: "card__<id>"`.
|
||||
|
||||
Reference in New Issue
Block a user