Update
This commit is contained in:
@@ -1,35 +1,115 @@
|
||||
from core.models import ProgressReport
|
||||
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 ""
|
||||
if "DURING" in s or "PROCESS" in s:
|
||||
return ""
|
||||
if "NOT STARTED" in s:
|
||||
return ""
|
||||
return f"`{status}`"
|
||||
|
||||
@staticmethod
|
||||
def build_table(report: ProgressReport) -> str:
|
||||
if not report.tasks:
|
||||
return "_No tasks updated._"
|
||||
return "_No tasks found._"
|
||||
|
||||
# Table header
|
||||
header = "| Category | Task | Status | Progress | Notes |\n"
|
||||
separator = "| :--- | :--- | :--- | :--- | :--- |\n"
|
||||
header = "| Phase | ID | Task | Assignee | Timeline | Progress | Status |\n"
|
||||
separator = "| :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n"
|
||||
rows = []
|
||||
|
||||
|
||||
current_phase = ""
|
||||
for task in report.tasks:
|
||||
# Map status to professional badges
|
||||
status_clean = task.status.lower().strip()
|
||||
|
||||
if any(x in status_clean for x in ["done", "complete", "finished"]):
|
||||
badge = ""
|
||||
elif any(x in status_clean for x in ["progress", "doing", "active"]):
|
||||
badge = ""
|
||||
elif any(x in status_clean for x in ["planned", "todo", "waiting"]):
|
||||
badge = ""
|
||||
elif any(x in status_clean for x in ["bug", "error", "fix"]):
|
||||
badge = ""
|
||||
else:
|
||||
badge = f"`{task.status}`" # Fallback to code text
|
||||
|
||||
# Progress bar simulation using HTML/Unicode if needed,
|
||||
# but simple text "75%" is often cleaner.
|
||||
|
||||
row = f"| **{task.category}** | {task.task_name} | {badge} | `{task.progress}` | {task.notes} |"
|
||||
rows.append(row)
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user