💡 Want to learn more? Access more tutorials from the Tutorials page in the main menu or in the Help submenu.
', - onNextClick: () => { - updateProgress(index) - driver.destroy() - }, - onPrevClick: () => { - sendUserToast('Previous is not available for this step', true, [], undefined, 3000) - } - } - } - ] - - return steps - }} -/> diff --git a/frontend/src/lib/components/tutorials/RunsTutorial.svelte b/frontend/src/lib/components/tutorials/RunsTutorial.svelte deleted file mode 100644 index 0b19ac5f0e..0000000000 --- a/frontend/src/lib/components/tutorials/RunsTutorial.svelte +++ /dev/null @@ -1,510 +0,0 @@ - - -💡 Want to learn more? Access more tutorials from the Tutorials page in the main menu or in the Help submenu.
', - side: 'top', - onNextClick: () => { - if (!checkStepComplete(7)) return - updateProgress(index) - driver.destroy() - } - } - } - ] - - return steps - }} -/> diff --git a/frontend/src/lib/components/tutorials/Tutorial.svelte b/frontend/src/lib/components/tutorials/Tutorial.svelte deleted file mode 100644 index fc95141f5c..0000000000 --- a/frontend/src/lib/components/tutorials/Tutorial.svelte +++ /dev/null @@ -1,157 +0,0 @@ - - -{#if tutorial} -
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: - '
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: - '
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/components/tutorials/workspace/WorkspaceOnboardingTutorial.svelte b/frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingTutorial.svelte deleted file mode 100644 index 30307463a1..0000000000 --- a/frontend/src/lib/components/tutorials/workspace/WorkspaceOnboardingTutorial.svelte +++ /dev/null @@ -1,95 +0,0 @@ - - -
Open the New menu to create a script. Scripts turn code into tools. Write in Python, TypeScript, Go, Bash, SQL and more. Run them manually, on schedule, or via webhooks.
', - onNextClick: () => { - driver.moveNext() - } - }, - element: '#create-new-button' - }, - { - popover: { - title: 'Create your first flow', - description: - '
The same New menu lets you create a flow. Flows orchestrate multiple scripts. Chain them together with branching, loops, and error handling to build complex workflows.
', - onNextClick: () => { - driver.moveNext() - } - }, - element: '#create-new-button' - }, - { - popover: { - title: 'Create your first app', - description: - '
And from the New menu you can also create an app. Apps are custom UIs built with drag-and-drop. Combine tables, forms, charts, and buttons that trigger your scripts and flows. That\'s it for the tour!
💡 Want to learn more? Access more tutorials from the Tutorials page in the main menu or in the Help submenu.
', - onNextClick: async () => { - // 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: '#create-new-button' - } - ] - - return steps - }} -/> diff --git a/frontend/src/lib/stores.ts b/frontend/src/lib/stores.ts index ed5bc6f025..2e8658bb4b 100644 --- a/frontend/src/lib/stores.ts +++ b/frontend/src/lib/stores.ts @@ -68,8 +68,6 @@ export function clearWorkspaceFromStorage() { sessionStorage.removeItem('workspace') } -export const tutorialsToDo = writable
`
-- 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