Repository navigation
Commit eb6199b
feat(app-shell,plugin-list): a personal view's own conditions are Filter panel rows, saved back by 保存 (#30242)
Fixes #30073
Clause-②: no
Metadata-protocol: none
## 维护者速读
-
改了什么:打开「我的视图」时,它自己的筛选条件以普通行出现在「筛选」面板里;改动条件后出现「已个性化」,标记里提供「保存」,把面板写回这个视图;「另存为我的视图」之后,原来那个视图的临时条件和「已个性化」一并清掉。
- 为什么改:按裁决 A(「其他全部同意」):销售要能直接调整自己视图的条件,不必重建再删除;另存后原列表不再少行、不再像是数据丢了。
- 风险与回滚:只动 Console
前端;存储形状不变、不加新键。面板容纳不了的条件(「或」分组夹在其他条件旁)或读不到的字段,仍按原样在列表底下生效、不进面板。回滚即还原本
PR。
-
先看:`ui/packages/app-shell/src/views/ObjectView.tsx`(保存与另存后的清理)、`ui/packages/app-shell/src/views/personalViews.ts`(条件变行、保存体)、`ui/packages/plugin-list/src/ListView.tsx`(「已个性化」的筛选判断)。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/ObjectView.personalViews-29635.test.tsx`,预期
20 个用例全绿。
- 需要你做的:无,席位落地。
## What changes
Ruling A on #30073 (comment 6631079402), the maintainer's words
「其他全部同意」: a personal view's conditions appear as ordinary rows in the
filter panel, editing them offers 保存 to that view, saving a view also
clears the source view's temporary conditions, and conditions that
cannot be folded keep today's refusal. The stored shape does not change
and no key is added.
- **Opening a personal view seeds its conditions as Filter panel rows**
(`personalViewPanelFilters` in `personalViews.ts`, reading the stored
list through `@object-ui/core`'s `builderRulesOfSpecFilter`, the read
direction of the fold). While the panel holds them they are the list's
filter: the renderer no longer applies the stored `filter` under the
list as well, so each condition is applied once. A stored list the panel
cannot hold (an any-of group beside other conditions), or one naming a
field the object does not declare or the reader cannot read, keeps
today's behaviour: applied under the list, not drawn as rows. The field
gate is the one the list state is read back through, so a row it would
drop on reload never makes the view select more records than it
declares.
- **The 「Personalized」 judgement for filters** (`ListView`): a host that
shows the view's own conditions as rows passes them as
`viewDefaults.filters`; the panel's finished conditions are then
compared with them (field, operator, value, and the logic once two rows
make it matter), so the view's own rows are not a personalization and an
edit, a removal or "Clear all" is. Without the key, behaviour is as
before.
- **保存 in the 「Personalized」 marker**, on a personal view, for a reader
allowed to update `sys_personal_view`: it builds the body with
`buildPersonalViewConfig` (the one Save as my view uses, so the stored
`ListView` shape is the same), replaces the row's `config` through the
data API's `update`, then clears the reader's list state for that view
and the list opens again on the saved view. Nothing is written before
the click. A panel the fold refuses (`nested_group`) shows the same
refusal Save as my view gives and writes nothing.
- **Save as my view clears the source view**: after the row is created,
the source view's stored list state and cached search term are cleared
and the address being left loses its `uf_*` params
(`clearSourceListState`), so neither Back nor the next open of the
source brings the conditions back or reads 已个性化.
- **Both saves read the panel as the list reports it**
(`readPanelFilters`), not the address's copy: an emptied panel leaves no
`uf__filter` param, exactly as an untouched one, so the address alone
could not tell "removed every condition" from "unchanged".
Landing point: `ui/packages/app-shell/src/views/**` and the filter-state
region of `ui/packages/plugin-list/src/ListView.tsx` (the `viewDefaults`
prop type and the personalization judgement); the hidden-fields panel is
untouched.
## Tests
- `personalViews.test.ts`: `personalViewPanelFilters` (AND list, the
fold's OR group, and the three cases that stay under the list);
`buildPersonalViewConfig` with panel-held conditions (untouched keeps
the stored list, edited is the whole filter and parses under
`ListViewSchema`, emptied stores none, nested refuses).
- `ObjectView.personalViews-29635.test.tsx`, new top-level `describe` in
the shared harness: (1) opening `pv_mine` shows `Filter, 1 active`, the
`Paris` row in the panel, `Paris` once in the list query, no marker; (2)
an edited panel shows the marker, 保存 calls `update('sys_personal_view',
'pv_mine', { config })` with `filter: [{ field: 'city', operator:
'equals', value: 'Rome' }]`, the body parses under `ListViewSchema`, and
the list reopens unpersonalized on `Rome`; no 保存 without the update
grant; (3) Save as my view from a filtered `v1` stores the conditions in
the new view, clears `v1`'s stored list state, and a fresh open of `v1`
has no condition and no marker; the nested-group panel keeps the refusal
and writes nothing; a stored list the panel cannot hold stays applied
under the list.
- `ListView.personalization-28950.test.tsx`: `viewDefaults.filters`
equal rows report nothing, edited or emptied rows report `filters`.
## Acceptance notes
- `personalViewPanelFilters` builds builder rows the way the Studio
inspector's private `groupOfStoredRules` (`metadata-admin/widgets.tsx`)
does; that file is outside this card's surface, so the two are not
merged here.
- A link to a personal view that carries `uf__filter` now opens with the
link's rows as the whole panel (the panel is the filter), rather than
those rows laid over the view's stored conditions. Personal views are
the reader's own and the address this page writes already carries the
whole panel.
- 保存 and Save as my view clear the reader's whole stored entry for the
view (sort, filters, column layout, density, hidden fields): every part
that entry holds is in the saved body, except column widths, which no
saved view body carries today.
## Verification
All readings on head `3ee4384a5` (after merging `origin/main`),
objectstack-ai/objectstack.
<details><summary>Tests (isolated, as CI shards run them)</summary>
- `pnpm --dir ui exec vitest run --isolate --maxWorkers=2
packages/plugin-list/`: Test Files 189 passed (189), Tests 1799 passed
(1799); lock VERDICT command-exit 0.
- app-shell, narrowed and declared: the 128 app-shell test files that
import a touched module (`ObjectView`, `objectViewListRenderer`,
`objectViewListUrlState`, `personalViews`, `ListPersonalizedMarker`),
`--isolate --maxWorkers=2`: Test Files 128 passed (128), Tests 1125
passed (1125); lock VERDICT command-exit 0. The whole package (2177
files) does not fit a local run at two workers; Test UI in CI runs it.
The narrowing is by import and is blind to a test that reaches these
modules through another import.
- `pnpm --dir ui exec vitest run scripts/` (after the seven
`@objectstack` builds): Test Files 170 passed, 2 skipped (172); Tests
4985 passed, 2 skipped.
- `pnpm exec turbo run type-check --filter=@object-ui/app-shell
--filter=@object-ui/plugin-list` (each runs `tsc --noEmit` and `tsc -p
tsconfig.test.json`): Tasks 69 successful, 69 total.
</details>
<details><summary>Reverse verification (each mutation applied by
`scripts/ablation-replace.mjs`, which proved it landed and restored it;
tree clean after each)</summary>
- Base filter applied again for panel-held conditions (`const base =
false ? undefined : (`): "applied once" goes red, `expected [ 'Paris',
'Paris' ] to have a length of 1 but got 2`.
- `clearSourceListState(activeView.id)` deleted: "Save as my view leaves
the view it came from ..." goes red, the source's stored `filters` still
present.
- `viewDefaults.filters` ignored in `ListView`: "applied once ... not
personalized" goes red, the marker is drawn.
</details>
<details><summary>Gates</summary>
`node scripts/pm/dispatch-gates.mjs --commands` derived 35 commands; all
35 run, each exit 0 (`check:type-check-debt` first returned exit 3
PREREQUISITE NOT MET on a lock queue timeout, then re-run under the
lock: `re-measure: OK`, exit 0). `--ran` reconciliation: 35 derived, 35
run, 0 NOT-MEASURED, 0 UNRUN. Also `pnpm check:changeset-fixed` (roster
under `.changeset`) exit 0 and `pnpm check:new-line-citations` 0 new
citations.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QSeKYpFBMr917PmVkG9up7)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent cd5f554 commit eb6199b
11 files changed
Lines changed: 508 additions & 22 deletions
File tree
- .changeset
- ui/packages
- app-shell/src/views
- plugin-form/src
- plugin-list/src
- __tests__
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
12 | 16 | | |
13 | 17 | | |
14 | 18 | | |
| |||
17 | 21 | | |
18 | 22 | | |
19 | 23 | | |
20 | | - | |
| 24 | + | |
21 | 25 | | |
22 | 26 | | |
23 | 27 | | |
| |||
40 | 44 | | |
41 | 45 | | |
42 | 46 | | |
| 47 | + | |
43 | 48 | | |
44 | 49 | | |
45 | 50 | | |
46 | 51 | | |
| 52 | + | |
| 53 | + | |
47 | 54 | | |
48 | 55 | | |
49 | 56 | | |
| |||
97 | 104 | | |
98 | 105 | | |
99 | 106 | | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
100 | 122 | | |
101 | 123 | | |
102 | 124 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
85 | 93 | | |
86 | 94 | | |
87 | 95 | | |
| |||
91 | 99 | | |
92 | 100 | | |
93 | 101 | | |
94 | | - | |
| 102 | + | |
95 | 103 | | |
| 104 | + | |
96 | 105 | | |
97 | 106 | | |
98 | 107 | | |
| |||
219 | 228 | | |
220 | 229 | | |
221 | 230 | | |
| 231 | + | |
222 | 232 | | |
223 | 233 | | |
224 | 234 | | |
| |||
543 | 553 | | |
544 | 554 | | |
545 | 555 | | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
0 commit comments