From 303fd54d17e86de9f4e6a7e6743076ee85e5f21f 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: Tue, 28 Oct 2025 08:29:43 +0300 Subject: [PATCH] feat: setup refactoring infrastructure (Phase 0) - Created static file structure: * static/css/components/ - reusable CSS components * static/css/pages/ - page-specific styles * static/js/utils/ - utility functions * static/js/components/ - interactive components - Created infrastructure files: * static/css/variables.css - CSS custom properties * static/css/components/index.css - CSS entry point * static/js/utils/index.js - JS utilities entry point * static/js/components/index.js - JS components entry point - Added comprehensive tests: * tests/test_static_files.py - 12 tests for structure, syntax, encoding - Updated .gitignore: * Added staticfiles/ to ignore list * Clarified that static/ sources are tracked - Added REFACTORING_PLAN.md: * New strategy: extract CSS/JS before HTML decomposition * Documented lessons learned from previous attempts * Defined phases 0-6 for systematic refactoring --- .gitignore | 3 + backend/static/css/components/.gitkeep | 2 + backend/static/css/components/index.css | 21 + backend/static/css/pages/.gitkeep | 2 + backend/static/css/variables.css | 137 ++ backend/static/js/components/.gitkeep | 2 + backend/static/js/components/index.js | 20 + backend/static/js/utils/.gitkeep | 2 + backend/static/js/utils/index.js | 26 + backend/templates/REFACTORING_PLAN.md | 1691 +++++++++++++++++++++++ backend/tests/test_static_files.py | 253 ++++ 11 files changed, 2159 insertions(+) create mode 100644 backend/static/css/components/.gitkeep create mode 100644 backend/static/css/components/index.css create mode 100644 backend/static/css/pages/.gitkeep create mode 100644 backend/static/css/variables.css create mode 100644 backend/static/js/components/.gitkeep create mode 100644 backend/static/js/components/index.js create mode 100644 backend/static/js/utils/.gitkeep create mode 100644 backend/static/js/utils/index.js create mode 100644 backend/templates/REFACTORING_PLAN.md create mode 100644 backend/tests/test_static_files.py diff --git a/.gitignore b/.gitignore index a6789871..d53c77f0 100644 --- a/.gitignore +++ b/.gitignore @@ -147,6 +147,9 @@ dmypy.json # папки со статикой и медиа media/ +# Собранные статические файлы Django (collectstatic) +staticfiles/ +# Исходные static файлы НЕ игнорируются (backend/static/) # Others node_modules diff --git a/backend/static/css/components/.gitkeep b/backend/static/css/components/.gitkeep new file mode 100644 index 00000000..ac14e3c3 --- /dev/null +++ b/backend/static/css/components/.gitkeep @@ -0,0 +1,2 @@ +# Placeholder for CSS components +# This directory will contain reusable CSS components like feed-cards, ios-search, modals, etc. diff --git a/backend/static/css/components/index.css b/backend/static/css/components/index.css new file mode 100644 index 00000000..df8b5b22 --- /dev/null +++ b/backend/static/css/components/index.css @@ -0,0 +1,21 @@ +/** + * CSS Components Index + * + * Этот файл служит единой точкой входа для всех CSS компонентов. + * Импортируйте компоненты по мере их создания. + * + * Использование в шаблонах: + * {% block extra_css %} + * + * {% endblock %} + */ + +/* Переменные (будут созданы далее) */ +/* @import 'variables.css'; */ + +/* Общие компоненты (будут созданы в Фазе 3) */ +/* @import 'feed-cards.css'; */ +/* @import 'ios-search.css'; */ +/* @import 'modals.css'; */ +/* @import 'badges.css'; */ +/* @import 'buttons.css'; */ diff --git a/backend/static/css/pages/.gitkeep b/backend/static/css/pages/.gitkeep new file mode 100644 index 00000000..4c42788e --- /dev/null +++ b/backend/static/css/pages/.gitkeep @@ -0,0 +1,2 @@ +# Placeholder for page-specific CSS +# This directory will contain CSS files specific to individual pages diff --git a/backend/static/css/variables.css b/backend/static/css/variables.css new file mode 100644 index 00000000..33f65c61 --- /dev/null +++ b/backend/static/css/variables.css @@ -0,0 +1,137 @@ +/** + * CSS Variables + * + * Глобальные CSS переменные для обеспечения единообразия дизайна. + * Использование: var(--variable-name) + * + * Подключение в base.html: + * + */ + +:root { + /* ========== Цветовая схема ========== */ + + /* Основные цвета интерфейса (наследуются от Bootstrap) */ + /* --bs-primary, --bs-secondary, --bs-success, --bs-danger, --bs-warning, --bs-info */ + + /* Дополнительные цвета приложения */ + --app-primary: #0d6efd; + --app-success: #198754; + --app-danger: #dc3545; + --app-warning: #ffc107; + --app-info: #0dcaf0; + + /* Фоновые цвета */ + --bg-light: #f8f9fa; + --bg-dark: #212529; + --bg-card: #ffffff; + + /* Цвета текста */ + --text-primary: #212529; + --text-secondary: #6c757d; + --text-muted: #adb5bd; + + /* ========== Размеры и отступы ========== */ + + /* Высота компонентов */ + --navbar-height: 60px; + --sidebar-width: 260px; + --rightbar-width: 280px; + + /* Радиусы скругления */ + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 18px; + --radius-xl: 24px; + --radius-full: 50%; + + /* Отступы */ + --spacing-xs: 0.25rem; /* 4px */ + --spacing-sm: 0.5rem; /* 8px */ + --spacing-md: 1rem; /* 16px */ + --spacing-lg: 1.5rem; /* 24px */ + --spacing-xl: 2rem; /* 32px */ + + /* ========== Тени ========== */ + + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.05); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08); + --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.12); + --shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.16); + + /* ========== Компоненты Feed ========== */ + + --feed-radius: 18px; + --feed-shadow: var(--shadow-md); + --feed-padding: 1rem; + --feed-avatar-size: 44px; + --feed-gap: 0.75rem; + + /* ========== Переходы и анимации ========== */ + + --transition-fast: 0.15s ease; + --transition-base: 0.2s ease; + --transition-slow: 0.3s ease; + + /* ========== Z-индексы ========== */ + + --z-dropdown: 1000; + --z-sticky: 1020; + --z-fixed: 1030; + --z-modal-backdrop: 1040; + --z-modal: 1050; + --z-popover: 1060; + --z-tooltip: 1070; + + /* ========== Типографика ========== */ + + --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + --font-family-mono: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + + --font-size-xs: 0.75rem; /* 12px */ + --font-size-sm: 0.875rem; /* 14px */ + --font-size-base: 1rem; /* 16px */ + --font-size-lg: 1.125rem; /* 18px */ + --font-size-xl: 1.25rem; /* 20px */ + + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + /* ========== Границы ========== */ + + --border-width: 1px; + --border-color: #dee2e6; + --border-radius: var(--radius-md); +} + +/* ========== Тёмная тема (если потребуется) ========== */ +/* +@media (prefers-color-scheme: dark) { + :root { + --bg-card: #2d3748; + --text-primary: #f7fafc; + --text-secondary: #e2e8f0; + --border-color: #4a5568; + } +} +*/ + +/* ========== Вспомогательные классы с переменными ========== */ + +.shadow-sm { box-shadow: var(--shadow-sm); } +.shadow-md { box-shadow: var(--shadow-md); } +.shadow-lg { box-shadow: var(--shadow-lg); } +.shadow-xl { box-shadow: var(--shadow-xl); } + +.radius-sm { border-radius: var(--radius-sm); } +.radius-md { border-radius: var(--radius-md); } +.radius-lg { border-radius: var(--radius-lg); } +.radius-xl { border-radius: var(--radius-xl); } +.radius-full { border-radius: var(--radius-full); } + +.transition-fast { transition: all var(--transition-fast); } +.transition-base { transition: all var(--transition-base); } +.transition-slow { transition: all var(--transition-slow); } diff --git a/backend/static/js/components/.gitkeep b/backend/static/js/components/.gitkeep new file mode 100644 index 00000000..21772879 --- /dev/null +++ b/backend/static/js/components/.gitkeep @@ -0,0 +1,2 @@ +# Placeholder for JavaScript components +# This directory will contain interactive components like employeeForm, calendarWidget, etc. diff --git a/backend/static/js/components/index.js b/backend/static/js/components/index.js new file mode 100644 index 00000000..90a3e86f --- /dev/null +++ b/backend/static/js/components/index.js @@ -0,0 +1,20 @@ +/** + * JavaScript Components Index + * + * Этот файл служит единой точкой входа для всех JS компонентов. + * Экспортирует все компоненты для удобного импорта. + * + * Использование в шаблонах: + * + */ + +// Компоненты (будут созданы в Фазе 4) +// export { EmployeeForm } from './employeeForm.js'; +// export { CalendarWidget } from './calendarWidget.js'; +// export { TeamWheel } from './teamWheel.js'; +// export { ListFilter } from './listFilter.js'; + +// Placeholder export для валидности модуля +export const COMPONENTS_VERSION = '1.0.0'; diff --git a/backend/static/js/utils/.gitkeep b/backend/static/js/utils/.gitkeep new file mode 100644 index 00000000..4b675110 --- /dev/null +++ b/backend/static/js/utils/.gitkeep @@ -0,0 +1,2 @@ +# Placeholder for JavaScript utilities +# This directory will contain utility functions like stringUtils, timing, scroll, etc. diff --git a/backend/static/js/utils/index.js b/backend/static/js/utils/index.js new file mode 100644 index 00000000..7e888336 --- /dev/null +++ b/backend/static/js/utils/index.js @@ -0,0 +1,26 @@ +/** + * JavaScript Utilities Index + * + * Этот файл служит единой точкой входа для всех JS утилит. + * Экспортирует все утилиты для удобного импорта. + * + * Использование в шаблонах: + * + * + * Или импорт конкретной утилиты: + * import { esc } from '{% static "js/utils/stringUtils.js" %}'; + */ + +// Утилиты работы со строками (будут созданы в Фазе 2) +// export { esc, norm } from './stringUtils.js'; + +// Утилиты для работы со временем (будут созданы в Фазе 2) +// export { debounce, throttle } from './timing.js'; + +// Утилиты прокрутки (будут созданы в Фазе 2) +// export { smoothScrollTo } from './scroll.js'; + +// Placeholder export для валидности модуля +export const UTILS_VERSION = '1.0.0'; diff --git a/backend/templates/REFACTORING_PLAN.md b/backend/templates/REFACTORING_PLAN.md new file mode 100644 index 00000000..cc863b04 --- /dev/null +++ b/backend/templates/REFACTORING_PLAN.md @@ -0,0 +1,1691 @@ +# План рефакторинга templates/ + +## Статистика проекта + +**Общая информация:** +- Всего файлов: 61 (HTML/CSS/JS) +- HTML шаблонов: 58 +- Общий объём: 11,479 строк кода + +**Распределение по модулям:** +``` +admin/ 1 файл (change_form.html) +auth/ 12 файлов (login, register, password reset, logout, verify) +communications/ 2 файла (chat_list, chat_detail) +documents/ 1 файл (document_list) +emails/ 2 файла (password_reset_email, registration_verify_code) +employees/ 15 файлов (списки, детали, формы) +feed/ 10 файлов (посты, комментарии, ленты) +includes/ 4 файла (navbar, sidebar, rightbar_calendar, messages) +requests/ 1 файл (request_list.html - ДУБЛИКАТ!) +requests_app/ 7 файлов (all_requests, my_requests, process, etc.) +search/ 1 файл (results) +base.html 1 файл (корневой шаблон) +``` + +## Обнаруженные проблемы + +### 🔴 КРИТИЧЕСКИЕ ПРОБЛЕМЫ + +#### 1. **Дублирование папок: requests/ vs requests_app/** + +**requests/request_list.html** (788 строк): +- Путь: `templates/requests/request_list.html` +- Использование: `requests_app/views_front.py:174` → `template_name = "requests/request_list.html"` +- Назначение: Комплексная страница со списком заявлений + документов + recipient picker + +**requests_app/all_requests.html** (147 строк): +- Путь: `templates/requests_app/all_requests.html` +- Использование: `requests_app/views.py:315` → `"requests_app/all_requests.html"` +- Назначение: Простой список всех заявлений с фильтрами + +**requests_app/my_requests.html** (102 строки): +- Путь: `templates/requests_app/my_requests.html` +- Использование: `requests_app/views.py:251` → `"requests_app/my_requests.html"` +- Назначение: Список моих заявлений + +**Вывод**: +- `requests/` - устаревшая папка (1 файл) +- `requests_app/` - актуальная структура (7 файлов) +- **Необходимо**: объединить всё в `requests_app/` + +#### 2. **Дублирование auth шаблонов** + +**auth/logout.html** (171 строка): +- Использование: `employees/views_auth.py:182` → `template_name = "auth/logout.html"` +- Статус: **ИСПОЛЬЗУЕТСЯ** ✅ +- Описание: Современный iOS-стиль, overlay, анимации, полнофункциональный + +**auth/logout_confirm.html** (33 строки): +- Использование: ❌ **НЕ НАЙДЕНО** +- Статус: **НЕИСПОЛЬЗУЕМЫЙ ДУБЛИКАТ** +- Описание: Простой standalone HTML без base.html + +**Вывод**: `logout_confirm.html` - устаревший файл → **УДАЛИТЬ** + +#### 3. **Дублирование password reset шаблонов** + +**auth/password_reset.html** (83 строки): +- Использование: `employees/views_auth.py:199` → `template_name = "auth/password_reset.html"` +- Статус: **ИСПОЛЬЗУЕТСЯ** ✅ +- Описание: Полноценная форма с валидацией, extends base.html + +**auth/password_reset_form.html** (7 строк): +- Использование: ❌ **НЕ НАЙДЕНО** +- Статус: **НЕИСПОЛЬЗУЕМЫЙ ДУБЛИКАТ** +- Описание: Простая заглушка без стилей + +**Вывод**: `password_reset_form.html` - устаревший файл → **УДАЛИТЬ** + +### 🟡 СРЕДНИЙ ПРИОРИТЕТ + +#### 4. **Огромные файлы требуют декомпозиции** + +**employees/_employee_edit.html** (1391 строка): +- Проблема: Монолитная форма редактирования сотрудника +- Решение: Разбить на компоненты: + - `_employee_edit_personal.html` (ФИО, email, телефон) + - `_employee_edit_position.html` (должность, отдел) + - `_employee_edit_contact.html` (контакты, адреса) + - `_employee_edit_skills.html` (навыки) + - `_employee_edit_documents.html` (документы) + +**employees/department_detail.html** (1025 строк): +- Проблема: Детальная страница отдела со множеством разделов +- Решение: Выделить компоненты: + - `_department_header.html` (заголовок, руководитель) + - `_department_members.html` (список сотрудников) + - `_department_stats.html` (статистика) + - `_department_subdepts.html` (подотделы) + +**includes/rightbar_calendar.html** (1129 строк): +- Проблема: Правый сайдбар с календарём + события +- Решение: Разбить на: + - `_calendar_widget.html` (виджет календаря) + - `_calendar_events.html` (список событий) + - `_calendar_filters.html` (фильтры) + +**documents/document_list.html** (743 строки): +- Проблема: Список документов + фильтры + модалки +- Решение: Выделить: + - `_document_filters.html` (панель фильтров) + - `_document_card.html` (карточка документа) + - `_document_modals.html` (модальные окна) + +**requests/request_list.html** (788 строк): +- Проблема: Комплексная страница с заявлениями, документами, recipient picker +- Решение: После переноса в requests_app/ разбить на компоненты + +**employees/employee_detail.html** (600 строк): +- Решение: Выделить табы в отдельные компоненты + +#### 5. **Дублирование CSS стилей** + +Обнаружены повторяющиеся блоки стилей: +- `.feed-stream`, `.feed-card`, `.feed-hd` - определены в 5+ файлах +- `.btn-icon`, `.badge-status` - дублируются +- `.ios-overlay`, `.ios-sheet` - iOS-стиль модалок + +**Решение**: Создать общие файлы стилей: +- `static/css/components/feed.css` - стили для лент +- `static/css/components/modals.css` - iOS-стиль модалок +- `static/css/components/badges.css` - бейджи статусов + +### 🟢 НИЗКИЙ ПРИОРИТЕТ + +#### 6. **Оптимизация структуры includes/** + +Текущие: +- `includes/navbar.html` (143 строки) +- `includes/sidebar.html` (259 строк) +- `includes/rightbar_calendar.html` (1129 строк) +- `includes/messages.html` (9 строк) + +**Рекомендации**: +- Выделить из navbar: `_navbar_search.html`, `_navbar_user_menu.html` +- Выделить из sidebar: `_sidebar_menu.html`, `_sidebar_profile.html` + +#### 7. **Консистентность именования** + +**Проблемы**: +- Некоторые файлы начинаются с `_` (партиалы), другие нет +- Смешанное использование `confirm_delete` vs `delete_confirm` +- `employee_feed.html` vs `feed_list.html` (разная логика именования) + +**Стандарт**: +- `_` - только для партиалов (переиспользуемых компонентов) +- `{model}_list.html` - списки +- `{model}_detail.html` - детальные страницы +- `{model}_form.html` - формы создания/редактирования +- `{model}_confirm_delete.html` - подтверждение удаления + +## ⚠️ ВАЖНЫЕ ВЫВОДЫ ИЗ ПРЕДЫДУЩИХ ПОПЫТОК + +### Проблемы при декомпозиции HTML без предварительной работы со стилями/скриптами: + +1. **Стили в неправильных местах**: При извлечении компонентов стили ` на: + {% block extra_css %} + + {% endblock %} + + # 4. Проверить рендер + python manage.py runserver + # Открыть страницу, проверить визуально + + # 5. Запустить тесты + python manage.py test tests.test_template_rendering + + # 6. Если всё ОК - коммит, если нет - откат из backup + ``` + +4. **Подключить в base.html**: + ```django + {% block extra_css %} + + + + + {% endblock %} + ``` + +**Критерий завершения**: +- Создано 4-5 CSS компонентов ✅ +- Из шаблонов удалено ~300-400 строк дублирующих стилей ✅ +- Все страницы рендерятся идентично ✅ +- Git commits: по одному на каждый извлечённый компонент ✅ + +--- + +#### Задача 3.2: Извлечь специфичные стили страниц + +**Для больших файлов** создать отдельные CSS файлы: + +1. **employees/department_detail.html** → `static/css/pages/department-detail.css`: + ```css + /* Стили специфичные для страницы отдела */ + .team-wheel { /* ... */ } + .wheel-columns { /* ... */ } + /* ... */ + ``` + +2. **includes/rightbar_calendar.html** → `static/css/components/calendar.css`: + ```css + /* Стили календаря */ + .calendar-wrap { /* ... */ } + .fc { /* ... */ } + /* ... */ + ``` + +3. **documents/document_list.html** → `static/css/pages/document-list.css` + +**Критерий завершения**: +- Каждый шаблон > 50 строк CSS имеет отдельный файл ✅ +- Встроенных `