Skip to content

Commit efb51fc

Browse files
os-zhuangclaude
andcommitted
feat(showcase): ADR-0047 — lookup quick-filter example (project)
Adds the project master-detail field to the Task List view's dropdown filters: the record-picker dropdown path (search + multi-select records) that CRM consumers (hotcrm account workbench: owner user lookup) rely on. Browser-verified + covered by objectui e2e (user-filters.spec.ts). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 3786f15 commit efb51fc

11 files changed

Lines changed: 123 additions & 8 deletions

File tree

content/docs/references/api/metadata.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ Metadata query with filtering, sorting, and pagination
314314

315315
| Property | Type | Required | Description |
316316
| :--- | :--- | :--- | :--- |
317-
| **types** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>[]` | optional | Filter by metadata types |
317+
| **types** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'doc' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>[]` | optional | Filter by metadata types |
318318
| **namespaces** | `string[]` | optional | Filter by namespaces |
319319
| **packageId** | `string` | optional | Filter by owning package |
320320
| **search** | `string` | optional | Full-text search query |
@@ -349,7 +349,7 @@ Metadata query with filtering, sorting, and pagination
349349

350350
| Property | Type | Required | Description |
351351
| :--- | :--- | :--- | :--- |
352-
| **type** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>` || Metadata type |
352+
| **type** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'doc' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>` || Metadata type |
353353
| **name** | `string` || Item name (snake_case) |
354354
| **data** | `Record<string, any>` || Metadata payload |
355355
| **namespace** | `string` | optional | Optional namespace |

content/docs/references/automation/approval.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const result = ApprovalDecision.parse(data);
7171
| **lockRecord** | `boolean` || Lock the record from editing while pending |
7272
| **approvalStatusField** | `string` | optional | Business-object field to mirror request status onto |
7373
| **escalation** | `Object` | optional | Per-node SLA escalation |
74+
| **maxRevisions** | `integer` || Max send-backs for revision before auto-reject (0 = send-back disabled) |
7475

7576

7677
---

content/docs/references/automation/node-executor.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Canonical cross-paradigm action/node descriptor (ADR-0018)
7676
| **supportsRetry** | `boolean` || Supports retry on failure |
7777
| **needsOutbox** | `boolean` || Dispatch via service-messaging outbox (retry/idempotency/dead-letter) |
7878
| **isAsync** | `boolean` || Suspends the flow awaiting an external reply |
79+
| **maturity** | `Enum<'ga' \| 'beta' \| 'reserved'>` || Runtime maturity: ga (shipped), beta, or reserved (contract only — designers grey this out) |
7980
| **source** | `Enum<'builtin' \| 'plugin'>` || builtin = platform baseline; plugin = third-party contributed |
8081
| **deprecated** | `boolean` || Deprecated alias kept for back-compat |
8182
| **aliasOf** | `string` | optional | Canonical type this alias forwards to |

content/docs/references/kernel/metadata-plugin.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const result = MetadataBulkRegisterRequest.parse(data);
130130
| Property | Type | Required | Description |
131131
| :--- | :--- | :--- | :--- |
132132
| **event** | `Enum<'metadata.registered' \| 'metadata.updated' \| 'metadata.unregistered' \| 'metadata.validated' \| 'metadata.deployed' \| 'metadata.overlay.applied' \| 'metadata.overlay.removed' \| 'metadata.imported' \| 'metadata.exported'>` || Event type |
133-
| **metadataType** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>` || Metadata type |
133+
| **metadataType** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'doc' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>` || Metadata type |
134134
| **name** | `string` || Metadata item name |
135135
| **namespace** | `string` | optional | Namespace |
136136
| **packageId** | `string` | optional | Owning package ID |
@@ -147,7 +147,7 @@ const result = MetadataBulkRegisterRequest.parse(data);
147147

