Repository navigation
feat(studio): edit an email template or a translation in the All metadata area, and customize a read-only package's one per locale - #28743
Merged
Conversation
…ta area An email template or a translation opens a simplified form editor in a package's All metadata area: Setup's form and the type's preview, mounted. A writable package saves its draft; a read-only base customizes the item into its pair with N-17's controls, one email template locale at a time. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTJcKuqRSJyv696zZ9
…ion editor The editor over a per-member server double and the real ensure door: a writable package's draft, a read-only base's pair draft for one template locale and one translation bundle, the other locale untouched, Restore and the walled caller. The area routes the two types to it, and the surface hands it the customization and its pending count. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTJcKuqRSJyv696zZ9
…the hooks lint Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTJcKuqRSJyv696zZ9
…-mtqfy5 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTJcKuqRSJyv696zZ9
Contributor
Author
|
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu 席位核对 · ACCEPT · 2026-11-01T16:57ZHead-sha:
|
This was referenced Nov 1, 2026
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 #28569
Clause-②: no
Metadata-protocol: none
维护者速读
email_template与translation不再落到通用条目页,而是打开一个简化表单编辑器:Setup 表单的字段(served schema,缺省用内置 schema)+ 该类型已注册的预览(EmailTemplatePreview/TranslationPreview,挂载复用,非拷贝)。可写包写自己的草稿;只读基座走 N-17 的 Customize 路径(ensure → 草稿写入<base>.custom并声明overrides: {package, basedOn}→ 头部 Publish 发布 pair → ⋯ 菜单「Restore package original」)。StudioBundleItemEditor.tsx,StudioMetadataArea的条目路由多一个分支,useServedOverride多一个可选member)与 studio 命名空间三条字符串;服务端零改动。Setup 页面、跨包~all腿、?scope=environment、?review=1仍走通用条目页。回滚 = revert 本 PR。ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.tsx的doSave(只读基座分支:ensure 一次、overrideDraftBody、recordRead(..., {ifNoneMatch:'*'}))和restoreOriginal(先删 pair 草稿再删行,均带member);再看metadataArea.ts#areaItemOpensFormEditor。cd ui && pnpm exec vitest run packages/app-shell/src/views/studio-design/StudioBundleItemEditor.customize-28569.test.tsx packages/app-shell/src/views/studio-design/StudioMetadataArea.routes-28561.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.metadataArea-28561.test.tsx,应全部通过。What changes
metadataArea.tsgainsAREA_FORM_EDITOR_TYPES(email_template,translation) andareaItemOpensFormEditor({packageId, type, search}): true inside one package, outside?scope=environmentand?review=1.StudioMetadataArea's item route (AreaItemOpen) decides once: the form editor, else the pillar, elseMetadataResourceEditPageas before. The item is keyed bytype/name/member, so another locale is another editor (the draft-save guard's version pin is keyed by type, name and package, not member).StudioBundleItemEditor.tsx, new).SchemaFormover the served schema, else the default schema (as the generic item page resolves it), withnameandoverrideshidden, andlocaletoo for an email template. Beside it, the type's registered preview. Autosave throughuseDraftAutoSaveand the shareduseDraftSaveGuard(same version pin and conflict dialog as the pillars). Header: type, label, locale chip, override badge, autosave status, Customize, ⋯ (History, Restore package original).StudioCustomizeButton) only unlocks the form. The first saved edit calls the surface'sensure()once, saves the draft into the pair withoverrides: {package, basedOn}(overrideDraftBody), and bumps the badge. Restore (StudioRestoreOriginalDialog) deletes the pair's draft, then its row, at the item's member, then re-reads the base. A walled caller sees Customize disabled with the reason.?member=<locale>from the list row's link (BUNDLE_MEMBER_PARAM).useServedOverridetakes an optionalmemberand passes it togetDraft/layered. A translation has no member; before the first save on a read-only base the editor says the whole bundle is replaced. For an email template it says only this locale is customized.StudioDesignSurfacepasses its existingcustomization,publishNonceandonDraftSavedtoStudioMetadataArea; nothing else in the surface moves.engine.studio.area.formEditor.*keys in the studio namespace (en,zh). That table isRecord<string, string>outside the locales packs, soClause-②: noholds as claimed.Tests
StudioBundleItemEditor.customize-28569.test.tsx(new, 6): writable draft of one member (no door, no declaration, no_keys, locale field hidden, preview live); read-only Customize of email template zh-CN (ensure once, pair draft body exact with the declaration, badge, base untouched, pair read at member zh-CN); the other locale (en-US) untouched; Restore deletes the pair's draft and row of zh-CN alone and the base reads back; walled admin sees Customize disabled; translation whole-bundle note then the whole bundle saved into the pair, no member in any read.StudioMetadataArea.routes-28561.test.tsx(+4): writable translation and read-only email template at member zh-CN open the editor;?review=1and~allopen the generic page.StudioDesignSurface.metadataArea-28561.test.tsx(+2): the surface hands the area a read-only base's customization (base,baseLabel,basedOn,walled,pairId,ensure), and null for a writable package, whose saved draft moves the changes count.Ablations (6, through
scripts/ablation-replace.mjs; each landed on disk, went red, and was restored to HEAD by the tool)memberuseServedOverride) dropsmemberlocaleshown in the email template formoverridesdeclarationmemberareaItemOpensFormEditoralways falseAcceptance notes
?member=(400VALIDATION_ERROR, supported: force, mode, package, surface); the member is the body'slocale. The editor sends the body it read, locale included and hidden from the form, so a save stays on its locale.overlayMemberWhere,memberOption(member)), so the card's stop rule ("server serves or gates a per-(name, locale) override wrongly") did not fire on reads. The write gate's shipper lookup is per (type, name); see the report's finding.Verification
scripts/pm/os-verify-lock.sh: every test file namingStudioCustomizeControls,useServedOverride,StudioMetadataArea,metadataArea,StudioBundleItemEditororInterfacesPillar, plus every test importing the studio namespace (zh-base-term.i18n-13131, the count-family census among them): 159 files, 2064 tests passed, at37edd173(main's merge after it touches no ui file).turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/i18n: exit 0 (at1f6a135c; the later commits add one lint comment and main's non-ui files). ESLint on the 10 changed ts/tsx: 0 errors (warnings are the files' existing ones plusreact-hooksadvisories).node scripts/check-sdui-manifest.mjs: exit 0.node scripts/pm/dispatch-gates.mjs --commands) atca3cc565: 34 of 34 run, each exit 0 (check:type-check-debtunder the lock);--ranreconciles 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.pnpm --dir ui exec vitest run scripts/: 169 files passed, 2 skipped.objectstack dev --freshforexamples/app-showcase(basecom.example.showcase0.1.0, which shipsshowcase_task_done_emailinen-USonly): ensure answered 201 then 200 withcom.example.showcase.custom; a declared draft ofen-USin the pair saved 200. The write side of the per-locale gate is the report's finding, not this PR's.🤖 Generated with Claude Code
https://claude.ai/code/session_01QsR2jTJcKuqRSJyv696zZ9