Add HTML5 flowchart fragment
This commit is contained in:
@@ -231,6 +231,7 @@ def render_html5_editor(
|
|||||||
{render_html5_symbols(snapshot, q, project_id)}
|
{render_html5_symbols(snapshot, q, project_id)}
|
||||||
</div>
|
</div>
|
||||||
{render_html5_symbol_detail(project_id, None)}
|
{render_html5_symbol_detail(project_id, None)}
|
||||||
|
{render_html5_flowchart(project_id, None)}
|
||||||
{render_html5_project_report(project_id, None)}
|
{render_html5_project_report(project_id, None)}
|
||||||
{render_html5_review(project_id, None)}
|
{render_html5_review(project_id, None)}
|
||||||
{render_html5_authoring_preview(project_id, None)}
|
{render_html5_authoring_preview(project_id, None)}
|
||||||
@@ -246,6 +247,48 @@ def render_html5_editor(
|
|||||||
return _page(f"SFERA HTML5 - {project_id}", content)
|
return _page(f"SFERA HTML5 - {project_id}", content)
|
||||||
|
|
||||||
|
|
||||||
|
def render_html5_flowchart(project_id: str, flowchart: object | None) -> str:
|
||||||
|
if flowchart is None:
|
||||||
|
return f"""
|
||||||
|
<div
|
||||||
|
class="flowchart-panel"
|
||||||
|
data-html5-flowchart
|
||||||
|
hx-get="/html5/projects/{quote(project_id)}/flowchart"
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
<div class="panel-title">Карта связей</div>
|
||||||
|
<p class="muted padded">Сервер собирает граф проекта.</p>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
nodes = getattr(flowchart, "nodes", []) or []
|
||||||
|
edges = getattr(flowchart, "edges", []) or []
|
||||||
|
mode = str(getattr(flowchart, "mode", "overview"))
|
||||||
|
body = "".join(_flowchart_edge_item(item, nodes) for item in edges[:10])
|
||||||
|
if not body:
|
||||||
|
body = "".join(_flowchart_node_item(item) for item in nodes[:10])
|
||||||
|
if not body:
|
||||||
|
body = '<p class="muted padded">Связи проекта не найдены</p>'
|
||||||
|
return f"""
|
||||||
|
<div
|
||||||
|
class="flowchart-panel"
|
||||||
|
data-html5-flowchart
|
||||||
|
hx-get="/html5/projects/{quote(project_id)}/flowchart"
|
||||||
|
hx-trigger="every 30s"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
<div class="panel-title">Карта связей · {escape(mode)}</div>
|
||||||
|
<dl class="report-grid">
|
||||||
|
{_metric("Nodes", len(nodes))}
|
||||||
|
{_metric("Edges", len(edges))}
|
||||||
|
{_metric("Total nodes", getattr(flowchart, "total_nodes", 0))}
|
||||||
|
{_metric("Total edges", getattr(flowchart, "total_edges", 0))}
|
||||||
|
</dl>
|
||||||
|
<div class="compact-list">{body}</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def render_html5_project_report(project_id: str, report: dict | None) -> str:
|
def render_html5_project_report(project_id: str, report: dict | None) -> str:
|
||||||
if report is None:
|
if report is None:
|
||||||
return f"""
|
return f"""
|
||||||
@@ -1527,6 +1570,19 @@ def _flowchart_edge_item(edge: object, nodes: Iterable[object]) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _flowchart_node_item(node: object) -> str:
|
||||||
|
name = str(getattr(node, "qualified_name", "") or getattr(node, "label", "") or "node")
|
||||||
|
kind = str(getattr(node, "kind", "") or "NODE")
|
||||||
|
level = getattr(node, "level", 0)
|
||||||
|
count = getattr(node, "count", 1)
|
||||||
|
return f"""
|
||||||
|
<article class="object-context-item" data-html5-flowchart-node="{escape(kind)}">
|
||||||
|
<strong>{escape(name)}</strong>
|
||||||
|
<small>{escape(kind)} · level {escape(str(level))} · count {escape(str(count))}</small>
|
||||||
|
</article>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _authoring_diff_item(line: object) -> str:
|
def _authoring_diff_item(line: object) -> str:
|
||||||
kind = str(getattr(line, "kind", ""))
|
kind = str(getattr(line, "kind", ""))
|
||||||
text = str(getattr(line, "text", ""))
|
text = str(getattr(line, "text", ""))
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ from api_server.html5 import (
|
|||||||
render_html5_authoring_preview_result,
|
render_html5_authoring_preview_result,
|
||||||
render_html5_authoring_rollback_result,
|
render_html5_authoring_rollback_result,
|
||||||
render_html5_editor,
|
render_html5_editor,
|
||||||
|
render_html5_flowchart,
|
||||||
render_html5_index,
|
render_html5_index,
|
||||||
render_html5_metadata_apply_result,
|
render_html5_metadata_apply_result,
|
||||||
render_html5_metadata_preview_result,
|
render_html5_metadata_preview_result,
|
||||||
@@ -1741,6 +1742,20 @@ async def html5_project_review(project_id: str) -> Response:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/html5/projects/{project_id}/flowchart")
|
||||||
|
async def html5_project_flowchart(
|
||||||
|
project_id: str,
|
||||||
|
focus: str | None = None,
|
||||||
|
depth: int = 1,
|
||||||
|
limit: int = 80,
|
||||||
|
) -> Response:
|
||||||
|
flowchart = await project_flowchart(project_id, focus=focus, depth=depth, limit=limit)
|
||||||
|
return Response(
|
||||||
|
render_html5_flowchart(project_id, flowchart),
|
||||||
|
media_type="text/html; charset=utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/html5/projects/{project_id}/objects/context/{object_name}")
|
@app.get("/html5/projects/{project_id}/objects/context/{object_name}")
|
||||||
async def html5_project_object_context(project_id: str, object_name: str) -> Response:
|
async def html5_project_object_context(project_id: str, object_name: str) -> Response:
|
||||||
schema = await get_object_schema(project_id, object_name)
|
schema = await get_object_schema(project_id, object_name)
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
assert "data-html5-editor" in editor.text
|
assert "data-html5-editor" in editor.text
|
||||||
assert "data-html5-symbol-results" in editor.text
|
assert "data-html5-symbol-results" in editor.text
|
||||||
assert "data-html5-symbol-detail" in editor.text
|
assert "data-html5-symbol-detail" in editor.text
|
||||||
|
assert "data-html5-flowchart" in editor.text
|
||||||
|
assert f'hx-get="/html5/projects/{project_id}/flowchart"' in editor.text
|
||||||
assert "data-html5-project-report" in editor.text
|
assert "data-html5-project-report" in editor.text
|
||||||
assert f'hx-get="/html5/projects/{project_id}/report"' in editor.text
|
assert f'hx-get="/html5/projects/{project_id}/report"' in editor.text
|
||||||
assert "data-html5-review" in editor.text
|
assert "data-html5-review" in editor.text
|
||||||
@@ -335,6 +337,38 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
assert "<html" not in context.text
|
assert "<html" not in context.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_html5_flowchart_fragment(tmp_path: Path):
|
||||||
|
client = TestClient(app)
|
||||||
|
project_id = f"html5-flowchart-{uuid4()}"
|
||||||
|
(tmp_path / "module.bsl").write_text(
|
||||||
|
"""
|
||||||
|
Процедура ПровестиЗаказ()
|
||||||
|
ПроверитьОстатки();
|
||||||
|
Движения.ОстаткиТоваров.Записать();
|
||||||
|
КонецПроцедуры
|
||||||
|
|
||||||
|
Процедура ПроверитьОстатки()
|
||||||
|
КонецПроцедуры
|
||||||
|
""",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
indexed = client.post("/projects/index", json={"path": str(tmp_path), "project_id": project_id})
|
||||||
|
assert indexed.status_code == 200
|
||||||
|
|
||||||
|
flowchart = client.get(
|
||||||
|
f"/html5/projects/{project_id}/flowchart",
|
||||||
|
params={"focus": "ПровестиЗаказ"},
|
||||||
|
)
|
||||||
|
assert flowchart.status_code == 200
|
||||||
|
assert "text/html" in flowchart.headers["content-type"]
|
||||||
|
assert "data-html5-flowchart" in flowchart.text
|
||||||
|
assert "Карта связей" in flowchart.text
|
||||||
|
assert "Nodes" in flowchart.text
|
||||||
|
assert "Edges" in flowchart.text
|
||||||
|
assert "ПровестиЗаказ" in flowchart.text or "ПроверитьОстатки" in flowchart.text
|
||||||
|
assert "<html" not in flowchart.text
|
||||||
|
|
||||||
|
|
||||||
def test_html5_project_setup_renders_server_fragments():
|
def test_html5_project_setup_renders_server_fragments():
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
project_id = f"html5-setup-{uuid4()}"
|
project_id = f"html5-setup-{uuid4()}"
|
||||||
|
|||||||
Reference in New Issue
Block a user