MCP GitHub Issue Server

import { Task } from '../../types/task.js'; /** * Base formatter interface for task visualization */ export interface TaskFormatter { format(tasks: Task[]): string; } /** * Base formatter implementation with common utilities */ export abstract class BaseFormatter implements TaskFormatter { /** * Format tasks into string representation */ abstract format(tasks: Task[]): string; /** * Build task hierarchy from flat list */ protected buildHierarchy(tasks: Task[]): Map<string, Task[]> { const hierarchy = new Map<string, Task[]>(); // Group tasks by parent path tasks.forEach(task => { const parentPath = task.parentPath || ''; if (!hierarchy.has(parentPath)) { hierarchy.set(parentPath, []); } hierarchy.get(parentPath)!.push(task); }); return hierarchy; } /** * Sort tasks by path and status */ protected sortTasks(tasks: Task[]): Task[] { return [...tasks].sort((a, b) => { // First sort by path depth (root tasks first) const aDepth = (a.path.match(/\//g) || []).length; const bDepth = (b.path.match(/\//g) || []).length; if (aDepth !== bDepth) return aDepth - bDepth; // Then sort by path alphabetically if (a.path !== b.path) return a.path.localeCompare(b.path); // Finally sort by status return a.status.localeCompare(b.status); }); } /** * Get task progress value based on status */ protected getTaskProgress(task: Task): number { switch (task.status) { case 'COMPLETED': return 100; case 'IN_PROGRESS': return 50; case 'BLOCKED': return 25; case 'PENDING': case 'CANCELLED': default: return 0; } } /** * Format date for display */ protected formatDate(date: string | number): string { return new Date(date).toLocaleString(); } /** * Get status emoji */ protected getStatusEmoji(status: string): string { switch (status) { case 'PENDING': return '⏳'; case 'IN_PROGRESS': return '🔄'; case 'COMPLETED': return '✅'; case 'BLOCKED': return '🚫'; case 'CANCELLED': return '❌'; default: return '❔'; } } }