Добавлена поддержка автосохранения товаров в черновиках заказов

- Исправлен ID контейнера формсета (order-items-container)
- Добавлена поддержка событий Select2 для полей выбора товара
- Добавлен MutationObserver для отслеживания новых форм товаров
- Удалены отладочные console.log

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 13:32:21 +03:00
parent 9530dd15eb
commit 58dd60b19a

View File

@@ -25,25 +25,20 @@
* Инициализация модуля автосохранения * Инициализация модуля автосохранения
*/ */
function init() { function init() {
console.log('[Autosave] Attempting to initialize...');
// Проверяем, что мы на странице редактирования // Проверяем, что мы на странице редактирования
const isEditPage = window.location.pathname.includes('/edit/'); const isEditPage = window.location.pathname.includes('/edit/');
if (!isEditPage) { if (!isEditPage) {
console.log('[Autosave] Not on edit page, exiting');
return; return;
} }
const orderForm = document.getElementById('order-form'); const orderForm = document.getElementById('order-form');
if (!orderForm) { if (!orderForm) {
console.log('[Autosave] Order form not found, exiting');
return; return;
} }
// Получаем ID заказа из URL // Получаем ID заказа из URL
const urlMatch = window.location.pathname.match(/\/orders\/(\d+)\/edit\//); const urlMatch = window.location.pathname.match(/\/orders\/(\d+)\/edit\//);
if (!urlMatch) { if (!urlMatch) {
console.log('[Autosave] Could not extract order ID from URL, exiting');
return; return;
} }
orderId = urlMatch[1]; orderId = urlMatch[1];
@@ -51,12 +46,9 @@
// Проверяем, является ли заказ черновиком // Проверяем, является ли заказ черновиком
isDraft = checkIfDraft(); isDraft = checkIfDraft();
if (!isDraft) { if (!isDraft) {
console.log('[Autosave] Not a draft order, exiting');
return; return;
} }
console.log('[Autosave] Initialized for draft order #' + orderId);
// Инициализируем UI индикатора // Инициализируем UI индикатора
initStatusIndicator(); initStatusIndicator();
@@ -71,7 +63,6 @@
// Проверяем через data-атрибут на форме // Проверяем через data-атрибут на форме
const form = document.getElementById('order-form'); const form = document.getElementById('order-form');
if (form && form.dataset.isDraft === 'true') { if (form && form.dataset.isDraft === 'true') {
console.log('[Autosave] Form has data-is-draft="true"');
return true; return true;
} }
@@ -165,12 +156,9 @@
function attachEventListeners() { function attachEventListeners() {
const form = document.getElementById('order-form'); const form = document.getElementById('order-form');
if (!form) { if (!form) {
console.log('[Autosave] Form not found in attachEventListeners');
return; return;
} }
console.log('[Autosave] Attaching event listeners to form fields');
// Слушаем изменения в основных полях заказа // Слушаем изменения в основных полях заказа
const fieldsToWatch = [ const fieldsToWatch = [
'select[name="customer"]', 'select[name="customer"]',
@@ -202,15 +190,13 @@
// Слушаем изменения в формах товаров (formset) // Слушаем изменения в формах товаров (formset)
observeFormsetChanges(); observeFormsetChanges();
console.log('[Autosave] Event listeners attached');
} }
/** /**
* Наблюдает за изменениями в формсете товаров * Наблюдает за изменениями в формсете товаров
*/ */
function observeFormsetChanges() { function observeFormsetChanges() {
const formsetContainer = document.getElementById('order-items-formset'); const formsetContainer = document.getElementById('order-items-container');
if (!formsetContainer) { if (!formsetContainer) {
return; return;
} }
@@ -242,9 +228,15 @@
} }
const fields = form.querySelectorAll('select, input[type="number"], input[type="checkbox"]'); const fields = form.querySelectorAll('select, input[type="number"], input[type="checkbox"]');
fields.forEach(field => { fields.forEach(field => {
if (field.tagName === 'SELECT' || field.type === 'checkbox') { if (field.tagName === 'SELECT' || field.type === 'checkbox') {
field.addEventListener('change', scheduleAutosave); field.addEventListener('change', scheduleAutosave);
// Для Select2 добавляем дополнительный обработчик
if (window.jQuery && jQuery(field).data('select2')) {
jQuery(field).on('select2:select', scheduleAutosave);
}
} else { } else {
field.addEventListener('input', scheduleAutosave); field.addEventListener('input', scheduleAutosave);
} }
@@ -267,8 +259,6 @@
autosaveTimer = setTimeout(() => { autosaveTimer = setTimeout(() => {
performAutosave(); performAutosave();
}, CONFIG.AUTOSAVE_DELAY); }, CONFIG.AUTOSAVE_DELAY);
console.log('[Autosave] Scheduled in ' + CONFIG.AUTOSAVE_DELAY + 'ms');
} }
/** /**
@@ -276,7 +266,6 @@
*/ */
async function performAutosave() { async function performAutosave() {
if (isAutosaving) { if (isAutosaving) {
console.log('[Autosave] Already in progress, skipping');
return; return;
} }
@@ -303,15 +292,12 @@
if (response.ok && data.success) { if (response.ok && data.success) {
const lastSaved = formatDateTime(data.last_saved); const lastSaved = formatDateTime(data.last_saved);
showStatus('success', 'Сохранено ' + lastSaved); showStatus('success', 'Сохранено ' + lastSaved);
console.log('[Autosave] Success:', data);
} else { } else {
showStatus('error', 'Ошибка: ' + (data.error || 'Неизвестная ошибка')); showStatus('error', 'Ошибка: ' + (data.error || 'Неизвестная ошибка'));
console.error('[Autosave] Error:', data);
} }
} catch (error) { } catch (error) {
showStatus('error', 'Ошибка соединения с сервером'); showStatus('error', 'Ошибка соединения с сервером');
console.error('[Autosave] Exception:', error);
} finally { } finally {
isAutosaving = false; isAutosaving = false;
} }
@@ -408,7 +394,7 @@
const items = []; const items = [];
const itemForms = document.querySelectorAll('.order-item-form'); const itemForms = document.querySelectorAll('.order-item-form');
itemForms.forEach((form, index) => { itemForms.forEach(form => {
// Пропускаем удаленные формы // Пропускаем удаленные формы
const deleteCheckbox = form.querySelector('input[name$="-DELETE"]'); const deleteCheckbox = form.querySelector('input[name$="-DELETE"]');
if (deleteCheckbox && deleteCheckbox.checked) { if (deleteCheckbox && deleteCheckbox.checked) {