From 07e26d139551c0b17610c6a972f7d7ad582130c2 Mon Sep 17 00:00:00 2001 From: Ali <010109ali@gmail.com> Date: Sat, 5 Apr 2025 00:04:27 +0400 Subject: [PATCH] fixed bug with universal field, and fixed table fields --- formula_editor/api.py | 11 +- .../doctype/formula_editor/formula_editor.js | 491 ++++++++++-------- 2 files changed, 289 insertions(+), 213 deletions(-) diff --git a/formula_editor/api.py b/formula_editor/api.py index d9aca4b..4b03239 100644 --- a/formula_editor/api.py +++ b/formula_editor/api.py @@ -21,15 +21,8 @@ def get_doctype_fields(doctype): "fieldtype": sub_field.fieldtype }) - # Добавляем поля для конкретных строк таблицы (первые 10 строк) - for row_idx in range(1, 11): - fields.append({ - "fieldname": f"{child.fieldname}_{row_idx}_{sub_field.fieldname}", - "label": f"{child.label} → Строка {row_idx} → {sub_field.label}", - "fieldtype": sub_field.fieldtype, - "is_row_specific": True, - "row_index": row_idx - }) + # Убираем генерацию полей для конкретных строк таблицы + # Теперь пользователь будет использовать селектор return fields @frappe.whitelist() diff --git a/formula_editor/formula_editor/doctype/formula_editor/formula_editor.js b/formula_editor/formula_editor/doctype/formula_editor/formula_editor.js index 0edf6c3..421529b 100644 --- a/formula_editor/formula_editor/doctype/formula_editor/formula_editor.js +++ b/formula_editor/formula_editor/doctype/formula_editor/formula_editor.js @@ -1718,6 +1718,7 @@ function openFormulaBuilder(frm, targetFieldname, isTableField, currentFormula, // Очистка предыдущих обработчиков и данных $modal.off('click', '.field-btn'); + $modal.off('click', '.universal-field-btn'); $resultContainer.empty(); $modal.find(".field-groups-container").empty(); @@ -1756,7 +1757,20 @@ function openFormulaBuilder(frm, targetFieldname, isTableField, currentFormula, // Обработчики для кнопок универсальных полей $modal.on('click', '.universal-field-btn', function() { const fieldId = $(this).data('field-id'); - addTokenToFormula(fieldId, 'universal-field', $resultContainer, isTableField, null, frm); + const universalFields = JSON.parse(frm.doc.universal_fields_storage || "{}"); + const field = universalFields[fieldId]; + + if (field) { + const formulaText = `univ(${field.name})`; + const $token = $(`${formulaText}×`); + $resultContainer.append($token).append(' '); + + // Добавляем обработчики для токенов + addTokenHandlers($resultContainer); + + // Переносим курсор в конец контейнера + setEndOfContentEditable($resultContainer[0]); + } }); // Показываем модальное окно @@ -1911,6 +1925,7 @@ function populateFieldsPanel($modal, frm, grouped_fields, isTableField) { const $fieldBtn = $(` - `); - - $buttonsContainer.append($fieldBtn); - } - }); - - // Добавляем группу только если есть хотя бы одно поле - if ($buttonsContainer.children().length > 0) { - // Изначально скрываем группу, будем показывать по клику на заголовок - $buttonsContainer.hide(); - $container.append($fieldGroup); - - // Добавляем обработчик для отображения/скрытия полей по клику на заголовок - $fieldGroup.find('.field-group-title').on('click', function() { - $(this).siblings('.field-buttons-container').toggle(); - }); - } - } - }); - }); - }); -} - function populateTableRowTriggerFields($modal, frm) { const $container = $modal.find(".trigger-field-groups-container"); + $container.empty(); - // Получаем информацию о табличных частях - const tableDoctypes = {}; - frappe.model.with_doctype(frm.doc.target_doctype, function() { - const meta = frappe.get_meta(frm.doc.target_doctype); - if (!meta) return; + // Добавляем секцию предопределенных событий + const $predefinedEventsGroup = $(` +
+
Предопределенные события
+
+
+ `); + + const $predefinedButtonsContainer = $predefinedEventsGroup.find('.trigger-field-buttons-container'); + + // Добавляем кнопки для предопределенных событий + const predefinedEvents = [ + { name: "При открытии документа", id: "При открытии документа" } + ]; + + predefinedEvents.forEach(event => { + const $eventBtn = $(` + + `); - meta.fields.forEach(field => { - if (field.fieldtype === 'Table' && field.options) { - tableDoctypes[field.fieldname] = field.options; - } - }); - - // Для каждой табличной части создаем группу полей строк - Object.keys(tableDoctypes).forEach(tableName => { - const childDoctype = tableDoctypes[tableName]; - - // Получаем поля дочернего DocType - frappe.model.with_doctype(childDoctype, function() { - const childMeta = frappe.get_meta(childDoctype); - if (!childMeta) return; - - // Максимальное количество строк для предпросмотра - const maxRows = 25; - - // Создаем группы для каждой строки - for (let rowIndex = 1; rowIndex <= maxRows; rowIndex++) { - const groupName = `${tableName} (Строка ${rowIndex})`; - - const $fieldGroup = $(` -
-
${groupName}
-
-
- `); - - const $buttonsContainer = $fieldGroup.find('.trigger-field-buttons-container'); - - // Добавляем поля для строки - childMeta.fields.forEach(field => { - if (field.fieldname) { - const fieldId = `${tableName}_row_${rowIndex}_${field.fieldname}`; - const $fieldBtn = $(` - - `); - - $buttonsContainer.append($fieldBtn); - } - }); - - // Добавляем группу только если есть хотя бы одно поле - if ($buttonsContainer.children().length > 0) { - // Изначально скрываем группу, будем показывать по клику на заголовок - $buttonsContainer.hide(); - $container.append($fieldGroup); - - // Добавляем обработчик для отображения/скрытия полей по клику на заголовок - $fieldGroup.find('.trigger-field-group-title').on('click', function() { - $(this).siblings('.trigger-field-buttons-container').toggle(); - }); - } - } - }); - }); + $predefinedButtonsContainer.append($eventBtn); }); + + // Добавляем группу предопределенных событий в начало контейнера + $container.prepend($predefinedEventsGroup); + + // Добавляем секцию универсальных полей, если они есть + if (frm.doc.universal_fields_storage) { + const universalFields = JSON.parse(frm.doc.universal_fields_storage || "{}"); + + if (Object.keys(universalFields).length > 0) { + const $universalFieldGroup = $(` +
+
Универсальные поля
+
+
+ `); + + const $universalButtonsContainer = $universalFieldGroup.find('.trigger-field-buttons-container'); + + Object.keys(universalFields).forEach(fieldId => { + const field = universalFields[fieldId]; + + if (!field || !field.name) return; + + const $fieldBtn = $(` + + `); + + $universalButtonsContainer.append($fieldBtn); + }); + + $container.append($universalFieldGroup); + } + } + + // Добавляем обычные поля + if (frm.grouped_trigger_fields) { + Object.keys(frm.grouped_trigger_fields).forEach(group => { + // Пропускаем пустые группы + if (!frm.grouped_trigger_fields[group] || frm.grouped_trigger_fields[group].length === 0) return; + + const $fieldGroup = $(` +
+
${group}
+
+
+ `); + + const $buttonsContainer = $fieldGroup.find('.trigger-field-buttons-container'); + + frm.grouped_trigger_fields[group].forEach(field => { + // Создаем кнопку поля с информацией о типе поля + const isTableField = group !== "Основные поля"; + const btnClass = isTableField ? "trigger-field-btn table-field-btn" : "trigger-field-btn"; + + const $fieldBtn = $(` + + `); + + $buttonsContainer.append($fieldBtn); + }); + + $container.append($fieldGroup); + }); + } + + // Добавляем группу для полей строк табличных частей + const $tableRowGroup = $(` +
+
Поля строк табличных частей
+
+ +
+
+ `); + + $container.append($tableRowGroup); + + // Добавляем обработчик для кнопки выбора поля строки табличной части + $tableRowGroup.find('.select-table-row-trigger-field').on('click', function() { + // Получаем контейнер для триггеров + const $triggerContainer = $modal.find(".trigger-result"); + + // Открываем селектор для поля строки таблицы + openTableRowFieldSelector(frm, $triggerContainer, true); + }); + + // Добавляем стили для выделения различных типов триггеров + if (!$("#trigger-field-styles").length) { + $("head").append(` + + `); + } } function addTableRowFieldsStyles() {