docyrus-data-view-config-design

v2026.09.24

Design, configure, validate, and test Docyrus data views (saved grid/gallery views) with the `docyrus studio` data-view CLI commands. A data view is a named saved configuration of how one data source's records are presented — visible columns, order/pinning/grouping, row height, table/gallery display, sorting, filters (column filters + react-querybuilder query), quick-filter fields, row/cell color rules, paging, inline editing, and a bound form. Use when creating or editing a saved view / tab / list view, hiding or reordering columns, setting a default filtered/sorted view, grouping rows, adding color rules, configuring paging or inline editing, or binding a form to a view. Triggers on "create a data view", "saved view", "add a grid tab", "default view", "filter/sort a view", "hide columns", "group by", "color rules", "gallery view", `docyrus studio create-data-view`, `update-data-view`, `list-data-views`. For the schema use docyrus-data-source-design; for the React grid UI use docyrus-data-grid-page-design.

GitHub
Install command
npx skhub add docyrus/docyrus-data-view-config-design
Markdown
SKILL.md

Docyrus Data View Config Design

A data view is a saved, named configuration over a single data source's records. It does not change the schema or the data — it controls how a grid/gallery surface (TanStack Table + react-querybuilder) presents that data source: which columns show, in what order, how rows are filtered/sorted/grouped/colored, and how paging/inline-editing/forms behave. Views back the "tab strip" / view picker in Docyrus list pages (useDocyrusDataViewSelect).

Author views with docyrus studio *-data-view, then validate (read back) and test (confirm the saved JSON unpacks to the intended grid state). An unvalidated view is not done.

For the schema being viewed see docyrus-data-source-design; for the React grid that renders views see docyrus-data-grid-page-design; for full CLI flag reference see docyrus-cli-app.

Critical model: opaque JSON blobs with packed sub-keys

The backend stores a view as a flat row (tenant_app_config_data_view) with four opaque jsonb columns — columns, filters, sort, color_rules — plus scalar columns (name, description, icon, color, is_default, sort_order, quick_filter_fields, archived, tenant_app_id). The backend does not validate the inner shape of the four jsonb blobs (the DTO only checks they are objects). The grid UI packs/unpacks them with specific sub-keys — if you write the wrong sub-keys the view saves fine but renders as empty defaults.

The single most important fact: the stored sub-key names differ from the TanStack/UI property names. e.g. visible-columns is stored as columns.visibility (not columnVisibility); color rules are color_rules.row / color_rules.cell (not rowColorRules). Get these exact key names from references/view-config-fields.md — do not guess them.

columns      → { visibility, order, pinning, grouping, rowHeight, displayMode,
                 pagingEnabled, pagingMode, pageSize, inlineEditingEnabled,
                 readOnlyColumns, columnOptions, formId }
filters      → { columnFilters, filterQuery }
sort         → { sorting }
color_rules  → { row, cell }

Workflow

  1. Confirm auth, app, and data source. A view belongs to a data source inside an app.

    docyrus auth who --json
    docyrus apps list --json                                   # find appSlug
    docyrus studio list-fields --appSlug <app> --dataSourceSlug <ds> --json
    

    The list-fields output gives the column ids / field slugs you reference in visibility, order, grouping, sorting, filters, and color rules. For enum/select/status filter values you need enum row UUIDs — docyrus studio list-enums --appSlug <app> --dataSourceSlug <ds> --fieldSlug <f> --json. If there is no session, stop and ask the user to run docyrus auth login.

  2. Decide the view's intent. Per view settle: name (tab label), which columns are visible and in what order, default sort, any filter (simple column filters and/or a query), grouping, row height, display mode (table or gallery), color rules, paging, inline editing, whether it is the default view. Sketch this for the user when ambiguous. If the data source has a status/single-select field, default to status-based views — see Status fields → design views per status.

  3. Build the payload. Prefer --from-file ./view.json for anything beyond a trivial view — the blobs are nested JSON and awkward inline. Use the per-blob convenience flags (--columns, --filters, --sort, --colorRules, --quickFilterFields take JSON strings; --name, --description, --icon, --color, --isDefault, --sortOrder are scalars) only for small views. See references/view-config-fields.md for every key's exact name, type, and accepted values, and references/workflow-examples.md for ready-to-adapt payloads.

  4. Create the view. See Create.

  5. Validate. Re-read with get-data-view and confirm every blob has the intended sub-keys with the right column ids / enum UUIDs. See Validate.

  6. Test. Confirm the saved JSON round-trips to the grid state you intended (and, if possible, that it filters/sorts real records correctly). See Test.

