Repository navigation
Commit d5da45b
fix(plugin-grid): over the 5000-record cap, the select-all-matching bulk bar says only the first 5000 matching records will be processed (#28606)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbQQZgSv2t6j3vyRpg7oswBa)_
Fixes #28552
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
- **改了什么**:列表「选择全部匹配记录」的批量栏,在匹配数超过 5000
时,横幅、「选择全部」按钮、已选计数和选区右键菜单都改为点名上限,例如「将处理前 5000 条(共匹配 7200 条记录)。」;5000
及以下文案不变。上限与实际取数(`resolveBulkRows`)读同一个常量 `BULK_SELECT_ALL_MATCHING_CAP`。
- **为什么改**:维护者裁决(#28345 第 ④ 条)。原来横幅按服务器总数说「已选择全部 7200 项」,批量删除实际只处理前 5000
条,屏幕上什么都不说,是破坏性路径上的静默部分执行。
- **风险与回滚**:低。只改 plugin-grid 的三处文案选择和十个语言包各加三条 `grid.*`
文案;取数逻辑、上限数值、接口都不变。回滚即还原本 PR。
-
**先看**:`ui/packages/plugin-grid/src/components/BulkActionBar.tsx`(`overCap`
三处分支)、`ui/packages/plugin-grid/src/bulkSelectAllMatchingCap.ts`、`BulkActionBar.selectAllMatchingCap-28552.test.tsx`。
- **两分钟验证**:`pnpm --dir ui exec vitest run
packages/plugin-grid/src/__tests__/BulkActionBar.selectAllMatchingCap-28552.test.tsx
packages/plugin-grid/src/__tests__/bulkFanoutHostParams.test.tsx`,预期 2
个文件、16 个测试全绿。
- **需要你做的**:无,席位落地。
## What changes
- **One constant.**
`ui/packages/plugin-grid/src/bulkSelectAllMatchingCap.ts` holds
`BULK_SELECT_ALL_MATCHING_CAP` (5000) and
`exceedsBulkSelectAllMatchingCap(totalMatching)`. `resolveBulkRows` in
`ObjectGrid.tsx` stops its paged fan-out at that constant (it was a
local literal), and every string below reads the same constant. The
module is not exported from the package entry.
- **Over the cap, the bar names it** (`BulkActionBar`): the select-all
button reads `grid.bulkSelectAllMatchingCapped` ("Select the first 5000
of 7200 matching"), the banner after selecting reads
`grid.bulkAllMatchingSelectedCapped` ("Only the first 5000 of 7200
matching records will be processed."), and the count chip reads
`grid.bulkSelectedAllMatchesCapped` ("5000 selected (of 7200 matches)").
- **The selection's context menu** (`SelectionContextMenuItems` in
`RowContextMenu.tsx`) counted `totalMatching` with the same
`grid.bulkSelectedAllMatches` key; over the cap it now reads the same
capped key. This is the same defect on the second surface that renders
the count, so it is fixed here.
- **At or under the cap, nothing changes**: the three existing keys,
with `count`, as before.
- **Strings** (`@object-ui/i18n`, `grid` namespace, all ten built-in
packs): three new keys interpolating `cap` and `total`. They take no
`count`, so they are not i18next count families. In `ru` and `ar` the
total stands alone (in parentheses or after a preposition with no noun)
so no noun has to agree with it; the cap is always 5000.
- One root changeset: `@object-ui/plugin-grid` patch, `@object-ui/i18n`
patch. No `packages/spec/**`, no server change, no metadata key.
## Why
Ruling 6545938831 on #28345, item ④, verbatim:
「bulk-select-all-matching: file a product defect card — the banner names
the cap (e.g. 「将处理前 5000 条」); the checklist gains one criterion pinning
it.」 The checklist criterion rides #28551, not this PR.
**Clause-② reading** (measured on the built declaration closure,
objectstack `a2e75562`, `turbo run build
--filter='@object-ui/plugin-grid^...'`, 49/49 tasks): plugin-grid
exports no language pack (its `package.json` has only the `.` entry).
The grid strings live in `@object-ui/i18n`, which publishes `./locales`
and `./locales/*` and re-exports `en` and `type TranslationKeys`
(`typeof en`) from its `.` entry; the built `dist/locales/en.d.ts`
declares each leaf as a readonly string literal. So the three new keys
widen the published declaration of `en` and `TranslationKeys`:
`Clause-②: yes (widening)`, as amended on the card's Claim. Nothing is
narrowed and no metadata author surface moves: `Metadata-protocol:
none`, patch.
## Tests
- New
`ui/packages/plugin-grid/src/__tests__/BulkActionBar.selectAllMatchingCap-28552.test.tsx`,
nine cases, strings read from the packs and the cap from the constant:
- the constant is the 5000 the fan-out pin already holds;
- over the cap (7200 matches, a 50-row page): the button reads the
capped key and not today's; after selecting, the banner reads the capped
key and contains the cap, and the chip reads the capped key; under `zh`
the banner reads the `zh` pack; the selection's context menu reads the
capped key;
- exactly at the cap (5000) and under it (1200): the button, the banner
and the chip read today's three keys.
- `bulkFanoutHostParams.test.tsx`, "still honours HARD_CAP over a match
set larger than the cap": in the same ObjectGrid run that delivers 5000
of 6000 records to the bulk delete, the banner now reads the capped key
filled with `BULK_SELECT_ALL_MATCHING_CAP` and 6000, and the delivered
length equals the constant. So the number shown and the number delivered
are pinned in one run.
## Acceptance notes
- The numbers are shown unformatted (5000, not 5,000), the same as every
existing count in these strings.
- The banner is only reachable when the host passes find params
(`canOfferSelectAllMatching`), unchanged.
## Verification
All at head `a9224125` (this branch merged `origin/main` `cd065d36`; the
merge touched none of this diff's packages, and the delta against main
is still these 17 files, +246 / -15), in a worktree, every build and
test under `scripts/pm/os-verify-lock.sh`.
<details><summary>Tests, ablations, type-check, lint</summary>
- New file alone, verbose: `Tests 9 passed (9)`.
- Ablation 1 (`node scripts/ablation-replace.mjs`, `BulkActionBar.tsx`,
anchor ` const overCap =
exceedsBulkSelectAllMatchingCap(totalMatching);` replaced by ` const
overCap = false && exceedsBulkSelectAllMatchingCap(totalMatching);`,
anchor x1 to x0) over the new file and `bulkFanoutHostParams.test.tsx`:
`Tests 4 failed | 12 passed (16)`, the three bar cases over the cap and
the fan-out case; the context-menu case stays green because it reads the
cap on its own. Restored: blob equal to HEAD.
- Ablation 2 (`RowContextMenu.tsx`, anchor ` ?
exceedsBulkSelectAllMatchingCap(totalMatching)` replaced by ` ? false &&
exceedsBulkSelectAllMatchingCap(totalMatching)`) over the new file:
`Tests 1 failed | 8 passed (9)`, the context-menu case. Restored: blob
equal to HEAD.
- `pnpm --dir ui exec vitest run packages/plugin-grid/` (before the
merge of main, at `08c376a5`): `Test Files 270 passed (270)`, `Tests
2349 passed (2349)`.
- `pnpm --dir ui exec vitest run packages/i18n/` (at `08c376a5`): `Test
Files 94 passed (94)`, `Tests 1438 passed | 13 skipped (1451)`; this
includes `count-families-11445` and `all-locales-key-parity`.
- After the merge, at `a9224125`: the new file, `bulkFanoutHostParams`,
`BulkActionBar` and `rowContextMenu-28434`: `Test Files 4 passed (4)`,
`Tests 41 passed (41)`.
- `pnpm --filter @object-ui/plugin-grid run type-check && pnpm --filter
@object-ui/i18n run type-check`: `VERDICT command-exit 0`; plugin-grid's
`tsconfig.test.json` lists both touched test files.
- eslint on the five plugin-grid files and the `en` and `zh` packs: 0
errors; the 30 warnings are existing `any`s, and this diff adds no
`any`.
- `pnpm check:new-line-citations` (from `ui/`): `0 new citation(s)`.
</details>
<details><summary>Derived dispatch gates</summary>
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 35 commands over the 17 paths, the
same list before and after the merge of main; every one exited 0, the 29
that are neither a suite nor a PR-body gate re-run at `a9224125`.
`--ran`: 35 derived, 35 run, 0 NOT-MEASURED. The PR-body gates
(`check-closing-keyword-parity`, `check-adr-0087-registration --base
origin/main`, `check-changeset-no-major --base origin/main`,
`check-empty-changeset --base origin/main`) ran against this body
through `GITHUB_EVENT_PATH`.
- `pnpm --dir ui exec vitest run scripts/` (at `08c376a5`; the merge of
main changed no ui script): `Test Files 169 passed | 2 skipped (171)`,
`Tests 4900 passed | 2 skipped (4902)`.
- `node scripts/check-sdui-manifest.mjs`: present and intact (106
components); CI's Build & E2E UI regenerates and compares it.
- `pnpm check:type-check-debt` (at `a9224125`): `0 raw tsc error(s)
total, none above its recorded number`.
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01QsR2jTrUjyA3Jhqgsi86rz
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jTrUjyA3Jhqgsi86rz)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 479ad08 commit d5da45b
17 files changed
Lines changed: 246 additions & 15 deletions
File tree
- .changeset
- ui/packages
- i18n/src/locales
- plugin-grid/src
- __tests__
- components
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
506 | 506 | | |
507 | 507 | | |
508 | 508 | | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
509 | 512 | | |
510 | 513 | | |
511 | 514 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
468 | 468 | | |
469 | 469 | | |
470 | 470 | | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
471 | 474 | | |
472 | 475 | | |
473 | 476 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
720 | 720 | | |
721 | 721 | | |
722 | 722 | | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
723 | 726 | | |
724 | 727 | | |
725 | 728 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
481 | 481 | | |
482 | 482 | | |
483 | 483 | | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
484 | 487 | | |
485 | 488 | | |
486 | 489 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
476 | 476 | | |
477 | 477 | | |
478 | 478 | | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
479 | 482 | | |
480 | 483 | | |
481 | 484 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
468 | 468 | | |
469 | 469 | | |
470 | 470 | | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
471 | 474 | | |
472 | 475 | | |
473 | 476 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
468 | 468 | | |
469 | 469 | | |
470 | 470 | | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
471 | 474 | | |
472 | 475 | | |
473 | 476 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
476 | 476 | | |
477 | 477 | | |
478 | 478 | | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
479 | 482 | | |
480 | 483 | | |
481 | 484 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
487 | 487 | | |
488 | 488 | | |
489 | 489 | | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
490 | 493 | | |
491 | 494 | | |
492 | 495 | | |
| |||
0 commit comments