feat: fundar plataforma mais humana
This commit is contained in:
119
src/mais_humana/html_export.py
Normal file
119
src/mais_humana/html_export.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""HTML export for quick local review of human reports."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
|
||||
from .models import PlatformHumanReport, ReportBundle
|
||||
from .quality import PlatformQualityReport
|
||||
|
||||
|
||||
def esc(value: object) -> str:
|
||||
return (
|
||||
str(value)
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace('"', """)
|
||||
)
|
||||
|
||||
|
||||
def html_shell(title: str, body: str) -> str:
|
||||
return f"""<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{esc(title)}</title>
|
||||
<style>
|
||||
body {{ font-family: Arial, sans-serif; margin: 0; color: #18202a; background: #f8fafc; }}
|
||||
header {{ padding: 28px 36px; background: #0f172a; color: #f8fafc; }}
|
||||
main {{ padding: 24px 36px 56px; max-width: 1180px; margin: 0 auto; }}
|
||||
table {{ border-collapse: collapse; width: 100%; background: white; }}
|
||||
th, td {{ border: 1px solid #dbe3ef; padding: 8px 10px; text-align: left; vertical-align: top; }}
|
||||
th {{ background: #e8eef7; }}
|
||||
.grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }}
|
||||
.card {{ background: white; border: 1px solid #dbe3ef; border-radius: 8px; padding: 14px; }}
|
||||
.score {{ font-weight: 700; font-size: 22px; }}
|
||||
.ok {{ color: #1f7a4d; }}
|
||||
.warn {{ color: #a16207; }}
|
||||
.blocker {{ color: #b42318; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header><h1>{esc(title)}</h1></header>
|
||||
<main>{body}</main>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
def report_card(report: PlatformHumanReport, quality: PlatformQualityReport | None) -> str:
|
||||
quality_text = ""
|
||||
if quality is not None:
|
||||
status_class = "ok" if quality.human_ready else "blocker" if quality.blocker_count else "warn"
|
||||
quality_text = (
|
||||
f'<p class="{status_class}">technical_ready={quality.technical_ready}; '
|
||||
f"human_ready={quality.human_ready}; blockers={quality.blocker_count}; warnings={quality.warning_count}</p>"
|
||||
)
|
||||
gaps = "".join(f"<li>{esc(gap)}</li>" for gap in report.missing_for_humans[:4])
|
||||
return (
|
||||
'<section class="card">'
|
||||
f"<h2>{esc(report.platform.title)}</h2>"
|
||||
f'<div class="score">{report.average_score}</div>'
|
||||
f"<p>{esc(report.summary)}</p>"
|
||||
+ quality_text
|
||||
+ "<ul>"
|
||||
+ gaps
|
||||
+ "</ul>"
|
||||
"</section>"
|
||||
)
|
||||
|
||||
|
||||
def index_html(reports: Sequence[PlatformHumanReport], qualities: Sequence[PlatformQualityReport], bundle: ReportBundle | None = None) -> str:
|
||||
quality_by_platform = {quality.platform_id: quality for quality in qualities}
|
||||
cards = "".join(report_card(report, quality_by_platform.get(report.platform.platform_id)) for report in reports)
|
||||
rows = []
|
||||
for report in sorted(reports, key=lambda item: item.platform.platform_id):
|
||||
quality = quality_by_platform.get(report.platform.platform_id)
|
||||
rows.append(
|
||||
"<tr>"
|
||||
f"<td>{esc(report.platform.platform_id)}</td>"
|
||||
f"<td>{report.average_score}</td>"
|
||||
f"<td>{report.scan.code_lines}</td>"
|
||||
f"<td>{len(report.scan.evidence)}</td>"
|
||||
f"<td>{esc(quality.human_ready if quality else 'n/a')}</td>"
|
||||
f"<td>{esc('; '.join(report.scan.warnings[:3]))}</td>"
|
||||
"</tr>"
|
||||
)
|
||||
intro = ""
|
||||
if bundle is not None:
|
||||
intro = (
|
||||
f"<p>Gerados {len(bundle.generated_files)} arquivos, "
|
||||
f"{bundle.matrix_cells} celulas de matriz e "
|
||||
f"{bundle.total_code_lines_analyzed} linhas de codigo analisadas.</p>"
|
||||
)
|
||||
body = (
|
||||
intro
|
||||
+ '<section class="grid">'
|
||||
+ cards
|
||||
+ "</section>"
|
||||
+ "<h2>Resumo tabular</h2>"
|
||||
+ "<table><thead><tr><th>Plataforma</th><th>Score</th><th>Linhas</th><th>Evidencias</th><th>Human ready</th><th>Avisos</th></tr></thead><tbody>"
|
||||
+ "".join(rows)
|
||||
+ "</tbody></table>"
|
||||
)
|
||||
return html_shell("Mais Humana - indice operacional", body)
|
||||
|
||||
|
||||
def write_index_html(
|
||||
path: Path,
|
||||
reports: Sequence[PlatformHumanReport],
|
||||
qualities: Sequence[PlatformQualityReport],
|
||||
bundle: ReportBundle | None = None,
|
||||
) -> Path:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(index_html(reports, qualities, bundle), encoding="utf-8")
|
||||
return path
|
||||
|
||||
Reference in New Issue
Block a user