fix(requests): сохраняем шапку таблицы при ajax загрузке, исправлен порядок, счетчик комментариев, preventDefault для Enter

- Добавлен отдельный контейнер для данных заявлений
- JS работает только с #reqListContent, шапка всегда видна
- Исправлен порядок заявлений (order_by)
- comments_count через annotate
- Исправлен обработчик формы комментария (preventDefault)
- Удаление начального спиннера после загрузки
This commit is contained in:
admin i 2025-12-05 15:59:21 +03:00
parent c65558f5a2
commit c364d0635a
5 changed files with 27 additions and 10 deletions

View File

@ -87,6 +87,8 @@ class RequestReadSerializer(serializers.ModelSerializer):
recipient_count = serializers.SerializerMethodField()
cc_count = serializers.SerializerMethodField()
is_recipient = serializers.SerializerMethodField()
# Используем аннотированное поле из queryset
comments_count = serializers.IntegerField(read_only=True)
class Meta:
model = Request
@ -116,6 +118,7 @@ class RequestReadSerializer(serializers.ModelSerializer):
"recipient_count",
"cc_count",
"is_recipient",
"comments_count",
)
read_only_fields = (
"employee",
@ -132,6 +135,7 @@ class RequestReadSerializer(serializers.ModelSerializer):
"recipient_count",
"cc_count",
"is_recipient",
"comments_count",
)
def get_recipient_count(self, obj):

View File

@ -2,7 +2,7 @@ from __future__ import annotations
from typing import Any, List, Optional # было: Any, Dict, List, Type
from django.db.models import Q, QuerySet
from django.db.models import Q, QuerySet, Count
from django.shortcuts import get_object_or_404 # раскомментируйте импорт
from employees.models import EmployeeDepartment, Department # добавлен Department
from requests_app.models import Request as EmployeeRequest
@ -59,7 +59,9 @@ class RequestViewSet(viewsets.ModelViewSet):
queryset = EmployeeRequest.objects.select_related(
"employee", "approver", "department"
).all()
).annotate(
comments_count=Count('comments')
).order_by('-created_at')
parser_classes = (MultiPartParser, FormParser, JSONParser)
# Используем глобальную пагинацию из settings (PageNumberPagination, PAGE_SIZE=20)

View File

@ -153,8 +153,11 @@ export function initRequestCommentsHandler(options) {
async function handleCommentSubmit(e) {
const form = e.target;
// Проверяем, что это форма комментария внутри блока заявки
if (!form.matches(`${collapseSelector} form[data-role=form]`)) return;
// Проверяем, что это форма комментария
if (!form.matches('form[data-role=form]')) return;
// Проверяем, что форма находится внутри блока заявки
if (!form.closest(collapseSelector)) return;
e.preventDefault();
e.stopPropagation();

View File

@ -22,11 +22,11 @@ export function initRequestListHandler(options) {
headers = {}
} = options;
const listElement = document.getElementById('reqList');
const listElement = document.getElementById('reqListContent');
const searchInput = document.getElementById('reqFilter');
if (!listElement) {
console.warn('initRequestListHandler: #reqList not found');
console.warn('initRequestListHandler: #reqListContent not found');
return { load: () => {}, destroy: () => {} };
}
@ -158,6 +158,11 @@ export function initRequestListHandler(options) {
if (spinner) {
spinner.remove();
}
// Удаляем начальный спиннер из шаблона
const initialSpinner = document.getElementById('reqListLoading');
if (initialSpinner) {
initialSpinner.remove();
}
}
/**

View File

@ -49,10 +49,13 @@
</div>
</div>
{# Список загружается через JavaScript из requestListHandler.js #}
<div class="text-center py-4" id="reqListLoading">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Загрузка...</span>
{# Контейнер для данных заявлений #}
<div id="reqListContent">
{# Список загружается через JavaScript из requestListHandler.js #}
<div class="text-center py-4" id="reqListLoading">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
</div>
</div>
</div>