Repository navigation
fix(plugin-list): a stored view sort the platform refuses is not sent, so the list loads; an explicit column honours its field's sortable: false under client-side sorting - #30032
Merged
Conversation
…explicit column honours its field's sortable: false under client-side sorting ListView seeded currentSort from the stored view sort and mapped it into the data request unfiltered, so a sort naming a field the served sortability projection refuses reached the Data API and the list failed with 400 INVALID_SORT. The fetch, the server export and the child views that fetch their own rows now read serverSort, currentSort filtered by filterPlatformSortableSort through the one projection read, now declared beside objectDef. The grid's explicit-columns path read only the column's sortable flag. It now also reads the field's, as the derived paths already do. Under client-side sorting the projection still does not judge the header (#3950 doctrine kept). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzi9idgN8uB7bkz9nTg
…t sent With the projection now refusing an author-declared sortable: false field, pin that ListView's fetch drops that entry too and the list loads. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzi9idgN8uB7bkz9nTg
Contributor
Author
|
domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd 维护者速读(席位终稿)
席位核对 · ACCEPT · head
|
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 Yibo Wang · project thread
Fixes #30024
Clause-②: no
Metadata-protocol: none
Landing order with #30021: #30021 merged first (
140d8ce8, 2026-11-04T08:35Z) and this branch carries it (merge oforigin/mainc618e890). Land this PR before the next release cut so both ship in the same release: a release with #30021 and without this PR fails to load any existing view whosesortnames asortable: falsefield. This PR drops only entries the served projection refuses, so it needs no change of its own when the projection gains a verdict.维护者速读
sortable: false时,浏览器内排序也不再给排序点击。sort若指向平台拒收的字段(今天是公式字段,fix(spec,metadata-protocol)!: honour field.sortable false in the sortability projection and the data door #30021 落地后还有sortable: false字段),列表首次取数就把它发出去,接口答 400INVALID_SORT,整张列表显示加载失败而不是数据。ui/packages/plugin-list/src/ListView.tsx的serverSort(新的请求侧排序,及platformSortability上移到objectDef旁)、ui/packages/plugin-grid/src/objectGridGenerateColumns.tsx第一条路径的sortable行、ui/packages/plugin-list/src/__tests__/ListView.refusedSortNotSent-30024.test.tsx。cd ui && pnpm exec vitest run packages/plugin-list/src/__tests__/ListView.refusedSortNotSent-30024.test.tsx packages/plugin-grid/src/__tests__/clientSortAuthorUnsortable-30024.test.tsx,预期 8 个用例全过。What changes
ListView.tsx).serverSortiscurrentSortpassed throughfilterPlatformSortableSort(currentSort, platformSortability), the same reader the header display (ObjectGridmanualSort) and the persist path (emitSortChange) already use. The data fetch's$orderby, the server export'ssort, and thesorthanded to child views read it. The kanban, calendar, timeline and gantt fetch their own rows from thatsort, so a refused entry reaches the server from none of them. With no projection served,serverSortiscurrentSortunchanged.platformSortabilitymoved up besideobjectDef, because the fetch effect's dependency list is evaluated where the effect is declared and the old declaration sat about 2,000 lines below it. The sort picker andemitSortChangeread the same memo as before. No second reader and no spec key.currentSortkeeps the refused entry, so the sort picker still lists it removable only (docs(pm-dispatch): step 0 扫描判据扩为三个析取,兜住两种不可行动的卡片形状 (#6405) #6455, objectui#11943), and the picker's value and the toolbar's sort count read it.pageResetSignaturestill readscurrentSortby value.emitSortChangedocblock said the refused entry stays "the order this list asks the server for". They now say that no request carries it either.objectGridGenerateColumns.tsx, path A). Seat ruling B: an explicit column now reads its field'ssortable: false(objectDefField?.sortable !== false) beside the column's own flag, as paths B-D (fieldDef?.sortable !== false) already did. Where the sort stays in the browser, the served projection still does not judge the header. That keeps the refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950 doctrine stated inObjectGrid.tsxwithSortability("Only under manual sorting. A client-side sort keys off the value the cell renders ... which is honest, so those headers stay"), pinned byObjectGrid.unmaterializedSort.test.tsx"keeps the formula header live where the sort never leaves the browser". Where the sort leaves the browser,withSortabilitystill applies the projection, unchanged.Tests
ListView.refusedSortNotSent-30024.test.tsx(6 cases). The data source double answers400 INVALID_SORT(status400,codeINVALID_SORT) for any$orderbynaming a refused field, as the Data API does. The projection is the platform's ownresolveObjectSortabilityover an object with aformulafield (refused asvirtual-type) and asortable: falsetext field (refused asauthor-declaredsince fix(spec,metadata-protocol)!: honour field.sortable false in the sortability projection and the data door #30021). No case hand-writes a verdict.$orderby, and no load-error panel is drawn.amount desc).[name asc, expected_revenue desc, amount desc]sends[name asc, amount desc].[internal_code asc, amount desc]on atextfield markedsortable: false(projection{ sortable: false, reason: 'author-declared' }since fix(spec,metadata-protocol)!: honour field.sortable false in the sortability projection and the data door #30021) sends[amount desc], and the list loads.clientSortAuthorUnsortable-30024.test.tsx(2 cases, inline rows so the sort stays in the browser). A column on asortable: falsefield offers no sort click, whileAmountandNameon the same table still do, and no request is made. Theformulaheader stays live with a refusing projection served (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950 doctrine).Acceptance notes
sortnames asortable: falsefield can be loaded against the real door; the reading goes into the os-dev-report on ui(list): a stored viewsortthe platform's sortability projection refuses is still sent to the server on fetch (ListView L3186), so the list 400s instead of dropping it; client-side sorting still offers asortable: falseheader #30024.objectDefLoaded, andsetObjectDef(def)andsetObjectDefLoaded(true)are set in the same async continuation (batched), so the first request already sees the projection. WhengetObjectSchemafails or is absent, there is no projection and the sort is sent unchanged, as before.ObjectGrid'smanualSortstill filters the header arrows for display. ListView's grid hand-off (sort: currentSortin the manual-sort block) is unchanged, becauseObjectGridalready filters it there and the grid on that path does not fetch.domain:uiclaim touchesplugin-listorplugin-grid(seat read 2026-11-04T08:31Z, in the claim).Verification
Local runs at head
a3a33266(merge oforigin/mainc618e890+ this PR's two commits):Suites, type-check, lint
cd ui && pnpm exec vitest run packages/plugin-grid/(underos-verify-lock): Test Files 277 passed (277), Tests 2376 passed (2376), exit 0.cd ui && pnpm exec vitest run packages/plugin-list/: Test Files 189 passed (189), Tests 1796 passed (1796), exit 0.pnpm --filter @object-ui/plugin-list --filter @object-ui/plugin-grid run type-check(tsc --noEmit && tsc -p tsconfig.test.json, both packages): exit 0.npx eslinton the four changedsrcfiles from each package dir (CI's ui lint form): 0 errors.npx turbo run build --filter='@object-ui/plugin-list...' --filter='@object-ui/plugin-grid...' --concurrency=2after the main merge: 54 tasks, exit 0.Ablation (fix committed first, mutation through scripts/ablation-replace.mjs, restored to the HEAD blob)
serverSort→currentSortat the$orderbybuild), post-merge: 3 of 6 cases red (thesortable: falsecase, the formula-only case, the mixed case); both CONTROLs and the sanity case stay green. Restore: blob == HEAD,git diff HEADempty, marker count 0. The same mutation before the merge: 2 of 5 red.objectDefField?.sortable !== falsedropped from path A): both grid cases red (the#3950case waits on thesortable: falseheader first). Restore verified the same way.src(relative import / ui's@object-ui/*source alias), so no dist rebuild sits between the mutation and the run.dispatch-gates --commands (35 derived, serial, unlocked except where a gate takes the lock itself)
At PR open, 24 of 35 had run, every one
exit 0: the ADR-0087 pair,check-changeset-no-major, closing-keyword parity pair, comment-mask corpus, empty-changeset pair,check-sdui-manifestpair, release-rehearsal and release-pending-publish self-tests,pnpm --dir ui exec vitest run scripts/, speccheck:duration-unit-keys,check:changeset-gate-self-tests,check:closed-ceremony-text,check:cross-package-test-inputs,check:dispatcher-error-vocabulary,check:driver-memory-census,check:engine-double-contract,check:gitlink-declared,check:nul-bytes,check:published-files,check:query-options-erasure. The remaining 11 (ending withcheck:type-check-debt) were still running; the full--ranreconciliation goes into the os-dev-report on #30024.Generated by Claude Code