Repository navigation
feat(plugin-grid,console): list cells show the record a referenceVia pointer names; the empty inbox says who else is waiting - #12658
Conversation
…s who else is waiting (objectui#12608) A list grid column for a `text` field declaring `referenceVia` now draws the record the row's pointer pair names: the target object's icon and the record's name, linking to the record, with the raw id as the tooltip. An unreadable target reads "OBJECT · record unavailable". The pair is resolved per row by `resolveRecordPointer`; the page's targets are read with one `find` per object. The Approvals Inbox's empty pending tab makes one count query and, for a non-zero total, adds "N requests are waiting on other approvers · Browse all requests". Claude-Session: https://claude.ai/code/session_018mfTYw2pCvEqHeGZDvybj8 Co-authored-by: Claude <noreply@anthropic.com>
…erCell (objectui#12608) The annotation every other `resolveIcon` call site carries: `react-hooks/static-components` cannot see that the seam returns a stable, cached component. Claude-Session: https://claude.ai/code/session_018mfTYw2pCvEqHeGZDvybj8 Co-authored-by: Claude <noreply@anthropic.com>
席位核对 — ACCEPT · objectui#12608 · head
|
Contract reviewServed-tier: Face: the ① Derived judgments
② Semver levelThe changeset bumps ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
Landing · head
|
Part of #12608
Clause-②: yes
This is the objectui half of the card. The column set, the step and flow labels, Waiting on and the Action History record column are producer work on objectstack-ai/objectstack. They are listed under Producer proposals, so this PR does not close the card.
What changed
Target 1 and 2 (objectui half): the pointer cell. In
ObjectGrid, a column for atextfield that declaresreferenceVianow draws the record the row's pointer pair names: the target object's icon and the record's name. The raw id moves to the tooltip. The pair is resolved per row by the existingresolveRecordPointerfrom@object-ui/fields, the same rule the record details grid uses. The new cell,RecordPointerCellin plugin-grid, only draws what that rule returns. The name comes fromgetRecordDisplayNameafterwithoutDeniedFields. The page's targets are read with onefindper target object, using anid$infilter; object definitions come fromgetObjectSchema. Both answers are cached per data source. The face is wired into all four column paths of the grid, so everyreferenceViafield in every list gets it:sys_approval_request.record_id,sys_activity.source_id, and the sharing, audit and mail pointers.Target 4. A target that cannot be read shows
Opportunity · record unavailable, with the id only in the tooltip. Deleted records, rows outside the viewer's access, an unavailable definition and failed reads all get this one rendering, for the same no-existence-oracle reasonRecordPreviewCardgives.Target 3. When the caller's pending tab in the Approvals Inbox is empty, the page sends one count query:
listRequestswith status pending andlimit1, so the server returnstotal. The server counts under the same visibility as the All tab's own read. If the total is above zero, the empty state adds one muted line:N requests are waiting on other approvers · Browse all requests. The existing Browse all requests control moves into that line, so it still appears once. If the count read fails, no line is shown.New language-pack keys in all ten shipped locales:
grid.recordUnavailableand theapprovalsInbox.waitingOnOthersplural family, with the CLDR categories each language needs.Deviations
recordHref/openRecord, and a unit test pins the link. The console list host,listRecordActionsValuein app-shellObjectView.tsx, deliberately answersrecordHrefonly for the object being listed, so in Setup the name renders without a link. That is outside this claim's files, and changing it would also turn every lookup cell in every list into a link. It is left to the seat.@object-ui/i18nentry. The claim's file surface names them; the seat decides whether Clause-② covers them. No export, prop or type member is added;RecordPointerCellis internal to plugin-grid.Producer proposals (objectstack)
sys_approval_request.current_stepandsys_approval_action.step_namestore the node id (manager_review). The engine should write a label snapshot when it opens or advances a step, and the list views should show that instead.process_nameisflow:NAME. The engine should write aprocess_labelsnapshot of the flow's label, keeping the api name inprocess_name.pending_approversis a textarea of slot addresses. It needs an engine-served display column, resolved by the approvals service's own resolver, inall_requestsandmy_pending.request_iddisplays the request'sdisplay_titleformula, which isprocess_name · record_id, so the raw id leaks. Add the pointer pair (object_nameandrecord_idwithreferenceVia) tosys_approval_action; this PR's cell then draws it.acted_asshows a raw user id. It needs a served display label.Screenshots (HotCRM, 1280 px)
Record cells read from the DOM at capture, first three rows of
all_requests:Opportunity · record unavailable, titleSzIsIKdI_MYlObTf(its opportunity was deleted)Globex Manufacturing Suite, title28W5lzLQhZs_53LL, iconlucide-dollar-signInitech Cloud Migration, title9C2hdzZMz96ZbHzk, iconlucide-dollar-signThe 50-row page sent exactly one
crm_opportunitydata request. The inbox read52 requests are waiting on other approvers · Browse all requests: 53 requests, one of them cancelled.About the seed: a fresh HotCRM boot (
e50d048) has no approval requests. I created 53 through the flows by raising 10 open deals to $100K or more and adding 43 new ones. I then ranpnpm demo:staff, reassigned the admin's 10 slots to the sales manager, and deleted one target.Test evidence (head b04cf2e)
ObjectGrid.recordPointerCell-126083/3 passed;ApprovalsInboxPage.waitingOnOthers-126083/3 passed. Each pin was ablated once and went red: pointer face off, 2 failed; unreadable cell prints the id, 1 failed; line never drawn, 1 failed; line always drawn, 2 failed. Each mutant was restored to HEAD.pnpm --filter @object-ui/app-shell test: 1437 files passed, 13596 tests passed, exit 0.Session:
https://claude.ai/code/session_018mfTYw2pCvEqHeGZDvybj8Generated by Claude Code