- employee_list.html:
• убраны лишние внешние отступы у карточек сотрудников
• нормализованы внутренние паддинги (feed-hd, feed-actions, feed-body)
• добавлены стили для более компактного списка (#empList)
- department_detail.html:
• добавлены блоки управления отделом для staff и руководителя:
- редактирование названия и описания (POST /departments/<id>/edit/)
- назначение/снятие руководителя (POST /departments/<id>/set-head/)
• секция «Команда отдела» теперь показывает только сотрудников с назначенными ролями
• реализована форма изменения роли участника (POST /departments/<id>/set_member_role/)
доступно только staff и руководителю, кроме самого себя
• исправлены условия в шаблоне (убран синтаксис с круглыми скобками)
• корректный вывод ФИО и fallback «Сотрудник #id», если данных нет
• ссылки на сотрудников и отделы нормализованы через {% url %}
• сообщения «пока нет сотрудников» и «пока нет публикаций» для пустых состояний
- views_front.py:
• department_detail теперь подтягивает:
- dept (детали отдела)
- roles (роли отдела)
- links (активные employee-departments)
- posts (публикации отдела)
• department_edit: редирект исправлен на employees:department_detail
• department_set_head и set_member_role проксируют данные в API и возвращают флеш-сообщения
- базовый шаблон:
• уточнено, что стили можно выносить в base.html
• сохранён общий вид feed-card, но для списка сотрудников применяется упрощённый layout
Итог: появилась полноценная страница отдела —
редактируем основные поля, управляем руководителем,
назначаем роли сотрудникам. Список сотрудников в отделе
отображается компактно и с корректными отступами.
Основное
- Переписан шаблон `templates/employees/_employee_edit.html`:
- Разделы: «Личные данные», «Контакты», «Должность» (аккордеон-блоки с единым отступом `.py-3` в заголовках).
- Поля: first_name, last_name, patronymic, gender (коды 1/2, допускается `null`), birth_date.
- Контакты: phone_number, email, telegram, whatsapp, wechat.
- Валидация:
- требуем минимум один контакт (любой из: email/phone_number/telegram/whatsapp/wechat);
- e-mail валидируется HTML5 + regex-фолбэком; live-очистка ошибок.
- Должность:
- выпадающий список из `all_positions`;
- доступ к редактированию/созданию скрывается/показывается по флагам контекста (см. ниже);
- «Создать должность» (name/description) + выбор групп прав.
- Выбор групп прав:
- мобильный модальный пикер (поиск, чекбоксы, чипсы выбранных значений, скрытый input с csv id);
- модал центрируется (`.modal-dialog-centered`), выносится в `document.body`, задран z-index (`.modal{z-index:1080}`, backdrop 1075), убран «просвет» (принудительный `background-color`).
- Кнопки: индикаторы загрузки (label + spinner), аккуратная блокировка в процессе.
JS (внутри того же шаблона)
- Сборка payload для `PATCH`:
- отправляем только изменённые поля;
- для `gender`, `birth_date`, `position_id` при очистке отправляем `null`;
- `gender` приводим к числу;
- поддержка `skills_ids` (мультиселект): сравнение с `data-init`, отправка массива только при изменении;
- `avatar`: чтение файла → dataURL (Base64ImageField), очистка через пустую строку.
- Валидация перед отправкой:
- `ensureOneContact()` — хотя бы один контакт обязателен;
- `validateEmail()` — валидный `email`, если поле непустое.
- Обработка ошибок API: подсветка конкретных полей (`.is-invalid` + `.invalid-feedback`), fallback-alert для общих ошибок.
- Успех: закрытие обёртки `#editFormWrap` (если есть collapse) + `location.reload()`.
- Блок «Создать должность»:
- `POST` в `positions_create_url` с `name/description` и (если разрешено) `groups`;
- затем `PATCH` сотрудника на `endpoint` с `position_id` созданной должности;
- обновление селекта должностей.
- Исправления:
- валидация e-mail перенесена внутрь IIFE (был reference error на `form`);
- удалён двойной вызов `ensureOneContact()`; оставлена единая связка `ensureOneContact() || !validateEmail()`.
Контекст (ожидается из context_processors, без правок views_front)
- Передавать в шаблон (минимум):
- `all_positions`: список объектов `{id, name}` (для выпадающего списка);
- `all_groups`: список объектов `{id, name}` (для модального выбора);
- `positions_create_url`: URL `POST /api/v1/positions/` (создание должности);
- флаги доступа:
- `can_edit_position` — право менять должность сотрудника (или глобальные staff/superuser);
- `can_create_position` — право создавать должности;
- `can_assign_position_groups` — право назначать групповые права должности.
- Также в шаблоне допускаются `request.user.is_staff`/`is_superuser` (поддержаны как запасной сигнал в условиях показа).
API
- Используется уже имеющийся `PositionViewSet` (`/api/v1/positions/`):
- создание должности с полем `groups` (список id) через `PositionSerializer`.
- Добавлен простой эндпоинт групп (если ещё не было):
- `GET /api/v1/groups/` (list, опционально `?search=` по `name`);
- сериализатор: `id`, `name`.
- Примечание: в шаблоне сейчас используется предзагруженный `all_groups`; эндпоинт нужен для возможной ajax-подгрузки/фильтрации в будущем.
UI/стили
- Единый вертикальный ритм заголовков секций через `.py-3`.
- Модальный выбор групп по центру экрана; корректный stacking-context и непрозрачность.
- Мобильная дружелюбность: полноэкранный на sm-и ниже (`modal-fullscreen-sm-down`), поиск, чеклист, чипсы выбранных.
Как проверить
1) Откройте карточку сотрудника → «Редактировать».
2) Смените/очистите пол, дату рождения, должность — убедитесь, что очистка отправляет `null`, а изменение — нужное значение.
3) Удалите все контакты → форма подсветит ошибки и не отправится; добавьте валидный e-mail — ошибки исчезнут.
4) Создайте новую должность с группами → должность появится в селекте и применится сотруднику.
5) Проверить поведение прав:
- без `can_edit_position`/staff/superuser — блок должности только для чтения;
- без `can_assign_position_groups` — кнопка выбора групп скрыта.
Refs: DRF serializers (`EmployeeSerializer`, `PositionSerializer`, `Base64ImageField`), `PositionViewSet` (create + groups).