diff --git a/frontend/sfera-web/src/components/editor/ide-workspace.tsx b/frontend/sfera-web/src/components/editor/ide-workspace.tsx
index 7a5061d..111540c 100644
--- a/frontend/sfera-web/src/components/editor/ide-workspace.tsx
+++ b/frontend/sfera-web/src/components/editor/ide-workspace.tsx
@@ -3055,13 +3055,16 @@ function FormDesignerPanel({
}
}, [objectForms, selectedFormId, selectedFormQualifiedName]);
const form =
- objectForms.find((item) => item.form.lineage_id === selectedFormId) ??
objectForms.find((item) => item.form.qualified_name === selectedFormQualifiedName) ??
+ objectForms.find((item) => item.form.lineage_id === selectedFormId) ??
objectForms[0];
const commands = form?.commands.slice(0, 6) ?? [];
const formKey = form?.form.lineage_id ?? "draft";
const baseElements = useMemo(() => buildIdeFormElements(form), [form]);
const elements = elementDrafts[formKey] ?? baseElements;
+ const flatElements = useMemo(() => flattenIdeFormElements(elements), [elements]);
+ const sidebarElements = flatElements.slice(0, 160);
+ const propertyElements = flatElements.slice(0, 48);
const formTitle = titleByForm[formKey] ?? form?.form.name ?? "ФормаДокумента";
const formObjectCaption = language === "ru" ? `${formTitle} (форма 1С 8.5)` : `${formTitle} (1C 8.5 form)`;
const layout = layoutByForm[formKey] ?? "auto";
@@ -3131,10 +3134,10 @@ function FormDesignerPanel({
- {flattenIdeFormElements(elements).length === 0 ? (
+ {flatElements.length === 0 ? (
{t.none}
) : (
- flattenIdeFormElements(elements).map((element) => (
+ sidebarElements.map((element) => (
@@ -3144,6 +3147,11 @@ function FormDesignerPanel({
))
)}
+ {flatElements.length > sidebarElements.length ? (
+
+ +{flatElements.length - sidebarElements.length} {language === "ru" ? "элементов в макете" : "layout items"}
+
+ ) : null}
{t.commands}
@@ -3240,7 +3248,7 @@ function FormDesignerPanel({
-
+
@@ -3261,7 +3269,7 @@ function FormDesignerPanel({
- {flattenIdeFormElements(elements).map((element) => (
+ {propertyElements.map((element) => (
))}
+ {flatElements.length > propertyElements.length ? (
+
+ {language === "ru"
+ ? `Показаны первые ${propertyElements.length} свойств из ${flatElements.length}. Остальные элементы доступны в макете формы.`
+ : `Showing first ${propertyElements.length} properties out of ${flatElements.length}. Other items are available in the form layout.`}
+
+ ) : null}
diff --git a/frontend/sfera-web/src/lib/api.ts b/frontend/sfera-web/src/lib/api.ts
index 1c4b7aa..bd6e603 100644
--- a/frontend/sfera-web/src/lib/api.ts
+++ b/frontend/sfera-web/src/lib/api.ts
@@ -819,6 +819,9 @@ export async function getBslCompletions(
function ownerQualifiedNameForForm(formQualifiedName: string) {
const parts = formQualifiedName.split(".");
+ if (parts[0] === "ОбщаяФорма") {
+ return formQualifiedName;
+ }
return parts.length > 1 ? parts.slice(0, -1).join(".") : formQualifiedName;
}
diff --git a/services/api-server/src/api_server/main.py b/services/api-server/src/api_server/main.py
index a3709a0..620c20e 100644
--- a/services/api-server/src/api_server/main.py
+++ b/services/api-server/src/api_server/main.py
@@ -4748,12 +4748,20 @@ async def get_object_ui(project_id: str, object_name: str) -> ObjectUiResponse:
snapshot, graph = _snapshot_and_graph(project_id)
object_node = _find_graph_node(graph, object_name, _ACCESS_TARGET_KINDS)
if object_node is None:
+ object_node = _find_graph_node(graph, object_name, {NodeKind.FORM})
+ if object_node is None:
+ common_form = _common_form_ui_from_source(project_id, object_name)
+ if common_form is not None:
+ return common_form
raise HTTPException(status_code=404, detail=f"Object not found: {object_name}")
- form_lineages = {
- edge.target_lineage
- for edge in graph.edges.values()
- if edge.kind == EdgeKind.HAS_FORM and edge.source_lineage == object_node.lineage_id
- }
+ if object_node.kind == NodeKind.FORM:
+ form_lineages = {object_node.lineage_id}
+ else:
+ form_lineages = {
+ edge.target_lineage
+ for edge in graph.edges.values()
+ if edge.kind == EdgeKind.HAS_FORM and edge.source_lineage == object_node.lineage_id
+ }
return ObjectUiResponse(
object=_named_node(object_node),
forms=_hydrate_object_ui_forms_from_source(
@@ -7924,6 +7932,52 @@ def _hydrate_object_ui_forms_from_source(
]
+def _common_form_ui_from_source(project_id: str, object_name: str) -> ObjectUiResponse | None:
+ if not object_name.startswith("ОбщаяФорма."):
+ return None
+ source_root = _current_project_source_root(project_id)
+ if source_root is None:
+ return None
+ form_name = object_name.split(".", 1)[1]
+ form_file = _edt_form_file_for_object(source_root, object_name, form_name)
+ if form_file is None:
+ return None
+ try:
+ xml_objects = parse_one_c_xml_file(form_file)
+ except (OSError, UnicodeDecodeError, ET.ParseError):
+ return None
+ form_object = next((item for item in xml_objects if item.object_kind == "FORM"), None)
+ if form_object is None:
+ return None
+ source_path = form_file.as_posix()
+ form_node = NamedNode(
+ lineage_id=make_lineage_id(
+ NodeKind.FORM.value,
+ f"{project_id}:{source_path}:FORM:{form_object.qualified_name}",
+ ),
+ kind=NodeKind.FORM.value,
+ name=form_object.name,
+ qualified_name=form_object.qualified_name,
+ attributes=form_object.attributes,
+ )
+ elements = [
+ NamedNode(
+ lineage_id=make_lineage_id(
+ NodeKind.FORM_ELEMENT.value,
+ f"{project_id}:{source_path}:ELEMENT:{item.qualified_name}",
+ ),
+ kind=NodeKind.FORM_ELEMENT.value,
+ name=item.name,
+ qualified_name=item.qualified_name,
+ attributes=item.attributes,
+ )
+ for item in xml_objects
+ if item.object_kind == "ELEMENT" and item.qualified_name.startswith(f"{form_node.qualified_name}.")
+ ]
+ form = FormSemanticsResponse(form=form_node, commands=[], elements=elements, command_handlers={})
+ return ObjectUiResponse(object=form_node, forms=[form])
+
+
def _hydrate_form_elements_from_source(
project_id: str,
source_root: Path,