Vistas
List, Form, Kanban, Calendar, Gantt y más — cómo se declara cada superficie de objeto en Console.
Vistas
Una vista es la forma en que un usuario ve y edita registros en Console. Las vistas son metadatos declarativos — con el mismo ciclo de vida que los objetos: decláralas una vez, distribúyelas con tu paquete y renderízalas en cualquier lugar.
Dos tipos:
- Vistas de lista — visualizan muchos registros (grid, kanban, calendar, …)
- Vistas de formulario — ver / editar un único registro (simple, con pestañas, asistente, …)
Fuente del esquema:
packages/spec/src/ui/view.zod.ts.
La declaración más corta posible
Cada objeto obtiene automáticamente una lista en grid + un formulario simple por
defecto, incluso si no declaras ninguna vista. Añade view para sobrescribir o
ampliar:
import { defineObject, F, P } from '@objectstack/spec'
export default defineObject({
name: 'support_ticket',
fields: [ /* ... */ ],
view: {
list: { type: 'grid', columns: ['subject', 'status', 'priority', 'assignee'] },
form: { sections: [ { label: 'Details', fields: ['subject','description','priority','status','assignee'] } ] }
}
})Para objetos con varias vistas (p. ej. un Kanban y un calendario sobre los mismos datos) usa las variantes con nombre:
view: {
listViews: {
by_status: { type: 'kanban', kanban: { groupByField: 'status' }, columns: ['subject','priority'] },
schedule: { type: 'calendar', calendar: { startDateField: 'due_at', titleField: 'subject' } },
by_owner: { type: 'grid', columns: ['subject','status','priority'], filterableFields: ['assignee'] }
},
formViews: {
quick: { type: 'modal', sections: [ /* ... */ ] },
full: { type: 'tabbed', sections: [ /* ... */ ] }
}
}Tipos de vista de lista
type | Renderiza | Configuración requerida |
|---|---|---|
grid | Tabla de datos (por defecto) | columns |
kanban | Tablero con columnas | kanban: { groupByField } |
gallery | Baraja de tarjetas | gallery: { coverField, titleField } |
calendar | Mes / semana / día | calendar: { startDateField, titleField } |
timeline | Feed cronológico | timeline: { startDateField, titleField } |
gantt | Cronograma de proyecto + dependencias | gantt: { startDateField, endDateField, titleField } |
map | Pines geoespaciales | map: { locationField } |
chart | Gráfico incrustado | chart: { chartType, xAxisField, yAxisFields } |
Opciones comunes de lista
{
type: 'grid',
columns: ['subject','status','priority','assignee','created_at'],
filter: [ { field: 'archived', operator: 'equals', value: false } ],
sort: [ { field: 'created_at', order: 'desc' } ],
pagination: { pageSize: 25 },
searchableFields: ['subject','description'],
filterableFields: ['status','priority','assignee'],
navigation: { mode: 'drawer' }, // 'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none'
selection: { type: 'multiple' }, // 'none' | 'single' | 'multiple'
rowActions: ['close_ticket','assign_to_me'],
bulkActions: ['bulk_close','bulk_export'],
conditionalFormatting: [
{ condition: P`record.priority == 'urgent'`, style: { background: '#fef2f2', fontWeight: 600 } }
],
exportOptions: ['csv','xlsx'],
emptyState: { title: 'No tickets yet', message: 'Create one to get started', icon: 'inbox' }
}filter y sort se compilan a ObjectQL;
rowActions y bulkActions referencian actions por nombre.
Kanban
{
type: 'kanban',
kanban: {
groupByField: 'status', // discrete field — usually a select
summarizeField: 'amount', // optional total per column
columns: ['subject', 'priority', 'assignee'] // fields shown on each card
}
}Las columnas del tablero provienen de los valores del groupByField; su orden
y color se toman de las definiciones de opciones select de ese campo.
Arrastrar y soltar entre columnas emite una actualización que establece el campo agrupado — con las mismas reglas de permisos que una edición manual.
Calendar
{
type: 'calendar',
calendar: {
startDateField: 'start_at',
endDateField: 'end_at', // optional — single-point if omitted
titleField: 'subject',
colorField: 'priority' // optional — colours events by value
}
}Gantt
{
type: 'gantt',
gantt: {
startDateField: 'start_at',
endDateField: 'due_at',
titleField: 'name',
progressField: 'percent_complete', // optional, drives the progress bar
dependenciesField: 'depends_on' // optional — multiselect lookup to same object
}
}Chart (en línea)
{
type: 'chart',
chart: {
chartType: 'bar', // 'bar' | 'line' | 'pie' | 'area' | 'scatter'
xAxisField: 'created_at',
yAxisFields: ['amount'],
aggregation: 'sum',
groupByField: 'status'
}
}Las vistas de gráfico son para paneles en línea sobre un único objeto — para analíticas más ricas y entre objetos, usa la superficie dedicada de informes.
Tipos de vista de formulario
type | Diseño |
|---|---|
simple | Columna única o secciones (por defecto) |
tabbed | Secciones con pestañas |
wizard | Flujo paso a paso |
split | Maestro-detalle de dos paneles |
drawer | Formulario en panel lateral |
modal | Formulario en diálogo |
{
type: 'tabbed',
sections: [
{ label: 'Overview', fields: ['subject','status','priority','assignee'] },
{ label: 'Customer', fields: ['customer','contact','email','phone'] },
{ label: 'Resolution', fields: ['resolution_notes','resolved_at'] }
],
submitBehavior: { kind: 'next-record' } // 'thank-you' | 'redirect' | 'continue' | 'next-record'
}Formularios públicos
Los formularios pueden hacerse accesibles de forma anónima:
{
type: 'simple',
sections: [ { fields: ['name','email','message'] } ],
sharing: {
enabled: true,
publicLink: 'contact-us', // slug under /forms/
allowAnonymous: true
},
submitBehavior: { kind: 'thank-you' }
}Esto expone automáticamente GET /api/v1/forms/contact-us y
POST /api/v1/forms/contact-us/submit — rutas de formulario público que
no requieren autenticación. Consulta REST API → Public forms.
Visibilidad, ARIA, temas
visibleOn: P\...`` — en secciones y campos de formulario, ocúltalos según el usuario / registro / entorno (predicado CEL)aria: { label, description, ... }— atributos ARIA para lectores de pantalla (vistas de lista y de formulario)appearance: { showDescription, allowedVisualizations: [...] }— en vistas de lista, restringe a qué tipos de lista pueden cambiar los usuarios finales
Construye por chat
Normalmente no escribes los metadatos de vista a mano. Dile al AI Builder:
"Añade una vista kanban del objeto support_ticket agrupada por status, con tarjetas que muestren subject y priority. Colorea las columnas en rojo / ámbar / verde según el status."
Este llama a las herramientas de metadatos, pone en cola el diff y, una vez que lo apruebas, la vista aparece en Console. Consulta AI Builder.
Consulta también
- Data model — los objetos de los que leen las vistas
- Actions — a qué referencian
rowActions/bulkActions - ObjectQL — a qué se compilan
filter/sort - CEL —
conditionalFormatting,visibleOn @objectstack/spec/ui/view.zod.ts— esquema