diff --git a/HISTORY.md b/HISTORY.md index 082e5f5..5e8bbd6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,14 @@ # История изменений ERP WaterSurf -# История изменений ERP WaterSurf +## 2025-02-25 23:15 UTC – Удаление строки табличной части по кнопке-крестику + +**Проблема**: Удаление строки происходило при сохранении документа (чекбокс «Удалить»), что было неочевидно и неудобно. + +**Решение**: В формах заказа клиента и заказа поставщику чекбокс и подпись «Удалить» заменены на кнопку в виде красного крестика (×). По нажатию строка сразу удаляется из DOM, индексы полей formset пересчитываются (reindexRows), обновляется TOTAL_FORMS и пересчёт сумм по строкам. При добавлении новой строки после вставки клона также вызывается reindexRows(). + +**Изменения**: order_form.html (кнопка .ws-btn-remove-row, reindexRows, делегированный click на tbody), supplier_order_form.html (аналогично), theme-compact.css (стили .ws-btn-remove-row — красный крестик, hover; удалены стили .ws-delete-row-label). + +--- ## 2025-02-25 22:50 UTC – Добавление строки: одна строка за клик, понятное удаление diff --git a/app/static/css/theme-compact.css b/app/static/css/theme-compact.css index d08d353..67f7f77 100644 --- a/app/static/css/theme-compact.css +++ b/app/static/css/theme-compact.css @@ -132,11 +132,25 @@ width: 5%; } -.ws-table-items label.ws-delete-row-label { +.ws-table-items .ws-btn-remove-row { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + padding: 0; + border: none; + border-radius: 4px; + background: transparent; + color: #c62828; + font-size: 18px; + line-height: 1; cursor: pointer; - font-size: 13px; - color: var(--ws-text-muted); - white-space: nowrap; +} + +.ws-table-items .ws-btn-remove-row:hover { + background: rgba(198, 40, 40, 0.12); + color: #b71c1c; } .ws-table-items .ws-col-product select { diff --git a/app/templates/documents/order_form.html b/app/templates/documents/order_form.html index 6f6378d..ec1a246 100644 --- a/app/templates/documents/order_form.html +++ b/app/templates/documents/order_form.html @@ -72,7 +72,7 @@ {{ f.currency }} {{ f.quantity }} — - + {% endfor %} @@ -133,6 +133,34 @@ updateRowAmounts(); + function reindexRows() { + var prefix = getPrefix(); + var rows = tbody.querySelectorAll('.item-row'); + rows.forEach(function(row, i) { + row.querySelectorAll('input, select').forEach(function(el) { + var n = el.getAttribute('name'); + if (n && n.indexOf(prefix) === 0) { + el.setAttribute('name', n.replace(new RegExp('^' + prefix + '\\d+'), prefix + i)); + } + var id = el.getAttribute('id'); + if (id) { + el.setAttribute('id', id.replace(new RegExp(prefix + '\\d+'), prefix + i)); + } + }); + }); + totalInput.value = String(rows.length); + updateRowAmounts(); + } + + tbody.addEventListener('click', function(e) { + var btn = e.target.closest('.ws-btn-remove-row'); + if (!btn) return; + var row = btn.closest('tr.item-row'); + if (!row) return; + row.remove(); + reindexRows(); + }); + document.getElementById('add-order-row').addEventListener('click', function() { var rows = tbody.querySelectorAll('.item-row'); var lastRow = rows[rows.length - 1]; @@ -156,13 +184,8 @@ }); var amountCell = clone.querySelector('.row-amount'); if (amountCell) amountCell.textContent = '—'; - var delCheckbox = clone.querySelector('input[name$="-DELETE"]'); - if (delCheckbox) { - var delLabel = clone.querySelector('label.ws-delete-row-label'); - if (delLabel) delLabel.setAttribute('for', delCheckbox.id); - } tbody.appendChild(clone); - totalInput.value = nextIndex + 1; + reindexRows(); }); })(); diff --git a/app/templates/documents/supplier_order_form.html b/app/templates/documents/supplier_order_form.html index a8d7b39..5301379 100644 --- a/app/templates/documents/supplier_order_form.html +++ b/app/templates/documents/supplier_order_form.html @@ -79,7 +79,7 @@ {{ f.currency }} {{ f.quantity }} — - + {% endfor %} @@ -138,6 +138,34 @@ updateRowAmounts(); + function reindexRows() { + var prefix = getPrefix(); + var rows = tbody.querySelectorAll('.item-row'); + rows.forEach(function(row, i) { + row.querySelectorAll('input, select').forEach(function(el) { + var n = el.getAttribute('name'); + if (n && n.indexOf(prefix) === 0) { + el.setAttribute('name', n.replace(new RegExp('^' + prefix + '\\d+'), prefix + i)); + } + var id = el.getAttribute('id'); + if (id) { + el.setAttribute('id', id.replace(new RegExp(prefix + '\\d+'), prefix + i)); + } + }); + }); + totalInput.value = String(rows.length); + updateRowAmounts(); + } + + tbody.addEventListener('click', function(e) { + var btn = e.target.closest('.ws-btn-remove-row'); + if (!btn) return; + var row = btn.closest('tr.item-row'); + if (!row) return; + row.remove(); + reindexRows(); + }); + document.getElementById('add-supplier-order-row').addEventListener('click', function() { var rows = tbody.querySelectorAll('.item-row'); var lastRow = rows[rows.length - 1]; @@ -151,9 +179,7 @@ el.setAttribute('name', name.replace(new RegExp('^' + prefix + '\\d+-'), prefix + nextIndex + '-')); el.setAttribute('id', (el.getAttribute('id') || '').replace(new RegExp(prefix + '\\d+-'), prefix + nextIndex + '-')); } - if (el.name && el.name.indexOf('-DELETE') !== -1) { - el.checked = false; - } else if (el.name && el.name.indexOf('-id') !== -1) { + if (el.name && el.name.indexOf('-id') !== -1) { el.value = ''; } else if (el.type !== 'hidden') { el.value = ''; @@ -161,13 +187,8 @@ }); var amountCell = clone.querySelector('.row-amount'); if (amountCell) amountCell.textContent = '—'; - var delCheckbox = clone.querySelector('input[name$="-DELETE"]'); - if (delCheckbox) { - var delLabel = clone.querySelector('label.ws-delete-row-label'); - if (delLabel) delLabel.setAttribute('for', delCheckbox.id); - } tbody.appendChild(clone); - totalInput.value = nextIndex + 1; + reindexRows(); }); })();