diff --git a/backend/README_EUSRR.md b/backend/README_EUSRR.md index c0fea691..2f7d7e48 100644 --- a/backend/README_EUSRR.md +++ b/backend/README_EUSRR.md @@ -10,25 +10,25 @@ python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r backend/requirements.txt cp backend/.env backend/.env.local || true -# edit backend/.env.local if needed (USE_SQLITE=True by default) +# Edit backend/.env.local if needed (USE_SQLITE=True by default) python backend/manage.py migrate python backend/manage.py createsuperuser python backend/manage.py runserver 0.0.0.0:9000 ``` -Open http://127.0.0.1:9000/ +Open [http://127.0.0.1:9000/](http://127.0.0.1:9000/) ## Full stack with Docker (Postgres + Redis) 1. Put your secrets into `backend/.env` (use `.env.example` as a template). **Never commit real secrets.** -2. Fix Dockerfile to use `eusrr_backend.asgi` (or use the provided `Dockerfile.fixed`). +2. Ensure the `Dockerfile` uses `eusrr_backend.asgi` (or use the provided `Dockerfile.fixed`). 3. Launch: ```bash docker compose up --build ``` -The app will be available on http://127.0.0.1:9000/ +The app will be available at [http://127.0.0.1:9000/](http://127.0.0.1:9000/) ## Useful commands ```bash -# Telegram bot +# Start Telegram bot python backend/manage.py start_telegram_bot # Run tests @@ -36,6 +36,6 @@ pytest -q backend ``` ## Notes -- Set `API_BASE_URL` to match where the app is served (default http://127.0.0.1:9000/api). -- For Channels websockets, keep Redis reachable at `${REDIS_HOST}:${REDIS_PORT}`. -- The `hikcentral` DB is configured as a secondary Postgres. Externalize its DSN via envs if you plan to use it. +- Set `API_BASE_URL` to match where the app is served (default: [http://127.0.0.1:9000/api](http://127.0.0.1:9000/api)). +- For Channels websockets, ensure Redis is reachable at `${REDIS_HOST}:${REDIS_PORT}`. +- The `hikcentral` DB is configured as a secondary Postgres. Externalize its DSN via environment variables if you plan to use it. diff --git a/backend/analyze_templates.py b/backend/analyze_templates.py new file mode 100644 index 00000000..51d4d03d --- /dev/null +++ b/backend/analyze_templates.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +""" +Анализ шаблонов: поиск встроенных стилей и скриптов. +Помогает понять масштаб рефакторинга. +""" +import os +import re +from pathlib import Path +from collections import defaultdict + +# Путь к шаблонам +TEMPLATES_DIR = Path(__file__).parent / 'templates' + + +def analyze_template(filepath): + """Анализирует один шаблон""" + try: + content = filepath.read_text(encoding='utf-8') + except Exception as e: + return None + + lines = len(content.splitlines()) + + # Подсчёт тегов + style_tags = len(re.findall(r']*>', content)) + script_tags = len(re.findall(r']*>', content)) + + # Размер встроенных стилей и скриптов + style_blocks = re.findall(r']*>(.*?)', content, re.DOTALL) + script_blocks = re.findall(r']*>(.*?)', content, re.DOTALL) + + style_lines = sum(len(block.splitlines()) for block in style_blocks) + script_lines = sum(len(block.splitlines()) for block in script_blocks) + + # Поиск CSS классов + css_classes = set(re.findall(r'\.([a-z][a-z0-9\-_]*)\s*{', content, re.IGNORECASE)) + + # Поиск функций JavaScript + js_functions = set(re.findall(r'function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(', content)) + + return { + 'path': str(filepath.relative_to(TEMPLATES_DIR)), + 'total_lines': lines, + 'style_tags': style_tags, + 'script_tags': script_tags, + 'style_lines': style_lines, + 'script_lines': script_lines, + 'css_classes': css_classes, + 'js_functions': js_functions, + 'has_blocks': bool(re.search(r'{%\s*block\s+extra_(css|js)\s*%}', content)), + } + + +def main(): + """Главная функция анализа""" + print("=" * 80) + print("АНАЛИЗ ШАБЛОНОВ: встроенные стили и скрипты") + print("=" * 80) + + # Находим все HTML файлы + html_files = list(TEMPLATES_DIR.rglob('*.html')) + + results = [] + for filepath in sorted(html_files): + # Пропускаем backup файлы + if '.backup' in str(filepath): + continue + + result = analyze_template(filepath) + if result and (result['style_tags'] > 0 or result['script_tags'] > 0): + results.append(result) + + # Сортируем по количеству встроенного кода + results.sort(key=lambda x: x['style_lines'] + x['script_lines'], reverse=True) + + print(f"\nНайдено {len(results)} шаблонов со встроенными стилями/скриптами\n") + + # Таблица результатов + print(f"{'Файл':<60} {'Строк':<8} {' + +
+ {% csrf_token %} + + {# === ЛИЧНЫЕ ДАННЫЕ === #} +
+
+
+ +
Личные данные
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+ + {# === КОНТАКТЫ === #} +
+
+
+ +
Контакты
+
+
+
+
+ + +
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+
+
+ +{# === ДОЛЖНОСТЬ === #} +
+ {% if can_edit_position or request.user.is_staff or request.user.is_superuser %} +
+
+ +
Должность
+
+ +
+
+ + {# ТЕКУЩАЯ ДОЛЖНОСТЬ #} +
+ + {% if all_positions %} + + {% else %} + +
Передайте в контекст all_positions для выпадающего списка.
+ {% endif %} +
+ + {# СОЗДАТЬ НОВУЮ #} + {% if can_create_position or request.user.is_staff or request.user.is_superuser %} +
+ + +
+ +
+
+
+
+ + +
+
+ + +
+ + {% if can_assign_position_groups or request.user.is_staff or request.user.is_superuser %} +
+ {% if all_groups %} +
+
+ +
+ + {# Модал выбора групп для новой должности #} + + {% else %} +
+ + +
+ {% endif %} +
+ {% endif %} + +
+ + + +
+ +
+
+
+
+
+
+ {% endif %} + + {# РЕДАКТИРОВАТЬ ВЫБРАННУЮ #} +
+
+ +
+ +
+
+
+ + +
+
+ + +
+ + {% if can_assign_position_groups or request.user.is_staff or request.user.is_superuser %} +
+ +
+ +
+ + +
+
+ + {# Модал выбора групп для редактирования должности #} + + {% endif %} + +
+ + + +
+ +
+
+
+
+
+
+ +
{# /.row #} +
{# /.ios-acc-body #} +
+ {% else %} +
+
+ +
Должность
+
+
+ +
+
+ {% endif %} +
+ + +{# === ПЕРСОНАЛЬНЫЕ ГРУППЫ ПОЛНОМОЧИЙ === #} +
+ {% if request.user.is_staff or request.user.is_superuser %} +
+
+ +
Дополнительные полномочия
+
+
+
+ +
+
+
+
+ + {# <<< НОВОЕ: вывод уже назначенных групп сотруднику в виде «пилюль» >>> #} +
+ +
+ {% for g in emp_personal_groups %} + {% if g.id and g.name %} + {{ g.name }} + {% endif %} + {% empty %} + Нет персональных групп + {% endfor %} +
+
+ +
+
+ + + +
+ +
+
+ +
+ +
+ +
+ + +
+
+
+ +
+ +
+ + +
+
Удаляется и LDAP-группа, и объект в БД.
+
+
+
+
+
+ + {# Модал выбора групп для персонального назначения #} + + {% endif %} +
+ + + + {# === КНОПКИ === #} +
+ + +
+
+ + + + + + + + + + + diff --git a/backend/templates/employees/components/department_header.html b/backend/templates/employees/components/department_header.html new file mode 100644 index 00000000..6f86c873 --- /dev/null +++ b/backend/templates/employees/components/department_header.html @@ -0,0 +1,64 @@ + {# ===== Заголовок ===== #} +
+ +

{{ dept.name }}

+ {% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} +
+ + {# Добавить участника #} + + + {# Назначить роль #} + {% if roles %} + {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} + + {% endif %} + {% endif %} + + {# Удалить участника #} + + +
+ {% endif %} + +
+ {% url 'feed:post_create' as post_create_url %} + {% if user.is_authenticated and user.id in members_exclude_ids %} + + Создать публикацию + + {% endif %} + + +
+
+ + {# ===== Две колонки как в employee_detail: слева основное, справа сайдбар ===== #} +
+ + {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #} diff --git a/backend/templates/employees/components/department_info.html b/backend/templates/employees/components/department_info.html new file mode 100644 index 00000000..3cfcb27b --- /dev/null +++ b/backend/templates/employees/components/department_info.html @@ -0,0 +1,40 @@ + {# --- Инфо-блок отдела (под командой) --- #} + {% if dept.description or dept.head %} +
+
+ {% if dept.description %} +
+ {{ dept.description }} +
+ {% endif %} + + {% if dept.head %} +
+ Руководитель: + {% url 'employees:employee_detail' dept.head.id as head_url %} + {% if head_url %} + + {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} + + {% else %} + {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} + {% endif %} +
+ {% endif %} + + {% if user.is_staff or dept.head.id == user.id or can_manage or can_assign_roles or can_change_head %} + + {% endif %} +
+
+ {% endif %} diff --git a/backend/templates/employees/components/department_modals.html b/backend/templates/employees/components/department_modals.html new file mode 100644 index 00000000..38ddfeff --- /dev/null +++ b/backend/templates/employees/components/department_modals.html @@ -0,0 +1,197 @@ +{# ---------- МОДАЛ «Удалить участника» ---------- #} +{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} + +{% endif %} + +{# ---------- МОДАЛ «Добавить участника» ---------- #} +{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} + {% with exclude_ids=members_exclude_ids %} + + {% endwith %} +{% endif %} + +{# ---------- МОДАЛ «Назначить роль» ---------- #} +{% if roles %} + {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} + + {% endif %} +{% endif %} + diff --git a/backend/templates/employees/components/department_scripts.html b/backend/templates/employees/components/department_scripts.html new file mode 100644 index 00000000..4f6d9ad2 --- /dev/null +++ b/backend/templates/employees/components/department_scripts.html @@ -0,0 +1,513 @@ +{# ==== JS: круг с автоскроллом/ручным управлением и индикатором ==== #} + + +{# ===== Переключатель панели настроек (скролл к блоку при открытии) ===== #} + + +{# ===== Модал «Добавить участника»: AJAX-поиск ===== #} + + +{# ===== Модал «Удалить участника»: локальный выбор ===== #} + + +{# ===== Модал «Назначить роль»: подстановка empId в action ===== #} + + diff --git a/backend/templates/employees/components/department_sidebar.html b/backend/templates/employees/components/department_sidebar.html new file mode 100644 index 00000000..d8b2530e --- /dev/null +++ b/backend/templates/employees/components/department_sidebar.html @@ -0,0 +1,48 @@ +{# ===== ПРАВАЯ КОЛОНКА: настройки + лента ===== #} +{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} +
+
+
+
+ +
Настройки отдела
+
+ +
+
+ +
+ {% include "employees/_department_controls.html" with dept=dept edit_form=edit_form head_choices=head_choices %} +
+
+
+
+{% endif %} + +
+
+ +
+
Публикации отдела
+
+
+
+ {% if posts %} + {% include "feed/_feed_cards.html" with items=posts %} + {% else %} +
Публикаций пока нет.
+ {% endif %} +
+
+ +{# Простая пагинация (если нужно) #} +{% if page|default:0 %} +
+ {% if page|add:"-1" %} + ← Назад + {% endif %} +
+{% endif %} diff --git a/backend/templates/employees/components/department_styles.html b/backend/templates/employees/components/department_styles.html new file mode 100644 index 00000000..10615611 --- /dev/null +++ b/backend/templates/employees/components/department_styles.html @@ -0,0 +1,58 @@ +{# ==== СТИЛИ (можно вынести в base.html, чтобы не дублировать) ==== #} + + diff --git a/backend/templates/employees/components/department_team_circle.html b/backend/templates/employees/components/department_team_circle.html new file mode 100644 index 00000000..77e82d43 --- /dev/null +++ b/backend/templates/employees/components/department_team_circle.html @@ -0,0 +1,76 @@ + {# --- Команда отдела (круг) --- #} +
+
+ + +
+
{% url 'employees:employees_list' as employees_list_url %} + {% if employees_list_url %} + + Команда отдела → + + {% endif %}
+
+
+ +
+
+ + {# КРУГ #} +
+
+
+
+
+
+
+
+
+ + {# Слой фокуса #} +
+
+ + +
+
+ + {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #} + +
+ + {# Источник данных для круга #} +
+ {% for li in links %} + {% with emp=li.employee %} +
+ {% endwith %} + {% empty %} + {% endfor %} +
+ + {# Текст под кругом #} +
+
+
+
+
+
+
+ +
+
+
diff --git a/backend/templates/employees/components/employee_form_actions.html b/backend/templates/employees/components/employee_form_actions.html new file mode 100644 index 00000000..912eea65 --- /dev/null +++ b/backend/templates/employees/components/employee_form_actions.html @@ -0,0 +1,10 @@ +{# employees/components/employee_form_actions.html #} +{# Кнопки сохранения и отмены формы #} + +
+ + +
diff --git a/backend/templates/employees/components/employee_form_contact.html b/backend/templates/employees/components/employee_form_contact.html new file mode 100644 index 00000000..fb27c979 --- /dev/null +++ b/backend/templates/employees/components/employee_form_contact.html @@ -0,0 +1,52 @@ +{# employees/components/employee_form_contact.html #} +{# Секция "Контакты": Email, телефон, мессенджеры #} + +
+
+
+ +
Контакты
+
+
+
+
+ + +
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+
+
diff --git a/backend/templates/employees/components/employee_form_personal.html b/backend/templates/employees/components/employee_form_personal.html new file mode 100644 index 00000000..e4b25007 --- /dev/null +++ b/backend/templates/employees/components/employee_form_personal.html @@ -0,0 +1,50 @@ +{# employees/components/employee_form_personal.html #} +{# Секция "Личные данные": ФИО, пол, дата рождения #} + +
+
+
+ +
Личные данные
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
diff --git a/backend/templates/employees/components/employee_form_position.html b/backend/templates/employees/components/employee_form_position.html new file mode 100644 index 00000000..be04f442 --- /dev/null +++ b/backend/templates/employees/components/employee_form_position.html @@ -0,0 +1,359 @@ +{# === ДОЛЖНОСТЬ === #} +
+ {% if can_edit_position or request.user.is_staff or request.user.is_superuser %} +
+
+ +
Должность
+
+ +
+
+ + {# ТЕКУЩАЯ ДОЛЖНОСТЬ #} +
+ + {% if all_positions %} + + {% else %} + +
Передайте в контекст all_positions для выпадающего списка.
+ {% endif %} +
+ + {# СОЗДАТЬ НОВУЮ #} + {% if can_create_position or request.user.is_staff or request.user.is_superuser %} +
+ + +
+ +
+
+
+
+ + +
+
+ + +
+ + {% if can_assign_position_groups or request.user.is_staff or request.user.is_superuser %} +
+ {% if all_groups %} +
+
+ +
+ + {# Модал выбора групп для новой должности #} + + {% else %} +
+ + +
+ {% endif %} +
+ {% endif %} + +
+ + + +
+ +
+
+
+
+
+
+ {% endif %} + + {# РЕДАКТИРОВАТЬ ВЫБРАННУЮ #} +
+
+ +
+ +
+
+
+ + +
+
+ + +
+ + {% if can_assign_position_groups or request.user.is_staff or request.user.is_superuser %} +
+ +
+ +
+ + +
+
+ + {# Модал выбора групп для редактирования должности #} + + {% endif %} + +
+ + + +
+ +
+
+
+
+
+
+ +
{# /.row #} +
{# /.ios-acc-body #} +
+ {% else %} +
+
+ +
Должность
+
+
+ +
+
+ {% endif %} +
+ + +{# === ПЕРСОНАЛЬНЫЕ ГРУППЫ ПОЛНОМОЧИЙ === #} +
+ {% if request.user.is_staff or request.user.is_superuser %} +
+
+ +
Дополнительные полномочия
+
+
+
+ +
+
+
+
+ + {# <<< НОВОЕ: вывод уже назначенных групп сотруднику в виде «пилюль» >>> #} +
+ +
+ {% for g in emp_personal_groups %} + {% if g.id and g.name %} + {{ g.name }} + {% endif %} + {% empty %} + Нет персональных групп + {% endfor %} +
+
+ +
+
+ + + +
+ +
+
+ +
+ +
+ +
+ + +
+
+
+ +
+ +
+ + +
+
Удаляется и LDAP-группа, и объект в БД.
+
+
+
+
+
+ + {# Модал выбора групп для персонального назначения #} + + {% endif %} +
+ + + diff --git a/backend/templates/employees/components/employee_form_scripts.html b/backend/templates/employees/components/employee_form_scripts.html new file mode 100644 index 00000000..ceaf9a33 --- /dev/null +++ b/backend/templates/employees/components/employee_form_scripts.html @@ -0,0 +1,907 @@ + + + + + + + + diff --git a/backend/templates/employees/department_detail.html b/backend/templates/employees/department_detail.html index 64be2a33..cebdd602 100644 --- a/backend/templates/employees/department_detail.html +++ b/backend/templates/employees/department_detail.html @@ -1,4 +1,5 @@ {# backend/templates/employees/department_detail.html #} +{# Детальная страница отдела - рефакторированная версия #} {% extends 'base.html' %} {% load static django_bootstrap5 %} @@ -8,1018 +9,38 @@ {% with dept_id=dept.id %}
- {# ===== Заголовок ===== #} -
- -

{{ dept.name }}

- {% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} -
+ {# ===== ЗАГОЛОВОК ===== #} + {% include "employees/components/department_header.html" %} - {# Добавить участника #} - - - {# Назначить роль #} - {% if roles %} - {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} - - {% endif %} - {% endif %} - - {# Удалить участника #} - - -
- {% endif %} - -
- {% url 'feed:post_create' as post_create_url %} - {% if user.is_authenticated and user.id in members_exclude_ids %} - - Создать публикацию - - {% endif %} - - -
-
- - {# ===== Две колонки как в employee_detail: слева основное, справа сайдбар ===== #} + {# ===== ДВЕ КОЛОНКИ ===== #}
- {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #} + {# ===== ЛЕВАЯ КОЛОНКА: команда + инфо ===== #}
- {# --- Команда отдела (круг) --- #} -
-
- - -
-
{% url 'employees:employees_list' as employees_list_url %} - {% if employees_list_url %} - - Команда отдела → - - {% endif %}
-
-
- -
-
- - {# КРУГ #} -
-
-
-
-
-
-
-
-
- - {# Слой фокуса #} -
-
- - -
-
- - {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #} - -
- - {# Источник данных для круга #} -
- {% for li in links %} - {% with emp=li.employee %} -
- {% endwith %} - {% empty %} - {% endfor %} -
- - {# Текст под кругом #} -
-
-
-
-
-
-
- -
-
-
- - {# --- Инфо-блок отдела (под командой) --- #} - {% if dept.description or dept.head %} -
-
- {% if dept.description %} -
- {{ dept.description }} -
- {% endif %} - - {% if dept.head %} -
- Руководитель: - {% url 'employees:employee_detail' dept.head.id as head_url %} - {% if head_url %} - - {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} - - {% else %} - {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} - {% endif %} -
- {% endif %} - - {% if user.is_staff or dept.head.id == user.id or can_manage or can_assign_roles or can_change_head %} - - {% endif %} -
-
- {% endif %} - + {% include "employees/components/department_team_circle.html" %} + {% include "employees/components/department_info.html" %}
- {# ===== ПРАВАЯ КОЛОНКА (сайдбар): публикации/активность ===== #} + {# ===== ПРАВАЯ КОЛОНКА: настройки + лента ===== #}
- {% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} -
-
-
-
- -
Настройки отдела
-
- -
-
- -
- {% include "employees/_department_controls.html" with dept=dept edit_form=edit_form head_choices=head_choices %} -
-
-
-
- {% endif %} -
-
- -
-
Публикации отдела
-
-
-
- {% if posts %} - {% include "feed/_feed_cards.html" with items=posts %} - {% else %} -
Публикаций пока нет.
- {% endif %} -
-
- - {# Простая пагинация (если нужно) #} - {% if page|default:0 %} -
- {% if page|add:"-1" %} - ← Назад - {% endif %} -
- {% endif %} + {% include "employees/components/department_sidebar.html" %}
-{# ---------- МОДАЛ «Удалить участника» ---------- #} -{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} - -{% endif %} - -{# ---------- МОДАЛ «Добавить участника» ---------- #} -{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} - {% with exclude_ids=members_exclude_ids %} - - {% endwith %} -{% endif %} - -{# ---------- МОДАЛ «Назначить роль» ---------- #} -{% if roles %} - {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} - - {% endif %} -{% endif %} +{# ===== МОДАЛЬНЫЕ ОКНА ===== #} +{% include "employees/components/department_modals.html" %} {% endwith %} {% endblock %} -{% block extra_js %} - -{% url 'employees:employees_list' as employees_list_url %} - -{# ==== СТИЛИ (можно вынести в base.html, чтобы не дублировать) ==== #} - - -{# ==== JS: круг с автоскроллом/ручным управлением и индикатором ==== #} - - -{# ===== Переключатель панели настроек (скролл к блоку при открытии) ===== #} - - -{# ===== Модал «Добавить участника»: AJAX-поиск ===== #} - - -{# ===== Модал «Удалить участника»: локальный выбор ===== #} - - -{# ===== Модал «Назначить роль»: подстановка empId в action ===== #} - - - +{# ===== СТИЛИ в для правильного рендеринга ===== #} +{% block extra_css %} +{% include "employees/components/department_styles.html" %} +{% endblock %} + +{# ===== СКРИПТЫ ===== #} +{% block extra_js %} +{% include "employees/components/department_scripts.html" %} {% endblock %} diff --git a/backend/templates/employees/department_detail.html.backup b/backend/templates/employees/department_detail.html.backup new file mode 100644 index 00000000..64be2a33 --- /dev/null +++ b/backend/templates/employees/department_detail.html.backup @@ -0,0 +1,1025 @@ +{# backend/templates/employees/department_detail.html #} +{% extends 'base.html' %} +{% load static django_bootstrap5 %} + +{% block title %}{{ dept.name }}{% endblock %} + +{% block content %} +{% with dept_id=dept.id %} +
+ + {# ===== Заголовок ===== #} +
+ +

{{ dept.name }}

+ {% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} +
+ + {# Добавить участника #} + + + {# Назначить роль #} + {% if roles %} + {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} + + {% endif %} + {% endif %} + + {# Удалить участника #} + + +
+ {% endif %} + +
+ {% url 'feed:post_create' as post_create_url %} + {% if user.is_authenticated and user.id in members_exclude_ids %} + + Создать публикацию + + {% endif %} + + +
+
+ + {# ===== Две колонки как в employee_detail: слева основное, справа сайдбар ===== #} +
+ + {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #} +
+ {# --- Команда отдела (круг) --- #} +
+
+ + +
+
{% url 'employees:employees_list' as employees_list_url %} + {% if employees_list_url %} + + Команда отдела → + + {% endif %}
+
+
+ +
+
+ + {# КРУГ #} +
+
+
+
+
+
+
+
+
+ + {# Слой фокуса #} +
+
+ + +
+
+ + {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #} + +
+ + {# Источник данных для круга #} +
+ {% for li in links %} + {% with emp=li.employee %} +
+ {% endwith %} + {% empty %} + {% endfor %} +
+ + {# Текст под кругом #} +
+
+
+
+
+
+
+ +
+
+
+ + {# --- Инфо-блок отдела (под командой) --- #} + {% if dept.description or dept.head %} +
+
+ {% if dept.description %} +
+ {{ dept.description }} +
+ {% endif %} + + {% if dept.head %} +
+ Руководитель: + {% url 'employees:employee_detail' dept.head.id as head_url %} + {% if head_url %} + + {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} + + {% else %} + {{ dept.head.last_name }}{% if dept.head.first_name %} {{ dept.head.first_name }}{% endif %} + {% endif %} +
+ {% endif %} + + {% if user.is_staff or dept.head.id == user.id or can_manage or can_assign_roles or can_change_head %} + + {% endif %} +
+
+ {% endif %} + +
+ + {# ===== ПРАВАЯ КОЛОНКА (сайдбар): публикации/активность ===== #} +
+ {% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} +
+
+
+
+ +
Настройки отдела
+
+ +
+
+ +
+ {% include "employees/_department_controls.html" with dept=dept edit_form=edit_form head_choices=head_choices %} +
+
+
+
+ {% endif %} +
+
+ +
+
Публикации отдела
+
+
+
+ {% if posts %} + {% include "feed/_feed_cards.html" with items=posts %} + {% else %} +
Публикаций пока нет.
+ {% endif %} +
+
+ + {# Простая пагинация (если нужно) #} + {% if page|default:0 %} +
+ {% if page|add:"-1" %} + ← Назад + {% endif %} +
+ {% endif %} +
+ +
+
+ +{# ---------- МОДАЛ «Удалить участника» ---------- #} +{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} + +{% endif %} + +{# ---------- МОДАЛ «Добавить участника» ---------- #} +{% if user.is_staff or user.is_superuser or can_manage or dept.head.id == user.id %} + {% with exclude_ids=members_exclude_ids %} + + {% endwith %} +{% endif %} + +{# ---------- МОДАЛ «Назначить роль» ---------- #} +{% if roles %} + {% if user.is_superuser or user.is_staff or can_assign_roles or dept.head.id == user.id %} + + {% endif %} +{% endif %} + +{% endwith %} +{% endblock %} + +{% block extra_js %} + +{% url 'employees:employees_list' as employees_list_url %} + +{# ==== СТИЛИ (можно вынести в base.html, чтобы не дублировать) ==== #} + + +{# ==== JS: круг с автоскроллом/ручным управлением и индикатором ==== #} + + +{# ===== Переключатель панели настроек (скролл к блоку при открытии) ===== #} + + +{# ===== Модал «Добавить участника»: AJAX-поиск ===== #} + + +{# ===== Модал «Удалить участника»: локальный выбор ===== #} + + +{# ===== Модал «Назначить роль»: подстановка empId в action ===== #} + + + +{% endblock %} diff --git a/backend/templates/employees/department_list.html b/backend/templates/employees/department_list.html index 3f3b9c9f..971e5696 100644 --- a/backend/templates/employees/department_list.html +++ b/backend/templates/employees/department_list.html @@ -4,15 +4,9 @@ {% block title %}Отделы{% endblock %} {% block extra_css %} + \ No newline at end of file diff --git a/backend/templates/includes/rightbar_calendar.html.backup b/backend/templates/includes/rightbar_calendar.html.backup new file mode 100644 index 00000000..86586eb4 --- /dev/null +++ b/backend/templates/includes/rightbar_calendar.html.backup @@ -0,0 +1,1130 @@ +{% load static %} + + + +{# десктопная правая колонка #} +
+
+
+ +
+
Календарь
+ + {# Выпадающий выбор: Компания / Отделы #} + +
+ +
+ События + +
+
+ +
+
+ +
+ На этой неделе + +
+
+
+
+
+ +{# мобилка: offcanvas справа + плавающая кнопка #} + + +
+
+
Календарь
+ +
+
+
+ +
+ На этой неделе + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/backend/templates/requests/request_list.html b/backend/templates/requests_app/request_list_full.html similarity index 99% rename from backend/templates/requests/request_list.html rename to backend/templates/requests_app/request_list_full.html index 4048463f..837bc07e 100644 --- a/backend/templates/requests/request_list.html +++ b/backend/templates/requests_app/request_list_full.html @@ -311,7 +311,7 @@ Скрыть {% if obj.attachment %} - + Вложение {% endif %} diff --git a/backend/templates/search/results.html b/backend/templates/search/results.html index 94e46bf6..ab51c3c5 100644 --- a/backend/templates/search/results.html +++ b/backend/templates/search/results.html @@ -4,32 +4,9 @@ {% block title %}Поиск{% endblock %} {% block extra_css %} +