Files
rapid_dashboards/docs/guia.md
T
2026-04-06 00:57:13 +02:00

15 KiB

Rapid Dashboards — Guia de uso

Dashboard builder declarativo: defines un YAML, obtienes un dashboard desktop con datos en vivo.

Inicio rapido

cd apps/rapid_dashboards

# Desarrollo — usa symlink dashboard.yaml (ver "Cambiar entre dashboards")
wails dev

# Desarrollo — build produccion
CGO_ENABLED=1 wails build -tags fts5
./build/bin/rapid-dashboards --dashboard examples/fn_registry_overview.yaml

Compilar un dashboard especifico

Desarrollo (wails dev)

wails dev no pasa argumentos CLI al binario. El binario busca el dashboard en este orden:

  1. Flag --dashboard <path> (solo funciona con wails build, no con wails dev)
  2. Variable de entorno DASHBOARD (no se propaga al binario en wails dev)
  3. Archivo dashboard.yaml en el cwd (metodo recomendado para desarrollo)

Para desarrollo, usar un symlink:

# Apuntar al dashboard deseado
ln -sf examples/fn_registry_overview.yaml dashboard.yaml

# Lanzar — el binario encuentra dashboard.yaml automaticamente
wails dev

Produccion (wails build)

# Compilar
CGO_ENABLED=1 wails build -tags fts5

# Ejecutar con un YAML especifico
./build/bin/rapid-dashboards --dashboard examples/fn_registry_overview.yaml
./build/bin/rapid-dashboards --dashboard /ruta/absoluta/mi_dashboard.yaml

El binario compilado acepta el flag --dashboard directamente.


Cambiar entre dashboards

En vivo (dropdown en la app)

Si hay mas de un archivo .yaml en el directorio del dashboard actual, aparece un dropdown junto al titulo. Al seleccionar otro dashboard:

  • Se cargan las nuevas conexiones, queries y widgets
  • Se cierran las conexiones anteriores
  • El tema se aplica automaticamente

Los dashboards disponibles se escanean del directorio donde esta el YAML actual (por defecto examples/).

