Repository navigation
fix(plugin-list): a non-grid view's selection bar gates a declared bulk action by its requiredPermissions and visible, through the grid bar's own gate (#30535) - #30580
Merged
Conversation
…tion by the grid bar's own rule ListView's selection bar over kanban, calendar, gallery and the other non-grid views now passes the actions resolveBulkActions folds through plugin-grid's useBulkActionItems, the gate the grid's bar and its right-click menu read: requiredPermissions against the caller's held capabilities, the activation switch-off, and visible evaluated per selected record. A repeated bulkActions name draws one button. The unread-schema warning names its component instead of "the grid". Co-authored-by: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01L6bhgWBF1SZ4drR5vh5BSM
…-protocol none requires Co-authored-by: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01L6bhgWBF1SZ4drR5vh5BSM
…nly list Co-authored-by: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01L6bhgWBF1SZ4drR5vh5BSM
Contributor
Author
|
domain:ui#4 · os-sales · session_01L6bhgVfPeFZkN1FP93imKU 维护者速读
席位核对 — ACCEPT · head 9eda24e
Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Sales · project thread
domain:ui#4 · os-sales · session_01L6bhgWBF1SZ4drR5vh5BSM
Fixes #30535
Clause-②: yes (widening) —
@object-ui/plugin-gridnow exportsuseBulkActionItems(with theBulkActionItemsandLegacyBulkActionItemtypes its signature names), the grid selection bar's own gate, so@object-ui/plugin-listreuses it instead of a second copy. ItsactionDefsinput now readsreadonly BulkActionDef[], which accepts every list it accepted before.Metadata-protocol: none
维护者速读
requiredPermissions的不画;被停用的不画;visible按每条选中记录求值,至少一条通过才画。bulkActions里重复的名字只画一个按钮(原来两个按钮同一个 React key)。读不到对象 schema 时的开发态警告,处方句改为点名组件(ListView/ObjectGrid),不再一律写「the grid」。visible条件的操作对所有人、所有选择都显示;表格那边两道门都有。ui/packages/plugin-list/src/ListView.tsx(nonGridBulkFold/nonGridBulkItems/nonGridBulkBar三段)→ui/packages/plugin-grid/src/index.tsx(新导出)→ui/packages/plugin-grid/src/components/BulkActionBar.tsx(只读入参)。pnpm --dir ui exec vitest run packages/plugin-list/src/__tests__/ListView.nonGridBulkGate-30535.test.tsx,预期 6 条全过;消融门禁时其中 2 条转红,消融去重时 1 条转红。What changes
ListView draws its own selection bar for every view but the grid. Since #30394 it folds
bulkActionsthrough plugin-grid'sresolveBulkActionsand so holds each resolved action definition,requiredPermissionsandvisibleincluded, but it read only the label. This passes the fold through the grid bar's own gate.plugin-list/src/ListView.tsx. The formernonGridBulkBarmemo is split in three.nonGridBulkFolddedupes the names (first occurrence wins; the built-indeleteis one button whatever its case) and folds them throughresolveBulkActionsexactly as before.nonGridBulkItemshands the folded defs to plugin-grid'suseBulkActionItems, the hook the grid'sBulkActionBarand its right-clickRowContextMenualready read:requiredPermissionsagainst the caller's held capabilities (useCapabilityGate, unknown fails open), the activation switch-off (isActionSwitchedOff), andvisibleonce per selected record, offered when at least one passes.nonGridBulkBarthen draws, in authored order,delete(its own path, gate andvisibleWhensubset, unchanged) and each name the gate offers. The undeclared-name warning reads the fold'sundeclaredas before.plugin-grid/src/index.tsx. ExportsuseBulkActionItemsand theBulkActionItems/LegacyBulkActionItemtypes.plugin-grid/src/components/BulkActionBar.tsx.useBulkActionItems'sactionDefsreadsreadonly BulkActionDef[](the fold's own return type); the hook only filters it. No behaviour change.plugin-grid/src/undeclaredActionNames.ts. Theunreadprescription says "Give the ListView a data source…" or "Give the ObjectGrid a data source…", from the address'scomponent, instead of "Give the grid…".Why
The card's first measurement, the run door:
POST /api/v1/actions/OBJECT/ACTIONrefuses a declared action whoserequiredPermissionsthe caller lacks with 403 before anything dispatches (packages/runtime/src/domains/actions.ts,actionPermissionError). The existing pins say so on this head:pnpm --filter @objectstack/runtime exec vitest run src/http-dispatcher.test.ts -t 'ADR-0066 D4 action requiredPermissions gate'givesTests 5 passed | 246 skipped. So the gap here is the bar drawing a button the door will refuse, not a door that lets the call through.Tests
ui/packages/plugin-list/src/__tests__/ListView.nonGridBulkGate-30535.test.tsx(gallery view, selection stubbed as in the Console list views other than the grid (kanban, calendar, gallery…) still draw every bare bulkActions name as a selection-bar button, declared or not, after #30169 #30394 test): an action requiring a capability the caller lacks is not drawn; drawn when held; drawn when capabilities are unknown (fail open, the grid's rule);visible: "record.status == 'closed'"draws nothing over an open-only selection and draws over a mixed one;['tag_lead', 'tag_lead', 'delete', 'delete']draws one of each with no duplicate-key error.ui/packages/plugin-grid/src/__tests__/undeclaredActionNames.test.ts: theunreadprescription namesObjectGridby default andListViewfrom the address.Acceptance notes
onBulkAction(name, selectedRows)with the whole selection, where the grid runs a per-record-visibledef over the passing subset only. The bar now draws such an action only when one selected record passes; which records the host receives is left to that ruling.onBulkActionon this bar (ObjectView.relayRungCensus-7559.test.tsrecords it as host-runtime, delete only), so in the console a non-delete button here still has no host behind it; unchanged by this PR.Verification
All on
9eda24ebunless stated. Closure:pnpm exec turbo run build --filter='@objectstack/runtime^...' --filter='@object-ui/plugin-list^...' --filter='@object-ui/plugin-grid^...' --concurrency=2(53 tasks, lockVERDICT command-exit 0), thenpnpm --filter @object-ui/plugin-grid buildafter the readonly change.Package suites and type-check
pnpm exec vitest run --maxWorkers=2 packages/plugin-list/ packages/plugin-grid/(fromui/, on5f1f79b6;9eda24ebadds only the readonly parameter type and the changeset level):Test Files 469 passed (469),Tests 4218 passed (4218).9eda24eb: the new test plusBulkActionBar.test.tsx,bulkActionCapabilityGate.test.tsx,bulk-action-visible.test.tsx:Tests 32 passed (32),VERDICT command-exit 0.pnpm --filter @object-ui/plugin-grid --filter @object-ui/plugin-list run type-check: plugin-list first red on5f1f79b6(TS4104: the fold'sreadonly BulkActionDef[]into the hook's mutable parameter), read through the rebuilt plugin-grid.d.ts; bothDoneon9eda24ebafterpnpm --filter @object-ui/plugin-grid build.pnpm --dir ui run check:spec-symbols:: exit 0.Ablations (three, each on a tested behaviour, via scripts/ablation-replace.mjs)
The test imports ListView and plugin-grid from
src(ui vitest aliases@object-ui/*tosrc), so no dist leg.const labels = new Map(nonGridBulkItems.defs.map(replaced byconst labels = new Map(nonGridBulkFold.defs.map(inListView.tsx(anchor 1 → 0, blob2675189af304→7ed74bffb459):Tests 2 failed | 4 passed (6)(the lacking-capability case and the no-passing-record case). Restored: blob == HEAD,git diff HEADempty.if (seen.has(key)) return false;deleted (blob2675189af304→4a39ec23f849):Tests 1 failed | 5 passed (6)(the repeated-name case). Restored,git diff HEADempty.Give the grid a data sourceinundeclaredActionNames.ts(blobbaf3f36dd5d4→3602646c8b8c):Tests 1 failed | 5 passed (6). Restored,git diff HEADempty.Derived gates (dispatch-gates --commands, 35 families)
5f1f79b6and9eda24eb(35 families).--ranwith an exit code on every line: see the os-dev-report on the card for the final-head reconciliation.check-changeset-no-majorfed this body's declaration lines as the event: exit 1 with the changeset atminor(Metadata-protocol: nonetakespatch), exit 0 atpatch(5c534bc9).Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintis CI's.main, one pull request.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01L6bhgWBF1SZ4drR5vh5BSM
Generated by Claude Code