Enable configuration of intro flows per level#71424
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds per-level configuration for Lab2 “intro flows” (product tours) by introducing a product_tours level property, wiring it into the level editor UI, and updating client-side tour gating logic to respect the per-level setting.
Changes:
- Add a level editor section (“Product Tour Settings”) that saves selected tours into
level[product_tours]. - Add shared product-tour configuration/gating (
ToursPerLab,isTourEnabledOnLevel) and update Resource Panel + Sketchlab tours to use it. - Add unit tests for the new gating logic and Resource Panel tour behavior.
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| dashboard/app/views/levels/editors/fields/_product_tour_settings.html.haml | New level editor UI section that mounts React editor and passes initial settings/app name via script data. |
| dashboard/app/views/levels/editors/_weblab2.html.haml | Adds the new Product Tour Settings editor section to Web Lab 2 levels. |
| dashboard/app/views/levels/editors/_pythonlab.html.haml | Adds the new Product Tour Settings editor section to Python Lab levels. |
| dashboard/app/models/levels/level.rb | Adds product_tours to serialized properties so it’s permitted and persisted. |
| dashboard/app/controllers/levels_controller.rb | Parses product_tours JSON param into a first-order properties member on save. |
| apps/webpackEntryPoints.js | Registers the new level editor webpack entrypoint. |
| apps/src/sites/studio/pages/levels/editors/fields/_product_tour_settings.js | Mounts the React-based Product Tour Settings editor in levelbuilder. |
| apps/src/lab2/productTours/productToursPerLab.ts | Defines tour IDs/config per lab + the core isTourEnabledOnLevel gating helper. |
| apps/src/lab2/productTours/useResourcePanelShepherdTours.ts | Updates Resource Panel tour gating to depend on per-level productTours. |
| apps/src/lab2/productTours/onboardingTourShepherdSteps.ts | Adds Shepherd steps for the Resource Panel onboarding tour. |
| apps/src/lab2/productTours/validationTourShepherdSteps.ts | Adds Shepherd steps for the Resource Panel validation tour. |
| apps/src/lab2/views/components/Instructions/ResourcePanel/index.tsx | Removes boolean tour props and sources tour eligibility from level properties. |
| apps/src/lab2/types.ts | Adds productTours?: string[] to LevelProperties. |
| apps/src/sketchlab/useSketchlabShepherdTour.ts | Gates Sketchlab tour availability via isTourEnabledOnLevel. |
| apps/src/sketchlab/SketchlabView.tsx | Passes levelProperties.productTours into the Sketchlab tour hook. |
| apps/src/codebridge/InfoPanel/InfoPanel.tsx | Removes now-deleted ResourcePanel tour flag props. |
| apps/test/unit/lab2/productTours/productToursPerLabTest.ts | Unit tests for isTourEnabledOnLevel. |
| apps/test/unit/lab2/productTours/useResourcePanelShepherdToursTest.ts | Unit tests covering Resource Panel tour availability + analytics callbacks. |
| apps/src/lab2/levelEditors/productTourSettings/EditProductTourSettings.tsx | React editor UI for selecting level-triggered tours and writing hidden field payload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
fisher-alice
left a comment
There was a problem hiding this comment.
Nice! Just left a few minor comments.
There was a problem hiding this comment.
Do we rename files and remove 'Shepherd' since you've removed introJS?
There was a problem hiding this comment.
Also, I think we can remove resourcePanelTourHelpers.ts and the corresponding loc strings. (maybe as a follow-up)?
There was a problem hiding this comment.
Yeah I will do that cleanup as a follow-up
| // when the user first reaches a level with the tour enabled. If false, the tour will be triggered the first time | ||
| // the user reaches a lab that has that tour available. | ||
| triggeredByLevel: boolean; | ||
| // Description shown to level editors. Not necesarily if triggeredByLevel is false. |
There was a problem hiding this comment.
Nit: This comment made me pause.
Maybe 'Description shown to level editors if triggeredByLevel is true.' (based on my understanding)
There was a problem hiding this comment.
Oh I have a typo there, it should say "Not necessary if triggeredyByLevel is false". The whole tour isn't seen as an option on the level edit page if triggeredByLevel is false. I'll clarify.
There was a problem hiding this comment.
I think we can remove validationTourHelpers.ts now.
There was a problem hiding this comment.
will do as a follow-up
| tourAvailable: isToolbarReady, | ||
| tourAvailable: | ||
| isToolbarReady && | ||
| isTourEnabledOnLevel( |
There was a problem hiding this comment.
why do we need isTourEnabledOnLevel here?
There was a problem hiding this comment.
The reason I have it here is so the logic for whether a tour is shown or not is entirely based on the object in productToursPerLab. If we changed the object to have sketch lab triggered by level we wouldn't need to update this.
There was a problem hiding this comment.
Could remove sketchlabTourHelpers.ts.
There was a problem hiding this comment.
will do as follow-up
| export enum ProductTour { | ||
| ResourcePanelOnboarding = 'resource_panel_onboarding', | ||
| ResourcePanelValidation = 'resource_panel_validation', | ||
| SketchlabIntro = 'sketchlab_intro', |
There was a problem hiding this comment.
Since productTours directory has this list of all lab2 tours including Sketchlab, would it make sense to move sketchlabShepherdTourSteps to this location?
There was a problem hiding this comment.
I considered that, but since it's specific to sketch lab I think it makes sense to keep in the sketch lab folder.
This allows levelbuilders to set which intro flows are available on a given level. Each lab has a set of intro flows that it can show. Some intro flows will not be available for levelbuilders to trigger, because they will be shown the first time a user encounters them (for example, Sketch Lab onboarding). When an intro flow is available on a level, we will only show it to the user if all other requirements to show it are met; all intro flows will only be shown once per user, per browser, and some flows have additional requirements (such as validation requiring that validation exists on the level).
This PR includes:
productToursPerLab.ts). Additional lab2 intro flows should have a configuration added to this file.useResourcePanelShepherdTours.useResourcePanelShepherdToursandproductToursPerLabPer request from product/curriculum, it is by design that now the onboarding and validation flows will not show up by default. They will need to be turned on by curriculum after this PR goes in.
Note: a lot of lines of this PR are tests!
Editing screenshots
Python Lab
Web Lab 2
Links
Testing story
Tested locally and with unit tests.