This commit is contained in:
@@ -1,111 +1,105 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
from rich.layout import Layout
|
||||||
from rich.panel import Panel
|
from rich.panel import Panel
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
from rich.box import ROUNDED
|
|
||||||
|
from src.formatters.base import BaseFormatter
|
||||||
|
|
||||||
|
|
||||||
class DashboardFormatter:
|
class DashboardFormatter(BaseFormatter):
|
||||||
"""Rich console dashboard formatter."""
|
"""Terminal dashboard formatter using Rich."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def display(data: Any) -> None:
|
def display(data: Any) -> None:
|
||||||
"""Display data as a Rich dashboard."""
|
"""Display data as an interactive dashboard."""
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
title = Text("Git Insights - Productivity Dashboard", style="bold green", justify="center")
|
layout = Layout()
|
||||||
console.print(Panel(title, box=ROUNDED, style="green"))
|
layout.split_column(
|
||||||
console.print()
|
Layout(name="header", size=3),
|
||||||
|
Layout(name="body"),
|
||||||
|
)
|
||||||
|
|
||||||
|
layout["body"].split_row(
|
||||||
|
Layout(name="left"),
|
||||||
|
Layout(name="right"),
|
||||||
|
)
|
||||||
|
|
||||||
|
header = Panel(
|
||||||
|
Text("Git Insights Dashboard", justify="center", style="bold blue"),
|
||||||
|
style="white on blue",
|
||||||
|
)
|
||||||
|
layout["header"].update(header)
|
||||||
|
|
||||||
if hasattr(data, "commit_analysis") and data.commit_analysis:
|
if hasattr(data, "commit_analysis") and data.commit_analysis:
|
||||||
DashboardFormatter._print_commit_stats(console, data.commit_analysis)
|
ca = data.commit_analysis
|
||||||
|
left_content = f"""
|
||||||
|
[bold]Commit Overview[/bold]
|
||||||
|
|
||||||
|
Total Commits: [green]{ca.total_commits}[/green]
|
||||||
|
Unique Authors: [blue]{ca.unique_authors}[/blue]
|
||||||
|
Avg Commits/Day: [yellow]{ca.average_commits_per_day:.1f}[/yellow]
|
||||||
|
|
||||||
|
[bold]Top Contributors[/bold]
|
||||||
|
"""
|
||||||
|
for author in ca.top_authors[:5]:
|
||||||
|
left_content += f"\n {author.name}: {author.commit_count} commits"
|
||||||
|
|
||||||
|
layout["left"].update(
|
||||||
|
Panel(left_content, title="Commit Analysis"),
|
||||||
|
)
|
||||||
|
|
||||||
if hasattr(data, "velocity_analysis") and data.velocity_analysis:
|
if hasattr(data, "velocity_analysis") and data.velocity_analysis:
|
||||||
DashboardFormatter._print_velocity(console, data.velocity_analysis)
|
va = data.velocity_analysis
|
||||||
|
right_content = f"""
|
||||||
|
[bold]Velocity Metrics[/bold]
|
||||||
|
|
||||||
|
Commits/Day: [green]{va.commits_per_day}[/green]
|
||||||
|
Commits/Week: [blue]{va.commits_per_week}[/blue]
|
||||||
|
Trend: [yellow]{va.velocity_trend}[/yellow]
|
||||||
|
Most Active: [magenta]{va.most_active_day}[/magenta]
|
||||||
|
"""
|
||||||
|
layout["right"].update(
|
||||||
|
Panel(right_content, title="Velocity Analysis"),
|
||||||
|
)
|
||||||
|
|
||||||
|
console.print(layout)
|
||||||
|
|
||||||
if hasattr(data, "code_churn_analysis") and data.code_churn_analysis:
|
if hasattr(data, "code_churn_analysis") and data.code_churn_analysis:
|
||||||
DashboardFormatter._print_churn(console, data.code_churn_analysis)
|
cc = data.code_churn_analysis
|
||||||
|
churn_panel = Panel(
|
||||||
|
f"""
|
||||||
|
[bold]Code Churn Statistics[/bold]
|
||||||
|
|
||||||
|
Lines Added: [green]+{cc.total_lines_added:,}[/green]
|
||||||
|
Lines Deleted: [red]-{cc.total_lines_deleted:,}[/red]
|
||||||
|
Net Change: [blue]{cc.net_change:+}[/blue]
|
||||||
|
Avg Churn/Commit: [yellow]{cc.average_churn_per_commit:.1f}[/yellow]
|
||||||
|
""",
|
||||||
|
title="Code Churn",
|
||||||
|
)
|
||||||
|
console.print(churn_panel)
|
||||||
|
|
||||||
if hasattr(data, "risky_commit_analysis") and data.risky_commit_analysis:
|
if hasattr(data, "risky_commit_analysis") and data.risky_commit_analysis:
|
||||||
DashboardFormatter._print_risky(console, data.risky_commit_analysis)
|
ra = data.risky_commit_analysis
|
||||||
|
if ra.total_risky > 0:
|
||||||
|
risky_panel = Panel(
|
||||||
|
f"""
|
||||||
|
[bold]Risky Commits Summary[/bold]
|
||||||
|
|
||||||
|
Large Commits: [red]{len(ra.large_commits)}[/red]
|
||||||
|
Merge Commits: [yellow]{len(ra.merge_commits)}[/yellow]
|
||||||
|
Revert Commits: [blue]{len(ra.revert_commits)}[/blue]
|
||||||
|
Total Risky: [red]{ra.total_risky}[/red]
|
||||||
|
""",
|
||||||
|
title="Risk Detection",
|
||||||
|
)
|
||||||
|
console.print(risky_panel)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _print_commit_stats(console: Console, ca: Any) -> None:
|
def format(data: Any) -> str:
|
||||||
"""Print commit statistics."""
|
"""Format data as string (not used for dashboard)."""
|
||||||
table = Table(title="[bold]Commit Overview[/bold]", box=ROUNDED)
|
return "Dashboard output (use display() method)"
|
||||||
table.add_column("Metric", style="cyan")
|
|
||||||
table.add_column("Value", style="magenta")
|
|
||||||
|
|
||||||
table.add_row("Total Commits", str(ca.total_commits))
|
|
||||||
table.add_row("Unique Authors", str(ca.unique_authors))
|
|
||||||
table.add_row("Avg Commits/Day", f"{ca.average_commits_per_day:.1f}")
|
|
||||||
|
|
||||||
console.print(Panel(table, title="[bold yellow]Commits[/bold yellow]", box=ROUNDED))
|
|
||||||
console.print()
|
|
||||||
|
|
||||||
if ca.top_authors:
|
|
||||||
author_table = Table(title="[bold]Top Contributors[/bold]", box=ROUNDED)
|
|
||||||
author_table.add_column("Author", style="green")
|
|
||||||
author_table.add_column("Commits", justify="right", style="blue")
|
|
||||||
|
|
||||||
for author in ca.top_authors[:5]:
|
|
||||||
author_table.add_row(author.name, str(author.commit_count))
|
|
||||||
|
|
||||||
console.print(Panel(author_table, box=ROUNDED))
|
|
||||||
console.print()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _print_velocity(console: Console, va: Any) -> None:
|
|
||||||
"""Print velocity metrics."""
|
|
||||||
table = Table(box=ROUNDED)
|
|
||||||
table.add_column("Metric", style="cyan")
|
|
||||||
table.add_column("Value", style="magenta")
|
|
||||||
|
|
||||||
trend_style = "green" if va.velocity_trend == "increasing" else "orange" if va.velocity_trend == "decreasing" else "blue"
|
|
||||||
|
|
||||||
table.add_row("Commits/Day", f"{va.commits_per_day:.1f}")
|
|
||||||
table.add_row("Commits/Week", f"{va.commits_per_week:.1f}")
|
|
||||||
table.add_row("Velocity Trend", f"[{trend_style}]{va.velocity_trend}[/{trend_style}]")
|
|
||||||
table.add_row("Most Active Day", va.most_active_day)
|
|
||||||
table.add_row("Most Active Hour", va.most_active_hour)
|
|
||||||
|
|
||||||
console.print(Panel(table, title="[bold yellow]Velocity[/bold yellow]", box=ROUNDED))
|
|
||||||
console.print()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _print_churn(console: Console, cc: Any) -> None:
|
|
||||||
"""Print code churn metrics."""
|
|
||||||
table = Table(box=ROUNDED)
|
|
||||||
table.add_column("Metric", style="cyan")
|
|
||||||
table.add_column("Value", style="magenta")
|
|
||||||
|
|
||||||
net_color = "green" if cc.net_change >= 0 else "red"
|
|
||||||
|
|
||||||
table.add_row("Lines Added", f"[green]+{cc.total_lines_added:,}[/green]")
|
|
||||||
table.add_row("Lines Deleted", f"[red]-{cc.total_lines_deleted:,}[/red]")
|
|
||||||
table.add_row("Net Change", f"[{net_color}]{cc.net_change:+,}[/{net_color}]")
|
|
||||||
table.add_row("Avg Churn/Commit", f"{cc.average_churn_per_commit:.1f}")
|
|
||||||
table.add_row("High Churn Commits", str(len(cc.high_churn_commits)))
|
|
||||||
|
|
||||||
console.print(Panel(table, title="[bold yellow]Code Churn[/bold yellow]", box=ROUNDED))
|
|
||||||
console.print()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _print_risky(console: Console, ra: Any) -> None:
|
|
||||||
"""Print risky commit metrics."""
|
|
||||||
table = Table(box=ROUNDED)
|
|
||||||
table.add_column("Metric", style="cyan")
|
|
||||||
table.add_column("Value", style="magenta")
|
|
||||||
|
|
||||||
risk_color = "red" if ra.risk_score > 20 else "orange" if ra.risk_score > 10 else "green"
|
|
||||||
|
|
||||||
table.add_row("Total Risky Commits", str(ra.total_risky_commits))
|
|
||||||
table.add_row("Risk Score", f"[{risk_color}]{ra.risk_score:.1f}%[/]")
|
|
||||||
table.add_row("Large Changes", str(len(ra.large_change_commits)))
|
|
||||||
table.add_row("Merge Commits", str(len(ra.merge_commits)))
|
|
||||||
table.add_row("Reverts", str(len(ra.revert_commits)))
|
|
||||||
|
|
||||||
console.print(Panel(table, title="[bold yellow]Risky Commits[/bold yellow]", box=ROUNDED))
|
|
||||||
console.print()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user