fix(plugin-list): allowAddTab 的「新增 tab」按钮接上会话级行为(objectstack#5236) - #3926
Merged
Conversation
`TabFilters` 里 `allowAddTab` 渲染的按钮带 hover 态与 `title="Add filter tab"`, 却没有 `onClick`,组件也没有任何新增 tab 的回调入参 —— 一个看起来完全可点、点下去 什么都不发生的控件,它把「没实现」伪装成「点了没反应的 bug」。objectstack#5073 把 该键提升进 spec 的 `UserFiltersSchema` 之后这更要紧:键在 JSON Schema、Studio SchemaForm 与参考文档三处可见,作者照着写 `allowAddTab: true`,运行时不兑现。 按维护者裁决 A1 落地:点击弹出命名输入(复用该组件筛选 chip 与 More 溢出已在用的 Popover 原语),确认后把「此刻已应用的筛选条件」快照成一个新 tab,与预设同栏展示 并立即选中。会话级 tab 带删除入口;预设不带 —— 那是元数据。删掉当前选中的会话级 tab 时按初次挂载同一优先级回落到作者默认 tab,不会留下「无选中 tab 但仍套用着已删 tab 条件」的状态。 会话级语义选的是**组件态**,不写 `sys_metadata`、不发任何 API、不碰 web storage (ADR-0047:end-user 的筛选选择 session-scoped、从不落成元数据)。`sessionStorage` 是可用的,刻意没用:`UserFilters` 拿不到 object/view 身份,它能自己编出的任何 key 都会被同一浏览器 tab 里的所有列表共用,把一个列表的临时 tab 显示到另一个列表的栏 上。真要跨挂载存续,归已经握着筛选选择会话通道(`onSelectionsChange` → `uf_*` URL 参数)、且能按视图分键的宿主。合成 tab id 与其它 tab 切换一样经 `onSelectionsChange` 上报,宿主镜像进 URL 后下次挂载还回来时,既有的 id 校验找不到该 tab,回落作者默认。 公共 API 未变:`UserFiltersProps` 一字未动,`allowAddTab: false` 与缺省仍然完全不 渲染该控件。 Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
✅ 验收通过(objectui 分片 PM,session 实物核验:head 验收要点:
范围外 finding objectstack#6952(三个既有 button 缺 type)立单规范,冻结期不派。 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.
Fixes objectstack-ai/objectstack#5236
背景
packages/plugin-list/src/UserFilters.tsx的TabFilters里,allowAddTab渲染的「新增 tab」按钮(data-testid="filter-tab-add")带 hover 态与title="Add filter tab",却没有onClick,组件也没有任何onAddTab/addTab回调入参 —— 一个看起来完全可点、点下去什么都不发生的控件。它比「没有这个按钮」更糟:把「未实现」伪装成「点了没反应的 bug」。objectstack#5073 把该键提升进 spec 的
UserFiltersSchema之后这更要紧:键在 JSON Schema、Studio SchemaForm、参考文档三处可见,AI 作者会照着 schema 写allowAddTab: true,而运行时不兑现 —— declared ≠ enforced 的 UI 变体。前提复核(对
origin/main实测,非阅读推断):premise 成立,只是行号漂了 —— 按钮现在在UserFilters.tsx:778(issue 正文写的:742)。全仓git grep origin/main命中:filter-tab-add仅 1 处(那个按钮),onAddTab零命中,allowAddTab4 处(prop 声明、传入、渲染 +packages/types的 zod 镜像与其测试),确认无任何回调入参存在。本 PR 做了什么(维护者裁决 A1,评论 5200253516)
会话级语义:选了组件态,不是 sessionStorage(理由)
⛔ 不写
sys_metadata、不发任何 API、不碰 web storage —— ADR-0047:end-user 的筛选选择 session-scoped、从不落成元数据,渲染器保持元数据读方。sessionStorage是可用的,刻意没用:UserFilters拿不到 object/view 身份,它能自己编出的任何 storage key 都会被同一浏览器 tab 里的所有列表共用,把一个列表的临时 tab 显示到另一个列表的栏上 —— 那是个真 bug,换来的只是刷新后还在。要跨挂载存续,该归已经握着筛选选择会话通道(onSelectionsChange→uf_*URL 参数)、且能按视图分键的宿主;那需要给UserFiltersProps加公共入参,是裁决没做的契约决定,不该顺手塞进本单。合成 tab id(
__session_1__,沿用该文件为自己发明的__all__拼法)与其它 tab 切换一样经onSelectionsChange上报,宿主镜像的真实性不被撒谎;宿主把它持久到uf__tab后下次挂载还回来时,既有的 id 校验找不到该 tab,回落作者默认 —— 会话级 tab 没有走后门跨挂载存活的路径。这条降级被测试钉住了。测试
新增
packages/plugin-list/src/__tests__/UserFilters.addTab.test.tsx(12 例):onSelectionsChange报{ _tab: ['__session_1__'] }、onFilterChange最后一次调用等于创建时刻已应用的条件;空白名时确认按钮 disabled。create/update/delete/find/findOne)+fetch+Storage.prototype.setItem全部断言 0 次调用。该例先断言新 tab 确实出现,再断言这些 0 —— 否则「加不出 tab」也能让 0 断言空转通过(objectstack PR #5046 的空转陷阱)。_tab: ['__session_1__']从 URL 还回来)→ 会话级 tab 不在了,活动 tab 回落作者默认,重新发出默认条件。onFilterChange调用次数不变);预设没有删除入口。allowAddTab: false与缺省时都完全不渲染该控件(筛选栏本体照常渲染)。命令与实测输出:
反向验证(方向是先预测的:红)
把
UserFilters.tsx整体还原成origin/main的死按钮版本再跑新测试:9 红 / 3 绿,与预测一致。三个绿的是两条
allowAddTab关闭回归(本就该两向都绿,它们钉的是既有行为)+「预设没有删除入口」那条(负向断言,两向都绿;它防的是将来给预设误加删除入口,不是钉本次接线)。这里如实记一笔:零元数据写入那条是红的,红在它自己的非空转前置断言上 —— 正是它该红的位置。范围之外(未做,已确认)
UserFiltersSchema.allowAddTab的.describe()从「仅承诺渲染入口」升回真实语义 —— 裁决已归 spec 车道,渲染器不依赖该文案。本仓packages/types的 zod 镜像写的是'Allow adding new tabs',与新行为无冲突,未动。app-shell/src/views/metadata-admin/widgets.tsx的 Studio 编辑期 addTab(filter-mode-add-tab)—— 那是另一族。Changeset
.changeset/userfilters-allowaddtab-session-tabs-os5236.md,@object-ui/plugin-list: patch。定 patch 而非 minor 的理由:公共 API 面零变化(UserFiltersProps一字未动,没有新增入参),用户可见的变化是一个已发布但失灵的控件开始按其 title 与 spec 声明工作,属行为补全/修复;且按仓内约定 breaking 也只标 minor、major被 CI 禁掉,patch 与本仓「fix(...) + patch」的既有惯例一致。🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Generated by Claude Code