> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WorkspaceView

> WorkspaceView represents a named, workspace-scoped configuration for displaying a record root (e.g

WorkspaceView represents a named, workspace-scoped configuration for displaying a record root (e.g. invoices, companies) in the Well records table. It persists the full view state — visible columns, sort order, active filters, grouping, layout type, and layout-specific display settings — so users can switch between saved views without re-configuring each session. Each view is bound to exactly one Workspace and one record root string; a boolean flag marks at most one view per (workspace, root) combination as the default. Views are user-created and user-managed through a dedicated REST surface; they are never written by any connector or pipeline.

| Naming                          | Value                             |
| ------------------------------- | --------------------------------- |
| Object                          | WorkspaceView                     |
| Resource type (JSON:API `type`) | `workspace_view`                  |
| Collection / records root       | — <sub>(not a records root)</sub> |
| REST base                       | `/v1/workspace-views`             |
| Entity class                    | `WorkspaceView`                   |

<Note>
  **Internal object.** Not currently exposed on the public REST API. The operations below describe the intended contract.
</Note>

## API operations

| Operation | Method & path                     | Status     |
| --------- | --------------------------------- | ---------- |
| List      | `GET /v1/workspace-views`         | 🟡 Planned |
| Retrieve  | `GET /v1/workspace-views/{id}`    | 🟡 Planned |
| Create    | `POST /v1/workspace-views`        | 🟡 Planned |
| Update    | `PATCH /v1/workspace-views/{id}`  | 🟡 Planned |
| Delete    | `DELETE /v1/workspace-views/{id}` | 🟡 Planned |

## Data model

### Attributes

| Field           | Type                          | Required | Constraints                                                                                                                                                                                              | Allowed values                                                                                                                                                              | Description                                                                                                                                                                                                                                                        |
| --------------- | ----------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| view\_id        | string (UUID)                 | ✅ Yes    | gen\_random\_uuid() default; UNIQUE                                                                                                                                                                      | any valid UUID                                                                                                                                                              | Public stable identifier for this view. Exposed as the JSON:API id. Stable across renames — links to a saved view remain valid as long as the view exists.                                                                                                         |
| name            | string                        | ✅ Yes    | max length 255                                                                                                                                                                                           | any non-empty string ≤ 255 chars                                                                                                                                            | Human-readable display name for the view, shown in the view switcher tab and in the views list.                                                                                                                                                                    |
| root            | string                        | ✅ Yes    | max length 100; must match a value in the recordsQuerySchema root enum                                                                                                                                   | see DATA\_VIEW\_ROOTS (e.g. 'invoices', 'companies', 'people', 'transactions')                                                                                              | The record root this view targets. Immutable after creation. A view for 'invoices' cannot be reused on 'companies'.                                                                                                                                                |
| columns         | jsonb (ColumnConfig\[])       | ⚪ No     | default '\[]'; each element: field (string\[]), order (number), optional width (px), alias, icon, pinned ('left'\|'right')                                                                               | array of ColumnConfig objects                                                                                                                                               | Ordered list of visible column configurations. Defines which fields appear, their display order, pixel width, optional alias, and pin side. An empty array means the root's default column set is used.                                                            |
| sort            | jsonb (SortConfig\[])         | ⚪ No     | default '\[]'; each element: field (string\[]), direction ('asc'\|'desc')                                                                                                                                | array of SortConfig objects                                                                                                                                                 | Ordered list of sort rules applied to the query. Multiple entries are applied in array order (primary, secondary, etc.).                                                                                                                                           |
| filters         | jsonb (FilterConfig\[])       | ⚪ No     | default '\[]'; each element: field (string\[]), operator (FilterOperator), value, optional conjunction ('and'\|'or')                                                                                     | array of FilterConfig objects; operator one of: eq, neq, gt, gte, lt, lte, contains, not\_contains, starts\_with, ends\_with, is\_null, is\_not\_null, in, not\_in, between | Active filter conditions persisted with this view. Applied when the view is loaded. The conjunction field chains consecutive filters; defaults to 'and'.                                                                                                           |
| layout\_type    | string                        | ⚪ No     | max length 20; default 'table'; CHECK chk\_workspace\_views\_layout\_type enforces allowed values                                                                                                        | 'table' \| 'kanban' \| 'calendar' \| 'gallery' \| 'chart' \| 'list' \| 'graph'                                                                                              | The UI layout mode for this view. Determines which renderer and layout\_config shape apply. The CHECK constraint is authoritative; the LAYOUT\_TYPES constant in @wellapp/shared mirrors it.                                                                       |
| layout\_config  | jsonb (LayoutConfig)          | ⚪ No     | default '\{}'; shape depends on layout\_type (TableLayoutConfig \| KanbanLayoutConfig \| CalendarLayoutConfig \| GalleryLayoutConfig \| ChartLayoutConfig \| ListLayoutConfig \| Record\<string, never>) | layout-type-specific config object or empty object                                                                                                                          | Layout-specific presentation settings. Contains ONLY layout rendering preferences (row height, card size, chart type, etc.), NOT field selection — that lives in display\_fields. Ignored by the renderer when layout\_type changes until explicitly set.          |
| display\_fields | jsonb (DisplayFieldConfig\[]) | ⚪ No     | default '\[]'; each element: fieldId (dot-path string), visible (bool), order (number), optional displayType, skillId, skillRenderHint, width, role (LayoutFieldRole)                                    | array of DisplayFieldConfig objects; role one of: title, subtitle, group\_by, sub\_group, date, end\_date, measure, thumbnail, badge, color, assignee, status, detail       | Field visibility and rendering configuration for non-table layouts (kanban, calendar, gallery, chart, list, graph). Each entry declares what data appears on a card or tile, in what position, and with what display override.                                     |
| group\_by       | jsonb (string\[] \| null)     | ⚪ No     | nullable; null means no grouping                                                                                                                                                                         | array of dot-path field strings, or null                                                                                                                                    | Field paths to group records by in the current view. An empty array and null are both treated as 'no grouping'. Used by the kanban and grouped-table modes.                                                                                                        |
| is\_default     | boolean                       | ⚪ No     | default false; no DB-level unique constraint — enforcement is at the service layer (WorkspaceViewService sets is\_default=false on sibling views when one is promoted)                                   | true \| false                                                                                                                                                               | When true, this view is loaded automatically when a user navigates to the record root within the workspace. Only one view per (workspace, root) should be default at any given time; the service ensures this invariant on every PATCH that sets is\_default=true. |
| created\_at     | 🔒 system (timestamp)         | ✅ Yes    | set on create via onCreate hook; not nullable                                                                                                                                                            | ISO 8601 datetime                                                                                                                                                           | Timestamp of view creation. Set once by the MikroORM onCreate lifecycle hook; never updated.                                                                                                                                                                       |
| updated\_at     | 🔒 system (timestamp)         | ⚪ No     | set on create and on every update via onCreate/onUpdate hooks; nullable in schema                                                                                                                        | ISO 8601 datetime                                                                                                                                                           | Timestamp of the last mutation. Refreshed on every PATCH by the MikroORM onUpdate lifecycle hook. Null only if the entity was never flushed after initial creation (should not occur in production).                                                               |
| deleted\_at     | 🔒 system (timestamp \| null) | ⚪ No     | nullable; null = active row                                                                                                                                                                              | ISO 8601 datetime or null                                                                                                                                                   | Soft-delete timestamp. Set when the user calls DELETE /workspaces/:id/views/:viewId. Active view queries filter deleted\_at IS NULL. A soft-deleted view is not accessible via the API but its data is preserved for audit and recovery.                           |

### Relationships

| Name      | Type               | Required | Description                                                                                                                                                                                                                                                                                                          |
| --------- | ------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workspace | to-one (ManyToOne) | ✅ Yes    | The workspace this view belongs to. Every view is workspace-scoped. Declared as @ManyToOne(() => Workspace) on WorkspaceView. Target: Workspace entity (core\_api.workspaces). FK is workspace\_pk (internal). Cross-workspace access is blocked by the workspace middleware on all /workspaces/:id/views endpoints. |

### System-computed

* view\_id — generated by gen\_random\_uuid() at INSERT time; never supplied by the caller
* created\_at — set by MikroORM onCreate() hook to new Date() at creation; immutable thereafter
* updated\_at — set by MikroORM onCreate() hook at creation, then refreshed by onUpdate() hook on every flush after mutation
* deleted\_at — written by WorkspaceViewService.deleteView() to perform a soft delete; null on active rows; never set by any pipeline or connector
* is\_default sibling-reset — when a PATCH sets is\_default=true, WorkspaceViewService resets is\_default=false on all other views sharing the same (workspace, root) combination; this is a service-layer invariant, not a DB constraint

## Example

```json theme={null}
{
  "data": {
    "type": "workspace_view",
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "attributes": {
      "name": "Open Invoices — By Due Date",
      "root": "invoices",
      "columns": [
        { "field": ["invoices", "reference_number"], "order": 0, "width": 160 },
        { "field": ["invoices", "issuer", "name"], "order": 1, "width": 220 },
        { "field": ["invoices", "due_date"], "order": 2, "width": 130 },
        { "field": ["invoices", "grand_total"], "order": 3, "width": 120 }
      ],
      "sort": [
        { "field": ["invoices", "due_date"], "direction": "asc" }
      ],
      "filters": [
        { "field": ["invoices", "status"], "operator": "eq", "value": "pending", "conjunction": "and" }
      ],
      "layout_type": "table",
      "layout_config": { "rowHeight": "default" },
      "display_fields": [],
      "group_by": null,
      "is_default": true,
      "created_at": "2026-03-15T09:42:00.000Z",
      "updated_at": "2026-05-10T14:22:33.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "f0e1d2c3-b4a5-6789-0123-456789abcdef" }
      }
    }
  }
}
```

<sub>Source: `/Users/maximechampoux/platform/apps/api/src/database/entities/WorkspaceView.ts` · domain: workspace · tier: Infrastructure</sub>