Status fields → design views per status

A status field (status / single-select / "stage"-style enum) is a strong signal to design status-based views. The existence of such a field means the records move through stages, and the most useful tab strip on a list page is one that splits records by stage. When a data source has a status field, default to creating a set of status views (plus a default "All" view) unless the user wants otherwise.

How many views depends on how many enum options the status field has:

  • 3–4 options → one view per option. e.g. status New, Active, Won, Lost → four views New / Active / Won / Lost, each filtering status = <enum uuid>.
  • More than ~4 options → group related statuses into fewer, meaningful views. One tab per value becomes an unusable strip. Group them by stage of life, e.g. New, In Progress, On Hold → an "Open" view; Done, Cancelled → a "Closed" view. Pick group names the user's domain would recognise.
  • Usually also keep an "All" view (no status filter) and mark the most-used view (often "All" or "Open") as is_default.

Each status view is an ordinary view whose filters blob targets the status field by enum row UUID, never the label (read UUIDs from docyrus studio list-enums ... --fieldSlug status --json):

  • Single status: one filters.filterQuery rule with = (or a columnFilters entry).
  • Grouped (multi-status) view: a filters.filterQuery rule using in with an array of UUIDs.

Grouped "Open" view payload (filter only — merge with the rest of your view config):

{
  "name": "Open",
  "icon": "circle-dot",
  "sort_order": 2,
  "filters": {
    "columnFilters": [],
    "filterQuery": {
      "combinator": "and",
      "rules": [
        { "field": "status", "operator": "in",
          "value": ["<new-uuid>", "<in-progress-uuid>", "<on-hold-uuid>"] }
      ]
    }
  }
}

These status views are exactly what backs the view-type / status tab strip planned during project planning — keep one view per visible tab.

Studio data-view command cheat-sheet

Selectors — pass exactly one of each pair; the CLI resolves the other and routes to /v1/apps/<appSlug>/data-sources/<dataSourceSlug>/views: --appId | --appSlug, --dataSourceId | --dataSourceSlug. Mutations also accept --data '<json>' or --from-file ./view.json (JSON only); explicit per-blob flags are merged over the file/data payload. Append --json for machine output.

docyrus studio list-data-views   --appSlug crm --dataSourceSlug contacts --json
docyrus studio get-data-view     --appSlug crm --dataSourceSlug contacts --viewId <id> --json
docyrus studio create-data-view  --appSlug crm --dataSourceSlug contacts --from-file ./view.json --json
docyrus studio update-data-view  --appSlug crm --dataSourceSlug contacts --viewId <id> --from-file ./view.json --json
docyrus studio delete-data-view  --appSlug crm --dataSourceSlug contacts --viewId <id> --json
  • list-data-views / create-data-view accept an optional --tenantAppId (maps to tenant_app_id) to scope a view to a different app than the data source's owner. Most views omit it.
  • update-data-view additionally accepts --archived (soft-delete / hide from the tab strip). archived is not the same as deleting — prefer --archived true over delete-data-view when you just want to retire a view.
  • create-data-view requires name. Everything else is optional; an omitted blob means "grid defaults" for that aspect.

Create a data view

Minimal (just a named view — inherits all grid defaults):

docyrus studio create-data-view --appSlug crm --dataSourceSlug contacts \
  --name "All Contacts" --isDefault true --sortOrder 1 --json

Configured (recommended via file — see references/workflow-examples.md for full examples):

