diff --git a/services/api-server/src/api_server/html5.py b/services/api-server/src/api_server/html5.py index e93faaf..33ea7ea 100644 --- a/services/api-server/src/api_server/html5.py +++ b/services/api-server/src/api_server/html5.py @@ -252,11 +252,11 @@ def render_html5_flowchart( flowchart: object | None, *, focus: str | None = None, + depth: int = 1, oob: bool = False, ) -> str: - hx_url = f"/html5/projects/{quote(project_id)}/flowchart" - if focus: - hx_url = f"{hx_url}?focus={quote(focus, safe='')}" + normalized_depth = min(max(depth, 1), 3) + hx_url = _flowchart_url(project_id, focus, normalized_depth) oob_attr = ' hx-swap-oob="outerHTML"' if oob else "" if flowchart is None: return f""" @@ -290,6 +290,7 @@ def render_html5_flowchart( {oob_attr} >
Карта связей · {escape(mode)}
+ {_flowchart_depth_actions(project_id, focus, normalized_depth)}
{_metric("Nodes", len(nodes))} {_metric("Edges", len(edges))} @@ -1750,6 +1751,34 @@ def _flowchart_edge_item(edge: object, nodes: Iterable[object]) -> str: """ +def _flowchart_url(project_id: str, focus: str | None, depth: int) -> str: + params = [] + if focus: + params.append(f"focus={quote(focus, safe='')}") + params.append(f"depth={depth}") + return f"/html5/projects/{quote(project_id)}/flowchart?{'&'.join(params)}" + + +def _flowchart_depth_actions(project_id: str, focus: str | None, active_depth: int) -> str: + buttons = [] + for depth in [1, 2, 3]: + active = ' aria-current="page" data-html5-object-action-active="true"' if depth == active_depth else "" + url = _flowchart_url(project_id, focus, depth) + buttons.append( + f""" + Depth {depth} + """ + ) + return f'' + + 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") diff --git a/services/api-server/src/api_server/main.py b/services/api-server/src/api_server/main.py index 2a86cde..2cf72f8 100644 --- a/services/api-server/src/api_server/main.py +++ b/services/api-server/src/api_server/main.py @@ -1752,7 +1752,7 @@ async def html5_project_flowchart( ) -> Response: flowchart = await project_flowchart(project_id, focus=focus, depth=depth, limit=limit) return Response( - render_html5_flowchart(project_id, flowchart, focus=focus), + render_html5_flowchart(project_id, flowchart, focus=focus, depth=depth), media_type="text/html; charset=utf-8", ) @@ -1784,7 +1784,7 @@ async def html5_project_object_context(project_id: str, object_name: str, mode: flowchart, mode, ) - flowchart_context = render_html5_flowchart(project_id, flowchart, focus=object_name, oob=True) + flowchart_context = render_html5_flowchart(project_id, flowchart, focus=object_name, depth=1, oob=True) source_context = render_html5_source(source_node, oob=True) if source_node is not None else "" symbol_context = render_html5_symbol_detail(project_id, symbol_references, oob=True) report_context = render_html5_object_report( diff --git a/services/api-server/tests/test_api.py b/services/api-server/tests/test_api.py index 9e4e826..f8b726e 100644 --- a/services/api-server/tests/test_api.py +++ b/services/api-server/tests/test_api.py @@ -109,7 +109,7 @@ def test_html5_server_rendered_project_editor(tmp_path: Path): assert "data-html5-symbol-results" 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 f'hx-get="/html5/projects/{project_id}/flowchart?depth=1"' in editor.text assert "data-html5-project-report" in editor.text assert f'hx-get="/html5/projects/{project_id}/report"' in editor.text assert "data-html5-review" in editor.text @@ -421,6 +421,12 @@ def test_html5_flowchart_fragment(tmp_path: Path): assert flowchart.status_code == 200 assert "text/html" in flowchart.headers["content-type"] assert "data-html5-flowchart" in flowchart.text + assert "data-html5-flowchart-actions" in flowchart.text + assert "Depth 1" in flowchart.text + assert "Depth 2" in flowchart.text + assert "Depth 3" in flowchart.text + assert "depth=2" in flowchart.text + assert 'hx-target="[data-html5-flowchart]"' in flowchart.text assert 'hx-swap-oob="outerHTML"' not in flowchart.text assert "Карта связей" in flowchart.text assert "Nodes" in flowchart.text @@ -428,6 +434,14 @@ def test_html5_flowchart_fragment(tmp_path: Path): assert "ПровестиЗаказ" in flowchart.text or "ПроверитьОстатки" in flowchart.text assert "