ObjectOS
구축

List, Form, Kanban, Calendar, Gantt 등 — Console의 모든 오브젝트 표면을 선언하는 방법.

는 사용자가 Console에서 레코드를 보고 편집하는 방식입니다. 뷰는 선언적 메타데이터이며 — 오브젝트와 동일한 라이프사이클을 가집니다. 한 번 선언하고, 패키지와 함께 배포하며, 어디서나 렌더링합니다.

두 가지 종류:

  • List 뷰 — 여러 레코드를 시각화합니다 (grid, kanban, calendar 등)
  • Form 뷰 — 단일 레코드를 보거나 편집합니다 (simple, tabbed, wizard 등)

스키마 소스: packages/spec/src/ui/view.zod.ts.

가능한 가장 짧은 선언

모든 오브젝트는 뷰를 선언하지 않아도 기본 grid list와 simple form을 자동으로 가집니다. 재정의하거나 확장하려면 view를 추가하세요:

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'] } ] }
  }
})

여러 뷰를 가진 오브젝트(예: 동일한 데이터에 대해 Kanban calendar)의 경우 명명된 변형을 사용하세요:

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: [ /* ... */ ] }
  }
}

List 뷰 타입

type렌더링필수 설정
grid데이터 테이블 (기본값)columns
kanban컬럼이 있는 보드kanban: { groupByField }
gallery카드 덱gallery: { coverField, titleField }
calendar월 / 주 / 일calendar: { startDateField, titleField }
timeline시간순 피드timeline: { startDateField, titleField }
gantt프로젝트 타임라인 + 의존성gantt: { startDateField, endDateField, titleField }
map지리공간 핀map: { locationField }
chart임베드 차트chart: { chartType, xAxisField, yAxisFields }

공통 list 옵션

{
  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' }
}

filtersortObjectQL로 컴파일됩니다. rowActionsbulkActionsactions를 이름으로 참조합니다.

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
  }
}

보드의 컬럼은 groupByField의 값에서 가져오며, 그 순서와 색상은 해당 필드의 select 옵션 정의에서 가져옵니다.

컬럼 간 드래그 앤 드롭은 그룹화된 필드를 설정하는 업데이트를 발생시키며 — 수동 편집과 동일한 권한 규칙이 적용됩니다.

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 (인라인)

{
  type: 'chart',
  chart: {
    chartType: 'bar',                        // 'bar' | 'line' | 'pie' | 'area' | 'scatter'
    xAxisField:  'created_at',
    yAxisFields: ['amount'],
    aggregation: 'sum',
    groupByField: 'status'
  }
}

Chart 뷰는 단일 오브젝트의 인라인 대시보드를 위한 것입니다 — 더 풍부한 오브젝트 간 분석을 위해서는 전용 reports 표면을 사용하세요.

Form 뷰 타입

type레이아웃
simple단일 컬럼 또는 섹션 (기본값)
tabbed탭 섹션
wizard단계별 플로우
split마스터-디테일 두 개 창
drawer측면 패널 폼
modal다이얼로그 폼
{
  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'
}

공개 폼

폼은 익명 접근이 가능하도록 만들 수 있습니다:

{
  type: 'simple',
  sections: [ { fields: ['name','email','message'] } ],
  sharing: {
    enabled: true,
    publicLink: 'contact-us',                // slug under /forms/
    allowAnonymous: true
  },
  submitBehavior: { kind: 'thank-you' }
}

이는 GET /api/v1/forms/contact-usPOST /api/v1/forms/contact-us/submit를 자동으로 노출합니다 — 인증이 필요하지 않은 공개 폼 라우트입니다. REST API → Public forms를 참고하세요.

가시성, ARIA, 테마

  • visibleOn: P\...`` — form 섹션필드에서, 사용자 / 레코드 / 환경에 따라 숨깁니다 (CEL 술어)
  • aria: { label, description, ... } — 스크린 리더를 위한 ARIA 속성 (list 및 form 뷰)
  • appearance: { showDescription, allowedVisualizations: [...] } — list 뷰에서, 최종 사용자가 전환할 수 있는 list 타입을 제한합니다

채팅으로 빌드하기

일반적으로 뷰 메타데이터를 직접 작성하지 않습니다. AI Builder에게 알려주세요:

"subject와 priority를 보여주는 카드와 함께 status별로 그룹화된 support_ticket 오브젝트의 kanban 뷰를 추가해줘. status에 따라 컬럼을 빨강 / 호박색 / 초록으로 색칠해줘."

AI Builder가 메타데이터 도구를 호출하고, diff를 큐에 넣으며, 승인하면 해당 뷰가 Console에 나타납니다. AI Builder를 참고하세요.

참고

On this page