docyrus studio create-data-view --appSlug crm --dataSourceSlug contacts \
  --from-file ./active-leads-view.json --json

Critical rules

  • Stored sub-keys ≠ UI property names. Visible columns → columns.visibility, order → columns.order, pinning → columns.pinning, grouping → columns.grouping, color rules → color_rules.row / color_rules.cell, sort → sort.sorting, filters → filters.columnFilters / filters.filterQuery. Wrong key = silently ignored (view renders as defaults). Full list in references/view-config-fields.md.
  • Blobs are not validated server-side. The DTO only asserts each of columns/filters/sort/color_rules is an object. Malformed inner JSON is accepted and then ignored by the UI — so always validate by reading back and checking the unpacked shape; the create call succeeding proves nothing about correctness.
  • Column ids are field slugs (plus built-ins like id, name, autonumber_id). Get them from list-fields. A typo'd column id in visibility/order/sorting is dropped silently.
  • Enum/relation filter values are UUIDs, never labels (same rule as records). Read them from list-enums / the related data source before writing a filters blob that targets a select/status/relation field.
  • columns.visibility is an allow/deny map, not a column list. It is { "<colId>": true|false }; columns absent from the map use their default visibility. To hide a column set it false; to force-show set true. Use columns.order to control sequence.
  • Many features live inside the columns blob, not their own column: paging (pagingEnabled/pagingMode/pageSize), inline editing (inlineEditingEnabled/readOnlyColumns), per-column options (columnOptions), and the bound form (formId). This is so the backend needs no schema change — see references/view-config-fields.md.
  • is_default is per data source. Marking a view default does not auto-unset other views server-side; if exactly-one-default matters, clear the previous default's is_default yourself. The UI fallback chain is: persisted localStorage selection → is_default view → first view.
  • quick_filter_fields is a top-level uuid[] column (field ids), not part of any blob.
  • Validate then test, every time. Read back the view and confirm the unpacked shape; delete throwaway test views you create.

Validate

After authoring, confirm the saved view is exactly what you intended:

  1. docyrus studio get-data-view --appSlug <app> --dataSourceSlug <ds> --viewId <id> --json — confirm scalars (name, is_default, sort_order, icon, color, archived) and that each blob holds the expected sub-keys with valid column ids / enum UUIDs.
  2. Cross-check every column id in columns.visibility/order/grouping, every sort.sorting[].id, every filter field, and every color_rules formula reference against list-fields output — drop anything that does not resolve.
  3. docyrus studio list-data-views ... --json — confirm the view appears, ordering (sort_order), and that at most one is_default is set if that was the intent.

Per-field "what correct looks like" checklist is in references/workflow-examples.md.

Test

Prove the view behaves as intended:

  1. Round-trip check — re-read the view and unpack each blob using the key map in references/view-config-fields.md; confirm it yields the visible columns / order / sort / filter you designed.
  2. Filter sanity — run the equivalent query against real records to confirm the filter selects the right rows, e.g. docyrus ds list <app> <ds> --columns "..." --filter "..." (see docyrus-cli-app), or docyrus dsql for complex filters. The view's filters.filterQuery mirrors react-querybuilder; the column filters mirror TanStack columnFilters.
  3. Clean up — docyrus studio delete-data-view ... --viewId <id> for throwaway views (or --archived true to retire without deleting).

Full test playbook is in references/workflow-examples.md.

References

  • references/view-config-fields.md — The authoritative field reference: every scalar column, the exact packed sub-keys of columns / filters / sort / color_rules, their types, accepted values (display modes, row heights, paging modes), the UI-name↔stored-key mapping, and gotchas. Read this before writing any non-trivial view payload.
  • references/workflow-examples.md — End-to-end worked examples (default view, filtered+sorted+grouped view, color-coded view, gallery view, paging + inline-editing view, form-bound view) as copy-adaptable JSON payloads, plus the validation checklist and test playbook.
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

skills/docyrus-data-view-config-design

Default branch

main

Latest commit

5eb990f

Tree SHA

d012754