""" View models for displaying complex data structures. """ from typing import Dict, Any, List from .formatters import OutputFormatter class WorkspaceView: """View for workspace information display.""" @staticmethod def show_status(summary: Dict[str, Any]) -> None: """Display workspace status.""" if summary['clean']: OutputFormatter.info("No active issue workspace") print(" Use 'make tdd-start NUM=X' to begin working on an issue") return if summary['dirty']: OutputFormatter.warning("Workspace directory exists but no current issue file") print(" Run 'make tdd-finish' to clean up or 'make tdd-start' to create new workspace") return if summary['active']: WorkspaceView._show_active_workspace(summary) else: OutputFormatter.error("Failed to load workspace") @staticmethod def _show_active_workspace(summary: Dict[str, Any]) -> None: """Display active workspace details.""" OutputFormatter.header("Active Issue Workspace", "=") issue_num = summary['issue_number'] issue_title = summary['issue_title'] print(f"๐ŸŽฏ Issue #{issue_num}: {issue_title}") OutputFormatter.key_value("Status", summary['issue_state']) OutputFormatter.key_value("Workspace", f"{summary['workspace_dir']}/issue_{issue_num}/") OutputFormatter.empty_line() # Test files test_count = summary['test_count'] test_files = summary.get('test_files', []) print(f"๐Ÿงช Generated Tests ({test_count}):") if test_files: for test_file in test_files: print(f" - {test_file}") else: print(" - No tests generated yet") OutputFormatter.empty_line() # Workspace files print("๐Ÿ“‹ Workspace Files:") print(" - requirements.md (review and break down issue)") print(" - test_plan.md (plan test scenarios)") print(" - tests/ (generated test files)") OutputFormatter.empty_line() # Commands commands = [ "make tdd-add-test (generate another test)", "make tdd-finish (complete and move tests to main)" ] OutputFormatter.format_command_list(commands) @staticmethod def show_start_success(summary: Dict[str, Any]) -> None: """Display successful workspace start.""" issue_num = summary['issue_number'] OutputFormatter.success(f"Workspace created for issue #{issue_num}") OutputFormatter.key_value("Workspace", f"{summary['workspace_dir']}/issue_{issue_num}/") OutputFormatter.key_value("Requirements", summary['requirements_file']) OutputFormatter.key_value("Test plan", summary['test_plan_file']) OutputFormatter.empty_line() print("๐Ÿ’ก Next steps:") print(" 1. Review requirements.md and break down the issue") print(" 2. Plan test scenarios in test_plan.md") print(" 3. Use 'make tdd-add-test' to generate tests") print(" 4. Use 'make tdd-finish' when complete") @staticmethod def show_finish_success(issue_number: int, test_count: int) -> None: """Display successful workspace finish.""" OutputFormatter.info(f"Finishing work on issue #{issue_number}") OutputFormatter.empty_line() if test_count > 0: print(f"๐Ÿ“ฆ Moving {test_count} test(s) to tests/ directory...") OutputFormatter.success("Tests moved to main tests/ directory") else: OutputFormatter.warning("No tests found in workspace") print("๐Ÿงน Cleaning up workspace...") OutputFormatter.success(f"Issue #{issue_number} workspace cleaned up") OutputFormatter.empty_line() print("๐Ÿ’ก Next steps:") print(" - Run 'make test' to verify tests fail (red state)") print(" - Implement code to make tests pass (green state)") print(" - Start next issue with 'make tdd-start NUM=X'") class IssueView: """View for issue information display.""" @staticmethod def show_list(issues: List[Any], title: str = "Project Issues") -> None: """Display issue list.""" OutputFormatter.header(title, "=") if not issues: print("No issues found") return for issue in issues: status_icon = "๐ŸŸข" if issue.state == "open" else "๐Ÿ”ด" print(f"{status_icon} #{issue.number}: {issue.title}") print(f" Status: {issue.state.upper()} | Created: {issue.created_at.strftime('%Y-%m-%d')}") # Truncate body for list view body_preview = issue.body[:80] + "..." if len(issue.body) > 80 else issue.body if body_preview: print(f" {body_preview}") OutputFormatter.empty_line() print("๐Ÿ’ก Tip: Use 'make show-issue NUM=X' for full details") @staticmethod def show_open_issues(issues: List[Any]) -> None: """Display open issues list.""" OutputFormatter.header("Open Project Issues (Active Backlog)", "=") if not issues: print("No open issues found") return for issue in issues: print(f"[OPEN] #{issue.number}: {issue.title}") created = issue.created_at.strftime('%Y-%m-%d') updated = issue.updated_at.strftime('%Y-%m-%d') print(f" Created: {created} | Updated: {updated}") # Truncate body for list view body_preview = issue.body[:80] + "..." if len(issue.body) > 80 else issue.body if body_preview: print(f" {body_preview}") OutputFormatter.empty_line() print("๐Ÿ’ก Tip: Use 'make show-issue NUM=X' for full details or 'make list-issues' for all issues") @staticmethod def show_creation_success(result: Dict[str, Any], issue_type: str = "issue") -> None: """Display successful issue creation.""" OutputFormatter.success(f"{issue_type.title()} created successfully!") OutputFormatter.key_value("Number", f"#{result['number']}") OutputFormatter.key_value("Title", result['title']) OutputFormatter.key_value("Status", result['state']) if 'html_url' in result: OutputFormatter.key_value("URL", result['html_url']) OutputFormatter.empty_line() print("๐Ÿ’ก Next steps:") print(f" - Use 'make tdd-start NUM={result['number']}' to begin work") print(f" - Use 'make show-issue NUM={result['number']}' to view details") class ProjectView: """View for project management information display.""" @staticmethod def show_setup_success() -> None: """Display successful project setup.""" OutputFormatter.success("Project management setup complete!") print("๐Ÿ“‹ Available states: todo, active, review, done, blocked") print("๐Ÿ“Š Available priorities: low, medium, high, critical") @staticmethod def show_milestone_list(milestones: List[Any]) -> None: """Display milestone list.""" OutputFormatter.header("Project Milestones", "=") if not milestones: print("No milestones found") return for milestone in milestones: status_icon = "๐ŸŸข" if milestone.state == "open" else "๐Ÿ”ด" print(f"{status_icon} Milestone #{milestone.id}: {milestone.title}") print(f" State: {milestone.state.upper()}") print(f" Issues: {milestone.open_issues} open, {milestone.closed_issues} closed") if milestone.description: print(f" Description: {milestone.description}") if milestone.due_on: print(f" Due: {milestone.due_on}") OutputFormatter.empty_line() @staticmethod def show_overview(overview: Dict[str, Any]) -> None: """Display project overview.""" OutputFormatter.header("Project Management Overview", "=") OutputFormatter.key_value("Milestones", f"{overview['milestones']} total") OutputFormatter.key_value("Active Projects", overview['active_projects'], 1) OutputFormatter.key_value("Completed Projects", overview['completed_projects'], 1) OutputFormatter.key_value("Total Labels", overview['total_labels']) ready_status = "โœ… Yes" if overview['project_management_ready'] else "โŒ No - run setup-project-mgmt" OutputFormatter.key_value("Project Management Ready", ready_status)