refactor: optimize onboarding - #2138
Conversation
Turn dead-end empty states into actionable guidance via a shared EmptyGuide component, and add an in-product onboarding checklist so a first-time user has a clear path from install to a running setup. Empty-state guides (new src/components/EmptyGuide): - hosts/targets: always show the "deploy collector" guide (previously hidden when a business group was selected due to a gids gate) - datasources: explain why a datasource is needed + "add" CTA - dashboards: "create" + "import from template center" - alert rules: "create" + "import from template center" (opt-in via a new emptyGuide prop on ListNG so other usages keep the default) Landing onboarding checklist (new OnboardingChecklist): - two parallel tracks (host monitoring / data integration) with auto-detected, per-step progress - styled with the landing design system (violet-wash shell, panels, gradient/timeline nodes); stays until all steps are complete i18n added for zh_CN/en_US/zh_HK/ja_JP/ru_RU across the affected pages.
…idebar badge Clicking the sidebar onboarding badge now opens a compact checklist popover in place, instead of navigating away to the landing page — keeping the user in their current context (the "do a little, come back" loop that onboarding needs). - new PopoverContent: compact two-track checklist (host monitoring / data integration) reusing the same timeline/node visual language via global --fc-* tokens (works outside the landing page) - each step deep-links to its page and closes the popover; a footer link opens the full guide on /landing - extract shared ONBOARDING_TRACKS so the landing checklist and the popover share one definition; both still use useOnboardingProgress i18n: add onboarding.viewFull across zh_CN/en_US/zh_HK/ja_JP/ru_RU.
- Dashboard/alert-rule empty guides open the built-in import modal in place instead of navigating to /components; fall back to the template-center link for non-leaf business groups. - Rename "从模板中心导入" to "从模板导入" and refresh empty-state copy. - Host-dashboard onboarding step deep-links to /components?component=Linux. - Enlarge track-name font so the category outranks its steps, and move the data track ahead of the host track in the checklist/popover.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughAdds a new onboarding guidance system: a reusable ChangesOnboarding Progress and Empty-State Guidance
Sequence Diagram(s)sequenceDiagram
rect rgba(70, 130, 180, 0.5)
Note over SideMenu,history: Sidebar onboarding badge interaction
SideMenu->>OnboardingProgressBadge: render(collapsed, isCustomBg)
OnboardingProgressBadge->>useOnboardingProgress: get loaded/doneMap/doneCount
useOnboardingProgress->>sessionStorage: check n9e_onboarding_done
alt onboarding complete
useOnboardingProgress-->>OnboardingProgressBadge: DONE_DETECT (cached)
else probing required
useOnboardingProgress->>getMonObjectList: fetch machine list (parallel)
useOnboardingProgress->>getBusiGroupsDashboards: fetch dashboards (parallel)
useOnboardingProgress->>getBusiGroupsAlertRules: fetch alert rules (parallel)
getMonObjectList-->>useOnboardingProgress: machine result
getBusiGroupsDashboards-->>useOnboardingProgress: dashboard result
getBusiGroupsAlertRules-->>useOnboardingProgress: alert result
useOnboardingProgress->>useOnboardingProgress: compute doneMap (gate hostDashboard)
useOnboardingProgress->>sessionStorage: mark complete if doneCount===total
end
OnboardingProgressBadge-->>SideMenu: null if loading or complete
OnboardingProgressBadge->>Popover: open on badge click
Popover->>OnboardingPopoverContent: render(doneMap, doneCount, total, onNavigate)
OnboardingPopoverContent->>OnboardingPopoverContent: map ONBOARDING_TRACKS to steps
OnboardingPopoverContent-->>Popover: step button click → onNavigate(step.to)
OnboardingProgressBadge->>Popover: close
OnboardingProgressBadge->>history: push(step.to)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/components/OnboardingProgress/useOnboardingProgress.ts (1)
41-41: 📐 Maintainability & Code Quality | 🔵 TrivialReplace the
any[]cast withArray.isArray()runtime guard on line 41.The code uses
(dashboardRes.value as any[])to access.length, which bypasses TypeScript type checking. SincegetBusiGroupsDashboards()lacks an explicit return type annotation, this cast weakens type safety.Proposed fix
- dashboard: dashboardRes.status === 'fulfilled' && ((dashboardRes.value as any[])?.length ?? 0) > 0, + dashboard: + dashboardRes.status === 'fulfilled' && + Array.isArray(dashboardRes.value) && + dashboardRes.value.length > 0,This preserves the runtime check while eliminating the
anycast, keeping the code fully typed per the coding guidelines.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/OnboardingProgress/useOnboardingProgress.ts` at line 41, Replace the TypeScript `any[]` cast with a runtime `Array.isArray()` guard on the dashboard property assignment in the useOnboardingProgress hook. Instead of casting `dashboardRes.value as any[]` and then accessing its length, use `Array.isArray(dashboardRes.value)` as a conditional check to verify the value is an actual array before accessing its length property. This eliminates the unsafe `any` type cast while maintaining the same runtime validation and preserving type safety according to the coding guidelines.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/OnboardingProgress/index.tsx`:
- Around line 59-60: The ringColor and ringTrack variable assignments on lines
59-60 in the OnboardingProgress component use hardcoded color values (`#ffffff`
and rgba(255,255,255,0.28)) instead of theme tokens. Replace these hardcoded
color values with appropriate theme tokens from src/theme/variable.css following
the existing theme system pattern used elsewhere in the codebase. Ensure both
the white color and the white color with transparency values use theme variables
instead of magic color values.
In `@src/components/OnboardingProgress/style.less`:
- Around line 72-88: Replace all hardcoded white color values in the onboarding
badge styles with theme variables from src/theme/variable.css. Specifically,
update the .n9e-onboarding-badge-collapsed.is-custom-bg selector and its :hover
state to use theme variables instead of rgba(255, 255, 255, ...) for the
border-color and background properties, and update the color property in
.n9e-onboarding-badge-label and .n9e-onboarding-badge-count selectors to use a
theme variable instead of the hardcoded `#fff` value. Refer to the existing theme
variables in src/theme/variable.css to identify the appropriate replacements for
the various opacity levels used throughout this block.
In `@src/pages/landing/locale/zh_CN.ts`:
- Around line 3-16: In the zh_CN.ts locale file, the onboarding object has a
formatting inconsistency where the dismiss and hostTrack properties are placed
on the same line with only whitespace between them. Separate these two
properties by placing hostTrack on its own line (line 8) so that each property
in the onboarding object follows the consistent single-property-per-line
formatting convention used throughout the file and other locale files.
In `@src/pages/landing/style.less`:
- Around line 1633-1637: The `.n9e-landing-onboarding-node-done` class uses a
hardcoded color value `#fff` for the text color, which violates the project's
theme token guidelines. Replace the hardcoded white color in the color property
with an appropriate theme token variable from `src/theme/variable.css` that
represents white or light text color in the existing theme system, ensuring
consistency with other color values in the stylesheet that use theme variables.
---
Nitpick comments:
In `@src/components/OnboardingProgress/useOnboardingProgress.ts`:
- Line 41: Replace the TypeScript `any[]` cast with a runtime `Array.isArray()`
guard on the dashboard property assignment in the useOnboardingProgress hook.
Instead of casting `dashboardRes.value as any[]` and then accessing its length,
use `Array.isArray(dashboardRes.value)` as a conditional check to verify the
value is an actual array before accessing its length property. This eliminates
the unsafe `any` type cast while maintaining the same runtime validation and
preserving type safety according to the coding guidelines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e305a62a-b59f-4f96-a604-09be795b1397
📒 Files selected for processing (42)
src/components/EmptyGuide/index.tsxsrc/components/OnboardingProgress/PopoverContent.tsxsrc/components/OnboardingProgress/index.tsxsrc/components/OnboardingProgress/style.lesssrc/components/OnboardingProgress/tracks.tssrc/components/OnboardingProgress/useOnboardingProgress.tssrc/components/SideMenu/index.tsxsrc/pages/alertRules/List/ListNG.tsxsrc/pages/alertRules/List/index.tsxsrc/pages/alertRules/locale/en_US.tssrc/pages/alertRules/locale/ja_JP.tssrc/pages/alertRules/locale/ru_RU.tssrc/pages/alertRules/locale/zh_CN.tssrc/pages/alertRules/locale/zh_HK.tssrc/pages/dashboard/List/index.tsxsrc/pages/dashboard/locale/en_US.tssrc/pages/dashboard/locale/ja_JP.tssrc/pages/dashboard/locale/ru_RU.tssrc/pages/dashboard/locale/zh_CN.tssrc/pages/dashboard/locale/zh_HK.tssrc/pages/datasource/components/TableSource/index.tsxsrc/pages/datasource/index.tsxsrc/pages/datasource/locale/en_US.tssrc/pages/datasource/locale/ja_JP.tssrc/pages/datasource/locale/ru_RU.tssrc/pages/datasource/locale/zh_CN.tssrc/pages/datasource/locale/zh_HK.tssrc/pages/hosts/locale/en_US.tssrc/pages/hosts/locale/ja_JP.tssrc/pages/hosts/locale/ru_RU.tssrc/pages/hosts/locale/zh_CN.tssrc/pages/hosts/locale/zh_HK.tssrc/pages/hosts/pages/List/List.tsxsrc/pages/landing/OnboardingChecklist.tsxsrc/pages/landing/index.tsxsrc/pages/landing/landing.data.tssrc/pages/landing/locale/en_US.tssrc/pages/landing/locale/ja_JP.tssrc/pages/landing/locale/ru_RU.tssrc/pages/landing/locale/zh_CN.tssrc/pages/landing/locale/zh_HK.tssrc/pages/landing/style.less
| const ringColor = isCustomBg ? '#ffffff' : 'rgb(var(--fc-text-link-rgb))'; | ||
| const ringTrack = isCustomBg ? 'rgba(255,255,255,0.28)' : 'rgb(var(--fc-text-link-rgb) / 0.18)'; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Replace hardcoded ring colors with theme tokens.
Line 59 and Line 60 use magic color values (#ffffff, rgba(255,255,255,0.28)), which breaks the theme-token contract for TSX styling decisions.
As per coding guidelines, “Use color and theme-related values from src/theme/variable.css and existing theme system; avoid magic color values.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/OnboardingProgress/index.tsx` around lines 59 - 60, The
ringColor and ringTrack variable assignments on lines 59-60 in the
OnboardingProgress component use hardcoded color values (`#ffffff` and
rgba(255,255,255,0.28)) instead of theme tokens. Replace these hardcoded color
values with appropriate theme tokens from src/theme/variable.css following the
existing theme system pattern used elsewhere in the codebase. Ensure both the
white color and the white color with transparency values use theme variables
instead of magic color values.
Source: Coding guidelines
| border-color: rgba(255, 255, 255, 0.14); | ||
| background: rgba(255, 255, 255, 0.06); | ||
|
|
||
| &:hover { | ||
| background: rgba(255, 255, 255, 0.12); | ||
| border-color: rgba(255, 255, 255, 0.22); | ||
| } | ||
|
|
||
| .n9e-onboarding-badge-label, | ||
| .n9e-onboarding-badge-count { | ||
| color: #fff; | ||
| } | ||
| } | ||
|
|
||
| .n9e-onboarding-badge-collapsed.is-custom-bg:hover { | ||
| background: rgba(255, 255, 255, 0.12); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Tokenize hardcoded white values in onboarding badge styles.
This block introduces hardcoded white/alpha values (#fff, rgba(255,255,255,...)) instead of theme variables, which makes cross-theme maintenance harder.
As per coding guidelines, “Use color and theme-related values from src/theme/variable.css and existing theme system; avoid magic color values.”
Also applies to: 216-219
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/OnboardingProgress/style.less` around lines 72 - 88, Replace
all hardcoded white color values in the onboarding badge styles with theme
variables from src/theme/variable.css. Specifically, update the
.n9e-onboarding-badge-collapsed.is-custom-bg selector and its :hover state to
use theme variables instead of rgba(255, 255, 255, ...) for the border-color and
background properties, and update the color property in
.n9e-onboarding-badge-label and .n9e-onboarding-badge-count selectors to use a
theme variable instead of the hardcoded `#fff` value. Refer to the existing theme
variables in src/theme/variable.css to identify the appropriate replacements for
the various opacity levels used throughout this block.
Source: Coding guidelines
| onboarding: { | ||
| title: '新手引导', | ||
| subtitle: '跟着做完这几步,几分钟把监控跑起来', | ||
| progress: '已完成 {{done}}/{{total}}', | ||
| dismiss: '不再显示', hostTrack: '主机监控线', | ||
| dataTrack: '数据接入线', | ||
| steps: { | ||
| machine: { title: '部署采集器,接入主机', desc: '在主机部署 Categraf,机器会自动出现在设备列表' }, | ||
| hostDashboard: { title: '套用主机监控大盘', desc: '从模板中心一键导入内置主机大盘' }, | ||
| datasource: { title: '配置数据源', desc: '接入 Prometheus / VictoriaMetrics 等数据源' }, | ||
| dashboard: { title: '创建仪表盘', desc: '把关心的指标可视化成大盘' }, | ||
| alert: { title: '配置告警规则', desc: '为关键指标设置第一条告警规则' }, | ||
| }, | ||
| }, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for usage of dismiss in OnboardingChecklist and related components
rg -n "dismiss" src/pages/landing/ --type ts --type tsx -A 2 -B 2 | grep -E "(onboarding|dismiss)" | head -20Repository: n9e/fe
Length of output: 172
🏁 Script executed:
#!/bin/bash
# Verify all landing locale files have onboarding block
for lang in zh_CN zh_HK en_US ja_JP ru_RU; do
echo "=== Checking $lang ==="
grep -A 3 "onboarding:" "src/pages/landing/locale/${lang}.ts" 2>/dev/null | head -5 || echo "File not found or no onboarding key"
doneRepository: n9e/fe
Length of output: 898
🏁 Script executed:
#!/bin/bash
# First, read the actual file to see the formatting issue on line 7
cat -n src/pages/landing/locale/zh_CN.ts | sed -n '1,20p'Repository: n9e/fe
Length of output: 1014
🏁 Script executed:
#!/bin/bash
# Search for dismiss usage without the problematic --type tsx flag
rg -n "dismiss" src/pages/landing/ -A 2 -B 2Repository: n9e/fe
Length of output: 2172
🏁 Script executed:
#!/bin/bash
# Search for OnboardingChecklist component and its usage of dismiss
fd -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs rg "OnboardingChecklist" -lRepository: n9e/fe
Length of output: 385
🏁 Script executed:
#!/bin/bash
# Check for Prettier configuration in the repository
find . -maxdepth 2 -type f \( -name ".prettierrc*" -o -name "prettier.config.*" -o -name "package.json" \) | head -5Repository: n9e/fe
Length of output: 178
🏁 Script executed:
#!/bin/bash
# Read the OnboardingChecklist component to see how dismiss is used
cat src/pages/landing/OnboardingChecklist.tsx | head -100Repository: n9e/fe
Length of output: 3432
🏁 Script executed:
#!/bin/bash
# Check Prettier configuration
cat .prettierrc.jsonRepository: n9e/fe
Length of output: 445
Fix line 7 formatting: split dismiss and hostTrack to separate lines.
Line 7 of src/pages/landing/locale/zh_CN.ts places two object properties on the same line with only whitespace between them:
dismiss: '不再显示', hostTrack: '主机监控线',
This violates the formatting conventions used in the other four locale files (zh_HK, en_US, ja_JP, ru_RU), which correctly place each property on its own line. Prettier will reformat this during the next format pass. Move hostTrack to line 8:
progress: '已完成 {{done}}/{{total}}',
dismiss: '不再显示',
- hostTrack: '主机监控线',
+ hostTrack: '主机监控线',
dataTrack: '数据接入线',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| onboarding: { | |
| title: '新手引导', | |
| subtitle: '跟着做完这几步,几分钟把监控跑起来', | |
| progress: '已完成 {{done}}/{{total}}', | |
| dismiss: '不再显示', hostTrack: '主机监控线', | |
| dataTrack: '数据接入线', | |
| steps: { | |
| machine: { title: '部署采集器,接入主机', desc: '在主机部署 Categraf,机器会自动出现在设备列表' }, | |
| hostDashboard: { title: '套用主机监控大盘', desc: '从模板中心一键导入内置主机大盘' }, | |
| datasource: { title: '配置数据源', desc: '接入 Prometheus / VictoriaMetrics 等数据源' }, | |
| dashboard: { title: '创建仪表盘', desc: '把关心的指标可视化成大盘' }, | |
| alert: { title: '配置告警规则', desc: '为关键指标设置第一条告警规则' }, | |
| }, | |
| }, | |
| onboarding: { | |
| title: '新手引导', | |
| subtitle: '跟着做完这几步,几分钟把监控跑起来', | |
| progress: '已完成 {{done}}/{{total}}', | |
| dismiss: '不再显示', | |
| hostTrack: '主机监控线', | |
| dataTrack: '数据接入线', | |
| steps: { | |
| machine: { title: '部署采集器,接入主机', desc: '在主机部署 Categraf,机器会自动出现在设备列表' }, | |
| hostDashboard: { title: '套用主机监控大盘', desc: '从模板中心一键导入内置主机大盘' }, | |
| datasource: { title: '配置数据源', desc: '接入 Prometheus / VictoriaMetrics 等数据源' }, | |
| dashboard: { title: '创建仪表盘', desc: '把关心的指标可视化成大盘' }, | |
| alert: { title: '配置告警规则', desc: '为关键指标设置第一条告警规则' }, | |
| }, | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/landing/locale/zh_CN.ts` around lines 3 - 16, In the zh_CN.ts
locale file, the onboarding object has a formatting inconsistency where the
dismiss and hostTrack properties are placed on the same line with only
whitespace between them. Separate these two properties by placing hostTrack on
its own line (line 8) so that each property in the onboarding object follows the
consistent single-property-per-line formatting convention used throughout the
file and other locale files.
Source: Coding guidelines
| .n9e-landing-onboarding-node-done { | ||
| background: var(--landing-glyph-violet-bg); | ||
| color: #fff; | ||
| box-shadow: 0 4px 10px rgba(var(--landing-primary-rgb), 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.2); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use a theme token instead of hardcoded #fff in onboarding done-node text color.
Line 1635 hardcodes white, which conflicts with the project’s theme-token rule for stylesheet colors.
As per coding guidelines, “Use color and theme-related values from src/theme/variable.css and existing theme system; avoid magic color values.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/landing/style.less` around lines 1633 - 1637, The
`.n9e-landing-onboarding-node-done` class uses a hardcoded color value `#fff`
for the text color, which violates the project's theme token guidelines. Replace
the hardcoded white color in the color property with an appropriate theme token
variable from `src/theme/variable.css` that represents white or light text color
in the existing theme system, ensuring consistency with other color values in
the stylesheet that use theme variables.
Source: Coding guidelines
# Conflicts: # src/pages/hosts/pages/List/List.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/OnboardingProgress/useOnboardingProgress.ts (1)
70-80: 🎯 Functional Correctness | 🟡 Minor
hostDashboardanddashboardshare the same signal — possible false "done".Both steps derive from
detect.dashboard, which is true whenever any dashboard exists (fromgetBusiGroupsDashboards()returning count > 0). The onboarding step description says "从模板中心一键导入内置主机大盘" (import built-in host dashboards), but the detection never verifies that a host-specific or template dashboard was actually imported. A user who creates an unrelated dashboard and has a machine will seehostDashboardmarked complete even though no host dashboard was set up. Confirm if this optimistic assumption is acceptable, or detect host dashboards specifically (e.g., by checking board metadata, template identifier, or component type).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/OnboardingProgress/useOnboardingProgress.ts` around lines 70 - 80, The hostDashboard and dashboard properties in the doneMap object both rely on the same detect.dashboard signal, which causes hostDashboard to be marked as complete whenever any dashboard exists, even if it's not a host-specific dashboard. Fix this by updating the hostDashboard evaluation logic to specifically verify that a built-in or host-specific dashboard was imported, such as by checking board metadata, template identifier, or component type, rather than just checking if detect.dashboard is true. Keep the machine check as a gate, but add an additional condition that validates the dashboard is actually a host dashboard before marking that step as done.
🧹 Nitpick comments (1)
src/components/OnboardingProgress/useOnboardingProgress.ts (1)
56-68: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoffRe-probing on every route change can fire heavy endpoints repeatedly for new users.
For a user who hasn't completed any step,
lastDetectnever flips totrue, so eachpathnamechange re-runs all three checks — including the boards/alert-rules endpoints the comments themselves flag as heavy. New users navigate the most during onboarding, so this is the worst-case path. Consider only probing on relevant routes, throttling, or a short module-level TTL so unfinished facets aren't re-fetched on every navigation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/OnboardingProgress/useOnboardingProgress.ts` around lines 56 - 68, The useEffect hook in the useOnboardingProgress function re-runs the probeOnboarding function on every pathname change, causing expensive endpoint calls to fire repeatedly for new users who haven't completed onboarding. Implement a module-level caching mechanism with a short time-to-live (TTL) to store the probing results and avoid unnecessary re-fetches when pathname changes. Before calling probeOnboarding, check if cached results exist and are still valid based on the TTL; only make a new probe call if the cache has expired or doesn't exist. This will prevent the heavy endpoints mentioned in probeOnboarding from being called excessively during navigation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/OnboardingProgress/useOnboardingProgress.ts`:
- Around line 27-33: The logout handler has a fallback path using
history.push('/login') for client-side navigation that does not reload the page,
which leaves the module-level lastDetect variable and the sessionStorage
ONBOARDING_DONE_KEY in their previous state. When the fallback path executes
instead of the full page reload path, explicitly clear both the sessionStorage
entry (using sessionStorage.removeItem with ONBOARDING_DONE_KEY) and reset the
lastDetect variable to its initial state (with all properties set to false)
before calling history.push('/login') to prevent a new user from inheriting the
previous user's onboarding completion state.
In `@src/pages/hosts/pages/List/List.tsx`:
- Around line 391-398: The bare <a> tag with onClick handler for openCategrafDoc
on line 396 lacks an href attribute, making it inaccessible to keyboard users.
Replace this <a onClick={openCategrafDoc}>{t('categraf_doc')}</a> element with
an antd Button component using type='link' and the same onClick handler: <Button
type='link' onClick={openCategrafDoc}>{t('categraf_doc')}</Button>. This will
ensure the element is keyboard-focusable and can be activated using Enter or
Space keys.
---
Outside diff comments:
In `@src/components/OnboardingProgress/useOnboardingProgress.ts`:
- Around line 70-80: The hostDashboard and dashboard properties in the doneMap
object both rely on the same detect.dashboard signal, which causes hostDashboard
to be marked as complete whenever any dashboard exists, even if it's not a
host-specific dashboard. Fix this by updating the hostDashboard evaluation logic
to specifically verify that a built-in or host-specific dashboard was imported,
such as by checking board metadata, template identifier, or component type,
rather than just checking if detect.dashboard is true. Keep the machine check as
a gate, but add an additional condition that validates the dashboard is actually
a host dashboard before marking that step as done.
---
Nitpick comments:
In `@src/components/OnboardingProgress/useOnboardingProgress.ts`:
- Around line 56-68: The useEffect hook in the useOnboardingProgress function
re-runs the probeOnboarding function on every pathname change, causing expensive
endpoint calls to fire repeatedly for new users who haven't completed
onboarding. Implement a module-level caching mechanism with a short time-to-live
(TTL) to store the probing results and avoid unnecessary re-fetches when
pathname changes. Before calling probeOnboarding, check if cached results exist
and are still valid based on the TTL; only make a new probe call if the cache
has expired or doesn't exist. This will prevent the heavy endpoints mentioned in
probeOnboarding from being called excessively during navigation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: cb5ff6b4-4f90-404d-b6eb-3b9db11f9aef
📒 Files selected for processing (8)
src/components/OnboardingProgress/useOnboardingProgress.tssrc/pages/hosts/pages/List/List.tsxsrc/pages/landing/locale/en_US.tssrc/pages/landing/locale/ja_JP.tssrc/pages/landing/locale/ru_RU.tssrc/pages/landing/locale/zh_CN.tssrc/pages/landing/locale/zh_HK.tssrc/pages/landing/style.less
💤 Files with no reviewable changes (5)
- src/pages/landing/locale/ru_RU.ts
- src/pages/landing/locale/ja_JP.ts
- src/pages/landing/locale/zh_HK.ts
- src/pages/landing/locale/en_US.ts
- src/pages/landing/style.less
🚧 Files skipped from review as they are similar to previous changes (1)
- src/pages/landing/locale/zh_CN.ts
| // 全部完成后写入会话级标记,已上手的用户后续直接短路、不再探测,避免每次加载都拉全量大盘 / 告警 | ||
| const ONBOARDING_DONE_KEY = 'n9e_onboarding_done'; | ||
| const DONE_DETECT: DetectState = { machine: true, dashboard: true, alert: true, loaded: true }; | ||
|
|
||
| // 跨实例(侧栏徽标 + 着陆页清单)与多次挂载共享的最近一次探测结果: | ||
| // 既作初始值避免重复请求与闪烁,也用于跳过已完成步骤的探测(大盘 / 告警接口偏重,置真后不再重复拉取)。 | ||
| let lastDetect: DetectState = { machine: false, dashboard: false, alert: false, loaded: false }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find logout / account-switch handling to confirm whether a full reload occurs
rg -nP --type=ts --type=tsx -C3 '(logout|signOut|sign_out|location\.(reload|href)|window\.location)' -g '!**/*.test.*'
# Check for any reset of the onboarding session key elsewhere
rg -nP -C2 'n9e_onboarding_done'Repository: n9e/fe
Length of output: 172
🏁 Script executed:
#!/bin/bash
# Search for logout/account-switch patterns (corrected file type syntax)
rg -nP -t ts -t tsx -C3 '(logout|signOut|sign_out|location\.reload|location\.href|window\.location)' -g '!**/*.test.*' src/Repository: n9e/fe
Length of output: 172
🏁 Script executed:
#!/bin/bash
# Check for any reset of the onboarding session key
rg -nP 'n9e_onboarding_done' src/Repository: n9e/fe
Length of output: 257
🏁 Script executed:
#!/bin/bash
# Check auth/login context to see how user switches are handled
fd -e ts -e tsx -path '*/auth/*' -o -path '*/login/*' -o -path '*/provider/*' | head -20Repository: n9e/fe
Length of output: 313
🏁 Script executed:
#!/bin/bash
# Read the full useOnboardingProgress.ts file
cat -n src/components/OnboardingProgress/useOnboardingProgress.tsRepository: n9e/fe
Length of output: 4055
🏁 Script executed:
#!/bin/bash
# Search for logout/account switch without relying on file type
rg -nP -C3 '(logout|signOut|sign_out)' src/ --glob='!*.test.ts'Repository: n9e/fe
Length of output: 3585
🏁 Script executed:
#!/bin/bash
# Search for sessionStorage clear or reset patterns
rg -nP 'sessionStorage\.(clear|removeItem|setItem.*onboarding)' src/Repository: n9e/fe
Length of output: 349
🏁 Script executed:
#!/bin/bash
# Read the logout handler in SideMenu
sed -n '369,390p' src/components/SideMenu/index.tsxRepository: n9e/fe
Length of output: 735
🏁 Script executed:
#!/bin/bash
# Search for location.reload or window.location patterns in SideMenu or related files
rg -nP 'location\.(reload|href|replace)|window\.location' src/components/SideMenu/ src/pages/Repository: n9e/fe
Length of output: 4574
🏁 Script executed:
#!/bin/bash
# Check the Logout API implementation
cat -n src/services/login.ts | grep -A 10 "Logout"Repository: n9e/fe
Length of output: 510
🏁 Script executed:
#!/bin/bash
# Look for backend API definition or comments about Logout response
rg -nP 'logout.*redirect|redirectUrl|redirect_url' src/Repository: n9e/fe
Length of output: 507
Clear onboarding state on logout fallback path.
The logout handler has two paths: if the Logout API returns a redirect URL (string), it triggers window.location.href (full page reload), which properly clears sessionStorage and module-level state. However, the fallback path (history.push('/login')) performs client-side navigation without a reload, causing both ONBOARDING_DONE_KEY (sessionStorage) and lastDetect (module-level) to persist. If the app later supports user/account switching without full page reload, or if the Logout API doesn't reliably return a redirect URL, a new account could inherit the previous user's completed onboarding state.
Explicitly clear both in the fallback path:
else {
sessionStorage.removeItem(ONBOARDING_DONE_KEY);
lastDetect = { machine: false, dashboard: false, alert: false, loaded: false };
history.push('/login');
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/OnboardingProgress/useOnboardingProgress.ts` around lines 27 -
33, The logout handler has a fallback path using history.push('/login') for
client-side navigation that does not reload the page, which leaves the
module-level lastDetect variable and the sessionStorage ONBOARDING_DONE_KEY in
their previous state. When the fallback path executes instead of the full page
reload path, explicitly clear both the sessionStorage entry (using
sessionStorage.removeItem with ONBOARDING_DONE_KEY) and reset the lastDetect
variable to its initial state (with all properties set to false) before calling
history.push('/login') to prevent a new user from inheriting the previous user's
onboarding completion state.
| actions={ | ||
| <> | ||
| <Button type='primary' onClick={openCategrafDoc}> | ||
| {t('empty_guide.deploy_btn')} | ||
| </Button> | ||
| <a onClick={openCategrafDoc}>{t('categraf_doc')}</a> | ||
| </> | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm categraf_doc exists across hosts locale files
fd -t f . -p 'src/pages/hosts/locale' | xargs rg -nP "categraf_doc"Repository: n9e/fe
Length of output: 495
🏁 Script executed:
sed -n '385,405p' src/pages/hosts/pages/List/List.tsxRepository: n9e/fe
Length of output: 863
Use a focusable control instead of a bare <a>.
Line 396 has <a onClick={openCategrafDoc}> with no href, making it inaccessible by keyboard—it's not in the tab order and cannot be activated with Enter/Space. Use an antd Button type='link' instead.
Proposed fix
- <a onClick={openCategrafDoc}>{t('categraf_doc')}</a>
+ <Button type='link' className='p-0' onClick={openCategrafDoc}>
+ {t('categraf_doc')}
+ </Button>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/hosts/pages/List/List.tsx` around lines 391 - 398, The bare <a> tag
with onClick handler for openCategrafDoc on line 396 lacks an href attribute,
making it inaccessible to keyboard users. Replace this <a
onClick={openCategrafDoc}>{t('categraf_doc')}</a> element with an antd Button
component using type='link' and the same onClick handler: <Button type='link'
onClick={openCategrafDoc}>{t('categraf_doc')}</Button>. This will ensure the
element is keyboard-focusable and can be activated using Enter or Space keys.
"套用主机大盘" previously shared the same "any dashboard exists" signal as the data-track "create a dashboard" step, so creating any generic dashboard wrongly marked the host step complete. Detect it independently by board name (内置主机盘命名为「机器…」/含 Host, 对齐 integrations/Linux), reusing the same board-list request — no extra API call. Keep the machine gate so it can't complete without a collector.
- Extract shared OnboardingTracks component reused by the landing checklist and the sidebar popover (was duplicated markup) - Flatten OnboardingProgress badge: drop the render-prop helper and dual return in favor of a single Popover - Unify empty-guide in-group conditions into canManageInGroup in alert rules and dashboard lists (also requires businessGroup.id for the add button, avoiding /add/undefined and silent create no-ops) - Gate the onboarding badge and checklist to OSS builds via !IS_PLUS
Summary by CodeRabbit
Release Notes