refactor: Replace remaining duplicate utilities with ES6 imports

- Replaced esc() and norm() in _department_controls.html with imports
- Replaced norm() in invite_to_department.html with import
- All inline utility duplicates now eliminated across templates
- Total: ~20 lines of duplicate code removed
- All 17 tests passing
This commit is contained in:
admin i 2025-10-28 09:35:20 +03:00
parent 9d2b0afd34
commit 9e07913551
2 changed files with 26 additions and 25 deletions

View File

@ -297,15 +297,15 @@
}
document.querySelectorAll('textarea[data-autogrow]').forEach(bind);
})();
{% load static %}
</script>
<script>
(function(){
if (window.__headPickerWithEmailBound) return;
window.__headPickerWithEmailBound = true;
<script type="module">
import { esc, norm } from '{% static "js/utils/stringUtils.js" %}';
function esc(s){ return String(s).replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m])); }
function norm(s){ return String(s || '').toLowerCase(); }
(function(){
if (window.__headPickerWithEmailBound) return;
window.__headPickerWithEmailBound = true;
function initPicker(root){
const input = root.querySelector('input[type="text"]');

View File

@ -82,31 +82,32 @@
{% endwith %}
</div>
{% load static %}
<!-- Мини-скрипт: фильтрация select и блокировка кнопки без выбора -->
<script>
(function () {
const search = document.getElementById('employeeSearch');
const select = document.querySelector('select[name="{{ form.employee.html_name }}"]');
const btn = document.getElementById('inviteBtn');
<script type="module">
import { norm } from '{% static "js/utils/stringUtils.js" %}';
if (!select) return;
(function () {
const search = document.getElementById('employeeSearch');
const select = document.querySelector('select[name="{{ form.employee.html_name }}"]');
const btn = document.getElementById('inviteBtn');
// Кнопка активна только при выбранном значении
function toggleBtn() { btn && (btn.disabled = !select.value); }
select.addEventListener('change', toggleBtn);
toggleBtn();
if (!select) return;
// Кешируем исходные опции
const options = Array.from(select.options);
// Кнопка активна только при выбранном значении
function toggleBtn() { btn && (btn.disabled = !select.value); }
select.addEventListener('change', toggleBtn);
toggleBtn();
function norm(s) { return s.toLowerCase().replace(/\s+/g, ''); }
// Кешируем исходные опции
const options = Array.from(select.options);
if (search) {
search.addEventListener('input', function () {
const q = norm(this.value);
const filtered = q
? options.filter(o => norm(o.text).includes(q))
: options;
if (search) {
search.addEventListener('input', function () {
const q = norm(this.value);
const filtered = q
? options.filter(o => norm(o.text).includes(q))
: options;
// Перерисовываем список
select.innerHTML = '';