148148
| Property | Type | Required | Description |
149149
| :--- | :--- | :--- | :--- |
150-
| **types** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>[]` | optional | Filter by metadata types |
150+
| **types** | `Enum<'object' \| 'field' \| 'trigger' \| 'validation' \| 'hook' \| 'seed' \| 'view' \| 'page' \| 'dashboard' \| 'app' \| 'action' \| 'report' \| 'dataset' \| 'flow' \| 'job' \| 'datasource' \| 'external_catalog' \| 'translation' \| 'router' \| 'function' \| 'service' \| 'email_template' \| 'doc' \| 'permission' \| 'profile' \| 'role' \| 'agent' \| 'tool' \| 'skill'>[]` | optional | Filter by metadata types |
151151
| **namespaces** | `string[]` | optional | Filter by namespaces |
152152
| **packageId** | `string` | optional | Filter by owning package |
153153
| **search** | `string` | optional | Full-text search query |
@@ -202,6 +202,7 @@ const result = MetadataBulkRegisterRequest.parse(data);
202202
* `function`
203203
* `service`
204204
* `email_template`
205+
* `doc`
205206
* `permission`
206207
* `profile`
207208
* `role`
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: Doc
3+
description: Doc protocol schemas
4+
---
5+
6+
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */}
7+
8+
Package Documentation Metadata Protocol (ADR-0046)
9+
10+
One `doc` item per Markdown file under the package's flat `src/docs/`
11+
12+
directory (no subdirectories — flatness is the contract that keeps
13+
14+
cross-references stable). The CLI compiles each file into this shape at
15+
16+
build time; TS-first stacks may also declare items inline via
17+
18+
`defineStack(\{ docs: [...] \})`.
19+
20+
Identity model: `name` = filename stem and MUST carry the package
21+
22+
namespace prefix (`crm_lead_guide.md``crm_lead_guide`). Unlike object
23+
24+
names (validated in the kernel because they map to physical table
25+
26+
names), doc-name prefixing is a *logical* uniqueness requirement — the
27+
28+
metadata registry key carries no package coordinate — so it is enforced
29+
30+
by build/publish lint, not by this schema.
31+
32+
Docs are inert data: the kernel registers them without parsing
33+
34+
`content`, and they participate in no runtime behavior. Renderers
35+
36+
resolve relative links between docs (`[guide](./crm_lead_guide.md)`)
37+
38+
by stripping `./` and `.md` to obtain the target doc name.
39+
40+
<Callout type="info">
41+
**Source:** `packages/spec/src/system/doc.zod.ts`
42+
</Callout>
43+
44+
## TypeScript Usage
45+
46+
```typescript
47+
import { Doc } from '@objectstack/spec/system';
48+
import type { Doc } from '@objectstack/spec/system';
49+
50+
// Validate data
51+
const result = Doc.parse(data);
52+
```
53+
54+
---
55+
56+
## Doc
57+
58+
### Properties
59+
60+
| Property | Type | Required | Description |
61+
| :--- | :--- | :--- | :--- |
62+
| **name** | `string` || Unique doc name (= filename stem, namespace-prefixed snake_case) |
63+
| **label** | `string` | optional | Display title; defaults to the first `#` heading, then the name |
64+
| **content** | `string` || Raw Markdown content (CommonMark + GFM) |
65+
66+
67+
---
68+

content/docs/references/system/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This section contains all protocol schemas for the system layer of ObjectStack.
1616
<Card href="/docs/references/system/core-services" title="Core Services" description="Source: packages/spec/src/system/core-services.zod.ts" />
1717
<Card href="/docs/references/system/deploy-bundle" title="Deploy Bundle" description="Source: packages/spec/src/system/deploy-bundle.zod.ts" />
1818
<Card href="/docs/references/system/disaster-recovery" title="Disaster Recovery" description="Source: packages/spec/src/system/disaster-recovery.zod.ts" />
19+
<Card href="/docs/references/system/doc" title="Doc" description="Source: packages/spec/src/system/doc.zod.ts" />
1920
<Card href="/docs/references/system/email-config" title="Email Config" description="Source: packages/spec/src/system/email-config.zod.ts" />
2021
<Card href="/docs/references/system/email-template" title="Email Template" description="Source: packages/spec/src/system/email-template.zod.ts" />
2122
<Card href="/docs/references/system/encryption" title="Encryption" description="Source: packages/spec/src/system/encryption.zod.ts" />

content/docs/references/system/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"core-services",
1212
"deploy-bundle",
1313
"disaster-recovery",
14+
"doc",
1415
"email-config",
1516
"email-template",
1617
"encryption",

content/docs/references/ui/page.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ Interface-level page configuration (Airtable parity)
7878
| Property | Type | Required | Description |
7979
| :--- | :--- | :--- | :--- |
8080
| **source** | `string` | optional | Source object name for the page |
81+
| **sourceView** | `string` | optional | Named list view on the source object to inherit columns/filter/sort from (ADR-0047 iron rule: the page adds presentation policy only). Omit to use the object default view |
8182
| **levels** | `integer` | optional | Number of hierarchy levels to display |
8283
| **filterBy** | `Object[]` | optional | Page-level filter criteria |
8384
| **appearance** | `Object` | optional | Appearance and visualization configuration |
84-
| **userFilters** | `Object` | optional | User filter configuration |
85+
| **userFilters** | `Object` | optional | End-user quick-filter bar for this page (overrides the source view's userFilters) |
8586
| **userActions** | `Object` | optional | User action toggles |
8687
| **addRecord** | `Object` | optional | Add record entry point configuration |
8788
| **showRecordCount** | `boolean` | optional | Show record count at page bottom |

content/docs/references/ui/report.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const result = JoinedReportBlock.parse(data);
3636
| **chart** | `Object` | optional | |
3737
| **dataset** | `string` | optional | Dataset name to bind (ADR-0021) |
3838
| **rows** | `string[]` | optional | Dimension names down (dataset-bound) |
39+
| **columns** | `string[]` | optional | Dimension names across (matrix, dataset-bound) |
3940
| **values** | `string[]` | optional | Measure names to show (dataset-bound) |
4041
| **runtimeFilter** | `[__schema0](./__schema0)` | optional | Render-time scope filter (dataset-bound) |
4142

@@ -54,8 +55,10 @@ const result = JoinedReportBlock.parse(data);
5455
| **type** | `Enum<'tabular' \| 'summary' \| 'matrix' \| 'joined'>` || Report format type |
5556
| **dataset** | `string` | optional | Dataset name to bind (ADR-0021) |
5657
| **rows** | `string[]` | optional | Dimension names down |
58+
| **columns** | `string[]` | optional | Dimension names across (matrix) |
5759
| **values** | `string[]` | optional | Measure names to show |
5860
| **runtimeFilter** | `[__schema0](./__schema0)` | optional | Render-time scope filter |
61+
| **drilldown** | `boolean` || Click-through to underlying records |
5962
| **chart** | `Object` | optional | Embedded chart configuration |
6063
| **aria** | `Object` | optional | ARIA accessibility attributes |
6164
| **performance** | `Object` | optional | Performance optimization settings |

content/docs/references/ui/view.mdx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Migrated to shared/http.zod.ts. Re-exported here for backward compatibility.
1616
## TypeScript Usage
1717

1818
```typescript
19-
import { AddRecordConfig, AppearanceConfig, CalendarConfig, ColumnSummary, GalleryConfig, GanttConfig, GroupingConfig, GroupingField, KanbanConfig, ListChartConfig, ListColumn, NavigationConfig, NavigationMode, PaginationConfig, RowColorConfig, RowHeight, SelectionConfig, TimelineConfig, UserActionsConfig, ViewData, ViewFilterRule, ViewItemName, ViewKind, ViewScope, ViewSharing, ViewTab, VisualizationType } from '@objectstack/spec/ui';
20-
import type { AddRecordConfig, AppearanceConfig, CalendarConfig, ColumnSummary, GalleryConfig, GanttConfig, GroupingConfig, GroupingField, KanbanConfig, ListChartConfig, ListColumn, NavigationConfig, NavigationMode, PaginationConfig, RowColorConfig, RowHeight, SelectionConfig, TimelineConfig, UserActionsConfig, ViewData, ViewFilterRule, ViewItemName, ViewKind, ViewScope, ViewSharing, ViewTab, VisualizationType } from '@objectstack/spec/ui';
19+
import { AddRecordConfig, AppearanceConfig, CalendarConfig, ColumnSummary, GalleryConfig, GanttConfig, GroupingConfig, GroupingField, KanbanConfig, ListChartConfig, ListColumn, NavigationConfig, NavigationMode, PaginationConfig, RowColorConfig, RowHeight, SelectionConfig, TimelineConfig, UserActionsConfig, UserFilterField, UserFilters, ViewData, ViewFilterRule, ViewItemName, ViewKind, ViewScope, ViewSharing, ViewTab, VisualizationType } from '@objectstack/spec/ui';
20+
import type { AddRecordConfig, AppearanceConfig, CalendarConfig, ColumnSummary, GalleryConfig, GanttConfig, GroupingConfig, GroupingField, KanbanConfig, ListChartConfig, ListColumn, NavigationConfig, NavigationMode, PaginationConfig, RowColorConfig, RowHeight, SelectionConfig, TimelineConfig, UserActionsConfig, UserFilterField, UserFilters, ViewData, ViewFilterRule, ViewItemName, ViewKind, ViewScope, ViewSharing, ViewTab, VisualizationType } from '@objectstack/spec/ui';
2121

2222
// Validate data
2323
const result = AddRecordConfig.parse(data);
@@ -50,7 +50,7 @@ Appearance and visualization configuration
5050
| Property | Type | Required | Description |
5151
| :--- | :--- | :--- | :--- |
5252
| **showDescription** | `boolean` || Show the view description text |
53-
| **allowedVisualizations** | `Enum<'grid' \| 'kanban' \| 'gallery' \| 'calendar' \| 'timeline' \| 'gantt' \| 'map'>[]` | optional | Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"]) |
53+
| **allowedVisualizations** | `Enum<'grid' \| 'kanban' \| 'gallery' \| 'calendar' \| 'timeline' \| 'gantt' \| 'map' \| 'chart'>[]` | optional | Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"]) |
5454

5555

5656
---
@@ -316,6 +316,40 @@ User action toggles for the view toolbar
316316
| **buttons** | `string[]` | optional | Custom action button IDs to show in the toolbar |
317317

318318

319+
---
320+
321+
## UserFilterField
322+
323+
Quick-filter field configuration
324+
325+
### Properties
326+
327+
| Property | Type | Required | Description |
328+
| :--- | :--- | :--- | :--- |
329+
| **field** | `string` || Field name on the source object (must exist — checked by reference diagnostics) |
330+
| **label** | `string` | optional | Display label override (defaults to the field label) |
331+
| **type** | `Enum<'select' \| 'multi-select' \| 'boolean' \| 'date-range' \| 'text'>` | optional | Filter control type. Omit to infer from the field definition |
332+
| **options** | `Object[]` | optional | Static options. Omit to derive from the field definition (select options / lookup records) |
333+
| **showCount** | `boolean` | optional | Show per-option record counts |
334+
| **defaultValues** | `string \| number \| boolean[]` | optional | Pre-selected values when the view loads |
335+
336+
337+
---
338+
339+
## UserFilters
340+
341+
End-user quick-filter configuration (Airtable "User filters" parity)
342+
343+
### Properties
344+
345+
| Property | Type | Required | Description |
346+
| :--- | :--- | :--- | :--- |
347+
| **element** | `Enum<'dropdown' \| 'tabs' \| 'toggle'>` || Filter control style: dropdown selectors per field, tab presets, or on/off toggles |
348+
| **fields** | `Object[]` | optional | Fields exposed as quick filters (dropdown/toggle elements) |
349+
| **tabs** | `Object[]` | optional | Named filter presets rendered as tabs (tabs element). Reuses ViewTabSchema |
350+
| **showAllRecords** | `boolean` | optional | Show an "All records" tab before the presets (tabs element) |
351+
352+
319353
---
320354

321355
## ViewData
@@ -464,6 +498,7 @@ Visualization type that users can switch to
464498
* `timeline`
465499
* `gantt`
466500
* `map`
501+
* `chart`
467502

468503

469504
---

0 commit comments

Comments
 (0)