diff --git a/services/api-server/src/api_server/html5.py b/services/api-server/src/api_server/html5.py index e0eac52..2c3af4a 100644 --- a/services/api-server/src/api_server/html5.py +++ b/services/api-server/src/api_server/html5.py @@ -978,6 +978,7 @@ def render_html5_authoring_change_detail(project_id: str, preview: object | None {escape(original_version_id)} -> {escape(rollback_version_id)} {escape(change_id)} + {_authoring_detail_summary(diff, checks, apply_available)}
{check_rows}
{diff_rows}
{apply_form} @@ -1718,6 +1719,23 @@ def _authoring_changes_summary(changes: Iterable[object]) -> str: """ +def _authoring_detail_summary(diff: Iterable[object], checks: Iterable[object], apply_available: bool) -> str: + diff_list = list(diff) + check_list = list(checks) + diff_kinds = Counter(str(getattr(line, "kind", "") or "CHANGE") for line in diff_list) + check_statuses = Counter(str(getattr(check, "status", "") or "UNKNOWN") for check in check_list) + added = sum(1 for line in diff_list if str(getattr(line, "kind", "")) == "ADD") + removed = sum(1 for line in diff_list if str(getattr(line, "kind", "")) == "REMOVE") + diff_text = ", ".join(f"{name}: {count}" for name, count in sorted(diff_kinds.items())) or "empty diff" + check_text = ", ".join(f"{name}: {count}" for name, count in sorted(check_statuses.items())) or "no checks" + state = "rollback ready" if apply_available else "rollback blocked" + return f""" +

+ {escape(state)} · {escape(str(len(diff_list)))} diff lines · +{escape(str(added))} / -{escape(str(removed))} · {escape(diff_text)} · {escape(check_text)} +

+ """ + + def _named_node_item(label: str, node: object) -> str: name = getattr(node, "qualified_name", None) or getattr(node, "name", "") kind = getattr(node, "kind", label) diff --git a/services/api-server/tests/test_api.py b/services/api-server/tests/test_api.py index 0bb2622..45f6509 100644 --- a/services/api-server/tests/test_api.py +++ b/services/api-server/tests/test_api.py @@ -2700,6 +2700,9 @@ def test_authoring_context_and_completion_preview(tmp_path: Path): assert html5_detail.status_code == 200 assert "text/html" in html5_detail.headers["content-type"] assert "data-html5-authoring-detail" in html5_detail.text + assert "data-html5-authoring-detail-summary" in html5_detail.text + assert "rollback ready" in html5_detail.text + assert "diff lines" in html5_detail.text assert "Rollback preview" in html5_detail.text assert "data-html5-authoring-rollback-form" in html5_detail.text assert f'hx-post="/html5/projects/{project_id}/authoring/changes/{apply_payload["change_id"]}/apply-rollback"' in html5_detail.text