Files
BABA_YAGA/BABA_YAGA_Updater/mappers/markdown_builder.py
2026-06-07 20:24:36 +07:00

115 lines
5.2 KiB
Python

from core.models import ProgressReport, Task
class MarkdownBuilder:
@staticmethod
def _parse_progress(p_val: str) -> int:
if p_val == "1":
return 100
try:
return int(p_val.replace("%", ""))
except:
return 0
@staticmethod
def _get_status_badge(status: str) -> str:
s = status.upper().strip()
if "COMPLETED" in s:
return "![Completed](https://img.shields.io/badge/-COMPLETED-2ea44f?style=flat-square)"
if "DURING" in s or "PROCESS" in s:
return "![In Progress](https://img.shields.io/badge/-IN_PROGRESS-005cc5?style=flat-square)"
if "NOT STARTED" in s:
return "![Not Started](https://img.shields.io/badge/-NOT_STARTED-6a737d?style=flat-square)"
return f"`{status}`"
@staticmethod
def build_table(report: ProgressReport) -> str:
if not report.tasks:
return "_No tasks found._"
header = "| Phase | ID | Task | Assignee | Timeline | Progress | Status |\n"
separator = "| :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n"
rows = []
current_phase = ""
for task in report.tasks:
phase_display = f"**{task.phase}**" if task.phase != current_phase else ""
current_phase = task.phase
badge = MarkdownBuilder._get_status_badge(task.status)
prog_val = MarkdownBuilder._parse_progress(task.progress_val)
filled = prog_val // 10
bar = "" * filled + "" * (10 - filled)
rows.append(
f"| {phase_display} | `{task.task_id}` | {task.task_name} | `{task.assignee}` | {task.start_date} - {task.end_date} | `{bar} {prog_val}%` | {badge} |"
)
return header + separator + "\n".join(rows)
@staticmethod
def build_team_progress(report: ProgressReport) -> str:
if not report.tasks:
return ""
phases = {}
for t in report.tasks:
if t.phase not in phases:
phases[t.phase] = []
phases[t.phase].append(t)
total_tasks = len(report.tasks)
completed = len([t for t in report.tasks if "COMPLETED" in t.status.upper()])
in_progress = len([t for t in report.tasks if "DURING" in t.status.upper()])
avg_progress = sum(MarkdownBuilder._parse_progress(t.progress_val) for t in report.tasks) / total_tasks
# Build phase rows — NO leading spaces (prevents GitHub treating them as code blocks)
phase_rows_html = ""
colors = ["#B026FF", "#33CCFF", "#FF3333", "#FFD700"]
for i, (name, t_list) in enumerate(phases.items()):
p_total = len(t_list)
p_done = len([t for t in t_list if "COMPLETED" in t.status.upper()])
p_avg = sum(MarkdownBuilder._parse_progress(t.progress_val) for t in t_list) / p_total
color = colors[i % len(colors)]
# Key fix: use textwrap.dedent-style — keep lines flush left, no indentation
phase_rows_html += (
f'<tr>'
f'<td colspan="2" style="padding-top:10px;font-size:12px;color:#EEE;">'
f'<table width="100%" border="0" cellpadding="0" cellspacing="0">'
f'<tr><td align="left">{name}</td><td align="right">{p_avg:.0f}% ({p_done}/{p_total})</td></tr>'
f'</table>'
f'<div style="width:100%;background:#222;height:6px;border-radius:3px;overflow:hidden;margin-top:4px;">'
f'<div style="width:{p_avg}%;background:{color};height:100%;"></div>'
f'</div>'
f'</td>'
f'</tr>'
)
# Entire dashboard on as few lines as possible — no indented lines
dashboard = (
'<div align="center">'
'<table width="100%" border="0" cellpadding="0" cellspacing="0" style="background:#0D1117;border:1px solid #30363D;border-radius:8px;">'
'<tr>'
'<td width="40%" align="center" valign="middle" style="padding:25px;border-right:1px solid #30363D;">'
'<img src="https://api.iconify.design/lucide/target.svg?color=%23FFD700" width="32" height="32"/>'
f'<div style="margin:10px 0 5px 0;color:#FFD700;font-size:12px;letter-spacing:1px;font-weight:bold;">SYSTEM READINESS</div>'
f'<div style="font-size:48px;font-weight:800;color:#FFF;margin:5px 0;">{avg_progress:.1f}%</div>'
'<table border="0" cellpadding="0" cellspacing="0" style="margin-top:15px;">'
'<tr>'
f'<td align="center" style="padding:0 10px;"><div style="color:#2ea44f;font-size:16px;font-weight:bold;">{completed}</div><div style="color:#8B949E;font-size:9px;">DONE</div></td>'
f'<td style="border-left:1px solid #30363D;padding:0 10px;" align="center"><div style="color:#005cc5;font-size:16px;font-weight:bold;">{in_progress}</div><div style="color:#8B949E;font-size:9px;">ACTIVE</div></td>'
f'<td style="border-left:1px solid #30363D;padding:0 10px;" align="center"><div style="color:#8B949E;font-size:16px;font-weight:bold;">{total_tasks - completed - in_progress}</div><div style="color:#8B949E;font-size:9px;">BACKLOG</div></td>'
'</tr>'
'</table>'
'</td>'
'<td width="60%" valign="top" style="padding:20px;">'
'<div style="color:#8B949E;font-size:11px;text-transform:uppercase;letter-spacing:1px;font-weight:bold;margin-bottom:10px;">Phase Breakdown</div>'
f'<table width="100%" border="0" cellpadding="0" cellspacing="0">{phase_rows_html}</table>'
'</td>'
'</tr>'
'</table>'
'</div>'
)
return dashboard