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, 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} {'
+
+
+
+ {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #}
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 %}
+
+ {% 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 %}
+
+
+
+
+
+ {# порядок аргументов: emp_id, dept_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 @@
+ {# --- Команда отдела (круг) --- #}
+
+
+
+
+
+
+ {# КРУГ #}
+
+
+
+ {# Слой фокуса #}
+
+
+
+
+
+
+
+ {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #}
+
+
+
+
+
+
+ {# Источник данных для круга #}
+
+ {% 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 %}
+
+ — Не указано —
+ {% for p in all_positions %}
+ {% if p.id and p.name %}
+
+ {{ p.name }}
+
+ {% endif %}
+ {% endfor %}
+
+ {% 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 %}
+
+ Группы прав (id через запятую)
+
+
+ {% 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 %}
+
+
+
+
+
+
+ Выбрать группы
+
+
+ Назначить выбранные
+
+
+
+ Снять выбранные
+
+
+
+
+
+
+
+
+
+
+
Создать новую группу
+
+
+
+ Создать
+
+
+
+
+
+
+
+
Удалить группу
+
+
+ — Выберите группу —
+ {% for g in all_groups %}
+ {% if g.id and g.name %}
+ {{ g.name }}
+ {% endif %}
+ {% 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 %}
- {# ===== Заголовок ===== #}
-
-
- {# ===== Две колонки как в employee_detail: слева основное, справа сайдбар ===== #}
+ {# ===== ДВЕ КОЛОНКИ ===== #}
- {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #}
+ {# ===== ЛЕВАЯ КОЛОНКА: команда + инфо ===== #}
- {# --- Команда отдела (круг) --- #}
-
-
-
-
-
-
- {# КРУГ #}
-
-
-
- {# Слой фокуса #}
-
-
-
-
-
-
-
- {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #}
-
-
-
-
-
-
- {# Источник данных для круга #}
-
- {% 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 %}
-
- {% 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 %}
-
-
-
-
-
- {# порядок аргументов: emp_id, dept_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 %}
+
+
+ {# ===== Заголовок ===== #}
+
+
+ {# ===== Две колонки как в employee_detail: слева основное, справа сайдбар ===== #}
+
+
+ {# ===== ЛЕВАЯ КОЛОНКА (основная, как в профиле): команда + инфо ===== #}
+
+ {# --- Команда отдела (круг) --- #}
+
+
+
+
+
+
+ {# КРУГ #}
+
+
+
+ {# Слой фокуса #}
+
+
+
+
+
+
+
+ {# ПОЛУКРУЖНЫЙ ИНДИКАТОР СКРОЛЛА (справа по дуге) #}
+
+
+
+
+
+
+ {# Источник данных для круга #}
+
+ {% 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 %}
+
+ {% 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 %}
+
+
+
+
+
+ {# порядок аргументов: emp_id, dept_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 %}
+