From e96da540012fb37154c4d45a64bd8182ae325db7 Mon Sep 17 00:00:00 2001 From: Tristan TR <69242752+tristantr@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:19:30 +0100 Subject: [PATCH] fix: New tutorials (#7427) * Put back banner a new tutorial is available for a user that completed all his tutorials and never skipped all * Create onboarding tutorial for operators in tutorial config file * Add router and steps for onboarding tutorial for operators * Improve onboarding tutorial for operators * Improve the tutorial UX * Refactor * Remove cursor from last step of operator onboarding tutorial * Improve filtering per role * Add Runs page tutorial * Improve Runs page tutorial * Add failed run * Simplify Runs tutorial with job clicks into one unique step * Finish overall structure of Runs tutorial * Improve wordings * Prevent breaking animations by clicking on Next or Previous * Add success and failure logo to step title * Improve wording * Create util function for moving cursor * Nits * Improve wordings * Differentiate successfull and failed jobs steps * Remove delete flows if operator to prevent permission errors * Add comment --- .../lib/components/WorkspaceTutorials.svelte | 5 + .../lib/components/home/TutorialBanner.svelte | 54 +- .../tutorials/FlowBuilderLiveTutorial.svelte | 61 +- .../components/tutorials/RunsTutorial.svelte | 474 ++++++++++++++ .../tutorials/TroubleshootFlowTutorial.svelte | 26 +- .../src/lib/components/tutorials/utils.ts | 136 ++++ ...WorkspaceOnboardingOperatorTutorial.svelte | 141 +++++ frontend/src/lib/tutorialUtils.ts | 5 - frontend/src/lib/tutorials/config.ts | 34 +- frontend/src/lib/tutorials/roleUtils.ts | 8 +- .../src/routes/(root)/(logged)/+page.svelte | 5 + .../(logged)/runs/[...path]/+page.svelte | 20 +- .../(root)/(logged)/tutorials/+page.svelte | 4 +- frontend/static/script-tutorial-operator.png | Bin 0 -> 87054 bytes frontend/tutorial-system-guide.mdc | 598 ++++++++++++++++++ 15 files changed, 1479 insertions(+), 92 deletions(-) create mode 100644 frontend/src/lib/components/tutorials/RunsTutorial.svelte create mode 100644 frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingOperatorTutorial.svelte create mode 100644 frontend/static/script-tutorial-operator.png create mode 100644 frontend/tutorial-system-guide.mdc diff --git a/frontend/src/lib/components/WorkspaceTutorials.svelte b/frontend/src/lib/components/WorkspaceTutorials.svelte index 1eeacbe72f..f2f1bb63b6 100644 --- a/frontend/src/lib/components/WorkspaceTutorials.svelte +++ b/frontend/src/lib/components/WorkspaceTutorials.svelte @@ -1,6 +1,7 @@ + + { + return getTutorialSteps(driver) + }} +/> diff --git a/frontend/src/lib/components/tutorials/TroubleshootFlowTutorial.svelte b/frontend/src/lib/components/tutorials/TroubleshootFlowTutorial.svelte index 6fc53cf046..4fa9909e02 100644 --- a/frontend/src/lib/components/tutorials/TroubleshootFlowTutorial.svelte +++ b/frontend/src/lib/components/tutorials/TroubleshootFlowTutorial.svelte @@ -8,6 +8,7 @@ import { wait, type StateStore } from '$lib/utils' import { sendUserToast } from '$lib/toast' import { updateProgress } from '$lib/tutorialUtils' + import { DELAY_SHORT, DELAY_MEDIUM, DELAY_LONG, createFakeCursor } from './utils' interface Props { index: number @@ -30,11 +31,6 @@ 7: false }) - // Constants for delays - const DELAY_SHORT = 100 - const DELAY_MEDIUM = 300 - const DELAY_LONG = 500 - // Constants for cursor animation const CURSOR_START_OFFSET = -100 const CURSOR_CLICK_SCALE = 0.8 @@ -61,25 +57,13 @@ return true } - // Helper function to create and animate a fake cursor - async function createFakeCursor( + // Helper function to create and animate a fake cursor with start position + async function createFakeCursorWithStart( startElement: HTMLElement | null, endElement: HTMLElement, transitionDuration: number = 1.5 ): Promise { - const fakeCursor = document.createElement('div') - fakeCursor.style.cssText = ` - position: fixed; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: rgba(59, 130, 246, 0.8); - border: 2px solid white; - pointer-events: none; - z-index: 10000; - transition: all ${transitionDuration}s ease-in-out; - ` - document.body.appendChild(fakeCursor) + const fakeCursor = createFakeCursor() const endRect = endElement.getBoundingClientRect() let startX: number, startY: number @@ -122,7 +106,7 @@ transitionDuration: number = 1.5, options?: { usePointerEvents?: boolean } ): Promise { - const fakeCursor = await createFakeCursor(null, element, transitionDuration) + const fakeCursor = await createFakeCursorWithStart(null, element, transitionDuration) await wait(DELAY_MEDIUM) // Animate click (shrink cursor briefly) diff --git a/frontend/src/lib/components/tutorials/utils.ts b/frontend/src/lib/components/tutorials/utils.ts index 1d07c1080c..083e9712dd 100644 --- a/frontend/src/lib/components/tutorials/utils.ts +++ b/frontend/src/lib/components/tutorials/utils.ts @@ -4,6 +4,17 @@ import { emptyApp } from '../apps/editor/appUtils' import type { App } from '../apps/types' import { findGridItem } from '../apps/editor/appUtilsCore' import { isRunnableByName } from '../apps/inputType' +import { wait } from '$lib/utils' + +// Tutorial animation delay constants +export const DELAY_SHORT = 100 +export const DELAY_MEDIUM = 300 +export const DELAY_LONG = 500 +export const DELAY_ANIMATION = 1500 +export const DELAY_ANIMATION_LONG = 2500 +export const DELAY_TYPING = 50 +export const DELAY_CODE_CHAR = 2 +export const DELAY_CODE_NEWLINE = 5 export function setInputBySelector(selector: string, value: string) { const input = document.querySelector(selector) as HTMLInputElement @@ -190,3 +201,128 @@ export function waitForElementLoading( attempts++ }, interval) } + +// Helper function to move cursor to element (for continuous cursor movement in tutorials) +export async function moveCursorToElement( + cursor: HTMLElement, + element: HTMLElement, + duration: number = DELAY_ANIMATION +): Promise { + const rect = element.getBoundingClientRect() + cursor.style.transition = `all ${duration / 1000}s ease-in-out` + cursor.style.left = `${rect.left + rect.width / 2}px` + cursor.style.top = `${rect.top + rect.height / 2}px` + await wait(duration) +} + +// Helper function to create a fake cursor element for tutorial animations +export function createFakeCursor(): HTMLElement { + const fakeCursor = document.createElement('div') + fakeCursor.style.cssText = ` + position: fixed; + width: 20px; + height: 20px; + border-radius: 50%; + background-color: rgba(59, 130, 246, 0.8); + border: 2px solid white; + pointer-events: none; + z-index: 10000; + transition: all 1.5s ease-in-out; + ` + document.body.appendChild(fakeCursor) + return fakeCursor +} + +// Constants for cursor animation +const CURSOR_START_OFFSET = -100 +const CURSOR_CLICK_SCALE = 0.8 + +// Helper function to create and animate a fake cursor with start position +export async function createFakeCursorWithStart( + startElement: HTMLElement | null, + endElement: HTMLElement, + transitionDuration: number = 1.5 +): Promise { + const fakeCursor = createFakeCursor() + + const endRect = endElement.getBoundingClientRect() + let startX: number, startY: number + + if (startElement) { + const startRect = startElement.getBoundingClientRect() + startX = startRect.left + startRect.width / 2 + startY = startRect.top + startRect.height / 2 + } else { + startX = endRect.left + CURSOR_START_OFFSET + startY = endRect.top + endRect.height / 2 + } + + fakeCursor.style.left = `${startX}px` + fakeCursor.style.top = `${startY}px` + + await wait(DELAY_SHORT) + + fakeCursor.style.left = `${endRect.left + endRect.width / 2}px` + fakeCursor.style.top = `${endRect.top + endRect.height / 2}px` + + await wait(transitionDuration * 1000) + + return fakeCursor +} + +// Helper function to animate a fake cursor click +export async function animateFakeCursorClick( + element: HTMLElement, + transitionDuration: number = 1.5, + options?: { usePointerEvents?: boolean; startElement?: HTMLElement | null } +): Promise { + const fakeCursor = await createFakeCursorWithStart( + options?.startElement ?? null, + element, + transitionDuration + ) + await wait(DELAY_MEDIUM) + + // Animate click (shrink cursor briefly) + fakeCursor.style.transform = `scale(${CURSOR_CLICK_SCALE})` + await wait(DELAY_SHORT) + fakeCursor.style.transform = 'scale(1)' + await wait(DELAY_SHORT) + + // Trigger pointer events if needed (flow graph uses pointer events instead of click) + if (options?.usePointerEvents) { + element.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true })) + element.dispatchEvent(new PointerEvent('pointerup', { bubbles: true })) + } + + // Click the element + element.click() + await wait(DELAY_SHORT) + + // Remove fake cursor + fakeCursor.remove() +} + +// Helper function to animate cursor to element and click (for reusing a cursor across multiple clicks) +export async function animateCursorToElementAndClick( + cursor: HTMLElement, + element: HTMLElement, + startOffset: number = CURSOR_START_OFFSET +): Promise { + const rect = element.getBoundingClientRect() + + // Set initial position (off-screen to the left) + cursor.style.left = `${rect.left + startOffset}px` + cursor.style.top = `${rect.top + rect.height / 2}px` + await wait(DELAY_SHORT) + + // Animate to target position + cursor.style.left = `${rect.left + rect.width / 2}px` + cursor.style.top = `${rect.top + rect.height / 2}px` + await wait(DELAY_ANIMATION) + await wait(DELAY_MEDIUM) + + // Click on the element + element.click() + await wait(DELAY_SHORT) +} diff --git a/frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingOperatorTutorial.svelte b/frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingOperatorTutorial.svelte new file mode 100644 index 0000000000..5051719508 --- /dev/null +++ b/frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingOperatorTutorial.svelte @@ -0,0 +1,141 @@ + + + { + const steps: DriveStep[] = [ + { + popover: { + title: 'Welcome to Windmill! 🎉', + description: + "Let's take a quick tour! We'll show you the three main tools you can use: Scripts, Flows, and Apps.", + onNextClick: () => { + // Wait a bit to ensure the page is fully rendered before moving to next step + setTimeout(() => { + // Try to find the script tab button + const scriptsButton = document.querySelector('[data-value="script"]') as HTMLElement | null + + if (scriptsButton) { + driver.moveNext() + } else { + // If we can't find the button, just move to next step anyway + driver.moveNext() + } + }, 100) + } + } + }, + { + popover: { + title: 'Scripts - Run automated tasks', + description: + 'Script Example

Scripts are ready-to-use tasks that do things automatically for you.

You can run scripts whenever you need them - like generating a report, sending notifications, or processing data.

', + onNextClick: async () => { + // Move to the next step (Flows) + setTimeout(() => { + const flowsButton = document.querySelector('[data-value="flow"]') as HTMLElement | null + + if (flowsButton) { + driver.moveNext() + } else { + driver.moveNext() + } + }, 100) + } + }, + element: '[data-value="script"]' + }, + { + popover: { + title: 'Flows - Run step-by-step processes', + description: + 'Flow

Flows are processes that run multiple tasks in order, one after another.

You can start a flow and watch it complete each step automatically - perfect for tasks that have multiple stages.

', + onNextClick: async () => { + // Move to the next step (Apps) + setTimeout(() => { + const appsButton = document.querySelector('[data-value="app"]') as HTMLElement | null + + if (appsButton) { + driver.moveNext() + } else { + driver.moveNext() + } + }, 100) + } + }, + element: '[data-value="flow"]' + }, + { + popover: { + title: 'Apps - Use custom tools', + description: + 'App

Apps are easy-to-use tools with buttons, forms, and displays built just for your team.

You can open an app to work with your data, fill out forms, or trigger tasks - no technical knowledge needed!

', + onNextClick: async () => { + // Move to the next step (cursor animation) + driver.moveNext() + } + }, + element: '[data-value="app"]' + }, + { + popover: { + title: 'Finally, the Menu section', + description: 'Explore available tabs where you can access your history of runs, your scheduled scripts, your tutorials progress etc.

💡 Want to learn more? Access more tutorials from the Tutorials page in the main menu.

', + onNextClick: async () => { + // Find the target button and click it + const targetButton = document.querySelector('[role="menuitem"]') as HTMLElement | null + if (targetButton) { + targetButton.click() + } + + // Wait for menu to open + await wait(DELAY_MEDIUM) + + // Mark tutorial as complete + updateProgress(index) + driver.destroy() + + // Clean up URL parameter if present + if ($page.url.searchParams.has('tutorial')) { + goto(`${base}/`, { replaceState: true }) + } + } + }, + element: '[role="menuitem"]' + } + ] + + return steps + }} +/> diff --git a/frontend/src/lib/tutorialUtils.ts b/frontend/src/lib/tutorialUtils.ts index bd0ce09352..02222138e8 100644 --- a/frontend/src/lib/tutorialUtils.ts +++ b/frontend/src/lib/tutorialUtils.ts @@ -71,11 +71,6 @@ export async function skipAllTodos() { tutorialsToDo.set([]) skippedAll.set(true) - // Dismiss the tutorial banner when all tutorials are skipped - if (typeof window !== 'undefined') { - localStorage.setItem(TUTORIAL_BANNER_DISMISSED_KEY, 'true') - } - await UserService.updateTutorialProgress({ requestBody: { progress: bits, skipped_all: true } }) } diff --git a/frontend/src/lib/tutorials/config.ts b/frontend/src/lib/tutorials/config.ts index 3aa062e346..455c4c50e3 100644 --- a/frontend/src/lib/tutorials/config.ts +++ b/frontend/src/lib/tutorials/config.ts @@ -1,5 +1,5 @@ import type { ComponentType } from 'svelte' -import { Workflow, GraduationCap, Wrench, PlayCircle, Link2 } from 'lucide-svelte' +import { Workflow, GraduationCap, Wrench, PlayCircle, Link2, History } from 'lucide-svelte' import { base } from '$lib/base' import type { Role } from './roleUtils' @@ -43,7 +43,7 @@ export function getTutorialIndex(id: string): number { export const TUTORIALS_CONFIG: Record = { quickstart: { label: 'Quickstart', - roles: ['admin', 'developer'], + roles: ['admin', 'developer', 'operator'], progressBar: true, active: true, tutorials: [ @@ -88,7 +88,35 @@ export const TUTORIALS_CONFIG: Record = { comingSoon: false, roles: ['admin','developer'], order: 3 - } + }, + { + id: 'runs-tutorial', + icon: History, + title: 'Discover your monitoring dashboard', + description: 'Learn how to monitor, filter, and manage your script and flow executions.', + onClick: () => { + window.location.href = `${base}/runs?tutorial=runs-tutorial` + }, + index: 7, + active: true, + comingSoon: false, + roles: ['admin', 'developer','operator'], + order: 4 + }, + { + id: 'workspace-onboarding-operator', + icon: GraduationCap, + title: 'Workspace onboarding', + description: 'Discover the basics of Windmill with a quick tour of the workspace.', + onClick: () => { + window.location.href = `${base}/?tutorial=workspace-onboarding-operator` + }, + index: 6, + active: true, + comingSoon: false, + roles: ['operator'], + order: 1 + }, ] }, app_editor: { diff --git a/frontend/src/lib/tutorials/roleUtils.ts b/frontend/src/lib/tutorials/roleUtils.ts index 0372883784..a727fca8d3 100644 --- a/frontend/src/lib/tutorials/roleUtils.ts +++ b/frontend/src/lib/tutorials/roleUtils.ts @@ -53,12 +53,16 @@ export function hasRoleAccess( /** * Check if a preview role has access based on a roles array. * Used by admins to preview what other roles can see. - * This is a convenience wrapper around hasRoleAccess for preview mode. + * Uses exact role matching - only shows tutorials explicitly marked for the preview role. */ export function hasRoleAccessForPreview( previewRole: Role, roles?: Role[] ): boolean { - return hasRoleAccess(null, roles, previewRole) + // No roles specified = available to everyone + if (!roles || roles.length === 0) return true + + // Exact role match - tutorial must explicitly include the preview role + return roles.includes(previewRole) } diff --git a/frontend/src/routes/(root)/(logged)/+page.svelte b/frontend/src/routes/(root)/(logged)/+page.svelte index c668fc4374..687f5d156d 100644 --- a/frontend/src/routes/(root)/(logged)/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/+page.svelte @@ -110,6 +110,11 @@ setTimeout(() => { workspaceTutorials?.runTutorialById('workspace-onboarding') }, 500) + } else if (tutorialParam === 'workspace-onboarding-operator') { + // Small delay to ensure page is fully loaded + setTimeout(() => { + workspaceTutorials?.runTutorialById('workspace-onboarding-operator') + }, 500) } else if (!$ignoredTutorials.includes(8) && $tutorialsToDo.includes(8)) { // Check if user hasn't completed or ignored the workspace onboarding tutorial // Small delay to ensure page is fully loaded diff --git a/frontend/src/routes/(root)/(logged)/runs/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/runs/[...path]/+page.svelte index 8d6c5dd9fe..85c1d8367e 100644 --- a/frontend/src/routes/(root)/(logged)/runs/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/runs/[...path]/+page.svelte @@ -1,13 +1,31 @@ - {#key perPage} {/key} + + diff --git a/frontend/src/routes/(root)/(logged)/tutorials/+page.svelte b/frontend/src/routes/(root)/(logged)/tutorials/+page.svelte index 95ccbc9cc1..93ebdd4b20 100644 --- a/frontend/src/routes/(root)/(logged)/tutorials/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/tutorials/+page.svelte @@ -54,7 +54,9 @@ // This derived value only recalculates when userStore or selectedPreviewRole changes const accessCheckContext = $derived.by(() => { const user = $userStore - const usePreview = user?.is_admin && selectedPreviewRole !== userEffectiveRole + // Always use preview mode for admins to show role-specific tutorials + // This ensures admins only see tutorials for the selected role + const usePreview = user?.is_admin return { user, usePreview, previewRole: selectedPreviewRole } }) diff --git a/frontend/static/script-tutorial-operator.png b/frontend/static/script-tutorial-operator.png new file mode 100644 index 0000000000000000000000000000000000000000..d64480473c894760d9b4b78c9aa43b2fcfa7533f GIT binary patch literal 87054 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 igXh4z{l9_= = { + quickstart: { + label: 'Quickstart', + roles: ['admin', 'developer', 'operator'], + progressBar: true, + active: true, + tutorials: [ + { + id: 'my-new-tutorial', // Unique identifier + icon: GraduationCap, // Lucide icon component + title: 'My New Tutorial', + description: 'Learn something new', + onClick: () => { + window.location.href = `${base}/?tutorial=my-new-tutorial` + }, + index: 7, // Next available index (1-64) + active: true, + comingSoon: false, + roles: ['developer', 'admin'], // Who can access + order: 7 + } + ] + } +} +``` + +**Important:** +- Choose a unique `index` (1-64) not used by other tutorials +- The `id` must match the tutorial parameter in the URL +- Indexes are used for bitmask progress tracking + +### Step 2: Create Tutorial Component + +**File:** `frontend/src/lib/components/tutorials/workspace/MyNewTutorial.svelte` + +```svelte + + + +``` + +### Step 3: Register in Tutorial Router + +**File:** `frontend/src/lib/components/WorkspaceTutorials.svelte` (or appropriate container) + +```svelte + + + + + + +``` + +### Step 4: Add URL Parameter Handling + +**File:** `frontend/src/routes/(root)/(logged)/+page.svelte` (or appropriate page) + +```svelte + + + +``` + +### Step 5: Test Your Tutorial + +1. Login as a user with the appropriate role +2. Navigate to the tutorials page +3. Click your tutorial card +4. Verify URL changes to `/?tutorial=my-new-tutorial` +5. Verify tutorial starts automatically +6. Step through all steps +7. Verify completion marks tutorial as done +8. Check database: `SELECT * FROM tutorial_progress WHERE email = 'your@email.com'` + +--- + +## Key Components & APIs + +### Tutorial.svelte + +**Core tutorial engine that wraps driver.js** + +**Props:** +- `index: number` - Tutorial index for progress tracking (1-64) +- `getSteps: (driver) => DriveStep[]` - Function returning tutorial steps + +**Exports:** +- `runTutorial(options?: any)` - Start the tutorial + +**Features:** +- Auto-completes tutorial when last step is finished +- Renders custom controls and skip options +- Calls `updateProgress(index)` on completion + +### TutorialRouter.svelte + +**Manages multiple tutorial instances** + +**Usage:** +```svelte + + + + +``` + +**Exports:** +- `runTutorialById(id: string, options?: any)` - Start tutorial by ID + +**Features:** +- Maintains Map of tutorial instances +- Routes calls to correct tutorial component +- Handles tutorial not found errors + +### DriveStep Interface + +**TypeScript interface for tutorial steps** + +```typescript +interface DriveStep { + element?: string // CSS selector to highlight + popover?: { + title: string + description: string // Supports HTML + onNextClick?: (element, step, context) => void + onPrevClick?: (element, step, context) => void + } +} +``` + +**Tips:** +- Omit `element` for non-highlighted steps (like welcome/completion) +- Use HTML in `description` for images: `` +- Use callbacks for custom navigation logic + +--- + +## Progress Tracking System + +### Bitmask System + +Tutorials use a 64-bit bitmask where each bit represents one tutorial's completion status: + +``` +Bit 0: Tutorial with index 0 (unused, reserve) +Bit 1: workspace-onboarding +Bit 2: flow-live-tutorial +Bit 3: troubleshoot-flow +Bit 4: backgroundrunnables +Bit 5: connection +Bit 6: workspace-onboarding-operator +... +Bit 63: Maximum possible tutorial +``` + +### Key Functions (tutorialUtils.ts) + +```typescript +// Mark tutorial as complete +await updateProgress(tutorialIndex: number) + +// Sync progress from backend +await syncTutorialsTodos() + +// Skip all tutorials +await skipAllTodos() + +// Reset all progress +await resetAllTodos() + +// Skip specific tutorials +await skipTutorialsByIndexes(indexes: number[]) + +// Complete specific tutorial +await completeTutorialByIndex(index: number) +``` + +### Backend Integration + +**Table:** `tutorial_progress` +```sql +CREATE TABLE tutorial_progress ( + email VARCHAR PRIMARY KEY, + progress BIT(64) +); +``` + +**API Endpoint:** `POST /api/users/tutorial_progress` +```typescript +// Request body +{ + "index": 7, // Tutorial index to mark complete +} +``` + +--- + +## Role-Based Access + +### Available Roles + +```typescript +type Role = 'admin' | 'developer' | 'operator' +``` + +### Role Hierarchy + +- **Admin**: Full access, can see all tutorials +- **Developer**: Standard developer tutorials +- **Operator**: Limited to operator-specific tutorials + +### Key Functions (roleUtils.ts) + +```typescript +// Get current user's role +const role = getUserEffectiveRole(user) + +// Check if user can access tutorial +const canAccess = hasRoleAccess(userRole, tutorialRoles) +``` + +### Setting Role Requirements + +In `config.ts`: + +```typescript +{ + id: 'operator-only-tutorial', + roles: ['operator'], // Only operators see this + // ... +} + +{ + id: 'admin-dev-tutorial', + roles: ['admin', 'developer'], // Admins and developers see this + // ... +} + +{ + id: 'everyone-tutorial', + roles: ['admin', 'developer', 'operator'], // Everyone sees this + // ... +} +``` + +--- + +## Testing & Debugging + +### Testing Checklist + +- [ ] Tutorial appears in correct tab/category +- [ ] Tutorial only visible to correct roles +- [ ] Clicking tutorial navigates to correct URL with tutorial parameter +- [ ] Tutorial auto-starts on page load with parameter +- [ ] All steps highlight correct elements +- [ ] Navigation controls work (prev/next) +- [ ] Skip options work correctly +- [ ] Completion marks tutorial as done in database +- [ ] Banner updates to reflect completion +- [ ] Tutorial doesn't auto-start after completion + +### Common Issues + +**Tutorial doesn't auto-start:** +- Check URL parameter matches tutorial ID in config +- Verify `onMount()` logic in page component +- Ensure tutorial component is registered in router + +**Element not highlighting:** +- Verify CSS selector is correct +- Check if element exists when tutorial runs +- Try using more specific selectors or IDs + +**Progress not saving:** +- Check tutorial index is unique and correctly passed +- Verify `updateProgress()` is called on final step +- Check network tab for API call to `/api/users/tutorial_progress` +- Inspect database `tutorial_progress` table + +**Wrong users see tutorial:** +- Verify `roles` array in config +- Check `getUserEffectiveRole()` returns correct role +- Ensure role filtering logic in tutorial list component + +### Debugging Tools + +**Browser Console:** +```javascript +// Check current tutorials to do +console.log($tutorialsToDo) + +// Check if tutorial is skipped +console.log($skippedAll) + +// Get user role +import { getUserEffectiveRole } from '$lib/tutorials/roleUtils' +console.log(getUserEffectiveRole($workspaceStore?.operator, $userStore)) +``` + +**Database Queries:** +```sql +-- Check user's tutorial progress +SELECT email, progress::text FROM tutorial_progress WHERE email = 'user@example.com'; + +-- Reset user's progress (testing) +UPDATE tutorial_progress SET progress = B'0' WHERE email = 'user@example.com'; + +-- See all tutorials and their completion +SELECT + email, + (progress & (1::bit(64) << 1))::int AS workspace_onboarding, + (progress & (1::bit(64) << 2))::int AS flow_live_tutorial, + (progress & (1::bit(64) << 3))::int AS troubleshoot_flow +FROM tutorial_progress; +``` + +--- + +## Best Practices + +### Tutorial Design + +1. **Keep It Short**: 4-7 steps is ideal +2. **Clear Objectives**: State what users will learn upfront +3. **Highlight Key Elements**: Focus on essential features +4. **Use Images**: Visual aids help comprehension +5. **End with Encouragement**: Congratulate users on completion + +### Technical Best Practices + +1. **Unique Indexes**: Always use unique index numbers (1-64) +2. **Stable Selectors**: Use IDs or specific classes for element highlighting +3. **Error Handling**: Wrap `updateProgress()` in try-catch +4. **Role Testing**: Test with all relevant user roles +5. **Mobile Friendly**: Ensure tutorials work on different screen sizes + +### Code Organization + +1. **Group by Context**: Workspace, flow, app tutorials in separate folders +2. **Consistent Naming**: `[Feature]Tutorial.svelte` convention +3. **Reusable Steps**: Extract common step patterns to utilities +4. **Document Complex Logic**: Add comments for non-obvious step behaviors + +--- + +## Quick Reference + +### Creating a New Tutorial (Checklist) + +- [ ] Step 1: Add to `config.ts` with unique ID and index +- [ ] Step 2: Create component in appropriate folder +- [ ] Step 3: Register in tutorial router (WorkspaceTutorials, etc.) +- [ ] Step 4: Add URL parameter handling in page component +- [ ] Step 5: Test with appropriate user role +- [ ] Step 6: Verify progress tracking in database + +### File Paths (Quick Copy) + +``` +# Config +frontend/src/lib/tutorials/config.ts + +# Tutorial Containers +frontend/src/lib/components/WorkspaceTutorials.svelte +frontend/src/lib/components/FlowTutorials.svelte +frontend/src/lib/components/AppTutorials.svelte + +# Tutorial Components +frontend/src/lib/components/tutorials/Tutorial.svelte +frontend/src/lib/components/tutorials/TutorialRouter.svelte +frontend/src/lib/components/tutorials/workspace/[YourTutorial].svelte + +# Page Integration +frontend/src/routes/(root)/(logged)/+page.svelte + +# Utilities +frontend/src/lib/tutorialUtils.ts +frontend/src/lib/tutorials/roleUtils.ts +``` + +--- + +## Additional Resources + +- **Driver.js Documentation**: https://driverjs.com/docs/ +- **Svelte Tutorial System Examples**: See existing tutorials in `frontend/src/lib/components/tutorials/` +- **Database Schema**: See `backend/summarized_schema.txt` for `tutorial_progress` table details