Render forms from indexed form elements
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-21 05:30:53 +03:00
parent d26aaef44a
commit 5bd188fe6f
5 changed files with 86 additions and 83 deletions
@@ -3049,7 +3049,7 @@ function FormDesignerPanel({
const form = 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(data, form), [data, form]);
const baseElements = useMemo(() => buildIdeFormElements(form), [form]);
const elements = elementDrafts[formKey] ?? baseElements;
const formTitle = titleByForm[formKey] ?? form?.form.name ?? "ФормаДокумента";
const formObjectCaption = language === "ru" ? `${formTitle} (форма 1С 8.5)` : `${formTitle} (1C 8.5 form)`;
@@ -3057,9 +3057,9 @@ function FormDesignerPanel({
useEffect(() => {
if (form && !elementDrafts[form.form.lineage_id]) {
setElementDrafts((current) => ({ ...current, [form.form.lineage_id]: buildIdeFormElements(data, form) }));
setElementDrafts((current) => ({ ...current, [form.form.lineage_id]: buildIdeFormElements(form) }));
}
}, [data, elementDrafts, form]);
}, [elementDrafts, form]);
const updateElement = (id: string, patch: Partial<IdeFormElementDraft>) => {
setElementDrafts((current) => ({
@@ -3175,9 +3175,23 @@ function FormDesignerPanel({
"grid grid-cols-12 gap-x-3 gap-y-2 p-5",
layout === "compact" ? "gap-y-1" : ""
].join(" ")}>
{elements.map((element) => (
<IdeFormControl element={element} forceHalf={layout === "columns"} key={element.id} />
))}
{elements.length ? (
elements.map((element) => (
<IdeFormControl element={element} forceHalf={layout === "columns"} key={element.id} />
))
) : (
<div className="col-span-12 border border-dashed border-[#aeb8c6] bg-white px-4 py-6 text-sm text-slate-600" data-ide-form-empty>
<div className="font-semibold text-slate-900">{language === "ru" ? "Структура элементов формы не загружена" : "Form element structure is not loaded"}</div>
<div className="mt-1 text-xs">
{form?.form.qualified_name ?? form?.form.name ?? data.projectId}
</div>
<div className="mt-3 text-xs">
{language === "ru"
? "В текущем индексе для этой формы нет узлов элементов. SFERA не подставляет шаблонные поля, чтобы не искажать объект 1С."
: "The current index has no element nodes for this form. SFERA does not insert template fields because that would distort the 1C object."}
</div>
</div>
)}
</div>
<div className="mt-auto border-t border-[#ccd4df] bg-white px-4 py-3">
@@ -3306,7 +3320,7 @@ function ideFormControlInput(element: IdeFormElementDraft) {
if (element.controlKind === "text") {
return <textarea className="min-h-16 resize-none border border-[#aeb8c6] bg-white px-2 py-1 text-xs" readOnly value={element.binding} />;
}
return <input className="h-7 border border-[#aeb8c6] bg-white px-2 text-xs" readOnly value={element.controlKind === "date" ? "21.05.2026 0:00:00" : element.binding} />;
return <input className="h-7 border border-[#aeb8c6] bg-white px-2 text-xs" readOnly value={element.binding} />;
}
function IdeFormMetric({ label, value }: Readonly<{ label: string; value: number }>) {
@@ -3318,7 +3332,7 @@ function IdeFormMetric({ label, value }: Readonly<{ label: string; value: number
);
}
function buildIdeFormElements(data: ProjectWorkspaceData, form: ProjectWorkspaceData["forms"][number] | undefined): IdeFormElementDraft[] {
function buildIdeFormElements(form: ProjectWorkspaceData["forms"][number] | undefined): IdeFormElementDraft[] {
const explicitElements = form?.elements ?? [];
if (explicitElements.length) {
return explicitElements.map((element, index) => ({
@@ -3330,38 +3344,7 @@ function buildIdeFormElements(data: ProjectWorkspaceData, form: ProjectWorkspace
width: "stretch"
}));
}
const attributes = data.selectedObjectSchema?.attributes ?? [];
const tabularSections = data.selectedObjectSchema?.tabular_sections ?? [];
const fromSchema: IdeFormElementDraft[] = [
...attributes.map((attribute, index) => ({
id: attribute.lineage_id || `attribute.${index}`,
name: attribute.name,
caption: attribute.name,
controlKind: controlKindForFormNode(attribute.name, attribute.kind),
binding: attribute.name,
width: index < 2 ? "half" : "stretch"
} satisfies IdeFormElementDraft)),
...tabularSections.map((section, index) => ({
id: section.tabular_section.lineage_id || `table.${index}`,
name: section.tabular_section.name,
caption: section.tabular_section.name,
controlKind: "table" as const,
binding: section.tabular_section.name,
width: "stretch" as const
}))
];
if (fromSchema.length) {
return fromSchema;
}
const formName = form?.form.name ?? "ФормаДокумента";
if (formName.includes("ФормаДокумента")) {
return [
{ id: "default.number", name: "Номер", caption: "Номер", controlKind: "input", binding: "Объект.Номер", width: "half" },
{ id: "default.date", name: "Дата", caption: "Дата", controlKind: "date", binding: "Объект.Дата", width: "half" },
{ id: "default.table", name: "Товары", caption: "Товары", controlKind: "table", binding: "Объект.Товары", width: "stretch" }
];
}
return [{ id: "default.name", name: "Наименование", caption: "Наименование", controlKind: "input", binding: "Объект.Наименование", width: "stretch" }];
return [];
}
function controlKindForFormNode(name: string, kind: string): IdeFormElementDraft["controlKind"] {