Repository navigation
feat: organize global settings into categories, give every page an address and stop list flicker - #74
Conversation
…dress and stop list flicker
There was a problem hiding this comment.
Reviewed commit: 96085b8
Coverage: Snapshot: 200 files, 3398449 bytes; skipped 0 entries; Initial model context: 22 files; other accepted files available through tools; Git workspace contains a fixed snapshot, not full upstream history
| }, | ||
| // Where GitHub's webhooks arrive: a self-hosted HTTPS address, or a Cloudflare Tunnel in front of it. | ||
| async access(request) { | ||
| const view = settingsView = { request, onboarding: await api('/api/onboarding'), accounts: [], models: [] }; |
There was a problem hiding this comment.
F1 — medium, suggestion, state handling — A superseded category load can win the shared settingsView, so model actions on the 模型 category stop redrawing the cards
- Where:
static/settings.js:49(same pattern at 57 and 64; staleness check at line 19; use at lines 183-186) - Problem: every category loader publishes the module-wide
settingsViewas soon as its data arrives (const view = settingsView = { request, onboarding: await api(...), ... }), butrenderSettingscomparesrequest !== renderVersiononly after the loader returns. A load that has already been superseded can therefore resolve last and becomesettingsView.refreshSettingsModelscompares the view it was built with againstsettingsViewand returns without drawing, so adding, editing, deleting or re-pricing a shared model on the visible 模型 category leaves the card list unchanged and suppresses the已保存…flash. - Conditions: two category loads overlap and the earlier one resolves after the later one — e.g. 公网接入 is opened and 模型 is clicked before its
/api/onboardingreturns; that request waits 3 s + 3 s on the tunnel-metrics endpoint (src/onboarding/service.ts:39-49) when a tunnel token is saved but the tunnel is unreachable. - Impact: the action succeeds server-side, the page keeps showing the stale list, and no error appears; the user has to press 刷新. (Confirmed by driving
renderSettingswith an out-of-orderrespondintest/console-page.mjs.) - Fix: only publish the view after the staleness check — have the loaders return
{ view, cards }and doif (request !== renderVersion) return; settingsView = view; content.replaceChildren(...cards);inrenderSettings.
|
This PR splits 全局设置 into five addressed categories (with #/accounts and #/users redirected), gives every console page a hash address that survives reload, and replaces the 5-second full re-render of the task lists with an in-place row diff that leaves unchanged rows alone. I verified F2 — medium, suggestion, routing — Deleting your own account leaves the settings address, so the next login lands on the previous page
Reviewed commit: 96085b8 |
Global settings, the console's addresses and the task-list refresh, redone together.
Global settings
The page used to be one grid of seven unrelated cards. It now uses the project page's layout: categories on the left, one category on the right. Each category has its own address,
#/settings/<category>.#/accountsand#/users, redirect to#/settings/accountsand#/settings/users.Addresses
Every tab now writes its address:
#/projects,#/board,#/costs,#/reviews,#/developments,#/events,#/external,#onboardingand#/settings/.... A reload or a shared link opens the same page; before this, clicking a tab cleared the address, so a reload always returned to the projects list.pushStateand draws the page in the same click, so there is no gap waiting forhashchange. Back and forward still work throughhashchange.Flicker
The review and development lists refreshed every 5 seconds through the full
render(). That emptied the list and showed "正在加载…" until the request returned, so the page blinked every 5 seconds.The periodic refresh is now quiet:
Tests
test/concurrency.test.mjs: the settings tests walk the categories: navigation, cards per category, the address change flagging the App's webhook in the accounts category, and the accounts list.e2e/console-addresses.spec.mjs: every tab's address survives a reload; settings categories open and reload in place; the old accounts address redirects; the review list refreshes without being emptied and keeps unchanged rows while a changed row updates; a project admin's settings address falls back to projects; 390px has no sideways scroll.e2e/control-plane,e2e/app-permissionsande2e/admin-grantsreach accounts and users through global settings.test/docker-env.mjshad two stale steps:confirm()for reset, but reset now asks in the console's own dialog.Verification
npm run check: passednpm test: 271 passednpm run test:e2e: 17 passednpm run test:docker(real Docker project environments): 18 passednpm run test:agent(real Docker and Pi): 21 passed