Add HTML5 authoring diff preview
This commit is contained in:
@@ -371,6 +371,25 @@ def render_html5_authoring_preview(project_id: str, preview: object | None, erro
|
||||
<button type="submit">Preview</button>
|
||||
</form>
|
||||
{render_html5_authoring_preview_result(project_id)}
|
||||
<form
|
||||
class="authoring-preview-form"
|
||||
data-html5-authoring-diff-form
|
||||
method="post"
|
||||
action="/html5/projects/{quote(project_id)}/authoring/semantic-diff-preview"
|
||||
hx-post="/html5/projects/{quote(project_id)}/authoring/semantic-diff-preview"
|
||||
hx-target="[data-html5-authoring-diff-result]"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<input name="routine_name" placeholder="routine_name" />
|
||||
<input name="source_path" placeholder="source_path" />
|
||||
<input name="task_id" placeholder="task_id" />
|
||||
<input name="session_id" placeholder="session_id" />
|
||||
<input name="user_id" placeholder="user_id" />
|
||||
<textarea name="original_text" placeholder="Original BSL"></textarea>
|
||||
<textarea name="proposed_text" placeholder="Proposed BSL"></textarea>
|
||||
<button type="submit">Diff preview</button>
|
||||
</form>
|
||||
{render_html5_authoring_diff_result(project_id)}
|
||||
</div>
|
||||
"""
|
||||
return render_html5_authoring_preview_result(project_id, preview, error)
|
||||
@@ -411,6 +430,41 @@ def render_html5_authoring_preview_result(project_id: str, preview: object | Non
|
||||
"""
|
||||
|
||||
|
||||
def render_html5_authoring_diff_result(project_id: str, preview: object | None = None, error: str | None = None) -> str:
|
||||
if preview is None and error is None:
|
||||
return '<div class="authoring-diff-result" data-html5-authoring-diff-result></div>'
|
||||
if error:
|
||||
return f"""
|
||||
<div class="authoring-diff-result" data-html5-authoring-diff-result>
|
||||
<div class="panel-title">Diff preview</div>
|
||||
<p class="muted padded">{escape(error)}</p>
|
||||
</div>
|
||||
"""
|
||||
changed = bool(getattr(preview, "changed", False))
|
||||
added = getattr(preview, "added_lines", 0)
|
||||
removed = getattr(preview, "removed_lines", 0)
|
||||
target = getattr(preview, "target", None)
|
||||
target_name = getattr(target, "qualified_name", None) or getattr(target, "name", None) or "target unavailable"
|
||||
checks = getattr(preview, "checks", []) or []
|
||||
diff = getattr(preview, "semantic_diff", []) or []
|
||||
version_preview = getattr(preview, "version_preview", None)
|
||||
next_version_id = str(getattr(version_preview, "next_version_id", ""))
|
||||
check_rows = "".join(_authoring_check_item(check) for check in checks[:8])
|
||||
diff_rows = "".join(_authoring_diff_item(line) for line in diff[:12]) or '<p class="muted padded">Diff пустой</p>'
|
||||
return f"""
|
||||
<div class="authoring-diff-result" data-html5-authoring-diff-result data-html5-project-id="{escape(project_id)}">
|
||||
<div class="panel-title">Diff preview · {'changed' if changed else 'unchanged'}</div>
|
||||
<article class="authoring-change">
|
||||
<strong>{escape(str(target_name))}</strong>
|
||||
<span>+{escape(str(added))} / -{escape(str(removed))}</span>
|
||||
<small>{escape(next_version_id or "version preview unavailable")}</small>
|
||||
</article>
|
||||
<div class="check-list">{check_rows}</div>
|
||||
<div class="diff-list">{diff_rows}</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
def render_html5_authoring_change_detail(project_id: str, preview: object | None) -> str:
|
||||
if preview is None:
|
||||
return f"""
|
||||
|
||||
@@ -38,6 +38,7 @@ from pydantic import BaseModel, Field
|
||||
from api_server.html5 import (
|
||||
render_html5_authoring_changes,
|
||||
render_html5_authoring_change_detail,
|
||||
render_html5_authoring_diff_result,
|
||||
render_html5_authoring_preview_result,
|
||||
render_html5_authoring_rollback_result,
|
||||
render_html5_editor,
|
||||
@@ -1794,6 +1795,26 @@ async def html5_project_authoring_completion_preview(project_id: str, request: R
|
||||
return Response(html, media_type="text/html; charset=utf-8")
|
||||
|
||||
|
||||
@app.post("/html5/projects/{project_id}/authoring/semantic-diff-preview")
|
||||
async def html5_project_authoring_semantic_diff_preview(project_id: str, request: Request) -> Response:
|
||||
form = await _html5_form_data(request)
|
||||
payload = AuthoringSemanticDiffPreviewRequest(
|
||||
routine_name=_form_value(form, "routine_name"),
|
||||
source_path=_form_value(form, "source_path"),
|
||||
original_text=_form_value(form, "original_text") or "",
|
||||
proposed_text=_form_value(form, "proposed_text") or "",
|
||||
task_id=_form_value(form, "task_id"),
|
||||
session_id=_form_value(form, "session_id"),
|
||||
user_id=_form_value(form, "user_id"),
|
||||
)
|
||||
try:
|
||||
preview = _authoring_semantic_diff_preview(project_id, payload)
|
||||
html = render_html5_authoring_diff_result(project_id, preview)
|
||||
except HTTPException as error:
|
||||
html = render_html5_authoring_diff_result(project_id, error=str(error.detail))
|
||||
return Response(html, media_type="text/html; charset=utf-8")
|
||||
|
||||
|
||||
@app.get("/html5/projects/{project_id}/setup")
|
||||
async def html5_project_setup(project_id: str) -> Response:
|
||||
setup = _project_setup_response(project_id)
|
||||
|
||||
@@ -115,6 +115,8 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
||||
assert "data-html5-authoring-preview" in editor.text
|
||||
assert "data-html5-authoring-preview-form" in editor.text
|
||||
assert f'hx-post="/html5/projects/{project_id}/authoring/completion-preview"' in editor.text
|
||||
assert "data-html5-authoring-diff-form" in editor.text
|
||||
assert f'hx-post="/html5/projects/{project_id}/authoring/semantic-diff-preview"' in editor.text
|
||||
assert "data-html5-authoring-changes" in editor.text
|
||||
assert f'hx-get="/html5/projects/{project_id}/authoring/changes"' in editor.text
|
||||
assert 'hx-get="/html5/projects/' in editor.text
|
||||
@@ -2296,6 +2298,30 @@ def test_authoring_context_and_completion_preview(tmp_path: Path):
|
||||
assert "ADD" in html5_preview.text
|
||||
assert "<html" not in html5_preview.text
|
||||
|
||||
html5_diff_preview = client.post(
|
||||
f"/html5/projects/{project_id}/authoring/semantic-diff-preview",
|
||||
data={
|
||||
"routine_name": "Проведение",
|
||||
"source_path": str(module),
|
||||
"original_text": source_text,
|
||||
"proposed_text": source_text.replace(
|
||||
" Сумма = 0;",
|
||||
" Сумма = 0;\n Если Отказ Тогда\n Возврат;\n КонецЕсли;",
|
||||
),
|
||||
"task_id": "task.authoring",
|
||||
"session_id": "session.authoring",
|
||||
"user_id": "dev.ivan",
|
||||
},
|
||||
)
|
||||
assert html5_diff_preview.status_code == 200
|
||||
assert "text/html" in html5_diff_preview.headers["content-type"]
|
||||
assert "data-html5-authoring-diff-result" in html5_diff_preview.text
|
||||
assert "Diff preview" in html5_diff_preview.text
|
||||
assert "Если Отказ Тогда" in html5_diff_preview.text
|
||||
assert "task-session" in html5_diff_preview.text
|
||||
assert "BLOCKED" in html5_diff_preview.text
|
||||
assert "<html" not in html5_diff_preview.text
|
||||
|
||||
diff_preview = client.post(
|
||||
f"/projects/{project_id}/authoring/semantic-diff-preview",
|
||||
json={
|
||||
|
||||
Reference in New Issue
Block a user