Skip to content

refactor: optimize onboarding - #2138

Merged
jsers merged 11 commits into
mainfrom
optimize-onboarding
Jun 23, 2026
Merged

refactor: optimize onboarding#2138
jsers merged 11 commits into
mainfrom
optimize-onboarding

Conversation

@710leo

@710leo 710leo commented Jun 23, 2026

Copy link
Copy Markdown
Member
image image

Summary by CodeRabbit

Release Notes

  • New Features
    • Added an onboarding progress badge with a clickable popover checklist.
    • Added an onboarding checklist section on the landing page.
    • Improved empty states with guided messaging and contextual actions.
    • Updated quick-start documentation links to open in an in-page drawer.
  • Localization
    • Added onboarding and empty-state copy across English, Japanese, Russian, and Chinese (Simplified/Traditional).
  • Style
    • Refreshed onboarding badge/popover visuals and the landing checklist layout.

710leo added 5 commits June 18, 2026 16:52
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.
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8d96124f-4a1b-42ba-b88b-875f290ed737

📥 Commits

Reviewing files that changed from the base of the PR and between f3e69e2 and f528374.

📒 Files selected for processing (9)
  • src/components/OnboardingProgress/OnboardingTracks.tsx
  • src/components/OnboardingProgress/PopoverContent.tsx
  • src/components/OnboardingProgress/index.tsx
  • src/components/OnboardingProgress/useOnboardingProgress.ts
  • src/components/SideMenu/index.tsx
  • src/pages/alertRules/List/index.tsx
  • src/pages/dashboard/List/index.tsx
  • src/pages/landing/OnboardingChecklist.tsx
  • src/pages/landing/index.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/components/OnboardingProgress/OnboardingTracks.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/components/SideMenu/index.tsx
  • src/pages/alertRules/List/index.tsx
  • src/pages/landing/index.tsx
  • src/components/OnboardingProgress/index.tsx
  • src/pages/dashboard/List/index.tsx

📝 Walkthrough

Walkthrough

Adds a new onboarding guidance system: a reusable EmptyGuide component, an OnboardingProgress sidebar badge with popover checklist, and a landing-page OnboardingChecklist. Empty-state guides are integrated into Hosts, Datasource, Dashboard, and Alert Rules list pages. Progress is detected via parallel API calls in useOnboardingProgress with session-level caching and module-level detection result reuse. Localization strings are added in five languages.

Changes

Onboarding Progress and Empty-State Guidance

