Add HTML5 focused object review
This commit is contained in:
@@ -385,7 +385,14 @@ def render_html5_object_report(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def render_html5_review(project_id: str, findings: list[dict] | None) -> str:
|
def render_html5_review(
|
||||||
|
project_id: str,
|
||||||
|
findings: list[dict] | None,
|
||||||
|
*,
|
||||||
|
title: str = "Review",
|
||||||
|
oob: bool = False,
|
||||||
|
) -> str:
|
||||||
|
oob_attr = ' hx-swap-oob="outerHTML"' if oob else ""
|
||||||
if findings is None:
|
if findings is None:
|
||||||
return f"""
|
return f"""
|
||||||
<div
|
<div
|
||||||
@@ -394,8 +401,9 @@ def render_html5_review(project_id: str, findings: list[dict] | None) -> str:
|
|||||||
hx-get="/html5/projects/{quote(project_id)}/review"
|
hx-get="/html5/projects/{quote(project_id)}/review"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
|
{oob_attr}
|
||||||
>
|
>
|
||||||
<div class="panel-title">Review</div>
|
<div class="panel-title">{escape(title)}</div>
|
||||||
<p class="muted padded">Сервер готовит findings.</p>
|
<p class="muted padded">Сервер готовит findings.</p>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
@@ -410,8 +418,9 @@ def render_html5_review(project_id: str, findings: list[dict] | None) -> str:
|
|||||||
hx-get="/html5/projects/{quote(project_id)}/review"
|
hx-get="/html5/projects/{quote(project_id)}/review"
|
||||||
hx-trigger="every 20s"
|
hx-trigger="every 20s"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
|
{oob_attr}
|
||||||
>
|
>
|
||||||
<div class="panel-title">Review · {len(findings)}</div>
|
<div class="panel-title">{escape(title)} · {len(findings)}</div>
|
||||||
<div class="review-list">{body}</div>
|
<div class="review-list">{body}</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1770,6 +1770,7 @@ async def html5_project_object_context(project_id: str, object_name: str) -> Res
|
|||||||
knowledge = _knowledge_for_object_context(schema, impact, ui)
|
knowledge = _knowledge_for_object_context(schema, impact, ui)
|
||||||
source_node = _source_node_for_object_context(project_id, impact)
|
source_node = _source_node_for_object_context(project_id, impact)
|
||||||
symbol_references = await project_symbol_references(project_id, schema.object.lineage_id, direction="both")
|
symbol_references = await project_symbol_references(project_id, schema.object.lineage_id, direction="both")
|
||||||
|
focused_findings = _review_for_object_context(project_id, schema, impact, ui)
|
||||||
object_context = render_html5_object_context(
|
object_context = render_html5_object_context(
|
||||||
project_id,
|
project_id,
|
||||||
schema,
|
schema,
|
||||||
@@ -1794,8 +1795,9 @@ async def html5_project_object_context(project_id: str, object_name: str) -> Res
|
|||||||
integrations=integrations,
|
integrations=integrations,
|
||||||
oob=True,
|
oob=True,
|
||||||
)
|
)
|
||||||
|
review_context = render_html5_review(project_id, focused_findings, title="Review объекта", oob=True)
|
||||||
return Response(
|
return Response(
|
||||||
object_context + flowchart_context + source_context + symbol_context + report_context,
|
object_context + flowchart_context + source_context + symbol_context + report_context + review_context,
|
||||||
media_type="text/html; charset=utf-8",
|
media_type="text/html; charset=utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -8262,6 +8264,66 @@ def _source_node_for_object_context(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _review_for_object_context(
|
||||||
|
project_id: str,
|
||||||
|
schema: ObjectSchemaResponse,
|
||||||
|
impact: ObjectImpactResponse,
|
||||||
|
ui: ObjectUiResponse,
|
||||||
|
) -> list[dict]:
|
||||||
|
snapshot = _project_snapshot_or_404(project_id)
|
||||||
|
nodes_by_lineage = {node.lineage_id: node for node in snapshot.nodes}
|
||||||
|
names: set[str] = set()
|
||||||
|
lineages: set[str] = set()
|
||||||
|
|
||||||
|
def add_node(node: NamedNode | None) -> None:
|
||||||
|
if node is None:
|
||||||
|
return
|
||||||
|
lineages.add(node.lineage_id)
|
||||||
|
names.add(node.name.casefold())
|
||||||
|
names.add(node.qualified_name.casefold())
|
||||||
|
|
||||||
|
add_node(schema.object)
|
||||||
|
for attribute in schema.attributes:
|
||||||
|
add_node(attribute)
|
||||||
|
for section in schema.tabular_sections:
|
||||||
|
add_node(section.tabular_section)
|
||||||
|
for column in section.columns:
|
||||||
|
add_node(column)
|
||||||
|
for group in [
|
||||||
|
impact.modules,
|
||||||
|
impact.routines,
|
||||||
|
impact.forms,
|
||||||
|
impact.commands,
|
||||||
|
impact.roles,
|
||||||
|
impact.jobs,
|
||||||
|
impact.callees,
|
||||||
|
impact.query_tables,
|
||||||
|
impact.writes,
|
||||||
|
]:
|
||||||
|
for node in group:
|
||||||
|
add_node(node)
|
||||||
|
for form in ui.forms:
|
||||||
|
add_node(form.form)
|
||||||
|
for node in [*form.commands, *form.elements, *form.command_handlers.values()]:
|
||||||
|
add_node(node)
|
||||||
|
|
||||||
|
source_paths = {
|
||||||
|
node.source_ref.source_path
|
||||||
|
for lineage_id in lineages
|
||||||
|
if (node := nodes_by_lineage.get(lineage_id)) is not None and node.source_ref is not None
|
||||||
|
}
|
||||||
|
focused: list[dict] = []
|
||||||
|
for finding in get_review_payload(snapshot):
|
||||||
|
source_path = finding.get("source_path")
|
||||||
|
haystack = " ".join(
|
||||||
|
str(finding.get(key) or "").casefold()
|
||||||
|
for key in ["title", "message", "source_path"]
|
||||||
|
)
|
||||||
|
if (source_path and source_path in source_paths) or any(name and name in haystack for name in names):
|
||||||
|
focused.append(finding)
|
||||||
|
return focused
|
||||||
|
|
||||||
|
|
||||||
def _current_import_source(project_id: str) -> ImportSourceKind:
|
def _current_import_source(project_id: str) -> ImportSourceKind:
|
||||||
setup = _project_setup_response(project_id)
|
setup = _project_setup_response(project_id)
|
||||||
if setup.current_source is not None:
|
if setup.current_source is not None:
|
||||||
|
|||||||
@@ -337,6 +337,9 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
assert "data-html5-project-report" in context.text
|
assert "data-html5-project-report" in context.text
|
||||||
assert "Отчет объекта" in context.text
|
assert "Отчет объекта" in context.text
|
||||||
assert "server focused summary" in context.text
|
assert "server focused summary" in context.text
|
||||||
|
assert "data-html5-review" in context.text
|
||||||
|
assert "Review объекта" in context.text
|
||||||
|
assert "External integration endpoint" in context.text
|
||||||
assert "1 signals" in context.text
|
assert "1 signals" in context.text
|
||||||
assert "1 errors" in context.text
|
assert "1 errors" in context.text
|
||||||
assert "125.0 ms" in context.text
|
assert "125.0 ms" in context.text
|
||||||
|
|||||||
Reference in New Issue
Block a user