diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3cf99c3..ffd08d8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -21,7 +21,7 @@ "type": "npm", "script": "watch:esbuild", "group": "build", - "problemMatcher": "$esbuild-watch", + "problemMatcher": [], "isBackground": true, "label": "npm: watch:esbuild", "presentation": { diff --git a/Development Checklist.md b/Development Checklist.md new file mode 100644 index 0000000..803e0e0 --- /dev/null +++ b/Development Checklist.md @@ -0,0 +1,90 @@ +# ✅ Prompt Catalog Development Checklist + +## 🔧 Phase 1: Planning & Setup + +- [ ] Review and finalize requirements from `Prompt Catalog Features.md` +- [ ] Choose JavaScript framework (React, Vue, etc.) +- [ ] Set up Supabase project + - [ ] Create `prompts` table + - [ ] Create `users` table (future) + - [ ] Create `user_prompts` table (future) +- [ ] Define JSON structure for import/export +- [ ] Choose hosting platform (Vercel, Netlify, etc.) + +--- + +## 🧱 Phase 2: Database & API + +- [ ] Define and implement Supabase schema +- [ ] Set up Supabase RLS rules (if applicable) +- [ ] Connect frontend to Supabase using client API + + --- + +## 🖼 Phase 3: Front-End Interface + +- [ ] Build static UI from `Front End Interface.png` + - [ ] Sidebar navigation (System / Task) + - [ ] Search bar with filters + - [ ] Prompt list display + - [ ] Prompt detail view + - [ ] Tags display and interaction +- [ ] Integrate UI with Supabase for live data +- [ ] Implement CRUD operations for prompts + +--- + +## 🔍 Phase 4: Search & Tagging + +- [ ] Implement keyword and full-text search +- [ ] Add filter by: + - [ ] Type (System, Task) + - [ ] Tags (multi-select) +- [ ] Create tag suggestion/autocomplete + +--- + +## 🤖 Phase 5: AI Integration + +- [ ] Set up API key management (e.g., OpenAI, Together, Ollama) +- [ ] Add prompt suggestion UI for user input +- [ ] Integrate with AI API to return prompt suggestions + +--- + +## 📦 Phase 6: Import/Export + +- [ ] Implement prompt export to JSON +- [ ] Implement prompt import from JSON with validation + +--- + +## 🔐 Phase 7: Authentication & User Features (Future) + +- [ ] Add Supabase Auth for login/register +- [ ] Create user profile UI +- [ ] Track user-owned prompts +- [ ] Enable user favorites system + +--- + +## 🚀 Phase 8: Deployment & QA + +- [ ] Deploy frontend to hosting platform +- [ ] Set up Supabase production environment +- [ ] QA Testing: + - [ ] UI functionality + - [ ] Prompt CRUD operations + - [ ] Search and filtering + - [ ] Import/export behavior +- [ ] Write usage documentation + +--- + +## 🌱 Phase 9: Post-MVP Enhancements + +- [ ] Add prompt rating system +- [ ] Implement version history tracking +- [ ] Add social sharing (links, embed) +- [ ] Provide external API for prompt access +- [ ] Improve AI integration with context-aware suggestions diff --git a/media/roadmap.svg b/media/roadmap.svg new file mode 100644 index 0000000..8a16633 --- /dev/null +++ b/media/roadmap.svg @@ -0,0 +1,3 @@ + + + diff --git a/package.json b/package.json index 68f0519..f3d9d94 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,11 @@ "categories": [ "Other" ], - "activationEvents": [], + "activationEvents": [ + "onStartupFinished", + "onView:roadmapChecklist", + "workspaceContains:Development Checklist.md" + ], "main": "./dist/extension.js", "contributes": { "commands": [ @@ -17,7 +21,25 @@ "command": "vscode-project-roadmap.helloWorld", "title": "Hello World" } - ] + ], + "viewsContainers": { + "activitybar": [ + { + "id": "roadmapSidebar", + "title": "Roadmap", + "icon": "media/roadmap.svg" + } + ] + }, + "views": { + "roadmapSidebar": [ + { + "id": "roadmapChecklist", + "name": "Checklist", + "icon": "media/roadmap.svg" + } + ] + } }, "scripts": { "vscode:prepublish": "npm run package", diff --git a/src/extension.ts b/src/extension.ts index de30770..2c91997 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,26 +1,17 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; +import { RoadmapTreeProvider } from './roadmapTree'; +import * as path from 'path'; -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { + const checklistFile = path.join(vscode.workspace.workspaceFolders?.[0].uri.fsPath || '', 'Development Checklist.md'); + console.log('[Extension] Using checklist path:', checklistFile); - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "vscode-project-roadmap" is now active!'); + const roadmapProvider = new RoadmapTreeProvider(checklistFile); + vscode.window.registerTreeDataProvider('roadmapChecklist', roadmapProvider); - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - const disposable = vscode.commands.registerCommand('vscode-project-roadmap.helloWorld', () => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - vscode.window.showInformationMessage('Hello World from VSCode Project Roadmap!'); - }); - - context.subscriptions.push(disposable); + context.subscriptions.push( + vscode.commands.registerCommand('roadmapView.refresh', () => roadmapProvider.refresh()) + ); } -// This method is called when your extension is deactivated export function deactivate() {} diff --git a/src/roadmapTree.ts b/src/roadmapTree.ts new file mode 100644 index 0000000..9831717 --- /dev/null +++ b/src/roadmapTree.ts @@ -0,0 +1,73 @@ +import * as vscode from 'vscode'; + +export class RoadmapItem extends vscode.TreeItem { + constructor( + public readonly label: string, + public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly checked: boolean = false, + public readonly children: RoadmapItem[] = [] + ) { + super(label, collapsibleState); + this.description = checked ? '✅ Done' : ''; + this.iconPath = new vscode.ThemeIcon(checked ? 'check' : 'circle-large-outline'); + } +} + +export class RoadmapTreeProvider implements vscode.TreeDataProvider { + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + + private items: RoadmapItem[] = []; + + constructor(private readonly checklistPath: string) { + this.refresh(); // Load initial data + vscode.workspace.onDidSaveTextDocument(doc => { + if (doc.uri.fsPath === checklistPath) { + this.refresh(); + } + }); + } + + refresh(): void { + console.log('[Roadmap] Refresh called'); + const doc = vscode.workspace.textDocuments.find(d => d.uri.fsPath === this.checklistPath); + if (!doc) { + console.warn(`[Roadmap] Document not open: ${this.checklistPath}`); + } + + const content = doc?.getText() || ''; + console.log('[Roadmap] Loaded content:', content.slice(0, 200)); // preview first 200 chars + this.items = this.parseMarkdown(content); + this._onDidChangeTreeData.fire(); + } + + getTreeItem(element: RoadmapItem): vscode.TreeItem { + return element; + } + + getChildren(element?: RoadmapItem): vscode.ProviderResult { + return element ? element.children : this.items; + } + + private parseMarkdown(content: string): RoadmapItem[] { + const lines = content.split('\n'); + const items: RoadmapItem[] = []; + let currentPhase: RoadmapItem | null = null; + + for (const line of lines) { + const phaseMatch = line.match(/^##\s+(.+)/); + const taskMatch = line.match(/^[-*]\s+\[( |x)\]\s+(.+)/); + + if (phaseMatch) { + currentPhase = new RoadmapItem(phaseMatch[1].trim(), vscode.TreeItemCollapsibleState.Collapsed); + items.push(currentPhase); + } else if (taskMatch && currentPhase) { + const checked = taskMatch[1] === 'x'; + const task = new RoadmapItem(taskMatch[2].trim(), vscode.TreeItemCollapsibleState.None, checked); + currentPhase.children.push(task); + } + } + + return items; + } +}