Skip to content

fix(onboarding): restore page refresh on Go to Dashboard#1967

Merged
elibosley merged 10 commits intomainfrom
fix/onboarding-dashboard-refresh
Mar 27, 2026
Merged

fix(onboarding): restore page refresh on Go to Dashboard#1967
elibosley merged 10 commits intomainfrom
fix/onboarding-dashboard-refresh

Conversation

@Ajit-Mehrotra
Copy link
Copy Markdown
Contributor

@Ajit-Mehrotra Ajit-Mehrotra commented Mar 26, 2026

Summary

  • Fixes a regression introduced in refactor(onboarding): migrate to Nuxt UI + browser history support #1949 (afe1ae606) where exiting onboarding no longer triggers a page refresh
  • The refactor added session-aware close behavior (manual vs automatic), but this inadvertently skipped the reload for manual onboarding sessions across all close paths
  • Simplifies closeModal and removes dead code left over from the conditional reload logic

Problem

The onboarding refactor introduced !isManualSession gating on the reload flag in multiple close paths:

  1. NEXT_STEPS onComplete ("Go to Dashboard") — passed reload: !isManualSession.value, so manual sessions got no reload
  2. goToNextStep (reaching the last step) — same conditional reload
  3. handleActivationSkip — redundant reimplementation of goToNextStep with the same conditional reload
  4. closeModal() itself — short-circuited for manual sessions via window.history.go(), returning before ever reaching window.location.reload()
  5. handleExitConfirm (X button) and handlePopstate (browser back) — closed without any reload

Since onboarding changes server state (settings, activation, etc.), a refresh is always needed when exiting, regardless of how the modal was opened or dismissed.

Solution

  • closeModal() always reloads — removed the options parameter, conditional branching, and unreachable history.go() fallback. It now unconditionally cleans up and reloads in 4 lines.
  • All close paths use closeModal()handleExitConfirm (X button), handlePopstate (browser back), goToNextStep, and NEXT_STEPS onComplete all go through the same reload path.
  • Removed handleActivationSkip — it was a redundant wrapper around goToNextStep. The ACTIVATE_LICENSE case now relies on baseProps.onComplete which already calls goToNextStep.
  • Removed redundant onComplete override on ACTIVATE_LICENSEbaseProps already defines onComplete as goToNextStep.

Test plan

  • Start onboarding manually from the dashboard, complete all steps, click "Go to Dashboard" → page should fully refresh
  • Start onboarding automatically (first boot), complete all steps, click "Go to Dashboard" → page should fully refresh
  • Close onboarding via X button during a manual session → page should refresh
  • Close onboarding via X button during an automatic session → page should refresh
  • Press browser back button during a manual session to exit onboarding → page should refresh
  • Skip license activation step → should advance to next step normally

Summary by CodeRabbit

  • Bug Fixes

    • Onboarding modal now consistently reloads the page when closed, removing conditional back-navigation to ensure a clean application state after the setup wizard.
    • Activation step no longer overrides its completion handler, restoring default progression through the wizard.
  • Tests

    • Updated onboarding tests to expect a single page reload on completion instead of history back-navigation.

