Skip to content

Commit 85761cf

Browse files
os-zhuangclaude
andauthored
test(showcase): a specimen for legacy string rowActions (objectui#2960) (#4101)
* test(showcase): a specimen for legacy string rowActions (objectui#2960) objectui#2960: a list view declaring `rowActions: ['<action name>']` — the pre-`rowActionDefs` authoring form — rendered a menu item that performed zero network requests and reported success, and where the object ALSO declared the same action at `list_item`, the row menu showed a working entry and a dead duplicate of it side by side. Nothing in the showcase was authored the legacy way, so the whole class was invisible here. `showcase_task.legacy_row_actions` covers both cases a client has to handle, using actions the object already declares: showcase_recalc_estimate — `record_more` / `record_section`, i.e. NOT a `list_item` action, so no def is derived for it. The client must resolve the name against the object's actions or the entry is dead. showcase_quick_view — already a `list_item` action, so a def IS derived independently. Naming it here too must not produce a second, dead copy. `showcase_recalc_estimate` also gains `recordIdParam: 'recordId'`. Its endpoint is record-scoped and rejects a body without an id; on a record surface the page supplies one, but invoked from a list row nothing else can — the row id is injected only for an action that names the body key it belongs in. Without it the specimen's own action answers 400 "recordId required" from a row. This is additive on the record surfaces, where the id was already being supplied. Browser-verified against this specimen (objectui PR #2996 in the console): the row menu carries `Recalculate Estimate` and exactly ONE `Quick View`, and clicking the former issues POST /api/v1/showcase/recalc -> 200 with the action's own "Estimate recalculated." toast — not the runner's generic "Action completed successfully", which is what the dead-end used to emit. check:i18n-coverage unchanged (665, none new — a `listViews` label is not in the i18n lint's scope, so no new debt), os lint 0 errors, 60 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: empty changeset — the specimen releases nothing The Check Changeset gate requires every PR to add one, and names the empty changeset as the sanctioned "this PR releases nothing" declaration. The change is confined to `@objectstack/example-showcase` (`"private": true`), so no published package moves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 4d7bebf commit 85761cf

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
---
3+
4+
test(showcase): a specimen for legacy string rowActions (objectui#2960)
5+
6+
Releases nothing. The change is confined to `@objectstack/example-showcase`,
7+
which is `"private": true` and never published — it adds the
8+
`showcase_task.legacy_row_actions` view (a fixture for the objectui#2960 bug
9+
class) and `recordIdParam` on `showcase_recalc_estimate`, so no consumer-facing
10+
package changes.

examples/app-showcase/src/ui/actions/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ export const RecalcEstimateAction = defineAction({
109109
target: '/api/v1/showcase/recalc',
110110
successMessage: 'Estimate recalculated.',
111111
locations: ['record_more', 'record_section'],
112+
// The endpoint is record-scoped and rejects a body without an id. On a
113+
// record surface the page supplies it; invoked from a LIST ROW (see the
114+
// `legacy_row_actions` view) nothing else can, so name the body key the
115+
// clicked row's id should be written to.
116+
recordIdParam: 'recordId',
112117
refreshAfter: true,
113118
});
114119

examples/app-showcase/src/ui/views/task.view.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,30 @@ export const TaskViews = defineView({
8383
filter: [{ field: 'status', operator: 'equals', value: 'done' }],
8484
},
8585

86+
// ── Legacy `rowActions: string[]` coverage (objectui#2960) ──────────
87+
// The pre-`rowActionDefs` authoring form: the row menu is declared as bare
88+
// action NAMES rather than defs. Both cases the client has to handle are
89+
// present here on purpose:
90+
//
91+
// `showcase_recalc_estimate` — declared on the object at `record_more` /
92+
// `record_section`, i.e. NOT a `list_item` action, so nothing derives a
93+
// def for it. The client must resolve the name against the object's
94+
// actions or the entry is a dead menu item.
95+
//
96+
// `showcase_quick_view` — already a `list_item` action, so the client
97+
// derives a def for it independently. Naming it here too must NOT
98+
// produce a second, dead copy alongside the working one.
99+
//
100+
// Kept as a fixture: this is the only view in the showcase authored the
101+
// legacy way, and it is what makes the regression visible in a browser.
102+
legacy_row_actions: {
103+
label: 'Legacy Row Actions',
104+
type: 'grid',
105+
data,
106+
columns: [{ field: 'title' }, { field: 'project' }, { field: 'assignee' }, { field: 'status' }],
107+
rowActions: ['showcase_recalc_estimate', 'showcase_quick_view'],
108+
},
109+
86110
// 0 ── Tabular ───────────────────────────────────────────────────────
87111
// ADR-0021 Phase 2: replaces the former `showcase_task_list` report
88112
// (a flat record list — a ListView concern, not analytics).

0 commit comments

Comments
 (0)