# Ver dashboards disponibles
ls examples/*.yaml

# Cambiar al dashboard de apps
ln -sf examples/fn_registry_apps.yaml dashboard.yaml

# Cambiar al overview de funciones
ln -sf examples/fn_registry_overview.yaml dashboard.yaml

# Reiniciar wails dev para que tome el cambio

Por CLI (produccion)

# Dashboard de funciones
./build/bin/rapid-dashboards --dashboard examples/fn_registry_overview.yaml

# Dashboard de apps
./build/bin/rapid-dashboards --dashboard examples/fn_registry_apps.yaml

Temas

El campo theme del YAML controla toda la estetica del dashboard. Cada tema cambia colores de fondo, texto, cards, bordes, acentos y la paleta de colores de los graficos.

Temas disponibles

Tema Descripcion Uso recomendado
dark Azul-gris profundo, acentos azules Default, dashboards tecnicos
emerald Verde esmeralda oscuro, acentos dorados Dashboards financieros, naturaleza
amber Calido ambar/naranja sobre fondo oscuro Dashboards de alertas, operaciones
rose Rosa/magenta sobre fondo oscuro Dashboards de marketing, analytics
light Fondo claro con sombras sutiles Presentaciones, pantallas con luz

Ejemplo de uso

# Dashboard con tema esmeralda
theme: "emerald"

# Dashboard con tema claro
theme: "light"

Que cambia cada tema

  • Background y foreground: tonos base del fondo y texto
  • Card: color de fondo de widgets, sin bordes en temas oscuros, con sombra en light
  • Primary/accent: color de acento para interacciones y highlights
  • Border: tonos de separadores y bordes
  • Chart palette: cada tema tiene su propia secuencia de colores para graficos (--chart-1 a --chart-5)

Anadir un tema nuevo

Anadir un bloque [data-theme="nombre"] en frontend/src/app.css con todas las variables CSS. El tema se activa automaticamente al usar theme: "nombre" en el YAML.


Estructura del YAML

Un dashboard se define con 5 bloques:

settings:     # titulo, dimensiones, refresh global, columnas
theme:        # tema visual
connections:  # bases de datos
queries:      # SQL + refresh + params
filters:      # controles de filtro
sections:     # secciones con widgets

1. settings

settings:
  title: "Mi Dashboard"      # titulo de la ventana
  refresh: 30s                # refresh global por defecto
  width: 1280                 # ancho ventana (px)
  height: 800                 # alto ventana (px)
  columns: 12                 # columnas del grid CSS
  • refresh acepta duraciones Go: 200ms, 1s, 5s, 1m, 30m
  • columns define el grid base. Cada widget usa span para ocupar N columnas.

2. connections

Cada conexion tiene un nombre y un driver. Secrets via variables de entorno ${VAR}.

SQLite

connections:
  local:
    driver: sqlite
    path: ./data.db

PostgreSQL

connections:
  main_db:
    driver: postgres
    host: localhost
    port: 5432
    user: analytics
    password: "${PG_PASSWORD}"
    database: myapp
    sslmode: disable

DuckDB

connections:
  warehouse:
    driver: duckdb
    path: ./warehouse.duckdb

ClickHouse

connections:
  events:
    driver: clickhouse
    host: localhost
    port: 9000
    user: default
    password: ""
    database: events

Paths relativos: se resuelven desde el cwd del binario, NO desde la ubicacion del YAML. En desarrollo el cwd es apps/rapid_dashboards/, asi que ../../registry.db apunta a la raiz del repo.


3. queries

queries:
  revenue_total:
    connection: main_db
    sql: "SELECT SUM(amount) as value FROM orders"
    refresh: 10s
    stale_time: 5s

  revenue_by_date:
    connection: main_db
    sql: |
      SELECT date, SUM(amount) as revenue
      FROM orders
      WHERE date >= :date_from AND date <= :date_to
      ORDER BY date
    params:
      date_from: "$filter.date_range.from"
      date_to: "$filter.date_range.to"

Parametros

  • :nombre en el SQL se reemplaza por el valor del param.
  • $filter.xxx referencia el valor actual de un filtro.
  • $filter.date_range.from accede al subcampo from.
  • Placeholders se convierten al formato del driver ($1 para Postgres, ? para SQLite/DuckDB/ClickHouse).

Fechas relativas

Valor Resultado
now timestamp actual
now-7d hace 7 dias
now-24h hace 24 horas
now-30m hace 30 minutos

4. filters

Select

filters:
  category:
    type: select
    label: "Categoria"
    default: "all"
    options:
      - { label: "Todas", value: "all" }
      - { label: "Electronics", value: "electronics" }

Date Range

filters:
  date_range:
    type: date_range
    label: "Periodo"
    default: { from: "now-7d", to: "now" }
    presets:
      - { label: "7 dias", from: "now-7d", to: "now" }
      - { label: "30 dias", from: "now-30d", to: "now" }

Text

filters:
  search:
    type: text
    label: "Buscar"
    placeholder: "Buscar por nombre..."
    debounce: 300

5. sections y widgets

sections:
  - id: kpis
    title: "Metricas"
    columns: 4                  # override de columnas
    widgets:
      - id: total_users
        type: kpi
        title: "Usuarios"
        query: count_users
        mapping: { value: "value" }
        span: 1

  - id: charts
    title: "Graficos"
    collapsible: true
    columns: 2
    widgets:
      - id: revenue_line
        type: line_chart
        title: "Revenue"
        query: revenue_by_date
        mapping:
          x: "date"
          series:
            - { key: "revenue", name: "Revenue", color: "#3b82f6" }
        options:
          zoomable: true
        span: 1

Tipos de widget

kpi

- type: kpi
  mapping:
    value: "campo_sql"
    format: "$,.2f"             # opcional

line_chart

- type: line_chart
  mapping:
    x: "date"
    series:
      - { key: "revenue", name: "Revenue", color: "#3b82f6" }
  options:
    curve: monotone             # linear | monotone | step
    show_grid: true
    show_legend: true
    zoomable: true
    height: 400

bar_chart

- type: bar_chart
  mapping:
    x: "category"
    y: "count"
    # O multi-series con series: [...]
  options:
    horizontal: true            # barras horizontales
    show_grid: true
    show_legend: true
    height: 300

pie_chart

- type: pie_chart
  mapping:
    name: "domain"              # campo para nombres de segmentos
    value: "cantidad"           # campo numerico
  options:
    donut: true                 # hueco central
    show_legend: true           # default: true
    height: 300

area_chart

- type: area_chart
  mapping:
    x: "date"
    series:
      - { key: "users", name: "Usuarios" }
  options:
    stacked: true
    height: 300

sparkline

- type: sparkline
  mapping:
    value: "metric"
  options:
    variant: area               # line | area | bar
    width: 200
    height: 40

table

- type: table
  mapping:
    columns:
      - { key: "name", label: "Nombre" }
      - { key: "amount", label: "Monto", format: "$,.2f" }
      - { key: "created_at", label: "Fecha", format: "datetime" }
  options:
    heatmap_columns: ["go", "python", "bash"]   # colorea celdas por intensidad

Si no defines columns, se auto-detectan del resultado SQL.

Heatmap: options.heatmap_columns acepta un array de nombres de columna. Las celdas se colorean de azul oscuro (valor minimo) a azul brillante (valor maximo), calculado por columna.


Formatos de valor

Formato Ejemplo Resultado
$,.2f 1234.5 $1,234.50
,.2f 1234.5 1,234.50
.2f 1234.5 1234.50
, 1234 1,234
datetime ISO string locale datetime

Variables de entorno

Cualquier campo del YAML soporta ${VARIABLE}:

DB_HOST=prod.example.com DB_PASSWORD=secret \
  ./rapid-dashboards --dashboard prod.yaml

Puntos clave (aprendizajes)

Wails dev no pasa CLI args al binario

wails dev -- --flag value no funciona: Wails compila y ejecuta el binario como proceso hijo sin pasar los args despues de --. Tampoco propaga variables de entorno al binario. La solucion es usar un archivo dashboard.yaml en el cwd que el binario detecta automaticamente.

Wails genera bindings ejecutando el binario sin args

Durante wails dev, el primer paso es generar bindings TypeScript. Para esto Wails ejecuta el binario sin argumentos. Si el binario requiere flags obligatorios y hace os.Exit(1), la generacion falla. Solucion: detectar cuando no hay args y usar un config dummy con slices vacios (no nil) para que los tipos se generen correctamente.

Slices nil de Go se serializan como null en JSON

[]SectionDef(nil) se serializa como null, no como []. Si el frontend hace .map() sobre null, crash. Inicializar siempre con []SectionDef{} para el config dummy, y usar (config.sections ?? []) en el frontend.

Tipos de Wails vs tipos manuales de TypeScript

Wails genera models.ts con tipos string genericos. Si el frontend tiene tipos mas estrictos (union types como "select" | "date_range"), hay incompatibilidad. Solucion: castear los imports con as unknown as typeof X.

Paths relativos se resuelven desde el cwd, no desde el YAML

SQLiteOpen(path) resuelve paths relativos al cwd del proceso. Si el YAML esta en examples/ y el binario corre desde apps/rapid_dashboards/, un path ../../registry.db es correcto pero ../../../registry.db (relativo al YAML) no. Siempre pensar los paths desde el cwd del binario.

Recharts Pie necesita valores numericos

SQLite puede devolver numeros como strings en algunos contextos. Recharts Pie no renderiza nada si dataKey apunta a un string. Solucion: coercer a Number() antes de pasar a Pie.

Recharts PieLabelRenderProps es estricto

El tipo label de <Pie> no acepta callbacks con tipos genericos como Record<string, unknown>. Hay que importar PieLabelRenderProps de recharts y usar una funcion con nombre tipada, no un lambda inline.

Animaciones de Recharts

Las animaciones por defecto de Recharts Pie son lentas en dashboards que refrescan frecuentemente. Usar isAnimationActive={false} para render instantaneo.


Scripts de lanzamiento

Cada dashboard YAML debe tener forma de lanzarse rapido desde scripts/. La carpeta scripts/ contiene dos scripts genericos que reciben el nombre del dashboard como argumento:

# Listar dashboards disponibles
./scripts/dev.sh

# Desarrollo — crea symlink + wails dev
./scripts/dev.sh fn_registry_overview

# Produccion — compila si es necesario + ejecuta
./scripts/prod.sh fn_registry_apps

# Produccion con variables de entorno
DB_PASSWORD=secret ./scripts/prod.sh mi_dashboard

Convencion

Al crear un nuevo YAML en examples/, no hace falta crear scripts adicionales — dev.sh y prod.sh descubren automaticamente los .yaml de examples/. Solo ejecutar con el nombre (sin extension):

# Nuevo dashboard
vim examples/mi_nuevo_dashboard.yaml

# Lanzar inmediatamente
./scripts/dev.sh mi_nuevo_dashboard

dev.sh crea el symlink dashboard.yaml y lanza wails dev. prod.sh compila con CGO_ENABLED=1 wails build -tags fts5 si el binario no existe o el YAML es mas reciente, y ejecuta con --dashboard.


Compilacion multiplataforma

Linux (default)

CGO_ENABLED=1 wails build -tags fts5

Genera build/bin/rapid-dashboards con soporte para SQLite, PostgreSQL, DuckDB y ClickHouse.

Windows (cross-compile desde Linux)

CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 \
  wails build -tags "fts5 noduckdb noclickhouse" -platform windows/amd64 -skipbindings

Genera build/bin/rapid-dashboards.exe. Requiere mingw-w64 instalado (apt install gcc-mingw-w64-x86-64).

Limitacion: DuckDB y ClickHouse se excluyen con los tags noduckdb y noclickhouse porque go-duckdb depende de libstdc++ y no cross-compila bien desde Linux. El .exe solo soporta SQLite y PostgreSQL. Si un YAML usa esos drivers, dara error: "duckdb support not compiled".

Windows nativo (con DuckDB y ClickHouse)

Para compilar con todos los drivers, compilar directamente en Windows con Go y MinGW/MSYS2 instalados:

# En Windows con Go + MinGW (MSYS2)
$env:CGO_ENABLED=1
wails build -tags fts5

Esto genera un .exe con soporte completo: SQLite, PostgreSQL, DuckDB y ClickHouse.

Resumen de soporte por plataforma

Driver Linux Windows (cross-compile) Windows (nativo)
SQLite si si si
PostgreSQL si si si
DuckDB si no si
ClickHouse si no si

Rutas en Windows

Las rutas no se rompen entre plataformas. El codigo usa filepath.Join y filepath.IsAbs de Go, que adaptan los separadores automaticamente (/ en Linux, \ en Windows). Los paths relativos en el YAML (ej: ../../registry.db) funcionan igual en ambos OS.


Extensibilidad

Para anadir un tipo de widget nuevo:

  1. Crear frontend/src/components/widgets/MiWidget.tsx implementando WidgetProps
  2. Registrar en frontend/src/components/widgets/register.ts: registerWidget('mi_tipo', MiWidget)
  3. Usar en YAML: type: mi_tipo