Repository navigation
feat(console): an administrator's first-run checklist on Home replaces the currency and time zone dialog - #30552
Closed
objectstack-fleet[bot] wants to merge 8 commits into
Closed
objectstack-fleet[bot] wants to merge 8 commits into
objectstack-fleet[bot] wants to merge 8 commits into
Conversation
…s the currency and time zone dialog (#30206) The dialog that asked for the system timezone and default currency on the first page an administrator opened is gone. Its questions, and the other things a new workspace needs, are rows of a checklist at the top of Home: organization name, default language and country, system timezone, default currency, email delivery, and invite colleagues. Each row's state is read from the real setting; the localization rows edit in place with the Settings page's own fields, pre-filled from the browser and written only on the row's Confirm. Members see nothing; the close button hides it for that administrator in that workspace on that device. A country typed by name into a domain-bearing picker now commits the option's code (「中国」 → CN), and an invalid_format refusal reads in the console's words and the reader's language on the Settings page and the checklist. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
…国家/地区 (#30206) Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
… in its mock (#30206) Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
… workspace prompt (#30206) The console no longer opens the timezone and currency dialog, so the showcase smoke's global setup no longer looks for it. Before, with the currency unset, it waited 60 seconds for a dialog that never opens and then warned. Sign-in and the storageState it writes are unchanged. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
…eys as a narrowing (#30206) The ten published @object-ui/i18n packs drop the console.workspaceTimezonePrompt.* keys, so the declaration's arm is narrowing (the new keys stay named as its widening half), the summary carries the bang, and the body gains the BREAKING note, the removed-key table and the ADR-0087 runtime-interface-only disposition. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
Conflicts, each two neighbouring additions, both kept: the ten locale packs (main's console.settingsView.clientAddress* beside this branch's invalidFormat*), and de-quote-pairing-3876, whose counts now add main's one pair (#30323) and this branch's two: 107 matched spans, 107/107/0. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
…st's measured 203 bytes (#30206) Build & E2E UI went red on cda63e7: i18n-locale-en measured 60,138 gzipped bytes against a 60,000 ceiling. A control build of the PR base (main 48b3ae6, with ui/apps/console, ui/packages/i18n and ui/e2e restored to it) measures 59,935, so this branch adds 203 bytes: the first-run checklist copy and the invalid_format sentences, net of the retired prompt keys. Trimming the new copy saves at most 122 bytes, less than the 138 over, so the ceiling and PER_CHUNK_BASELINE both move by exactly 203. Headroom stays at the 65 bytes main had. The aggregate ceiling and every other key are unchanged. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
… checklist's measured 203 bytes (#30206)" This reverts commit 10e7823. The lane is not raising the i18n-locale-en ceiling: #30588 moves the marketplace.* copy into a lazily loaded namespace, which brings the eager en catalogue back under 60,000 once it lands and this branch merges main. Claude-Session: https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Nov 5, 2026
Merged
Contributor
Author
|
domain:ui#3 · os-tesla · session_01L9qibxW6qraU2Z3mwupUGp Superseded by #30868 (same change, head |
9 tasks done
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 Sales · project thread
Fixes #30206
Clause-②: yes (widening) — new console i18n keys
console.firstRunChecklist.*andconsole.settingsView.invalidFormat/.invalidFormatHelp/.invalidFormatPick(all ten packs); the retiredconsole.workspaceTimezonePrompt.*keys had no reader outside the removed dialogMetadata-protocol: none
维护者速读
ui/apps/console/src/pages/settings/FirstRunChecklist.tsx(读取与只在确认时写入)、firstRunChecklistLogic.ts(每行何时算完成)、SettingsField.tsx的optionByName(输入名称匹配代码)。os dev --fresh后用管理员登录,打开 /home,顶部应有清单;中文浏览器下点「默认语言和国家/地区」的「设置」,在国家框输入「中国」后点「确认」,应提示已保存、该行打勾,Setup 页不再弹任何对话框。What changes
The dialog is gone; Home carries an administrator's first-run checklist.
WorkspaceTimezonePrompt.tsxand its mount inAppContent.tsxare removed.FirstRunChecklistis drawn at the top of Home by the console's Home route (App.tsx), above the page's own sections, inside theConsolePermissionsScopethat route already sits under. Its logic,firstRunChecklistLogic.ts, is the dialog's logic widened to every row (git shows it as a delete and an add; it keepsbrowserTimeZone,browserLanguage,browserCurrency,isAdmissibleValueandmayWrite).Proposed row list (the card leaves it to the PR). Each row's state is read from the real setting every time it is drawn, never from a click:
Default Organization, the name plugin-auth gives it (#30125 row 1)localization.localeand.default_countryboth resolve from a rung other than the manifest defaultlocalization.timezoneresolves from a rung other than the defaultlocalization.currencyholds any value (it has no platform default)mail.provideris notlog,from_emailis set, and SMTP hassmtp_host; shown only to a session that may write mailA done row shows its value; a row whose state cannot be read (mail unreadable, members unreadable) is left out rather than shown as not done. Once every row shown is done the checklist draws nothing, and it comes back on its own if a setting is unset again.
The rulings the dialog was built on still hold (objectui#11693 B2, #28872). The browser only pre-fills rows 2 to 4. Nothing is written until the row's Confirm, which is
saveSettingsNamespace('localization', changes), the Settings page's ownPUT /api/settings/localization. Cancel writes nothing. An unset currency stays on the list until it is set. Language, country and currency are one offer read from the browser's first language (zh-CN→ 中文, CN, CNY), so they cannot contradict each other.Who sees it. A session that may write
localization(its manifest'swritePermission, failing closed on an unreported answer). A member sees nothing and sends oneGET /api/settings(the list, which never refuses) and no namespace read. The close button hides it for that administrator, in that workspace, on that device (localStorageos:first-run-checklist:ORG:USER); nothing is written to the server and no row changes. Its reads wait for the console's first paint (whenBootPainted, objectui#12980), as the dialog's did.「中国」 in 默认国家. The refusal started in the console:
DomainComboboxswapped typed text for a code only when it equalled the option label (「中国 (CN)」) or the code, so 「中国」 went to the server as typed, and the server's^[A-Za-z]{2}$pattern refused it withinvalid_formatin English. Now a typed name that exactly one option carries (the label without its own code beside it, trimmed, case-insensitive) is committed as that option's code; any other text is still committed verbatim and the server stays the judge. A refusal withcode: 'invalid_format'is now drawn in the console's words and the reader's language, naming the setting by the label its row draws (settingsFieldRefusals.ts): "Choose a value for Default country from the list." for a picker, and "Gateway model is not in a valid format. Use provider/model." for a typed field, repeating the field's own help line because the refusal takes its place. Every other refusal code keeps the server's sentence. The server's pattern check is unchanged (⛔packages/**).Files beyond the claim's named surface, each a reader of what was removed:
ui/apps/console/src/pages/auth/SetupPage.tsx(importsbrowserTimeZonefrom the renamed module),ui/apps/console/src/loadLocales.ts(comment), the four console tests that mocked the dialog's module,ui/e2e/live/global-setup.ts(it waited up to 60 s for the dialog's testid before every live run; the checklist is not modal, so that step is removed),docs/qa/platform-checklist/RUNNER.md(told QA runners to dismiss the dialog), and three i18n pins that named the dialog's keys or file (machineLocaleCensus-9909,console-copy-system-noun-12956) or count the de pack's quotes (de-quote-pairing-3876, 104 → 106 for two new „…“ pairs).Tests
ui/apps/console/src/pages/settings/__tests__/FirstRunChecklist.test.tsx(10), on the realapi.tsagainst a stubbedfetchand the realMePermissionsProvider: a member reads the list only and sees nothing; no capability answer or an empty one sends no request; a fresh workspace shows all six rows not done with their links and writes nothing; rows the server reports as set are done and a fully set workspace draws nothing; Set pre-fills the currency from the browser, nothing is written until Confirm, and Confirm sends exactly one PUT with{ currency: 'CNY' }; language and country are one offer ({ locale: 'zh-CN', default_country: 'CN' }); Cancel and the close button write nothing and the hide survives a remount with no request; aninvalid_formatrefusal is shown in the console's words and the row stays not done; zh copy; no read while the boot splash is up.firstRunChecklistLogic.test.ts(11):localeOffer,browserRegion, the admissible pre-fill,isKeySet, row done,isMailConfigured,isOrganizationNamed,hasInvitedColleagues, the dismissal record and unreadable storage.SettingsField.domainOptionTypedName-30206.test.tsx(5): 「中国」 commitsCN; trimmed and case-insensitive with full-width brackets; a name two options carry and part of a name stay verbatim; a currency name commits its code.settingsFieldRefusals-30206.test.ts(5), against the shippedentemplates.SettingsView.field-errors,SettingsView.crypto-unavailableandSettingsView.refusalToast-13146asserted the server's English sentence forinvalid_format; they now assert the console's sentence (and that the server's is gone).WorkspaceTimezonePrompt.test.tsx,.currency-28872.test.tsx,.afterBootPaint-12980.test.tsx; their pins (only Confirm writes, the browser zone pre-fill, the currency arm, the boot-paint wait, members never asked) are carried by the new files above.Acceptance notes
isDefaultlands its administrator in that app, and the checklist is then seen on the next visit to Home, not at sign-in. The card allowed "the home page or the top of Setup"; drawing it at the top of Setup too would be anapp-shellchange and is left for the seat to call.DEFAULT_ORGANIZATION_NAMEis a copy of plugin-auth's literal (ensure-default-organization.ts). No test holds the two equal: aui/test readingpackages/**source would be a cross-package input outside both CI rosters. A rename on the server side would make row 1 read "named" for an organization nobody named.invalid_format(for examplevalue_domain) still carry the server's English sentence; localizingFieldError.messageis a server concern and out of this card.os:workspace-timezone-prompt:*) is no longer read; it stays in browsers that have it, harmlessly.packages/plugins/plugin-auth/src/dev-admin-seed-workspace-timezone.test.tsstill describes the dialog in its doc comment (the condition it pins is still the one row 3 reads). Left alone: ⛔packages/**on this card.claude/project-thread-5murn7, notclaude/issue-30206-….Verification
All readings on head
9914c31f, unless a line names another.Live: before on main, after on the branch (showcase os dev --fresh, console dev server, 1440 wide, zh and en)
mainfa9c0aa2: entering Setup opened the currency dialog over the page, zh and en (before-setup-dialog-zh-1440.png,before-setup-dialog-en-1440.png).zh-CN,Asia/Shanghai):/homeshows the checklist, rowsorganization_name=false language_country=false timezone=true currency=false mail=false invite=true, progress已完成 2/6(the rig's dev seed sets the zone and seeds members). Opening 默认语言和国家/地区 pre-fills 简体中文 and 中国 (CN). Clearing the country box and typing 「中国」 leaves中国 (CN)in the box; Confirm sent exactly one write,PUT /api/settings/localization {"locale":"zh-CN","default_country":"CN"}, answered 200, and the row turned done (简体中文、中国 (CN)), progress已完成 3/6./apps/setupafterwards: 0 dialogs.en-US,America/New_York):3 of 6 done; opening Default currency pre-fillsUSD — US Dollarand sends no write;/apps/setup: 0 dialogs.issue-30206/):after-1-home-zh-CN-1440.png,after-2-editor-zh-CN-1440.png,after-3-saved-zh-CN-1440.png,after-4-setup-zh-CN-1440.png,after-1-home-en-US-1440.png,after-2-editor-en-US-1440.png,after-4-setup-en-US-1440.png.Tests and type-check
pnpm exec vitest run apps/console/(ui root, head3bcfe085tree): Test Files 299 passed (299), Tests 2931 passed (2931).9914c31f:pnpm exec vitest run apps/console/src/pages/settings/ apps/console/src/__tests__/ apps/console/src/components/FormPage.routePermissions-29187.test.tsx apps/console/src/pages/auth/: Test Files 133 passed (133), Tests 1504 passed (1504).pnpm exec vitest run packages/i18n/: Test Files 95 passed (95), Tests 1443 passed, 13 skipped.pnpm --filter @object-ui/console type-checkexit 0 (afterpnpm --filter @object-ui/i18n build; the console reads the i18n package's built types),pnpm --filter @object-ui/i18n type-checkexit 0,pnpm run type-check:e2eexit 0.Ablations (each through scripts/ablation-replace.mjs, restored to the HEAD blob with git diff HEAD empty)
SettingsField.tsxname match removed (?? optionByName(options, text)?.value):SettingsField.domainOptionTypedName-302063 failed, 2 passed (the two verbatim cases stay green, as they should).settingsFieldRefusals.tsre-wording disabled (every code keeps the server sentence): 7 failed acrosssettingsFieldRefusals-30206,FirstRunChecklistandSettingsView.field-errors.mayWriteno longer reads the manifest'swritePermission:FirstRunChecklist"a member … nothing is drawn" fails, 1 of 10.isKeySetno longer readssource: 7 failed acrossFirstRunChecklistandfirstRunChecklistLogic.Derived gates: node scripts/pm/dispatch-gates.mjs --commands (42) and --ran
pnpm --dir ui exec vitest run scripts/first went red oncheck-vi-mock-inherit(the new checklist test's@object-ui/app-shellmock did not inherit the real surface); fixed in9914c31fand re-run on that head: Test Files 170 passed, 2 skipped; Tests 4985 passed, 2 skipped.--ran:✓ dispatch-gates --ran: 42 derived famil(ies) accounted for — 42 run, 0 NOT-MEASURED.df45b9d1plus that one test edit; the list derived on9914c31fis the same 42.🤖 Generated with Claude Code
https://claude.ai/code/session_01L6bhgVwQZbHRRM9CaXeKif