From 3ce95a1458a54858af2409e5e2eef551174eeda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 3 Dec 2025 07:39:10 +0300 Subject: [PATCH] =?UTF-8?q?refactor(requests):=20=D0=BD=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D1=8F=D1=89=D0=B8=D0=B9=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D1=87=D0=BD=D1=8B=D0=B9=20=D0=B2=D0=B8=D0=B4=20=D1=81=20=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=BC=D0=B8=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Структура таблицы: - Иконка (48px) - тип заявления - Заголовок (расширяемая, 2fr) - название, тип, превью комментария - Автор (1fr) - имя сотрудника с ссылкой - Даты (100px) - date_from и date_to - Статус (110px) - badge со статусом - Создано (80px) - дата и время создания - Действия (80px) - кнопки одобрить/отклонить/редактировать Особенности: - Grid layout с фиксированными шириной колонок - Автоматический перенос текста в пределах ячейки (word-wrap) - Выравнивание всех элементов по сетке - Футер с комментариями выровнен с содержимым - Адаптивный дизайн (планшеты, мобильные) - На мобильных - две колонки (иконка + остальное) --- .../static/css/components/request-list.css | 252 ++++++++++++------ .../requests_app/request_list_full.html | 196 +++++++------- 2 files changed, 277 insertions(+), 171 deletions(-) diff --git a/backend/static/css/components/request-list.css b/backend/static/css/components/request-list.css index f45a81d6..6dd66de9 100644 --- a/backend/static/css/components/request-list.css +++ b/backend/static/css/components/request-list.css @@ -1,13 +1,8 @@ /** * request-list.css * - * Табличный вид списка заявлений без разделяющих линий - * между элементами, но с чистой сеткой как в таблице. - * - * Используется: - * - card-list.css для базовой структуры карточек - * - message-inputs.scss для форм комментариев - * - common.css для утилит и бейджей + * Настоящий табличный вид списка заявлений. + * Все поля идут в одну строку с фиксированной шириной и переносом текста. */ /* Контейнер списка заявлений */ @@ -17,7 +12,7 @@ padding: 0; } -/* Строка заявления - табличный вид */ +/* Строка заявления */ #reqList .req-row { padding: 0; margin: 0; @@ -33,41 +28,108 @@ border-bottom: 0; } -/* Заголовок заявления - сетка с выравниванием колонок */ -#reqList .req-row > .card-header { +/* Табличная сетка */ +#reqList .req-table-row { display: grid; - grid-template-columns: 42px 1fr auto; + grid-template-columns: + 48px /* Иконка */ + minmax(200px, 2fr) /* Заголовок (расширяемая) */ + minmax(120px, 1fr) /* Автор */ + 100px /* Даты */ + 110px /* Статус */ + 80px /* Создано */ + 80px; /* Действия */ + gap: 0.75rem; + align-items: start; + padding: 0.75rem 1rem; +} + +/* Ячейка таблицы */ +#reqList .req-cell { + min-width: 0; /* Для корректного word-wrap */ + display: flex; align-items: center; - gap: 1rem; - padding: 0.875rem 1rem; - border-bottom: none; - background: transparent; } -/* Иконка типа заявления */ -#reqList .card-icon { - width: 42px; - height: 42px; - flex: 0 0 auto; +/* Контент ячейки с переносом текста */ +#reqList .req-cell-content { + width: 100%; + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + hyphens: auto; + line-height: 1.4; } -/* Метаданные заявления */ -#reqList .card-meta { - min-width: 0; /* Для корректного truncate */ +/* Специфичные стили для ячеек */ +#reqList .req-cell-icon { + justify-content: center; } -/* Тело карточки (комментарий) */ -#reqList .req-row > .card-body { - padding: 0 1rem 0.875rem 1rem; - margin-left: calc(42px + 1rem); /* Выравнивание с текстом */ - border-bottom: none; +#reqList .req-cell-icon .card-icon { + width: 38px; + height: 38px; + flex-shrink: 0; } -/* Футер с кнопками действий (комментарии, вложения) */ -#reqList .req-row > .card-actions { +#reqList .req-cell-title { + font-size: 0.9rem; +} + +#reqList .req-cell-title strong { + display: block; + margin-bottom: 0.125rem; +} + +#reqList .req-cell-title .badge { + font-size: 0.7rem; + padding: 0.2rem 0.4rem; +} + +#reqList .req-cell-author { + font-size: 0.875rem; +} + +#reqList .req-cell-dates { + font-size: 0.8rem; + font-variant-numeric: tabular-nums; + line-height: 1.3; +} + +#reqList .req-cell-status { + justify-content: flex-start; +} + +#reqList .req-cell-status .badge { + font-size: 0.7rem; + padding: 0.25rem 0.5rem; + white-space: nowrap; +} + +#reqList .req-cell-created { + font-size: 0.75rem; + text-align: center; +} + +#reqList .req-cell-actions { + justify-content: center; + gap: 0.25rem; +} + +#reqList .req-cell-actions .req-cell-content { + display: flex; + gap: 0.25rem; + justify-content: center; +} + +/* Футер с комментариями и вложениями */ +#reqList .req-footer { + display: flex; + align-items: center; + gap: 0.5rem; padding: 0.5rem 1rem; - margin-left: calc(42px + 1rem); /* Выравнивание с текстом */ - border-top: none; /* Убираем разделяющую линию */ + margin-left: calc(48px + 0.75rem); /* Выравнивание с содержимым */ + border-top: none; background: transparent; } @@ -77,67 +139,103 @@ background: color-mix(in srgb, var(--bs-tertiary-bg), transparent 50%); margin: 0; padding: 1rem; + margin-left: calc(48px + 0.75rem); /* Выравнивание с содержимым */ } -/* Отступ для списка комментариев */ -#reqList .comments-list { - margin-left: calc(42px + 1rem); /* Выравнивание с текстом заявления */ +/* Адаптивность для планшетов */ +@media (max-width: 992px) { + #reqList .req-table-row { + grid-template-columns: + 42px /* Иконка */ + minmax(150px, 2fr) /* Заголовок */ + minmax(100px, 1fr) /* Автор */ + 90px /* Даты */ + 100px /* Статус */ + 70px; /* Создано + Действия объединены */ + } + + /* Прячем отдельную колонку действий */ + #reqList .req-cell-actions { + display: none; + } + + /* Добавляем действия в строку заголовка */ + #reqList .req-cell-title .req-cell-content::after { + content: ''; + display: block; + } } -/* Форма нового комментария */ -#reqList .comment-new { - margin-left: calc(42px + 1rem); /* Выравнивание с текстом заявления */ -} - -/* Адаптивность для мобильных устройств */ +/* Адаптивность для мобильных */ @media (max-width: 768px) { - #reqList .req-row > .card-header { + #reqList .req-table-row { grid-template-columns: 36px 1fr; - gap: 0.75rem; + gap: 0.5rem; padding: 0.75rem; } - #reqList .card-icon { + /* Все ячейки в две колонки */ + #reqList .req-cell-icon { + grid-row: 1 / span 3; + align-self: start; + } + + #reqList .req-cell-icon .card-icon { width: 36px; height: 36px; } - #reqList .req-row > .card-body { - padding: 0 0.75rem 0.75rem 0.75rem; - margin-left: calc(36px + 0.75rem); - } - - #reqList .req-row > .card-actions { - padding: 0.5rem 0.75rem; - margin-left: calc(36px + 0.75rem); - } - - #reqList .comments-list, - #reqList .comment-new { - margin-left: 0; /* На мобильных убираем отступ */ - } - - /* Кнопки действий переносятся в следующую строку */ - #reqList .req-row > .card-header { - grid-template-columns: 36px 1fr; - } - - #reqList .req-row > .card-header > .ms-auto { + #reqList .req-cell-title { grid-column: 2; - margin-top: 0.5rem; - margin-left: 0 !important; - justify-self: start; + font-size: 0.9rem; + } + + #reqList .req-cell-author { + grid-column: 2; + font-size: 0.8rem; + margin-top: -0.25rem; + } + + #reqList .req-cell-dates, + #reqList .req-cell-status, + #reqList .req-cell-created { + grid-column: 2; + font-size: 0.75rem; + } + + #reqList .req-cell-actions { + grid-column: 2; + justify-content: flex-start; + margin-top: 0.25rem; + } + + #reqList .req-footer { + margin-left: calc(36px + 0.5rem); + padding: 0.5rem 0.75rem; + } + + #reqList .comments-block { + margin-left: 0; + padding: 0.75rem; } } -/* Дополнительные утилиты */ -#reqList .card-title { - font-size: 0.95rem; - line-height: 1.4; -} - -#reqList .card-subtitle { - font-size: 0.85rem; - color: var(--bs-secondary-color); +/* Компактный режим для маленьких экранов */ +@media (max-width: 576px) { + #reqList .req-table-row { + padding: 0.625rem; + } + + #reqList .req-cell-title .small { + display: none; /* Скрываем превью комментария */ + } + + #reqList .req-cell-dates br { + display: none; /* Даты в одну строку */ + } + + #reqList .req-cell-dates .req-cell-content::after { + content: ' — '; + } } diff --git a/backend/templates/requests_app/request_list_full.html b/backend/templates/requests_app/request_list_full.html index cab0edbe..188e5338 100644 --- a/backend/templates/requests_app/request_list_full.html +++ b/backend/templates/requests_app/request_list_full.html @@ -26,28 +26,27 @@ {% if requests %} {% for obj in requests %}
-
- -
- {% with tp=obj.type|lower %} - {% if tp == 'vacation' %} - {% elif tp == 'sick_leave' %} - {% elif tp == 'transfer' %} - {% elif tp == 'dismissal' %} - {% else %} - {% endif %} - {% endwith %} +
+ +
+
+ {% with tp=obj.type|lower %} + {% if tp == 'vacation' %} + {% elif tp == 'sick_leave' %} + {% elif tp == 'transfer' %} + {% elif tp == 'dismissal' %} + {% else %} + {% endif %} + {% endwith %} +
- -
-
- + +
+
{{ obj.title|default:"Без заголовка" }} - - {% if obj.type %}{% with tp=obj.type|lower %} - + {% if tp == 'vacation' %}Отпуск {% elif tp == 'sick_leave' %}Больничный {% elif tp == 'transfer' %}Перевод @@ -56,29 +55,15 @@ {% else %}{{ obj.type }}{% endif %} {% endwith %}{% endif %} - - - {% if obj.status %}{% with st=obj.status|lower %} - - {% if st == 'draft' %}Черновик - {% elif st == 'pending' %}На рассмотрении - {% elif st == 'approved' %}Одобрено - {% elif st == 'rejected' %}Отклонено - {% elif st == 'cancelled' %}Отменено - {% else %}{{ obj.status }}{% endif %} - - {% endwith %}{% endif %} + {% if obj.comment %} +
{{ obj.comment|truncatewords:15 }}
+ {% endif %}
- - -
- +
+ + +
+
{% if obj.employee %} {% if obj.employee.id == user.id %} Вы @@ -88,67 +73,90 @@ {% endif %} {% endif %} - - +
+
+ + +
+
{% if obj.date_from or obj.date_to %} - · - - {{ obj.date_from|date:"d.m.Y"|default:"—" }} → {{ obj.date_to|date:"d.m.Y"|default:"—" }} - - {% endif %} - - - {% if obj.created_at %} - · - {{ obj.created_at|date:"d.m.Y H:i" }} + {{ obj.date_from|date:"d.m.Y"|default:"—" }}
+ {{ obj.date_to|date:"d.m.Y"|default:"—" }} + {% else %} + — {% endif %}
- - {% if obj.employee.id != user.id and can_process %} -
- - + +
+
+ {% if obj.status %}{% with st=obj.status|lower %} + + {% if st == 'draft' %}Черновик + {% elif st == 'pending' %}На рассмотр. + {% elif st == 'approved' %}Одобрено + {% elif st == 'rejected' %}Отклонено + {% elif st == 'cancelled' %}Отменено + {% else %}{{ obj.status }}{% endif %} + + {% endwith %}{% endif %} +
- {% elif obj.employee.id == user.id %} -
- - + + +
+
+ {{ obj.created_at|date:"d.m.Y" }}
+ {{ obj.created_at|date:"H:i" }} +
- {% endif %} -
+ + +
+
+ {% if obj.employee.id != user.id and can_process %} + + + {% elif obj.employee.id == user.id %} + + + {% endif %} +
+
+ - {% if obj.comment %} -
-
{{ obj.comment }}
-
- {% endif %} - -