Layer / File(s) Summary
Onboarding data model and progress hook
src/components/OnboardingProgress/tracks.ts, src/components/OnboardingProgress/useOnboardingProgress.ts
Defines OnboardingStep/OnboardingTrack interfaces, OnboardingStepKey union, ONBOARDING_TRACKS configuration with two tracks and five steps. useOnboardingProgress hook caches probe results in module-level lastDetect, short-circuits via sessionStorage when complete, runs three API calls in parallel via Promise.all with failure mapping, gates hostDashboard completion based on both machine and dashboard, and returns loaded/total/doneCount/doneMap.
EmptyGuide reusable component
src/components/EmptyGuide/index.tsx
New component wrapping antd Empty with optional title, description, actions, image, and className props, rendering content in a centered flex column with description={null}.
OnboardingProgress sidebar badge and popover
src/components/OnboardingProgress/PopoverContent.tsx, src/components/OnboardingProgress/index.tsx, src/components/OnboardingProgress/style.less
Implements OnboardingPopoverContent with track/step list, done/todo states, and navigation callbacks. Internal ProgressRing SVG computes geometry and percent completion. OnboardingProgressBadge manages collapsed/expanded layouts, Popover state, and closes popover before routing via history.push. Hides when loading or onboarding complete. Full LESS styles added for badge, ring, popover, tracks list, step rows with connector line, done/todo nodes with gradient/border/dot, and hover transitions.
OnboardingTracks shared component
src/components/OnboardingProgress/OnboardingTracks.tsx
Maps ONBOARDING_TRACKS to render per-track UI and per-step buttons with conditional done/todo rendering (including Check icon), localized text via useTranslation('n9e-landing'), and click navigation via onStepClick callback.
Sidebar badge integration
src/components/SideMenu/index.tsx
Conditionally renders OnboardingProgressBadge below SideMenuHeader when sidebar is not hidden and build is not IS_PLUS, passing collapsed and isCustomBg props to match sidebar layout and background mode.
Empty-state guides on list pages
src/pages/hosts/pages/List/List.tsx, src/pages/datasource/components/TableSource/index.tsx, src/pages/datasource/index.tsx, src/pages/dashboard/List/index.tsx, src/pages/alertRules/List/ListNG.tsx, src/pages/alertRules/List/index.tsx
Hosts List replaces Trans/all_no_data with EmptyGuide and openCategrafDoc helper. Datasource TableSource adds onAdd prop with EmptyGuide and conditional Add button, wired to modal via parent. Dashboard adds importData state and Import modal triggered from empty state. Alert Rules ListNG gains emptyGuide prop via locale.emptyText; parent List constructs guide with conditional Import or navigate actions.
Landing page onboarding checklist and documentation
src/pages/landing/OnboardingChecklist.tsx, src/pages/landing/index.tsx, src/pages/landing/landing.data.ts, src/pages/landing/style.less
Adds OnboardingChecklist component (hidden when loading or complete, shows track panels with done/todo navigation). Landing page gains handleOpenDoc callback opening DocumentDrawer in iframe mode, converting quick-start links from target="_blank" to embedded drawer. Second quickStart.ingest link URL updated. LESS styles include two-column tracks grid with 1-column collapse at 1100px, connector lines, done/todo node visuals, and arrow hover reveal.
Localization strings
src/pages/alertRules/locale/*, src/pages/dashboard/locale/*, src/pages/datasource/locale/*, src/pages/hosts/locale/*, src/pages/landing/locale/*
Adds empty_guide blocks to alert rules, dashboard, datasource, and hosts locale files; adds onboarding blocks to landing locale files across zh_CN, zh_HK, en_US, ja_JP, and ru_RU. Updates second quickStart.ingest link text in landing locales.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • n9e/fe#2090: Introduces the landing page route and component that this PR extends with OnboardingChecklist and the embedded doc drawer.

Poem

🐇 A bunny once lost in a brand-new app's maze,
Found checkboxes waiting to guide through the haze.
Deploy, import, configure — each step marks the trail,
A ring in the sidebar won't let progress pale.
With empty-state guides now on every blank screen,
No newbie shall wander where no map has been! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: optimize onboarding' directly and accurately describes the main change—consolidating and optimizing onboarding UI components and logic across the application.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch optimize-onboarding

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/components/OnboardingProgress/useOnboardingProgress.ts (1)

41-41: 📐 Maintainability & Code Quality | 🔵 Trivial

Replace the any[] cast with Array.isArray() runtime guard on line 41.

The code uses (dashboardRes.value as any[]) to access .length, which bypasses TypeScript type checking. Since getBusiGroupsDashboards() 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 any cast, 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

📥 Commits

Reviewing files that changed from the base of the PR and between 94fe9c5 and e6fa3c6.

📒 Files selected for processing (42)
  • src/components/EmptyGuide/index.tsx
  • src/components/OnboardingProgress/PopoverContent.tsx
  • src/components/OnboardingProgress/index.tsx
  • src/components/OnboardingProgress/style.less
  • src/components/OnboardingProgress/tracks.ts
  • src/components/OnboardingProgress/useOnboardingProgress.ts
  • src/components/SideMenu/index.tsx
  • src/pages/alertRules/List/ListNG.tsx
  • src/pages/alertRules/List/index.tsx
  • src/pages/alertRules/locale/en_US.ts
  • src/pages/alertRules/locale/ja_JP.ts
  • src/pages/alertRules/locale/ru_RU.ts
  • src/pages/alertRules/locale/zh_CN.ts
  • src/pages/alertRules/locale/zh_HK.ts
  • src/pages/dashboard/List/index.tsx
  • src/pages/dashboard/locale/en_US.ts
  • src/pages/dashboard/locale/ja_JP.ts
  • src/pages/dashboard/locale/ru_RU.ts
  • src/pages/dashboard/locale/zh_CN.ts
  • src/pages/dashboard/locale/zh_HK.ts
  • src/pages/datasource/components/TableSource/index.tsx
  • src/pages/datasource/index.tsx
  • src/pages/datasource/locale/en_US.ts
  • src/pages/datasource/locale/ja_JP.ts
  • src/pages/datasource/locale/ru_RU.ts
  • src/pages/datasource/locale/zh_CN.ts
  • src/pages/datasource/locale/zh_HK.ts
  • src/pages/hosts/locale/en_US.ts
  • src/pages/hosts/locale/ja_JP.ts
  • src/pages/hosts/locale/ru_RU.ts
  • src/pages/hosts/locale/zh_CN.ts
  • src/pages/hosts/locale/zh_HK.ts
  • src/pages/hosts/pages/List/List.tsx
  • src/pages/landing/OnboardingChecklist.tsx
  • src/pages/landing/index.tsx
  • src/pages/landing/landing.data.ts
  • src/pages/landing/locale/en_US.ts
  • src/pages/landing/locale/ja_JP.ts
  • src/pages/landing/locale/ru_RU.ts
  • src/pages/landing/locale/zh_CN.ts
  • src/pages/landing/locale/zh_HK.ts
  • src/pages/landing/style.less

Comment on lines +59 to +60
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)';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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

Comment on lines +72 to +88
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);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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

Comment on lines +3 to +16
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: '为关键指标设置第一条告警规则' },
},
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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 -20

Repository: 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"
done

Repository: 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 2

Repository: 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" -l

Repository: 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 -5

Repository: 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 -100

Repository: n9e/fe

Length of output: 3432


🏁 Script executed:

#!/bin/bash
# Check Prettier configuration
cat .prettierrc.json

Repository: 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.

Suggested change
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

Comment on lines +1633 to +1637
.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);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

hostDashboard and dashboard share the same signal — possible false "done".

Both steps derive from detect.dashboard, which is true whenever any dashboard exists (from getBusiGroupsDashboards() 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 see hostDashboard marked 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 tradeoff

Re-probing on every route change can fire heavy endpoints repeatedly for new users.

For a user who hasn't completed any step, lastDetect never flips to true, so each pathname change 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

📥 Commits

Reviewing files that changed from the base of the PR and between a9a0b74 and 1cdc595.

📒 Files selected for processing (8)
  • src/components/OnboardingProgress/useOnboardingProgress.ts
  • src/pages/hosts/pages/List/List.tsx
  • src/pages/landing/locale/en_US.ts
  • src/pages/landing/locale/ja_JP.ts
  • src/pages/landing/locale/ru_RU.ts
  • src/pages/landing/locale/zh_CN.ts
  • src/pages/landing/locale/zh_HK.ts
  • src/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

Comment on lines +27 to +33
// 全部完成后写入会话级标记,已上手的用户后续直接短路、不再探测,避免每次加载都拉全量大盘 / 告警
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 };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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 -20

Repository: n9e/fe

Length of output: 313


🏁 Script executed:

#!/bin/bash
# Read the full useOnboardingProgress.ts file
cat -n src/components/OnboardingProgress/useOnboardingProgress.ts

Repository: 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.tsx

Repository: 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.

Comment on lines +391 to +398
actions={
<>
<Button type='primary' onClick={openCategrafDoc}>
{t('empty_guide.deploy_btn')}
</Button>
<a onClick={openCategrafDoc}>{t('categraf_doc')}</a>
</>
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.tsx

Repository: 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.

710leo added 3 commits June 23, 2026 17:14
"套用主机大盘" 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants