Add HTML5 object data flow context
This commit is contained in:
@@ -325,6 +325,7 @@ def render_html5_object_context(
|
|||||||
runtime: Iterable[object] | None = None,
|
runtime: Iterable[object] | None = None,
|
||||||
knowledge: Iterable[object] | None = None,
|
knowledge: Iterable[object] | None = None,
|
||||||
privacy: object | None = None,
|
privacy: object | None = None,
|
||||||
|
integrations: Iterable[object] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if schema is None or impact is None:
|
if schema is None or impact is None:
|
||||||
return f"""
|
return f"""
|
||||||
@@ -340,13 +341,18 @@ def render_html5_object_context(
|
|||||||
modules = getattr(impact, "modules", []) or []
|
modules = getattr(impact, "modules", []) or []
|
||||||
routines = getattr(impact, "routines", []) or []
|
routines = getattr(impact, "routines", []) or []
|
||||||
forms = getattr(impact, "forms", []) or []
|
forms = getattr(impact, "forms", []) or []
|
||||||
|
commands = getattr(impact, "commands", []) or []
|
||||||
roles = getattr(impact, "roles", []) or []
|
roles = getattr(impact, "roles", []) or []
|
||||||
jobs = getattr(impact, "jobs", []) or []
|
jobs = getattr(impact, "jobs", []) or []
|
||||||
|
callees = getattr(impact, "callees", []) or []
|
||||||
|
query_tables = getattr(impact, "query_tables", []) or []
|
||||||
|
writes = getattr(impact, "writes", []) or []
|
||||||
grants = getattr(access, "grants", []) if access is not None else []
|
grants = getattr(access, "grants", []) if access is not None else []
|
||||||
ui_forms = getattr(ui, "forms", []) if ui is not None else []
|
ui_forms = getattr(ui, "forms", []) if ui is not None else []
|
||||||
runtime_items = list(runtime or [])
|
runtime_items = list(runtime or [])
|
||||||
knowledge_items = list(knowledge or [])
|
knowledge_items = list(knowledge or [])
|
||||||
privacy_markers = getattr(privacy, "markers", []) if privacy is not None else []
|
privacy_markers = getattr(privacy, "markers", []) if privacy is not None else []
|
||||||
|
integration_items = list(integrations or [])
|
||||||
return f"""
|
return f"""
|
||||||
<div class="object-context" data-html5-object-context data-html5-object-name="{escape(str(name))}">
|
<div class="object-context" data-html5-object-context data-html5-object-name="{escape(str(name))}">
|
||||||
<div class="panel-title">Object context</div>
|
<div class="panel-title">Object context</div>
|
||||||
@@ -360,7 +366,12 @@ def render_html5_object_context(
|
|||||||
{_metric("Modules", len(modules))}
|
{_metric("Modules", len(modules))}
|
||||||
{_metric("Routines", len(routines))}
|
{_metric("Routines", len(routines))}
|
||||||
{_metric("Forms", len(ui_forms) or len(forms))}
|
{_metric("Forms", len(ui_forms) or len(forms))}
|
||||||
|
{_metric("Commands", len(commands))}
|
||||||
{_metric("Roles", len(grants) or len(roles))}
|
{_metric("Roles", len(grants) or len(roles))}
|
||||||
|
{_metric("Reads", len(query_tables))}
|
||||||
|
{_metric("Writes", len(writes))}
|
||||||
|
{_metric("Calls", len(callees))}
|
||||||
|
{_metric("Integrations", len(integration_items))}
|
||||||
{_metric("Runtime", len(runtime_items))}
|
{_metric("Runtime", len(runtime_items))}
|
||||||
{_metric("Knowledge", len(knowledge_items))}
|
{_metric("Knowledge", len(knowledge_items))}
|
||||||
{_metric("Privacy", len(privacy_markers))}
|
{_metric("Privacy", len(privacy_markers))}
|
||||||
@@ -370,6 +381,11 @@ def render_html5_object_context(
|
|||||||
{''.join(_tabular_section_item(item) for item in sections[:4])}
|
{''.join(_tabular_section_item(item) for item in sections[:4])}
|
||||||
{''.join(_ui_form_item(item) for item in ui_forms[:4])}
|
{''.join(_ui_form_item(item) for item in ui_forms[:4])}
|
||||||
{''.join(_role_access_item(item) for item in grants[:6])}
|
{''.join(_role_access_item(item) for item in grants[:6])}
|
||||||
|
{''.join(_integration_endpoint_item(item) for item in integration_items[:4])}
|
||||||
|
{''.join(_named_node_item("command", item) for item in commands[:6])}
|
||||||
|
{''.join(_named_node_item("read", item) for item in query_tables[:4])}
|
||||||
|
{''.join(_named_node_item("write", item) for item in writes[:4])}
|
||||||
|
{''.join(_named_node_item("call", item) for item in callees[:6])}
|
||||||
{''.join(_runtime_summary_item(item) for item in runtime_items[:6])}
|
{''.join(_runtime_summary_item(item) for item in runtime_items[:6])}
|
||||||
{''.join(_knowledge_record_item(item) for item in knowledge_items[:6])}
|
{''.join(_knowledge_record_item(item) for item in knowledge_items[:6])}
|
||||||
{''.join(_privacy_marker_item(item) for item in privacy_markers[:6])}
|
{''.join(_privacy_marker_item(item) for item in privacy_markers[:6])}
|
||||||
@@ -1475,6 +1491,19 @@ def _privacy_marker_item(marker: object) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _integration_endpoint_item(endpoint: object) -> str:
|
||||||
|
name = str(getattr(endpoint, "name", "") or "integration")
|
||||||
|
kind = _enum_text(getattr(endpoint, "kind", "UNKNOWN"))
|
||||||
|
direction = str(getattr(endpoint, "direction", "UNKNOWN") or "UNKNOWN")
|
||||||
|
owner = str(getattr(endpoint, "owner", "") or "owner unavailable")
|
||||||
|
return f"""
|
||||||
|
<article class="object-context-item" data-html5-object-context-item="integration">
|
||||||
|
<strong>{escape(name)}</strong>
|
||||||
|
<small>{escape(kind)} · {escape(direction)} · {escape(owner)}</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", ""))
|
||||||
|
|||||||
@@ -1748,10 +1748,21 @@ async def html5_project_object_context(project_id: str, object_name: str) -> Res
|
|||||||
access = await get_object_access(project_id, object_name)
|
access = await get_object_access(project_id, object_name)
|
||||||
ui = await get_object_ui(project_id, object_name)
|
ui = await get_object_ui(project_id, object_name)
|
||||||
privacy = await object_privacy(project_id, object_name)
|
privacy = await object_privacy(project_id, object_name)
|
||||||
|
integrations = _integrations_for_object_context(project_id, impact)
|
||||||
runtime = _runtime_for_object_context(project_id, impact)
|
runtime = _runtime_for_object_context(project_id, impact)
|
||||||
knowledge = _knowledge_for_object_context(schema, impact, ui)
|
knowledge = _knowledge_for_object_context(schema, impact, ui)
|
||||||
return Response(
|
return Response(
|
||||||
render_html5_object_context(project_id, schema, impact, access, ui, runtime, knowledge, privacy),
|
render_html5_object_context(
|
||||||
|
project_id,
|
||||||
|
schema,
|
||||||
|
impact,
|
||||||
|
access,
|
||||||
|
ui,
|
||||||
|
runtime,
|
||||||
|
knowledge,
|
||||||
|
privacy,
|
||||||
|
integrations,
|
||||||
|
),
|
||||||
media_type="text/html; charset=utf-8",
|
media_type="text/html; charset=utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -8178,6 +8189,34 @@ def _knowledge_for_object_context(
|
|||||||
return sorted(records, key=lambda item: item.title.lower())[:12]
|
return sorted(records, key=lambda item: item.title.lower())[:12]
|
||||||
|
|
||||||
|
|
||||||
|
def _integrations_for_object_context(
|
||||||
|
project_id: str,
|
||||||
|
impact: ObjectImpactResponse,
|
||||||
|
) -> list[IntegrationEndpointResponse]:
|
||||||
|
owner_names = {
|
||||||
|
name
|
||||||
|
for group in [impact.modules, impact.routines]
|
||||||
|
for item in group
|
||||||
|
for name in [item.qualified_name, item.name]
|
||||||
|
if name
|
||||||
|
}
|
||||||
|
if not owner_names:
|
||||||
|
return []
|
||||||
|
snapshot = _project_snapshot_or_404(project_id)
|
||||||
|
return [
|
||||||
|
IntegrationEndpointResponse(
|
||||||
|
endpoint_id=endpoint.endpoint_id,
|
||||||
|
name=endpoint.name,
|
||||||
|
kind=endpoint.kind.value,
|
||||||
|
direction=endpoint.direction,
|
||||||
|
owner=endpoint.owner,
|
||||||
|
attributes=endpoint.attributes,
|
||||||
|
)
|
||||||
|
for endpoint in build_integration_topology(snapshot).endpoints
|
||||||
|
if endpoint.owner in owner_names
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
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:
|
||||||
|
|||||||
@@ -250,7 +250,19 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
)
|
)
|
||||||
module = tmp_path / "Documents" / "ЗаказПокупателя" / "Ext" / "ObjectModule.bsl"
|
module = tmp_path / "Documents" / "ЗаказПокупателя" / "Ext" / "ObjectModule.bsl"
|
||||||
module.parent.mkdir(parents=True)
|
module.parent.mkdir(parents=True)
|
||||||
module.write_text("Процедура ПровестиКоманда()\nКонецПроцедуры\n", encoding="utf-8")
|
module.write_text(
|
||||||
|
"""
|
||||||
|
Процедура ПровестиКоманда()
|
||||||
|
ПроверитьКонтрагента();
|
||||||
|
Соединение = Новый HTTPСоединение("api.example.local");
|
||||||
|
Адрес = "https://api.example.local/orders";
|
||||||
|
КонецПроцедуры
|
||||||
|
|
||||||
|
Процедура ПроверитьКонтрагента()
|
||||||
|
КонецПроцедуры
|
||||||
|
""",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
indexed = client.post("/projects/index", json={"path": str(tmp_path), "project_id": project_id})
|
indexed = client.post("/projects/index", json={"path": str(tmp_path), "project_id": project_id})
|
||||||
assert indexed.status_code == 200
|
assert indexed.status_code == 200
|
||||||
@@ -306,6 +318,10 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
assert "ФормаДокумента" in context.text
|
assert "ФормаДокумента" in context.text
|
||||||
assert "Провести" in context.text
|
assert "Провести" in context.text
|
||||||
assert "ПровестиКоманда" in context.text
|
assert "ПровестиКоманда" in context.text
|
||||||
|
assert "ПроверитьКонтрагента" in context.text
|
||||||
|
assert "HTTPConnection" in context.text
|
||||||
|
assert "https://api.example.local/orders" in context.text
|
||||||
|
assert "OUTBOUND" 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