Add HTML5 object UI context
This commit is contained in:
@@ -321,6 +321,7 @@ def render_html5_object_context(
|
|||||||
schema: object | None,
|
schema: object | None,
|
||||||
impact: object | None,
|
impact: object | None,
|
||||||
access: object | None = None,
|
access: object | None = None,
|
||||||
|
ui: 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"""
|
||||||
@@ -339,6 +340,7 @@ def render_html5_object_context(
|
|||||||
roles = getattr(impact, "roles", []) or []
|
roles = getattr(impact, "roles", []) or []
|
||||||
jobs = getattr(impact, "jobs", []) or []
|
jobs = getattr(impact, "jobs", []) 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 []
|
||||||
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>
|
||||||
@@ -351,12 +353,13 @@ def render_html5_object_context(
|
|||||||
{_metric("Tables", len(sections))}
|
{_metric("Tables", len(sections))}
|
||||||
{_metric("Modules", len(modules))}
|
{_metric("Modules", len(modules))}
|
||||||
{_metric("Routines", len(routines))}
|
{_metric("Routines", len(routines))}
|
||||||
{_metric("Forms", len(forms))}
|
{_metric("Forms", len(ui_forms) or len(forms))}
|
||||||
{_metric("Roles", len(grants) or len(roles))}
|
{_metric("Roles", len(grants) or len(roles))}
|
||||||
</dl>
|
</dl>
|
||||||
<div class="compact-list">
|
<div class="compact-list">
|
||||||
{''.join(_named_node_item("attr", item) for item in attributes[:6]) or '<p class="muted padded">Реквизиты не найдены</p>'}
|
{''.join(_named_node_item("attr", item) for item in attributes[:6]) or '<p class="muted padded">Реквизиты не найдены</p>'}
|
||||||
{''.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(_role_access_item(item) for item in grants[:6])}
|
{''.join(_role_access_item(item) for item in grants[:6])}
|
||||||
{''.join(_named_node_item("routine", item) for item in routines[:6])}
|
{''.join(_named_node_item("routine", item) for item in routines[:6])}
|
||||||
{''.join(_named_node_item("job", item) for item in jobs[:4])}
|
{''.join(_named_node_item("job", item) for item in jobs[:4])}
|
||||||
@@ -1391,6 +1394,35 @@ def _role_access_item(grant: object) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _ui_form_item(form_semantics: object) -> str:
|
||||||
|
form = getattr(form_semantics, "form", None)
|
||||||
|
commands = getattr(form_semantics, "commands", []) or []
|
||||||
|
elements = getattr(form_semantics, "elements", []) or []
|
||||||
|
handlers = getattr(form_semantics, "command_handlers", {}) or {}
|
||||||
|
form_name = getattr(form, "qualified_name", None) or getattr(form, "name", "form")
|
||||||
|
command_names = [
|
||||||
|
str(getattr(command, "name", getattr(command, "qualified_name", "")))
|
||||||
|
for command in commands[:3]
|
||||||
|
]
|
||||||
|
handler_names = [
|
||||||
|
str(getattr(handler, "name", getattr(handler, "qualified_name", "")))
|
||||||
|
for handler in list(handlers.values())[:3]
|
||||||
|
]
|
||||||
|
details = []
|
||||||
|
if command_names:
|
||||||
|
details.append("cmd: " + ", ".join(command_names))
|
||||||
|
if handler_names:
|
||||||
|
details.append("handler: " + ", ".join(handler_names))
|
||||||
|
if elements:
|
||||||
|
details.append(f"{len(elements)} elements")
|
||||||
|
return f"""
|
||||||
|
<article class="object-context-item" data-html5-object-context-item="ui-form">
|
||||||
|
<strong>{escape(str(form_name))}</strong>
|
||||||
|
<small>{escape(" · ".join(details) or "UI metadata")}</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", ""))
|
||||||
|
|||||||
@@ -1746,8 +1746,9 @@ async def html5_project_object_context(project_id: str, object_name: str) -> Res
|
|||||||
schema = await get_object_schema(project_id, object_name)
|
schema = await get_object_schema(project_id, object_name)
|
||||||
impact = await get_object_impact(project_id, object_name)
|
impact = await get_object_impact(project_id, object_name)
|
||||||
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)
|
||||||
return Response(
|
return Response(
|
||||||
render_html5_object_context(project_id, schema, impact, access),
|
render_html5_object_context(project_id, schema, impact, access, ui),
|
||||||
media_type="text/html; charset=utf-8",
|
media_type="text/html; charset=utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,9 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
<TabularSection name="Товары" qualifiedName="Документ.ЗаказПокупателя.Товары">
|
<TabularSection name="Товары" qualifiedName="Документ.ЗаказПокупателя.Товары">
|
||||||
<Attribute name="Количество" qualifiedName="Документ.ЗаказПокупателя.Товары.Количество" />
|
<Attribute name="Количество" qualifiedName="Документ.ЗаказПокупателя.Товары.Количество" />
|
||||||
</TabularSection>
|
</TabularSection>
|
||||||
|
<Form name="ФормаДокумента" qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента">
|
||||||
|
<Command name="Провести" qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента.Провести" action="ПровестиКоманда" />
|
||||||
|
</Form>
|
||||||
</Document>
|
</Document>
|
||||||
<Role name="Менеджер" qualifiedName="Роль.Менеджер">
|
<Role name="Менеджер" qualifiedName="Роль.Менеджер">
|
||||||
<Right object="Документ.ЗаказПокупателя" read="true" write="true" post="true" />
|
<Right object="Документ.ЗаказПокупателя" read="true" write="true" post="true" />
|
||||||
@@ -245,6 +248,9 @@ def test_html5_object_context_fragment(tmp_path: Path):
|
|||||||
""",
|
""",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
module = tmp_path / "Documents" / "ЗаказПокупателя" / "Ext" / "ObjectModule.bsl"
|
||||||
|
module.parent.mkdir(parents=True)
|
||||||
|
module.write_text("Процедура ПровестиКоманда()\nКонецПроцедуры\n", 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
|
||||||
@@ -262,6 +268,9 @@ 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 "Провести" in context.text
|
||||||
|
assert "ПровестиКоманда" in context.text
|
||||||
assert "Роль.Менеджер" in context.text
|
assert "Роль.Менеджер" in context.text
|
||||||
assert "read, write, post" in context.text or "post, read, write" in context.text
|
assert "read, write, post" in context.text or "post, read, write" in context.text
|
||||||
assert "<html" not in context.text
|
assert "<html" not in context.text
|
||||||
|
|||||||
Reference in New Issue
Block a user