Add optional built-in guided tour to webgl viewers#660
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces an optional guided-tour feature to the pycortex webgl viewer, allowing users to enable a dataset-agnostic stepper via cortex.webgl.make_static(tour=True). It adds the necessary frontend assets (CSS and JS), integrates the tour initialization into mriview.js, updates the HTML template, and adds corresponding unit tests. One critical issue was identified: rendering the template via cortex.webgl.show() will crash with a NameError because the tour variable is not defined in that context. It is recommended to wrap the tour conditional block in the template with a try/except NameError block to ensure backward compatibility.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| {% if tour %} | ||
| <script type='text/javascript' src="resources/js/tour.js"></script> | ||
| <link rel="stylesheet" href="resources/css/tour.css" type='text/css' /> | ||
| {% end %} |
There was a problem hiding this comment.
Rendering this template via cortex.webgl.show() (which uses mixer.html extending template.html) will crash with a NameError: name 'tour' is not defined because tour is not passed to html.generate() in show()'s MixerHandler.
To prevent this crash and ensure backward compatibility with other viewer entry points, wrap the tour conditional block in a try/except NameError block. This is a clean, template-level solution that avoids breaking cortex.webgl.show().
{% try %}
{% if tour %}
<script type='text/javascript' src="resources/js/tour.js"></script>
<link rel="stylesheet" href="resources/css/tour.css" type='text/css' />
{% end %}
{% except NameError %}
{% end %}
Summary
Adds an optional, built-in guided tour to the webgl viewers, enabled with a single argument:
Today, every gallantlab viewer that has a tour hand-carries its own copy of a
Tourclass, markup, and CSS inside a custommake_statictemplate. Those copies also share a show/hide bug: the oldshowhide()toggled only the title/content/buttons, leaving the stepper dots and a translucent strip stranded on screen. This PR promotes a cleaned tour into pycortex so viewers can stop copy-pasting it, and fixes that bug in the process.The built-in tour is a generic stub — a few dataset-agnostic steps (navigating,
f/i/rsurface keys,hfor shortcuts). It says nothing viewer-specific.What it does
make_static(..., tour=True)bakes the tour in; defaulttour=Falseemits nothing (existing viewers are unaffected).okey (twas already taken by surface morph). Theoshortcut is listed in thehhelp menu.Implementation
Mirrors the existing
leapmotion/python_interfaceoptional-feature pattern:cortex/webgl/resources/js/tour.js(new) — a self-containedTourclass that injects its own markup; per-stepview/callhooks are optional (the stub uses neither);toggle()shows/hides the whole box (the fix).cortex/webgl/resources/css/tour.css(new) — the tour styles.cortex/webgl/template.html— a{% if tour %}block that includes the two assets, beside the existing{% if leapmotion %}block.cortex/webgl/view.py— atour=Falseargument onmake_static; setsviewopts["tour"]and passestour=to the template renderer.cortex/webgl/resources/js/mriview.js— whenviewopts.touris set, constructs the tour and registers theotoggle.Tests
cortex/tests/test_webgl_tour.pyrenders the base template withtour=True/tour=False(via the sameFallbackLoadermachinerymake_staticuses, no subject fixture needed) and asserts the tour assets are included only when enabled.The
Tourruntime behavior (box injection, stepping, theofull-toggle, and the minimize link) was verified against jsdom + jQuery locally.🤖 Generated with Claude Code