mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 07:12:54 +01:00
Started tasks to migrate runtime to React 19. Added phase 3 projects
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
# DASH-001: Tabbed Navigation System
|
||||
|
||||
## Overview
|
||||
|
||||
Replace the current single-view dashboard with a proper tabbed interface. This is the foundation task that enables all other dashboard improvements.
|
||||
|
||||
## Context
|
||||
|
||||
The current Noodl editor dashboard (`projectsview.ts`) uses a basic pane-switching mechanism with jQuery. A new launcher is being developed in `packages/noodl-core-ui/src/preview/launcher/` using React, which already has a sidebar-based navigation but needs proper tab support for the main content area.
|
||||
|
||||
This task focuses on the **new React-based launcher** only. The old jQuery launcher will be deprecated.
|
||||
|
||||
## Current State
|
||||
|
||||
### Existing New Launcher Structure
|
||||
```
|
||||
packages/noodl-core-ui/src/preview/launcher/
|
||||
├── Launcher/
|
||||
│ ├── Launcher.tsx # Main component with PAGES array
|
||||
│ ├── components/
|
||||
│ │ ├── LauncherSidebar/ # Left navigation
|
||||
│ │ ├── LauncherPage/ # Page wrapper
|
||||
│ │ ├── LauncherProjectCard/
|
||||
│ │ └── LauncherSearchBar/
|
||||
│ └── views/
|
||||
│ ├── Projects.tsx # Current projects view
|
||||
│ └── LearningCenter.tsx # Empty learning view
|
||||
└── template/
|
||||
└── LauncherApp/ # App shell template
|
||||
```
|
||||
|
||||
### Current Page Definition
|
||||
```typescript
|
||||
// In Launcher.tsx
|
||||
export enum LauncherPageId {
|
||||
LocalProjects,
|
||||
LearningCenter
|
||||
}
|
||||
|
||||
export const PAGES: LauncherPageMetaData[] = [
|
||||
{ id: LauncherPageId.LocalProjects, displayName: 'Recent Projects', icon: IconName.CircleDot },
|
||||
{ id: LauncherPageId.LearningCenter, displayName: 'Learn', icon: IconName.Rocket }
|
||||
];
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
1. **Tab Bar Component**
|
||||
- Horizontal tab bar at the top of the main content area
|
||||
- Visual indicator for active tab
|
||||
- Smooth transition when switching tabs
|
||||
- Keyboard navigation support (arrow keys, Enter)
|
||||
|
||||
2. **Tab Configuration**
|
||||
- Projects tab (default, opens first)
|
||||
- Learn tab (tutorials, guides)
|
||||
- Templates tab (project starters)
|
||||
- Extensible for future tabs (Marketplace, Settings)
|
||||
|
||||
3. **State Persistence**
|
||||
- Remember last active tab across sessions
|
||||
- Store in localStorage or electron-store
|
||||
|
||||
4. **URL/Deep Linking (Optional)**
|
||||
- Support for `noodl://dashboard/projects` style deep links
|
||||
- Query params for tab state
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- Tab switching should feel instant (<100ms)
|
||||
- No layout shift when switching tabs
|
||||
- Accessible (WCAG 2.1 AA compliant)
|
||||
- Consistent with existing noodl-core-ui design system
|
||||
|
||||
## Technical Approach
|
||||
|
||||
### 1. Create Tab Bar Component
|
||||
|
||||
Create a new component in `noodl-core-ui` that can be reused:
|
||||
|
||||
```
|
||||
packages/noodl-core-ui/src/components/layout/TabBar/
|
||||
├── TabBar.tsx
|
||||
├── TabBar.module.scss
|
||||
├── TabBar.stories.tsx
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
### 2. Update Launcher Structure
|
||||
|
||||
```typescript
|
||||
// New page structure
|
||||
export enum LauncherPageId {
|
||||
Projects = 'projects',
|
||||
Learn = 'learn',
|
||||
Templates = 'templates'
|
||||
}
|
||||
|
||||
export interface LauncherTab {
|
||||
id: LauncherPageId;
|
||||
label: string;
|
||||
icon?: IconName;
|
||||
component: React.ComponentType;
|
||||
}
|
||||
|
||||
export const LAUNCHER_TABS: LauncherTab[] = [
|
||||
{ id: LauncherPageId.Projects, label: 'Projects', icon: IconName.Folder, component: Projects },
|
||||
{ id: LauncherPageId.Learn, label: 'Learn', icon: IconName.Book, component: LearningCenter },
|
||||
{ id: LauncherPageId.Templates, label: 'Templates', icon: IconName.Components, component: Templates }
|
||||
];
|
||||
```
|
||||
|
||||
### 3. State Management
|
||||
|
||||
Use React context for tab state:
|
||||
|
||||
```typescript
|
||||
// LauncherContext.tsx
|
||||
interface LauncherContextValue {
|
||||
activeTab: LauncherPageId;
|
||||
setActiveTab: (tab: LauncherPageId) => void;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Persistence Hook
|
||||
|
||||
```typescript
|
||||
// usePersistentTab.ts
|
||||
function usePersistentTab(key: string, defaultTab: LauncherPageId) {
|
||||
// Load from localStorage on mount
|
||||
// Save to localStorage on change
|
||||
}
|
||||
```
|
||||
|
||||
## Files to Create
|
||||
|
||||
1. `packages/noodl-core-ui/src/components/layout/TabBar/TabBar.tsx`
|
||||
2. `packages/noodl-core-ui/src/components/layout/TabBar/TabBar.module.scss`
|
||||
3. `packages/noodl-core-ui/src/components/layout/TabBar/TabBar.stories.tsx`
|
||||
4. `packages/noodl-core-ui/src/components/layout/TabBar/index.ts`
|
||||
5. `packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx`
|
||||
6. `packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/usePersistentTab.ts`
|
||||
7. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/Templates.tsx`
|
||||
|
||||
## Files to Modify
|
||||
|
||||
1. `packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx`
|
||||
- Import and use TabBar
|
||||
- Implement tab switching logic
|
||||
- Wrap with LauncherContext
|
||||
|
||||
2. `packages/noodl-core-ui/src/components/layout/index.ts`
|
||||
- Export TabBar component
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: TabBar Component
|
||||
1. Create TabBar component with basic functionality
|
||||
2. Add styling consistent with noodl-core-ui
|
||||
3. Write Storybook stories for testing
|
||||
4. Add keyboard navigation
|
||||
|
||||
### Phase 2: Launcher Integration
|
||||
1. Create LauncherContext
|
||||
2. Create usePersistentTab hook
|
||||
3. Integrate TabBar into Launcher.tsx
|
||||
4. Create empty Templates view
|
||||
|
||||
### Phase 3: Polish
|
||||
1. Add tab transition animations
|
||||
2. Test accessibility
|
||||
3. Add deep link support (if time permits)
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Tabs render correctly
|
||||
- [ ] Clicking tab switches content
|
||||
- [ ] Active tab is visually indicated
|
||||
- [ ] Keyboard navigation works (Tab, Arrow keys, Enter)
|
||||
- [ ] Tab state persists after closing/reopening
|
||||
- [ ] No layout shift on tab switch
|
||||
- [ ] Works at different viewport sizes
|
||||
- [ ] Screen reader announces tab changes
|
||||
|
||||
## Design Reference
|
||||
|
||||
The tab bar should follow the existing Tabs component style in noodl-core-ui but be optimized for the launcher context (larger, more prominent).
|
||||
|
||||
See: `packages/noodl-core-ui/src/components/layout/Tabs/`
|
||||
|
||||
## Dependencies
|
||||
|
||||
- None (this is a foundation task)
|
||||
|
||||
## Blocked By
|
||||
|
||||
- None
|
||||
|
||||
## Blocks
|
||||
|
||||
- DASH-002 (Project List Redesign)
|
||||
- DASH-003 (Project Organization)
|
||||
- DASH-004 (Tutorial Section Redesign)
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- Component creation: 2-3 hours
|
||||
- Launcher integration: 2-3 hours
|
||||
- Polish and testing: 1-2 hours
|
||||
- **Total: 5-8 hours**
|
||||
|
||||
## Success Criteria
|
||||
|
||||
1. User can switch between Projects, Learn, and Templates tabs
|
||||
2. Tab state persists across sessions
|
||||
3. Component is reusable for other contexts
|
||||
4. Passes accessibility audit
|
||||
5. Matches existing design system aesthetics
|
||||
@@ -0,0 +1,292 @@
|
||||
# DASH-002: Project List Redesign
|
||||
|
||||
## Overview
|
||||
|
||||
Transform the project list from a thumbnail grid into a more functional table/list view optimized for users with many projects. Add sorting, better information density, and optional view modes.
|
||||
|
||||
## Context
|
||||
|
||||
The current dashboard shows projects as large cards with auto-generated thumbnails. This works for users with a few projects but becomes unwieldy with many projects. The thumbnails add visual noise without providing much value.
|
||||
|
||||
The new launcher in `noodl-core-ui/src/preview/launcher/` already has the beginnings of a table layout with columns for Name, Version Control, and Contributors.
|
||||
|
||||
## Current State
|
||||
|
||||
### Existing LauncherProjectCard
|
||||
```typescript
|
||||
// From LauncherProjectCard.tsx
|
||||
export interface LauncherProjectData {
|
||||
id: string;
|
||||
title: string;
|
||||
cloudSyncMeta: {
|
||||
type: CloudSyncType;
|
||||
source?: string;
|
||||
};
|
||||
localPath: string;
|
||||
lastOpened: string;
|
||||
pullAmount?: number;
|
||||
pushAmount?: number;
|
||||
uncommittedChangesAmount?: number;
|
||||
imageSrc: string;
|
||||
contributors?: UserBadgeProps[];
|
||||
}
|
||||
```
|
||||
|
||||
### Current Layout (Projects.tsx)
|
||||
- Table header with Name, Version control, Contributors columns
|
||||
- Cards with thumbnail images
|
||||
- Basic search functionality via LauncherSearchBar
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
1. **List View (Primary)**
|
||||
- Compact row-based layout
|
||||
- Columns: Name, Last Modified, Git Status, Local Path (truncated)
|
||||
- Row hover state with quick actions
|
||||
- Sortable columns (click header to sort)
|
||||
- Resizable columns (stretch goal)
|
||||
|
||||
2. **Grid View (Secondary)**
|
||||
- Card-based layout for visual preference
|
||||
- Smaller cards than current (2-3x more per row)
|
||||
- Optional thumbnails (can be disabled)
|
||||
- View toggle in toolbar
|
||||
|
||||
3. **Sorting**
|
||||
- Sort by Name (A-Z, Z-A)
|
||||
- Sort by Last Modified (newest, oldest)
|
||||
- Sort by Git Status (synced first, needs attention first)
|
||||
- Persist sort preference
|
||||
|
||||
4. **Information Display**
|
||||
- Project name (primary)
|
||||
- Last modified timestamp (relative: "2 hours ago")
|
||||
- Git status indicator (icon + tooltip)
|
||||
- Local path (truncated with tooltip for full path)
|
||||
- Quick action buttons on hover (Open, Folder, Settings, Delete)
|
||||
|
||||
5. **Empty State**
|
||||
- Friendly message when no projects exist
|
||||
- Call-to-action to create new project or import
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- Handle 100+ projects smoothly (virtual scrolling if needed)
|
||||
- Row click opens project
|
||||
- Right-click context menu
|
||||
- Responsive to window resize
|
||||
|
||||
## Technical Approach
|
||||
|
||||
### 1. Data Layer
|
||||
|
||||
Create a hook for project data with sorting:
|
||||
|
||||
```typescript
|
||||
// useProjectList.ts
|
||||
interface UseProjectListOptions {
|
||||
sortField: 'name' | 'lastModified' | 'gitStatus';
|
||||
sortDirection: 'asc' | 'desc';
|
||||
filter?: string;
|
||||
}
|
||||
|
||||
interface UseProjectListReturn {
|
||||
projects: LauncherProjectData[];
|
||||
isLoading: boolean;
|
||||
sortField: string;
|
||||
sortDirection: string;
|
||||
setSorting: (field: string, direction: string) => void;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. List View Component
|
||||
|
||||
```
|
||||
packages/noodl-core-ui/src/preview/launcher/Launcher/components/
|
||||
├── ProjectList/
|
||||
│ ├── ProjectList.tsx # Main list component
|
||||
│ ├── ProjectListRow.tsx # Individual row
|
||||
│ ├── ProjectListHeader.tsx # Sortable header
|
||||
│ ├── ProjectList.module.scss
|
||||
│ └── index.ts
|
||||
```
|
||||
|
||||
### 3. View Mode Toggle
|
||||
|
||||
```typescript
|
||||
// ViewModeToggle.tsx
|
||||
export enum ViewMode {
|
||||
List = 'list',
|
||||
Grid = 'grid'
|
||||
}
|
||||
|
||||
interface ViewModeToggleProps {
|
||||
mode: ViewMode;
|
||||
onChange: (mode: ViewMode) => void;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Git Status Display
|
||||
|
||||
```typescript
|
||||
// GitStatusBadge.tsx
|
||||
export enum GitStatusType {
|
||||
NotInitialized = 'not-initialized',
|
||||
LocalOnly = 'local-only',
|
||||
Synced = 'synced',
|
||||
Ahead = 'ahead', // Have local commits to push
|
||||
Behind = 'behind', // Have remote commits to pull
|
||||
Diverged = 'diverged', // Both ahead and behind
|
||||
Uncommitted = 'uncommitted'
|
||||
}
|
||||
|
||||
interface GitStatusBadgeProps {
|
||||
status: GitStatusType;
|
||||
details?: {
|
||||
ahead?: number;
|
||||
behind?: number;
|
||||
uncommitted?: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Files to Create
|
||||
|
||||
1. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectList.tsx`
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListRow.tsx`
|
||||
3. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListHeader.tsx`
|
||||
4. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectList.module.scss`
|
||||
5. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/index.ts`
|
||||
6. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ViewModeToggle/ViewModeToggle.tsx`
|
||||
7. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/GitStatusBadge/GitStatusBadge.tsx`
|
||||
8. `packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useProjectList.ts`
|
||||
9. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/EmptyProjectsState/EmptyProjectsState.tsx`
|
||||
|
||||
## Files to Modify
|
||||
|
||||
1. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/Projects.tsx`
|
||||
- Replace current layout with ProjectList component
|
||||
- Add view mode toggle
|
||||
- Wire up sorting
|
||||
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/LauncherProjectCard/LauncherProjectCard.tsx`
|
||||
- Refactor for grid view (smaller)
|
||||
- Make thumbnail optional
|
||||
|
||||
3. `packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx`
|
||||
- Update mock data if needed
|
||||
- Add view mode to context
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Core List View
|
||||
1. Create ProjectListHeader with sortable columns
|
||||
2. Create ProjectListRow with project info
|
||||
3. Create ProjectList combining header and rows
|
||||
4. Add basic sorting logic
|
||||
|
||||
### Phase 2: Git Status Display
|
||||
1. Create GitStatusBadge component
|
||||
2. Define status types and icons
|
||||
3. Add tooltips with details
|
||||
|
||||
### Phase 3: View Modes
|
||||
1. Create ViewModeToggle component
|
||||
2. Refactor LauncherProjectCard for grid mode
|
||||
3. Add view mode to Projects view
|
||||
4. Persist preference
|
||||
|
||||
### Phase 4: Polish
|
||||
1. Add empty state
|
||||
2. Add hover actions
|
||||
3. Implement virtual scrolling (if needed)
|
||||
4. Test with large project counts
|
||||
|
||||
## Component Specifications
|
||||
|
||||
### ProjectListHeader
|
||||
|
||||
| Column | Width | Sortable | Content |
|
||||
|--------|-------|----------|---------|
|
||||
| Name | 40% | Yes | Project name |
|
||||
| Last Modified | 20% | Yes | Relative timestamp |
|
||||
| Git Status | 15% | Yes | Status badge |
|
||||
| Path | 25% | No | Truncated local path |
|
||||
|
||||
### ProjectListRow
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ 📁 My Project Name 2 hours ago ⚡ Ahead (3) ~/dev/... │
|
||||
│ [hover: Open 📂 ⚙️ 🗑️] │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### GitStatusBadge Icons
|
||||
|
||||
| Status | Icon | Color | Tooltip |
|
||||
|--------|------|-------|---------|
|
||||
| not-initialized | ⚪ | Gray | "No version control" |
|
||||
| local-only | 💾 | Yellow | "Local git only, not synced" |
|
||||
| synced | ✅ | Green | "Up to date with remote" |
|
||||
| ahead | ⬆️ | Blue | "3 commits to push" |
|
||||
| behind | ⬇️ | Orange | "5 commits to pull" |
|
||||
| diverged | ⚠️ | Red | "3 ahead, 5 behind" |
|
||||
| uncommitted | ● | Yellow | "Uncommitted changes" |
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] List renders with mock data
|
||||
- [ ] Clicking row opens project (or shows FIXME alert)
|
||||
- [ ] Sorting by each column works
|
||||
- [ ] Sort direction toggles on repeated click
|
||||
- [ ] Sort preference persists
|
||||
- [ ] View mode toggle switches layouts
|
||||
- [ ] View mode preference persists
|
||||
- [ ] Git status badges display correctly
|
||||
- [ ] Tooltips show on hover
|
||||
- [ ] Right-click shows context menu
|
||||
- [ ] Empty state shows when no projects
|
||||
- [ ] Search filters projects correctly
|
||||
- [ ] Performance acceptable with 100+ mock projects
|
||||
|
||||
## Dependencies
|
||||
|
||||
- DASH-001 (Tabbed Navigation System) - for launcher context
|
||||
|
||||
## Blocked By
|
||||
|
||||
- DASH-001
|
||||
|
||||
## Blocks
|
||||
|
||||
- DASH-003 (needs list infrastructure for folder/tag filtering)
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- ProjectList components: 3-4 hours
|
||||
- GitStatusBadge: 1-2 hours
|
||||
- View mode toggle: 1-2 hours
|
||||
- Sorting & persistence: 2-3 hours
|
||||
- Polish & testing: 2-3 hours
|
||||
- **Total: 9-14 hours**
|
||||
|
||||
## Success Criteria
|
||||
|
||||
1. Projects display in a compact, sortable list
|
||||
2. Git status is immediately visible
|
||||
3. Users can switch to grid view if preferred
|
||||
4. Sorting and view preferences persist
|
||||
5. Empty state guides new users
|
||||
6. Context menu provides quick actions
|
||||
|
||||
## Design Notes
|
||||
|
||||
The list view should feel similar to:
|
||||
- VS Code's file explorer
|
||||
- macOS Finder list view
|
||||
- GitHub repository list
|
||||
|
||||
Keep information density high but avoid clutter. Use icons where possible to save space, with tooltips for details.
|
||||
@@ -0,0 +1,357 @@
|
||||
# DASH-003: Project Organization - Folders & Tags
|
||||
|
||||
## Overview
|
||||
|
||||
Add the ability to organize projects using folders and tags. This enables users with many projects to group related work, filter their view, and find projects quickly.
|
||||
|
||||
## Context
|
||||
|
||||
Currently, projects are displayed in a flat list sorted by recency. Users with many projects (10+) struggle to find specific projects. There's no way to group related projects (e.g., "Client Work", "Personal", "Tutorials").
|
||||
|
||||
This task adds a folder/tag system that works entirely client-side, storing metadata separately from the Noodl projects themselves.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
1. **Folders**
|
||||
- Create, rename, delete folders
|
||||
- Drag-and-drop projects into folders
|
||||
- Nested folders (1 level deep max)
|
||||
- "All Projects" virtual folder (shows everything)
|
||||
- "Uncategorized" virtual folder (shows unorganized projects)
|
||||
- Folder displayed in sidebar
|
||||
|
||||
2. **Tags**
|
||||
- Create, rename, delete tags
|
||||
- Assign multiple tags per project
|
||||
- Color-coded tags
|
||||
- Tag filtering (show projects with specific tags)
|
||||
- Tags displayed as pills on project rows
|
||||
|
||||
3. **Filtering**
|
||||
- Filter by folder (sidebar click)
|
||||
- Filter by tag (tag click or dropdown)
|
||||
- Combine folder + tag filters
|
||||
- Search within filtered view
|
||||
- Clear all filters button
|
||||
|
||||
4. **Persistence**
|
||||
- Store folder/tag data in electron-store (not in project files)
|
||||
- Data structure keyed by project path (stable identifier)
|
||||
- Export/import organization data (stretch goal)
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- Organization changes feel instant
|
||||
- Drag-and-drop is smooth
|
||||
- Works offline
|
||||
- Survives app restart
|
||||
|
||||
## Data Model
|
||||
|
||||
### Storage Structure
|
||||
|
||||
```typescript
|
||||
// Stored in electron-store under 'projectOrganization'
|
||||
interface ProjectOrganizationData {
|
||||
version: 1;
|
||||
folders: Folder[];
|
||||
tags: Tag[];
|
||||
projectMeta: Record<string, ProjectMeta>; // keyed by project path
|
||||
}
|
||||
|
||||
interface Folder {
|
||||
id: string;
|
||||
name: string;
|
||||
parentId: string | null; // null = root level
|
||||
order: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
interface Tag {
|
||||
id: string;
|
||||
name: string;
|
||||
color: string; // hex color
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
interface ProjectMeta {
|
||||
folderId: string | null;
|
||||
tagIds: string[];
|
||||
customName?: string; // optional override
|
||||
notes?: string; // stretch goal
|
||||
}
|
||||
```
|
||||
|
||||
### Color Palette for Tags
|
||||
|
||||
```typescript
|
||||
const TAG_COLORS = [
|
||||
'#EF4444', // Red
|
||||
'#F97316', // Orange
|
||||
'#EAB308', // Yellow
|
||||
'#22C55E', // Green
|
||||
'#06B6D4', // Cyan
|
||||
'#3B82F6', // Blue
|
||||
'#8B5CF6', // Purple
|
||||
'#EC4899', // Pink
|
||||
'#6B7280', // Gray
|
||||
];
|
||||
```
|
||||
|
||||
## Technical Approach
|
||||
|
||||
### 1. Storage Service
|
||||
|
||||
```typescript
|
||||
// packages/noodl-editor/src/editor/src/services/ProjectOrganizationService.ts
|
||||
|
||||
class ProjectOrganizationService {
|
||||
private static instance: ProjectOrganizationService;
|
||||
|
||||
// Folder operations
|
||||
createFolder(name: string, parentId?: string): Folder;
|
||||
renameFolder(id: string, name: string): void;
|
||||
deleteFolder(id: string): void;
|
||||
reorderFolder(id: string, newOrder: number): void;
|
||||
|
||||
// Tag operations
|
||||
createTag(name: string, color: string): Tag;
|
||||
renameTag(id: string, name: string): void;
|
||||
deleteTag(id: string): void;
|
||||
changeTagColor(id: string, color: string): void;
|
||||
|
||||
// Project organization
|
||||
moveProjectToFolder(projectPath: string, folderId: string | null): void;
|
||||
addTagToProject(projectPath: string, tagId: string): void;
|
||||
removeTagFromProject(projectPath: string, tagId: string): void;
|
||||
|
||||
// Queries
|
||||
getFolders(): Folder[];
|
||||
getTags(): Tag[];
|
||||
getProjectMeta(projectPath: string): ProjectMeta | null;
|
||||
getProjectsInFolder(folderId: string | null): string[];
|
||||
getProjectsWithTag(tagId: string): string[];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Sidebar Folder Tree
|
||||
|
||||
```
|
||||
packages/noodl-core-ui/src/preview/launcher/Launcher/components/
|
||||
├── FolderTree/
|
||||
│ ├── FolderTree.tsx # Tree container
|
||||
│ ├── FolderTreeItem.tsx # Individual folder row
|
||||
│ ├── FolderTree.module.scss
|
||||
│ └── index.ts
|
||||
```
|
||||
|
||||
### 3. Tag Components
|
||||
|
||||
```
|
||||
├── TagPill/
|
||||
│ ├── TagPill.tsx # Small colored tag display
|
||||
│ └── TagPill.module.scss
|
||||
├── TagSelector/
|
||||
│ ├── TagSelector.tsx # Dropdown to add/remove tags
|
||||
│ └── TagSelector.module.scss
|
||||
├── TagFilter/
|
||||
│ ├── TagFilter.tsx # Filter bar with active tags
|
||||
│ └── TagFilter.module.scss
|
||||
```
|
||||
|
||||
### 4. Drag and Drop
|
||||
|
||||
Use `@dnd-kit/core` for drag-and-drop:
|
||||
|
||||
```typescript
|
||||
// DragDropContext for launcher
|
||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
|
||||
|
||||
// Draggable project row
|
||||
import { useDraggable } from '@dnd-kit/core';
|
||||
|
||||
// Droppable folder
|
||||
import { useDroppable } from '@dnd-kit/core';
|
||||
```
|
||||
|
||||
## Files to Create
|
||||
|
||||
1. `packages/noodl-editor/src/editor/src/services/ProjectOrganizationService.ts`
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/FolderTree/FolderTree.tsx`
|
||||
3. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/FolderTree/FolderTreeItem.tsx`
|
||||
4. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/FolderTree/FolderTree.module.scss`
|
||||
5. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TagPill/TagPill.tsx`
|
||||
6. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TagSelector/TagSelector.tsx`
|
||||
7. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TagFilter/TagFilter.tsx`
|
||||
8. `packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useProjectOrganization.ts`
|
||||
9. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/CreateFolderModal/CreateFolderModal.tsx`
|
||||
10. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/CreateTagModal/CreateTagModal.tsx`
|
||||
|
||||
## Files to Modify
|
||||
|
||||
1. `packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx`
|
||||
- Add DndContext wrapper
|
||||
- Add organization state to context
|
||||
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/LauncherSidebar/LauncherSidebar.tsx`
|
||||
- Add FolderTree component
|
||||
- Add "Create Folder" button
|
||||
|
||||
3. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/Projects.tsx`
|
||||
- Add TagFilter bar
|
||||
- Filter projects based on folder/tag selection
|
||||
- Make project rows draggable
|
||||
|
||||
4. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListRow.tsx`
|
||||
- Add tag pills
|
||||
- Add tag selector on hover/context menu
|
||||
- Make row draggable
|
||||
|
||||
## UI Mockups
|
||||
|
||||
### Sidebar with Folders
|
||||
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ 📁 All Projects (24) │
|
||||
│ 📁 Uncategorized (5) │
|
||||
├─────────────────────────┤
|
||||
│ + Create Folder │
|
||||
├─────────────────────────┤
|
||||
│ 📂 Client Work (8) │
|
||||
│ └─ 📁 Acme Corp (3) │
|
||||
│ └─ 📁 BigCo (5) │
|
||||
│ 📂 Personal (6) │
|
||||
│ 📂 Tutorials (5) │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
### Project Row with Tags
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────────┐
|
||||
│ 📁 E-commerce Dashboard 2h ago ✅ [🔴 Urgent] [🔵 Client] ~/dev/... │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Tag Filter Bar
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Filters: [🔴 Urgent ×] [🔵 Client ×] [+ Add Filter] [Clear All] │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Storage Foundation
|
||||
1. Create ProjectOrganizationService
|
||||
2. Define data model and storage
|
||||
3. Create useProjectOrganization hook
|
||||
4. Add to launcher context
|
||||
|
||||
### Phase 2: Folders
|
||||
1. Create FolderTree component
|
||||
2. Add to sidebar
|
||||
3. Create folder modal
|
||||
4. Implement folder filtering
|
||||
5. Add context menu (rename, delete)
|
||||
|
||||
### Phase 3: Tags
|
||||
1. Create TagPill component
|
||||
2. Create TagSelector dropdown
|
||||
3. Create TagFilter bar
|
||||
4. Add tags to project rows
|
||||
5. Implement tag filtering
|
||||
|
||||
### Phase 4: Drag and Drop
|
||||
1. Add dnd-kit dependency
|
||||
2. Wrap launcher in DndContext
|
||||
3. Make project rows draggable
|
||||
4. Make folders droppable
|
||||
5. Handle drop events
|
||||
|
||||
### Phase 5: Polish
|
||||
1. Add keyboard shortcuts
|
||||
2. Improve animations
|
||||
3. Handle edge cases (deleted projects, etc.)
|
||||
4. Test thoroughly
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Can create a folder
|
||||
- [ ] Can rename a folder
|
||||
- [ ] Can delete a folder (projects go to Uncategorized)
|
||||
- [ ] Can create nested folder
|
||||
- [ ] Clicking folder filters project list
|
||||
- [ ] Can create a tag
|
||||
- [ ] Can assign tag to project
|
||||
- [ ] Can remove tag from project
|
||||
- [ ] Clicking tag filters project list
|
||||
- [ ] Can combine folder + tag filters
|
||||
- [ ] Search works within filtered view
|
||||
- [ ] Clear filters button works
|
||||
- [ ] Drag project to folder works
|
||||
- [ ] Data persists after app restart
|
||||
- [ ] Removing project from disk shows appropriate state
|
||||
|
||||
## Dependencies
|
||||
|
||||
- DASH-001 (Tabbed Navigation System)
|
||||
- DASH-002 (Project List Redesign) - for project rows
|
||||
|
||||
### External Dependencies
|
||||
|
||||
Add to `package.json`:
|
||||
```json
|
||||
{
|
||||
"@dnd-kit/core": "^6.0.0",
|
||||
"@dnd-kit/sortable": "^7.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
## Blocked By
|
||||
|
||||
- DASH-002
|
||||
|
||||
## Blocks
|
||||
|
||||
- None (this is end of the DASH chain)
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- Storage service: 2-3 hours
|
||||
- Folder tree UI: 3-4 hours
|
||||
- Tag components: 3-4 hours
|
||||
- Drag and drop: 3-4 hours
|
||||
- Filtering logic: 2-3 hours
|
||||
- Polish & testing: 3-4 hours
|
||||
- **Total: 16-22 hours**
|
||||
|
||||
## Success Criteria
|
||||
|
||||
1. Users can create folders and organize projects
|
||||
2. Users can create tags and assign them to projects
|
||||
3. Filtering by folder and tag works correctly
|
||||
4. Drag-and-drop feels natural
|
||||
5. Organization data persists across sessions
|
||||
6. System handles edge cases gracefully (deleted projects, etc.)
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- Export/import organization data
|
||||
- Folder color customization
|
||||
- Project notes/descriptions
|
||||
- Bulk operations (move/tag multiple projects)
|
||||
- Smart folders (auto-organize by criteria)
|
||||
|
||||
## Design Notes
|
||||
|
||||
The folder tree should feel familiar like:
|
||||
- macOS Finder sidebar
|
||||
- VS Code Explorer
|
||||
- Notion page tree
|
||||
|
||||
Keep interactions lightweight - organization should help, not hinder, the workflow of quickly opening projects.
|
||||
@@ -0,0 +1,413 @@
|
||||
# DASH-004: Tutorial Section Redesign
|
||||
|
||||
## Overview
|
||||
|
||||
Redesign the tutorial section (Learn tab) to be more compact, informative, and useful. Move from large tiles to a structured learning center with categories, progress tracking, and better discoverability.
|
||||
|
||||
## Context
|
||||
|
||||
The current tutorial section (`projectsview.ts` and lessons model) shows tutorials as large tiles with progress bars. The tiles take up significant screen space, making it hard to browse many tutorials. There's no categorization beyond a linear list.
|
||||
|
||||
The new launcher has an empty `LearningCenter.tsx` view that needs to be built out.
|
||||
|
||||
### Current Tutorial System
|
||||
|
||||
The existing system uses:
|
||||
- `LessonProjectsModel` - manages lesson templates and progress
|
||||
- `lessonprojectsmodel.ts` - fetches from docs endpoint
|
||||
- Templates stored in docs repo with progress in localStorage
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
1. **Category Organization**
|
||||
- Categories: Getting Started, Building UIs, Data & Logic, Advanced Topics, Integrations
|
||||
- Collapsible category sections
|
||||
- Category icons/colors
|
||||
|
||||
2. **Tutorial Cards (Compact)**
|
||||
- Title
|
||||
- Short description (1-2 lines)
|
||||
- Estimated duration
|
||||
- Difficulty level (Beginner, Intermediate, Advanced)
|
||||
- Progress indicator (not started, in progress, completed)
|
||||
- Thumbnail (small, optional)
|
||||
|
||||
3. **Progress Tracking**
|
||||
- Visual progress bar per tutorial
|
||||
- Overall progress stats ("5 of 12 completed")
|
||||
- "Continue where you left off" section at top
|
||||
- Reset progress option
|
||||
|
||||
4. **Filtering & Search**
|
||||
- Search tutorials by name/description
|
||||
- Filter by difficulty
|
||||
- Filter by category
|
||||
- Filter by progress (Not Started, In Progress, Completed)
|
||||
|
||||
5. **Tutorial Detail View**
|
||||
- Expanded description
|
||||
- Learning objectives
|
||||
- Prerequisites
|
||||
- "Start Tutorial" / "Continue" / "Restart" button
|
||||
- Estimated time remaining (for in-progress)
|
||||
|
||||
6. **Additional Content Types**
|
||||
- Video tutorials (embedded or linked)
|
||||
- Written guides
|
||||
- Interactive lessons (existing)
|
||||
- External resources
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- Fast loading (tutorials list cached)
|
||||
- Works offline for previously loaded tutorials
|
||||
- Responsive layout
|
||||
- Accessible navigation
|
||||
|
||||
## Data Model
|
||||
|
||||
### Enhanced Tutorial Structure
|
||||
|
||||
```typescript
|
||||
interface Tutorial {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
longDescription?: string;
|
||||
category: TutorialCategory;
|
||||
difficulty: 'beginner' | 'intermediate' | 'advanced';
|
||||
estimatedMinutes: number;
|
||||
type: 'interactive' | 'video' | 'guide';
|
||||
thumbnailUrl?: string;
|
||||
objectives?: string[];
|
||||
prerequisites?: string[];
|
||||
|
||||
// For interactive tutorials
|
||||
templateUrl?: string;
|
||||
|
||||
// For video tutorials
|
||||
videoUrl?: string;
|
||||
|
||||
// For guides
|
||||
guideUrl?: string;
|
||||
}
|
||||
|
||||
interface TutorialCategory {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: IconName;
|
||||
color: string;
|
||||
order: number;
|
||||
}
|
||||
|
||||
interface TutorialProgress {
|
||||
tutorialId: string;
|
||||
status: 'not-started' | 'in-progress' | 'completed';
|
||||
lastAccessedAt: string;
|
||||
completedAt?: string;
|
||||
currentStep?: number;
|
||||
totalSteps?: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Default Categories
|
||||
|
||||
```typescript
|
||||
const TUTORIAL_CATEGORIES: TutorialCategory[] = [
|
||||
{ id: 'getting-started', name: 'Getting Started', icon: IconName.Rocket, color: '#22C55E', order: 0 },
|
||||
{ id: 'ui', name: 'Building UIs', icon: IconName.Palette, color: '#3B82F6', order: 1 },
|
||||
{ id: 'data', name: 'Data & Logic', icon: IconName.Database, color: '#8B5CF6', order: 2 },
|
||||
{ id: 'advanced', name: 'Advanced Topics', icon: IconName.Cog, color: '#F97316', order: 3 },
|
||||
{ id: 'integrations', name: 'Integrations', icon: IconName.Plug, color: '#EC4899', order: 4 },
|
||||
];
|
||||
```
|
||||
|
||||
## Technical Approach
|
||||
|
||||
### 1. Tutorial Service
|
||||
|
||||
Extend or replace `LessonProjectsModel`:
|
||||
|
||||
```typescript
|
||||
// packages/noodl-editor/src/editor/src/services/TutorialService.ts
|
||||
|
||||
class TutorialService {
|
||||
private static instance: TutorialService;
|
||||
|
||||
// Data fetching
|
||||
async fetchTutorials(): Promise<Tutorial[]>;
|
||||
async getTutorialById(id: string): Promise<Tutorial | null>;
|
||||
|
||||
// Progress
|
||||
getProgress(tutorialId: string): TutorialProgress;
|
||||
updateProgress(tutorialId: string, progress: Partial<TutorialProgress>): void;
|
||||
resetProgress(tutorialId: string): void;
|
||||
|
||||
// Queries
|
||||
getInProgressTutorials(): Tutorial[];
|
||||
getCompletedTutorials(): Tutorial[];
|
||||
getTutorialsByCategory(categoryId: string): Tutorial[];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Component Structure
|
||||
|
||||
```
|
||||
packages/noodl-core-ui/src/preview/launcher/Launcher/
|
||||
├── views/
|
||||
│ └── LearningCenter/
|
||||
│ ├── LearningCenter.tsx # Main view
|
||||
│ ├── LearningCenter.module.scss
|
||||
│ ├── ContinueLearning.tsx # "Continue" section
|
||||
│ ├── TutorialCategory.tsx # Category section
|
||||
│ └── TutorialFilters.tsx # Filter bar
|
||||
├── components/
|
||||
│ ├── TutorialCard/
|
||||
│ │ ├── TutorialCard.tsx # Compact card
|
||||
│ │ ├── TutorialCard.module.scss
|
||||
│ │ └── index.ts
|
||||
│ ├── TutorialDetailModal/
|
||||
│ │ ├── TutorialDetailModal.tsx # Expanded detail view
|
||||
│ │ └── TutorialDetailModal.module.scss
|
||||
│ ├── DifficultyBadge/
|
||||
│ │ └── DifficultyBadge.tsx # Beginner/Intermediate/Advanced
|
||||
│ ├── ProgressRing/
|
||||
│ │ └── ProgressRing.tsx # Circular progress indicator
|
||||
│ └── DurationLabel/
|
||||
│ └── DurationLabel.tsx # "15 min" display
|
||||
```
|
||||
|
||||
### 3. Learning Center Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Learn [🔍 Search... ] │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ Filters: [All ▾] [All Difficulties ▾] [All Progress ▾] [Clear] │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ ⏸️ Continue Learning │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 📚 OpenNoodl Basics 47% [●●●●●○○○○○] [Continue →] │ │
|
||||
│ │ Data-driven Components 12% [●○○○○○○○○○] [Continue →] │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ 🚀 Getting Started ▼ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ AI Walkthru │ │ Basics │ │ Layout │ │
|
||||
│ │ 🟢 Beginner │ │ 🟢 Beginner │ │ 🟢 Beginner │ │
|
||||
│ │ 15 min │ │ 15 min │ │ 15 min │ │
|
||||
│ │ ✓ Complete │ │ ● 47% │ │ ○ Not started│ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ 🎨 Building UIs ▼ │
|
||||
│ ... │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Files to Create
|
||||
|
||||
1. `packages/noodl-editor/src/editor/src/services/TutorialService.ts`
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter/LearningCenter.tsx`
|
||||
3. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter/LearningCenter.module.scss`
|
||||
4. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter/ContinueLearning.tsx`
|
||||
5. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter/TutorialCategory.tsx`
|
||||
6. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter/TutorialFilters.tsx`
|
||||
7. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TutorialCard/TutorialCard.tsx`
|
||||
8. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TutorialCard/TutorialCard.module.scss`
|
||||
9. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/TutorialDetailModal/TutorialDetailModal.tsx`
|
||||
10. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/DifficultyBadge/DifficultyBadge.tsx`
|
||||
11. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProgressRing/ProgressRing.tsx`
|
||||
12. `packages/noodl-core-ui/src/preview/launcher/Launcher/components/DurationLabel/DurationLabel.tsx`
|
||||
13. `packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useTutorials.ts`
|
||||
|
||||
## Files to Modify
|
||||
|
||||
1. `packages/noodl-core-ui/src/preview/launcher/Launcher/views/LearningCenter.tsx`
|
||||
- Replace empty component with full implementation
|
||||
- Move to folder structure
|
||||
|
||||
2. `packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx`
|
||||
- Update import for LearningCenter
|
||||
|
||||
3. `packages/noodl-editor/src/editor/src/models/lessonprojectsmodel.ts`
|
||||
- Either extend or create adapter for new TutorialService
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Data Layer
|
||||
1. Create TutorialService
|
||||
2. Define data types
|
||||
3. Create useTutorials hook
|
||||
4. Migrate existing lesson data structure
|
||||
|
||||
### Phase 2: Core Components
|
||||
1. Create TutorialCard component
|
||||
2. Create DifficultyBadge
|
||||
3. Create ProgressRing
|
||||
4. Create DurationLabel
|
||||
|
||||
### Phase 3: Main Layout
|
||||
1. Build LearningCenter view
|
||||
2. Create TutorialCategory sections
|
||||
3. Add ContinueLearning section
|
||||
4. Implement category collapse/expand
|
||||
|
||||
### Phase 4: Filtering
|
||||
1. Create TutorialFilters component
|
||||
2. Implement search
|
||||
3. Implement filter dropdowns
|
||||
4. Wire up filter state
|
||||
|
||||
### Phase 5: Detail View
|
||||
1. Create TutorialDetailModal
|
||||
2. Add start/continue/restart logic
|
||||
3. Show objectives and prerequisites
|
||||
|
||||
### Phase 6: Polish
|
||||
1. Add loading states
|
||||
2. Add empty states
|
||||
3. Smooth animations
|
||||
4. Accessibility review
|
||||
|
||||
## Component Specifications
|
||||
|
||||
### TutorialCard
|
||||
|
||||
```
|
||||
┌────────────────────────────┐
|
||||
│ [📹] OpenNoodl Basics │ <- Type icon + Title
|
||||
│ Learn the fundamentals │ <- Description (truncated)
|
||||
│ 🟢 Beginner ⏱️ 15 min │ <- Difficulty + Duration
|
||||
│ [●●●●●○○○○○] 47% │ <- Progress bar
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
Props:
|
||||
- `tutorial: Tutorial`
|
||||
- `progress: TutorialProgress`
|
||||
- `onClick: () => void`
|
||||
- `variant?: 'compact' | 'expanded'`
|
||||
|
||||
### DifficultyBadge
|
||||
|
||||
| Level | Color | Icon |
|
||||
|-------|-------|------|
|
||||
| Beginner | Green (#22C55E) | 🟢 |
|
||||
| Intermediate | Yellow (#EAB308) | 🟡 |
|
||||
| Advanced | Red (#EF4444) | 🔴 |
|
||||
|
||||
### ProgressRing
|
||||
|
||||
Small circular progress indicator:
|
||||
- Size: 24px
|
||||
- Stroke width: 3px
|
||||
- Background: gray
|
||||
- Fill: green (completing), green (complete)
|
||||
- Center: percentage or checkmark
|
||||
|
||||
## Compatibility Notes
|
||||
|
||||
### Existing Lesson System
|
||||
|
||||
The current system uses:
|
||||
```typescript
|
||||
// lessonprojectsmodel.ts
|
||||
interface LessonTemplate {
|
||||
name: string;
|
||||
description: string;
|
||||
iconURL: string;
|
||||
templateURL: string;
|
||||
progress?: number;
|
||||
}
|
||||
```
|
||||
|
||||
The new system should:
|
||||
1. Be backwards compatible with existing templates
|
||||
2. Migrate progress data from old format
|
||||
3. Support new enhanced metadata
|
||||
|
||||
### Migration Path
|
||||
|
||||
1. Keep `lessonprojectsmodel.ts` working during transition
|
||||
2. Create adapter in TutorialService to read old data
|
||||
3. Enhance existing tutorials with new metadata
|
||||
4. Eventually deprecate old model
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Tutorials load from docs endpoint
|
||||
- [ ] Categories display correctly
|
||||
- [ ] Category collapse/expand works
|
||||
- [ ] Progress displays correctly
|
||||
- [ ] Continue Learning section shows in-progress tutorials
|
||||
- [ ] Search filters tutorials
|
||||
- [ ] Difficulty filter works
|
||||
- [ ] Progress filter works
|
||||
- [ ] Clicking card shows detail modal
|
||||
- [ ] Start Tutorial launches tutorial
|
||||
- [ ] Continue Tutorial resumes from last point
|
||||
- [ ] Restart Tutorial resets progress
|
||||
- [ ] Progress persists across sessions
|
||||
- [ ] Empty states display appropriately
|
||||
- [ ] Responsive at different window sizes
|
||||
|
||||
## Dependencies
|
||||
|
||||
- DASH-001 (Tabbed Navigation System)
|
||||
|
||||
### External Dependencies
|
||||
|
||||
None - uses existing noodl-core-ui components.
|
||||
|
||||
## Blocked By
|
||||
|
||||
- DASH-001
|
||||
|
||||
## Blocks
|
||||
|
||||
- None
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- TutorialService: 2-3 hours
|
||||
- TutorialCard components: 2-3 hours
|
||||
- LearningCenter layout: 3-4 hours
|
||||
- Filtering: 2-3 hours
|
||||
- Detail modal: 2-3 hours
|
||||
- Polish & testing: 2-3 hours
|
||||
- **Total: 13-19 hours**
|
||||
|
||||
## Success Criteria
|
||||
|
||||
1. Tutorials are organized by category
|
||||
2. Users can easily find tutorials by search/filter
|
||||
3. Progress is clearly visible
|
||||
4. "Continue Learning" helps users resume work
|
||||
5. Tutorial cards are compact but informative
|
||||
6. Detail modal provides all needed information
|
||||
7. System is backwards compatible with existing tutorials
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- Video tutorial playback within app
|
||||
- Community-contributed tutorials
|
||||
- Tutorial recommendations based on usage
|
||||
- Learning paths (curated sequences)
|
||||
- Achievements/badges for completion
|
||||
- Tutorial ratings/feedback
|
||||
|
||||
## Design Notes
|
||||
|
||||
The learning center should feel like:
|
||||
- Duolingo's course browser (compact, progress-focused)
|
||||
- Coursera's course catalog (categorized, searchable)
|
||||
- VS Code's Getting Started (helpful, not overwhelming)
|
||||
|
||||
Prioritize getting users to relevant content quickly. The most common flow is:
|
||||
1. See "Continue Learning" → resume last tutorial
|
||||
2. Browse category → find new tutorial → start
|
||||
3. Search for specific topic → find tutorial → start
|
||||
|
||||
Don't make users click through multiple screens to start learning.
|
||||
@@ -0,0 +1,150 @@
|
||||
# DASH Series: Dashboard UX Foundation
|
||||
|
||||
## Overview
|
||||
|
||||
The DASH series modernizes the OpenNoodl editor dashboard, transforming it from a basic project launcher into a proper workspace management hub. These tasks focus on the **new React 19 launcher** in `packages/noodl-core-ui/src/preview/launcher/`.
|
||||
|
||||
## Target Environment
|
||||
|
||||
- **Editor**: React 19 version only
|
||||
- **Runtime**: React 19 version (if applicable)
|
||||
- **Backwards Compatibility**: Not required for old launcher
|
||||
|
||||
## Task Dependency Graph
|
||||
|
||||
```
|
||||
DASH-001 (Tabbed Navigation)
|
||||
│
|
||||
├── DASH-002 (Project List Redesign)
|
||||
│ │
|
||||
│ └── DASH-003 (Project Organization)
|
||||
│
|
||||
└── DASH-004 (Tutorial Section Redesign)
|
||||
```
|
||||
|
||||
## Task Summary
|
||||
|
||||
| Task ID | Name | Est. Hours | Priority |
|
||||
|---------|------|------------|----------|
|
||||
| DASH-001 | Tabbed Navigation System | 5-8 | Critical |
|
||||
| DASH-002 | Project List Redesign | 9-14 | High |
|
||||
| DASH-003 | Project Organization | 16-22 | Medium |
|
||||
| DASH-004 | Tutorial Section Redesign | 13-19 | Medium |
|
||||
|
||||
**Total Estimated: 43-63 hours**
|
||||
|
||||
## Implementation Order
|
||||
|
||||
### Week 1: Foundation
|
||||
1. **DASH-001** - Tabbed navigation (foundation for everything)
|
||||
2. **DASH-004** - Tutorial redesign (can parallel with DASH-002)
|
||||
|
||||
### Week 2: Project Management
|
||||
3. **DASH-002** - Project list redesign
|
||||
4. **DASH-003** - Folders and tags
|
||||
|
||||
## Key Technical Decisions
|
||||
|
||||
### Location
|
||||
All new components go in:
|
||||
```
|
||||
packages/noodl-core-ui/src/preview/launcher/Launcher/
|
||||
```
|
||||
|
||||
### State Management
|
||||
- Use React Context for launcher-wide state
|
||||
- Use electron-store for persistence
|
||||
- Keep component state minimal
|
||||
|
||||
### Styling
|
||||
- Use existing noodl-core-ui components
|
||||
- CSS Modules for custom styling
|
||||
- Follow existing color/spacing tokens
|
||||
|
||||
### Data
|
||||
- Services in `packages/noodl-editor/src/editor/src/services/`
|
||||
- Hooks in launcher `hooks/` folder
|
||||
- Types in component folders or shared types file
|
||||
|
||||
## Shared Components to Create
|
||||
|
||||
These components will be reused across DASH tasks:
|
||||
|
||||
| Component | Created In | Used By |
|
||||
|-----------|------------|---------|
|
||||
| TabBar | DASH-001 | All views |
|
||||
| GitStatusBadge | DASH-002 | Project list |
|
||||
| ViewModeToggle | DASH-002 | Project list |
|
||||
| FolderTree | DASH-003 | Sidebar |
|
||||
| TagPill | DASH-003 | Project rows |
|
||||
| ProgressRing | DASH-004 | Tutorial cards |
|
||||
| DifficultyBadge | DASH-004 | Tutorial cards |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
Each task includes a testing checklist. Additionally:
|
||||
|
||||
1. **Visual Testing**: Use Storybook for component development
|
||||
2. **Integration Testing**: Test in actual launcher context
|
||||
3. **Persistence Testing**: Verify data survives app restart
|
||||
4. **Performance Testing**: Check with 100+ projects/tutorials
|
||||
|
||||
## Cline Usage Notes
|
||||
|
||||
### Before Starting Each Task
|
||||
|
||||
1. Read the task document completely
|
||||
2. Explore the existing code in `packages/noodl-core-ui/src/preview/launcher/`
|
||||
3. Check existing components in `packages/noodl-core-ui/src/components/`
|
||||
4. Understand the data flow
|
||||
|
||||
### During Implementation
|
||||
|
||||
1. Create components incrementally with Storybook stories
|
||||
2. Test in isolation before integration
|
||||
3. Update imports/exports in index files
|
||||
4. Follow existing code style
|
||||
|
||||
### Confidence Checkpoints
|
||||
|
||||
Rate confidence (1-10) at these points:
|
||||
- After reading task document
|
||||
- After exploring existing code
|
||||
- Before creating first component
|
||||
- After completing each phase
|
||||
- Before marking task complete
|
||||
|
||||
### Common Gotchas
|
||||
|
||||
1. **Mock Data**: The launcher currently uses mock data - don't try to connect to real data yet
|
||||
2. **FIXME Alerts**: Many click handlers are `alert('FIXME: ...')` - that's expected
|
||||
3. **Storybook**: Run `npm run storybook` in noodl-core-ui to test components
|
||||
4. **Imports**: noodl-core-ui uses path aliases - check existing imports for patterns
|
||||
|
||||
## Success Criteria (Series Complete)
|
||||
|
||||
1. ✅ Launcher has tabbed navigation (Projects, Learn, Templates)
|
||||
2. ✅ Projects display in sortable list with git status
|
||||
3. ✅ Projects can be organized with folders and tags
|
||||
4. ✅ Tutorials are organized by category with progress tracking
|
||||
5. ✅ All preferences persist across sessions
|
||||
6. ✅ UI is responsive and accessible
|
||||
7. ✅ New components are reusable
|
||||
|
||||
## Future Work (Post-DASH)
|
||||
|
||||
The DASH series sets up infrastructure for:
|
||||
- **GIT series**: GitHub integration, sync status
|
||||
- **COMP series**: Shared components system
|
||||
- **AI series**: AI project creation
|
||||
- **DEPLOY series**: Deployment automation
|
||||
|
||||
These will be documented separately.
|
||||
|
||||
## Files in This Series
|
||||
|
||||
- `DASH-001-tabbed-navigation.md`
|
||||
- `DASH-002-project-list-redesign.md`
|
||||
- `DASH-003-project-organization.md`
|
||||
- `DASH-004-tutorial-section-redesign.md`
|
||||
- `DASH-OVERVIEW.md` (this file)
|
||||
Reference in New Issue
Block a user