Skip to content

Ensure tours only show once#365

Merged
superdav42 merged 1 commit intomainfrom
fix-tours
Mar 9, 2026
Merged

Ensure tours only show once#365
superdav42 merged 1 commit intomainfrom
fix-tours

Conversation

@superdav42
Copy link
Collaborator

@superdav42 superdav42 commented Mar 9, 2026

Summary by CodeRabbit

  • Refactor
    • Improved tour system code organization and consistency in handling tour completion and cancellation events
    • Enhanced settings persistence for tour state tracking

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

The PR refactors the tour initialization and event handling in the JavaScript tours module while adding conditional settings persistence in the PHP tours class. The changes improve code organization through named functions and localized logic without altering external behavior.

Changes

Cohort / File(s) Summary
JavaScript Tour Refactoring
assets/js/tours.js
Introduces named markTourFinished function for finish/cancel event handling; encapsulates per-step URL action logic in a locally defined action_url function; adjusts step processing loop to compute last_step and rebuild buttons arrays; refactors indentation and element access formatting throughout.
PHP Settings Persistence
inc/ui/class-tours.php
Adds conditional runtime check to call save_user_settings() after setting user tour flag if the function exists.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hops and cheers for cleaner tours today!
Named functions guide the visitor's way,
Events and steps now organized so fine,
Settings saved in rhythm and design! ✨

🚥 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 'Ensure tours only show once' clearly and concisely summarizes the main objective of the pull request, which is to prevent tours from displaying multiple times.
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 docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-tours

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

Copy link
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.

🧹 Nitpick comments (3)
assets/js/tours.js (3)

64-72: Consider hoisting action_url outside the step loop.

The action_url function is redefined on every step iteration. Since it doesn't depend on step-specific closures, it can be defined once outside the loop for minor efficiency gains.

♻️ Suggested refactor
+        const action_url = function(url, target = '_blank') {
+            return () => {
+                window.open(url, target);
+            };
+        };
+
         _.each(tour, function(step, step_index) {

             const last_step = (step_index + 1) === tour.length;

-            const action_url = function(url, target = '_blank') {
-
-                return () => {
-
-                    window.open(url, target);
-
-                };
-
-            };
-
             step.buttons = _.isArray(step.buttons) ? step.buttons : [];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/tours.js` around lines 64 - 72, The helper function action_url is
being redefined inside the step loop on every iteration; hoist it out of the
loop by declaring a single top-level function (e.g., function action_url(url,
target = '_blank') { return () => window.open(url, target); }) outside the loop
so all steps reuse the same function, keeping the same signature and behavior
and ensuring no step-specific closures are referenced.

44-58: Marking tour finished on cancel - verify this is intentional UX.

Wiring markTourFinished to both complete and cancel events means users who accidentally dismiss a tour will never see it again. This aligns with the PR title "Ensure tours only show once," but consider if this is the desired UX.

Also, the AJAX call lacks error handling. If the request fails, the tour dismisses client-side but isn't persisted, causing the tour to reappear on next load.

♻️ Optional: Add error handling for failed requests
 const markTourFinished = function() {

     $.ajax({
         url: ajaxurl,
         data: {
             action: 'wu_mark_tour_as_finished',
             tour_id,
             nonce: wu_tours_vars.nonce,
         },
+        error: function() {
+            console.warn('Failed to mark tour as finished:', tour_id);
+        },
     });

 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/tours.js` around lines 44 - 58, The current code binds
markTourFinished to both window[tour_id].on('complete') and .on('cancel') which
will persist-dismiss tours on cancel; decide whether cancel should not mark
finished and if so remove the cancel binding (remove or change
window[tour_id].on('cancel', markTourFinished')). Also add robust AJAX callbacks
inside markTourFinished (use $.ajax success/error or .done/.fail) targeting
action 'wu_mark_tour_as_finished' so failures are handled: on success keep
current behavior, on error surface an error (console/log/toast) and restore or
reopen the tour or retry the request so a failed persistence call does not
incorrectly hide the tour across page loads. Ensure you reference
markTourFinished, window[tour_id] and the AJAX action 'wu_mark_tour_as_finished'
when making edits.

23-39: Fragile DOM traversal pattern - verify Tippy.js API compatibility.

The deep nesting instance.popperChildren.content.children[0].children[0].children is brittle and may break with Shepherd.js or Tippy.js updates. In Tippy.js v6+, the popperChildren property was removed in favor of accessing elements directly via instance.popper.

Consider using more robust selectors:

const content = instance.popper.querySelector('.shepherd-content');
const header = content?.querySelector('.shepherd-header');
const text = content?.querySelector('.shepherd-text');
const footer = content?.querySelector('.shepherd-footer');
Shepherd.js 14.5 popperChildren API Tippy.js
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/tours.js` around lines 23 - 39, The onCreate handler uses a fragile
deep traversal
(instance.popperChildren.content.children[0].children[0].children) that can
break with Tippy/Shepherd changes; update onCreate to reference instance.popper
and use robust querySelector calls (e.g., find elements by '.shepherd-content',
'.shepherd-header', '.shepherd-text', '.shepherd-footer' or other stable class
names), add null/exists guards before calling classList.add, and keep the same
class additions ('wu-p-2', 'wu-pb-0', etc.) so styling behavior is preserved
while avoiding reliance on popperChildren.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@assets/js/tours.js`:
- Around line 64-72: The helper function action_url is being redefined inside
the step loop on every iteration; hoist it out of the loop by declaring a single
top-level function (e.g., function action_url(url, target = '_blank') { return
() => window.open(url, target); }) outside the loop so all steps reuse the same
function, keeping the same signature and behavior and ensuring no step-specific
closures are referenced.
- Around line 44-58: The current code binds markTourFinished to both
window[tour_id].on('complete') and .on('cancel') which will persist-dismiss
tours on cancel; decide whether cancel should not mark finished and if so remove
the cancel binding (remove or change window[tour_id].on('cancel',
markTourFinished')). Also add robust AJAX callbacks inside markTourFinished (use
$.ajax success/error or .done/.fail) targeting action 'wu_mark_tour_as_finished'
so failures are handled: on success keep current behavior, on error surface an
error (console/log/toast) and restore or reopen the tour or retry the request so
a failed persistence call does not incorrectly hide the tour across page loads.
Ensure you reference markTourFinished, window[tour_id] and the AJAX action
'wu_mark_tour_as_finished' when making edits.
- Around line 23-39: The onCreate handler uses a fragile deep traversal
(instance.popperChildren.content.children[0].children[0].children) that can
break with Tippy/Shepherd changes; update onCreate to reference instance.popper
and use robust querySelector calls (e.g., find elements by '.shepherd-content',
'.shepherd-header', '.shepherd-text', '.shepherd-footer' or other stable class
names), add null/exists guards before calling classList.add, and keep the same
class additions ('wu-p-2', 'wu-pb-0', etc.) so styling behavior is preserved
while avoiding reliance on popperChildren.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 49734e21-1003-4112-99f7-6ff264d6ced1

📥 Commits

Reviewing files that changed from the base of the PR and between 18c9c97 and a3e6295.

📒 Files selected for processing (2)
  • assets/js/tours.js
  • inc/ui/class-tours.php

@superdav42 superdav42 merged commit e8372af into main Mar 9, 2026
9 checks passed
@superdav42 superdav42 deleted the fix-tours branch March 9, 2026 23:26
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.

1 participant