Добавлено быстрое создание тегов на странице списка
API функционал: - Создан endpoint /api/tags/create/ для AJAX создания тегов - Валидация: пустое имя, длина, уникальность (регистронезависимо) - Автоматическая генерация slug через модель - Возврат JSON с данными созданного тега UI функционал на странице списка тегов: - Панель быстрого создания с крупным полем ввода - Автофокус на поле при загрузке страницы - Создание тега по нажатию Enter или клику на кнопку - Индикатор загрузки (спиннер) во время создания - Блокировка поля/кнопки во время запроса - Автоматическая перезагрузка страницы после создания - Возврат фокуса в поле при ошибке - Красивые alert-сообщения об успехе/ошибке - CSRF защита Workflow: ввёл название → Enter → тег создан → фокус снова в поле → можно вводить следующий 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,24 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Панель быстрого создания тега -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title mb-3">
|
||||
<i class="bi bi-lightning-charge"></i> Быстрое создание тега
|
||||
</h5>
|
||||
<div class="input-group">
|
||||
<input type="text" id="quick-tag-input" class="form-control form-control-lg"
|
||||
placeholder="Введите название тега и нажмите Enter..."
|
||||
autocomplete="off">
|
||||
<button class="btn btn-success" id="quick-tag-btn" type="button">
|
||||
<i class="bi bi-plus-circle"></i> Создать
|
||||
</button>
|
||||
</div>
|
||||
<div id="quick-tag-message" class="mt-2"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Панель поиска и фильтров -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
@@ -144,4 +162,85 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const input = document.getElementById('quick-tag-input');
|
||||
const btn = document.getElementById('quick-tag-btn');
|
||||
const messageDiv = document.getElementById('quick-tag-message');
|
||||
|
||||
// Автофокус на поле при загрузке страницы
|
||||
input.focus();
|
||||
|
||||
function createTag() {
|
||||
const name = input.value.trim();
|
||||
|
||||
if (!name) {
|
||||
showMessage('Введите название тега', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
// Блокируем кнопку и поле во время создания
|
||||
btn.disabled = true;
|
||||
input.disabled = true;
|
||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Создание...';
|
||||
|
||||
fetch('{% url "products:api-tag-create" %}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': '{{ csrf_token }}'
|
||||
},
|
||||
body: JSON.stringify({name: name})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showMessage(`✓ Тег "${data.tag.name}" успешно создан!`, 'success');
|
||||
input.value = '';
|
||||
|
||||
// Перезагружаем страницу через 1 секунду для обновления списка
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
} else {
|
||||
showMessage('Ошибка: ' + data.error, 'danger');
|
||||
// Разблокируем поле и кнопку при ошибке
|
||||
btn.disabled = false;
|
||||
input.disabled = false;
|
||||
btn.innerHTML = '<i class="bi bi-plus-circle"></i> Создать';
|
||||
input.focus();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showMessage('Ошибка сети при создании тега', 'danger');
|
||||
// Разблокируем поле и кнопку при ошибке
|
||||
btn.disabled = false;
|
||||
input.disabled = false;
|
||||
btn.innerHTML = '<i class="bi bi-plus-circle"></i> Создать';
|
||||
input.focus();
|
||||
});
|
||||
}
|
||||
|
||||
function showMessage(text, type) {
|
||||
messageDiv.innerHTML = `<div class="alert alert-${type} alert-dismissible fade show mb-0" role="alert">
|
||||
${text}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// Обработчик клика по кнопке
|
||||
btn.addEventListener('click', createTag);
|
||||
|
||||
// Обработчик нажатия Enter
|
||||
input.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
createTag();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user