- The onboarding refactor in afe1ae6 (#1949) introduced session-aware
  close behavior that distinguishes "manual" vs "automatic" onboarding
- For manual sessions, closeModal() short-circuited with history.go()
  and the NEXT_STEPS onComplete passed `reload: !isManualSession.value`,
  meaning manual sessions never triggered a page refresh
- This broke the "Go to Dashboard" flow: clicking it should always
  refresh so the dashboard loads with the newly configured state
- Fix: always pass `reload: true` for NEXT_STEPS completion, and
  prioritize the reload path in closeModal() so it executes before
  the history navigation short-circuit
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Caution

Review failed

Pull request was closed or merged during review

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

Review profile: CHILL

Plan: Pro

Run ID: 4a54466e-dda1-41c6-a923-e33cf8afdbaa

📥 Commits

Reviewing files that changed from the base of the PR and between 0379a96 and 6737f27.

📒 Files selected for processing (1)
  • web/src/components/Onboarding/OnboardingModal.vue

Walkthrough

closeModal in OnboardingModal.vue was simplified to take no parameters and always run the same cleanup sequence (onboardingModalStore.closeModal(), cleanup storage, clear history session) followed by window.location.reload(). Conditional history-navigation logic, isProgrammaticHistoryExit, and the ACTIVATE_LICENSE step onComplete override were removed.

Changes

Cohort / File(s) Summary
Onboarding modal logic
web/src/components/Onboarding/OnboardingModal.vue
Removed parameterized closeModal behavior and isProgrammaticHistoryExit branching; unified close/cleanup sequence now always calls window.location.reload() in a try/finally; ACTIVATE_LICENSE onComplete override and handleActivationSkip deleted; popstate now calls closeModal.
Tests updated
web/__test__/components/Onboarding/OnboardingModal.test.ts
Updated test to spy on window.location.reload() and assert onboardingModalStore.closeModal was called; removed assertions about window.history.go and popstate-driven expectations.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant OnboardingModal as OnboardingModal.vue
    participant Store as onboardingModalStore
    participant Storage as OnboardingStorage
    participant Browser as window.location

    User->>OnboardingModal: complete onboarding / trigger close
    OnboardingModal->>Store: onboardingModalStore.closeModal()
    OnboardingModal->>Storage: cleanupOnboardingStorage() / clearHistorySession()
    OnboardingModal->>Browser: reload() (window.location.reload)
    Browser-->>User: page reload
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through code with tiny paws,
One close to rule them, no backtrack laws,
Cleaned the crumbs and cleared the trails,
A gentle reload flaps my ears and sails,
Hop on—onboarding bakes fresh morsels! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: restoring page refresh on the 'Go to Dashboard' action in the onboarding modal, which is the central fix for the regression described in the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/onboarding-dashboard-refresh

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 and usage tips.

- The previous test asserted that manual sessions used history.go()
  instead of reloading when completing the NEXT_STEPS step
- Updated to verify that closeModal is called and window.location.reload
  fires, matching the fixed behavior where "Go to Dashboard" always
  triggers a page refresh regardless of session type
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 70.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.09%. Comparing base (9323b14) to head (6737f27).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
web/src/components/Onboarding/OnboardingModal.vue 70.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1967      +/-   ##
==========================================
- Coverage   52.12%   52.09%   -0.04%     
==========================================
  Files        1031     1031              
  Lines       71589    71573      -16     
  Branches     8102     8093       -9     
==========================================
- Hits        37319    37284      -35     
- Misses      34145    34164      +19     
  Partials      125      125              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ivationSkip

- Remove conditional `!isManualSession` reload gating from all
  completion paths — onboarding changes server state, so a refresh
  is always needed regardless of how the modal was opened
- goToNextStep now always passes `reload: true` when closing at the
  last step, and when no steps are available
- Simplify handleActivationSkip to delegate to goToNextStep since it
  was a redundant reimplementation of the same advance-or-close logic
  and ACTIVATE_LICENSE is never the last step anyway
- The only non-reload close paths remaining are the X button exit
  and browser back navigation, which are cancel/abandon actions
…nd back nav

- handleExitConfirm (X button) was closing the modal without reloading,
  meaning any state changes made during onboarding would not be reflected
- handlePopstate (browser back navigation) had the same issue, directly
  calling the store closeModal instead of the local closeModal with reload
- All close paths now consistently pass reload: true so the page always
  refreshes when exiting onboarding, regardless of how it was dismissed
- Since all callers now always want a reload, remove the options
  parameter and the conditional branching from closeModal
- Remove unreachable history.go() fallback and duplicate cleanup block
- Drop { reload: true } from all call sites since it's now the only
  behavior
- Replace handleActivationSkip with direct goToNextStep reference
  in the ACTIVATE_LICENSE onComplete handler since it was just a
  pass-through wrapper with no additional logic
…TE_LICENSE

- baseProps already defines onComplete as goToNextStep, so the
  explicit override in the ACTIVATE_LICENSE case was unnecessary
@Ajit-Mehrotra Ajit-Mehrotra marked this pull request as ready for review March 26, 2026 21:42
@Ajit-Mehrotra Ajit-Mehrotra self-assigned this Mar 26, 2026
@Ajit-Mehrotra Ajit-Mehrotra requested a review from elibosley March 26, 2026 21:42
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee245d4020

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (options?.reload) {
window.location.reload();
}
window.location.reload();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep cancel close paths from forcing page reload

closeModal now always calls window.location.reload(), and both non-completion paths (handleExitConfirm from the X/Exit flow and handlePopstate when backing out of a manual session) call this helper. That means abandoning onboarding mid-flow now refreshes the whole app instead of just closing the modal, which can drop unrelated in-page state and is inconsistent with the expected cancel behavior; reload should only happen on completion paths.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/components/Onboarding/OnboardingModal.vue`:
- Around line 306-310: The current closeModal function awaits
onboardingModalStore.closeModal() which can reject, causing
cleanupOnboardingStorage(), clearHistorySession(), and window.location.reload()
to be skipped; wrap the cleanup and reload steps in a finally block so they
always run regardless of onboardingModalStore.closeModal() success or failure
(i.e., call onboardingModalStore.closeModal() in try/catch if you want to log
errors, but invoke cleanupOnboardingStorage(), clearHistorySession(), and
window.location.reload() from a finally block) — reference the closeModal
wrapper, onboardingModalStore.closeModal(), cleanupOnboardingStorage(),
clearHistorySession(), and window.location.reload().
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a9e1f83d-ce83-4abe-b5c2-bb681671cc3b

📥 Commits

Reviewing files that changed from the base of the PR and between abad07f and ee245d4.

📒 Files selected for processing (1)
  • web/src/components/Onboarding/OnboardingModal.vue

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/components/Onboarding/OnboardingModal.vue (1)

438-443: ⚠️ Potential issue | 🔴 Critical

isProgrammaticHistoryExit is not defined — build failure.

The variable isProgrammaticHistoryExit is used on lines 439 and 443 but was never declared. This was likely left behind when the history navigation logic was removed. The pipeline confirms the ESLint error.

🐛 Proposed fix: remove orphaned references
 const handlePopstate = async (event: PopStateEvent) => {
-  if (isInternalBootLocked.value && !isProgrammaticHistoryExit.value) {
+  if (isInternalBootLocked.value) {
     window.history.forward();
     return;
   }
-  isProgrammaticHistoryExit.value = false;

   const nextHistoryState = getHistoryState(event.state);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/Onboarding/OnboardingModal.vue` around lines 438 - 443,
The code references an undefined variable isProgrammaticHistoryExit inside the
handlePopstate handler; remove the orphaned references instead of declaring an
unused flag. Edit the handlePopstate function (and any other places referencing
isProgrammaticHistoryExit) to drop the conditional checks and the assignment to
isProgrammaticHistoryExit.value, keeping the existing isInternalBootLocked check
and history.forward() behavior intact so no undefined identifier remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@web/src/components/Onboarding/OnboardingModal.vue`:
- Around line 438-443: The code references an undefined variable
isProgrammaticHistoryExit inside the handlePopstate handler; remove the orphaned
references instead of declaring an unused flag. Edit the handlePopstate function
(and any other places referencing isProgrammaticHistoryExit) to drop the
conditional checks and the assignment to isProgrammaticHistoryExit.value,
keeping the existing isInternalBootLocked check and history.forward() behavior
intact so no undefined identifier remains.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7be4eec4-d88f-4bbb-85c7-901b64adfb54

📥 Commits

Reviewing files that changed from the base of the PR and between ee245d4 and 0379a96.

📒 Files selected for processing (2)
  • web/__test__/components/Onboarding/OnboardingModal.test.ts
  • web/src/components/Onboarding/OnboardingModal.vue
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/test/components/Onboarding/OnboardingModal.test.ts

- If onboardingModalStore.closeModal() rejects (e.g. transient network
  error during refetchOnboarding), cleanup and reload were skipped,
  leaving the user stuck on stale onboarding state
- Wrap in try/finally so cleanupOnboardingStorage, clearHistorySession,
  and window.location.reload always execute regardless of store errors
- isProgrammaticHistoryExit was referenced in handlePopstate but never
  declared, causing a build error
- This flag was originally meant to allow programmatic history.go()
  calls to bypass the internal boot lock, but closeModal no longer
  uses history navigation — it always reloads
- Simplified the guard to just check isInternalBootLocked
@github-actions
Copy link
Copy Markdown
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1967/dynamix.unraid.net.plg

@elibosley elibosley merged commit 29f814b into main Mar 27, 2026
11 of 13 checks passed
@elibosley elibosley deleted the fix/onboarding-dashboard-refresh branch March 27, 2026 15:04
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