150 Commits

Author SHA1 Message Date
4a4f3b2fa0 refactor: Clean architecture + unified badge styling
PART 1: Extract UnreadBadgeManager (Clean Architecture)

Created managers/unreadBadgeManager.js:
✅ Single Responsibility: Manages ONLY badge UI
✅ Methods: increment(), reset(), setCount(), hasUnread()
✅ Handles all DOM manipulation internally
✅ Reusable and testable

Cleaned ChatControllerV2:
❌ Removed 150+ lines of UI logic
❌ Removed duplicate systems (_unreadCount + _newMessagesCount)
❌ Removed deprecated methods:
   - _incrementUnreadBadge()
   - _resetUnreadBadge()
   - _showNewMessagesIndicator()
   - _hideNewMessagesIndicator()
   - _findOrCreateNewMessagesButton()
✅ Now uses: this.badgeManager.increment/reset()

PART 2: Unified Badge Styling

Aligned unread-badge with sticky-date design:
- Same typography (font-size, weight, line-height)
- Same spacing (padding: 6px 12px)
- Same border-radius (10-12px)
- Same shadows (box-shadow hierarchy)
- Same transitions (0.2s ease)
- Same animation patterns (scale, hover effects)
- Added border: 2px for contrast with background

Result:
✅ Consistent UI across all badges
✅ Matches Telegram-like design system
✅ Better visual hierarchy
✅ ~950 lines in Controller (was 1125)
✅ Clean separation of concerns
2026-01-13 15:36:17 +03:00
a4d9ebe2f4 fix: Syntax error in loadLatest method
Fixed incorrect method placement that broke loadNewer.
loadLatest now properly placed after loadNewer method.
2026-01-13 15:24:38 +03:00
c0bb7530c5 feat: Smart button visibility and load-to-present on click
Two types of bottom:
1. Historical bottom (hasMoreAfter=true):
   - Button ALWAYS visible (even at scroll bottom)
   - Click → loads latest 50 messages to present time
   - Renders and scrolls to bottom

2. Present bottom (hasMoreAfter=false):
   - Button hidden when isNearBottom()
   - Click → smart scroll (to unread or bottom)

Changes:
- _setupSmartButtonVisibility() monitors hasMoreAfter
- _handleScrollButtonClick() loads history if hasMoreAfter
- Added public loadLatest() method
- Emits 'chat:messagesLoaded' event for UI updates

Result:
- Historical view: button always shows, loads to present
- Present view: button hides at bottom, smart unread scroll
- No more stuck in history without way to present
2026-01-13 15:21:52 +03:00
2cea8c2330 feat: Smart scroll button with unread badge and auto-scroll
Implements Telegram-like behavior for new messages:

1. Smart Auto-scroll (WS messages):
   ✅ User at bottom + present time → auto-scroll to new message
   ✅ User NOT at bottom + present time → show unread badge
   ❌ Historical view (hasMoreAfter=true) → no action

2. Smart Scroll Button (#scrollBtn):
   - Shows unread badge when new messages arrive
   - Click behavior:
     * Has unread + lastReadId → scroll to first unread
     * No unread → scroll to bottom
   - Auto-hides badge when user scrolls to bottom

3. Badge Styling:
   - Red badge with count on top-right of button
   - Pulse animation on appearance
   - Button subtle pulse when has unread

Key Logic:
- Only auto-scroll when hasMoreAfter=false (present time)
- Historical bottom (hasMoreAfter=true) doesn't trigger auto-scroll
- Badge resets on: manual scroll to bottom, button click
- Respects user's scroll position unless at bottom
2026-01-13 15:07:52 +03:00
7d0cdfedd1 chore: Add remaining test files and utilities
Added:
- Test chat API script
- Date group CSS and JS utilities
- IntersectionObserver modules
- Bidirectional loading test files
- Autoscroll testing checklist
2026-01-13 15:02:29 +03:00
8aeda0bbdd chore: Add documentation and supporting files for bidirectional loading
Added:
- Autoscroll audit and reports
- Date divider analysis and Telegram comparison
- Bidirectional loading tests and results
- Date group manager and utilities
- Test scripts and HTML test pages
- CSS for chat date groups
- IntersectionObserver utilities
2026-01-13 15:02:20 +03:00
ad3f141f1c feat: Add instant positioning to last read message on chat open
Problem: After removing autoscroll, last read message wasn't visible on initial load

Solution:
- ✨ NEW: _positionToMessage() - instant viewport positioning WITHOUT scroll animation
- Sets scrollTop BEFORE user sees chat (no visible scrolling)
- Centers last read message with sticky header offset (96px)
- Falls back to bottom position for new chats

Difference:
- ❌ Old: render → scrollIntoView() → visible scroll animation
- ✅ New: render → scrollTop = X → instant positioning

Result:
- Chat opens IMMEDIATELY showing last read message
- NO visible scrolling or animation
- Telegram-like behavior: position is set, not scrolled to
- Natural user experience
2026-01-13 14:41:24 +03:00
d3a876f1cb refactor: Remove all autoscroll except prepend physics correction
BREAKTHROUGH: Discovered append doesn't need autoscroll!

Changes:
- ✅ KEPT: scrollTop correction after prepend (physics, not autoscroll)
  Prevents infinite history loading by compensating scrollHeight growth
- ❌ REMOVED: scrollToBottom() - now empty stub
- ❌ REMOVED: scrollToMessage() - now empty stub
- ❌ REMOVED: Initial scroll on chat open
- ❌ REMOVED: Scroll after loadAround

Philosophy shift:
- Old: We control user's scroll position
- New: IntersectionObserver + physics = natural behavior

Results:
- Newer messages load perfectly WITHOUT autoscroll
- Older messages need ONLY physics correction
- User controls their own scroll position
- Natural infinite scroll experience
2026-01-13 14:35:49 +03:00
3e97ca2ac9 fix: add pauseScrollEvents method to ScrollManagerV2 2026-01-13 13:18:33 +03:00
8fa7cb2eae refactor: удалены .old файлы
- Deleted chatTestsV2.old.js
- Deleted postDetailModal.old.js

Финальная очистка deprecated кода завершена
2026-01-13 10:21:48 +03:00
fb2b534443 refactor: удалены test/example файлы и deprecated templates
- Deleted chatHistoryLoader.js (@deprecated)
- Deleted chatControllerUsage.js (example)
- Deleted chatTests.js (manual test, 1732 lines)
- Deleted test_message_editing.html
- Deleted test_message_renderer.html
- Deleted chat_detail_scripts.html (неиспользуемый template)
2026-01-13 10:18:12 +03:00
c8a64aa664 refactor: удален legacy код, chatDetailV2 переименован в chatDetail
УДАЛЕНО (57KB, 1306 строк):
✅ scrollManager.legacy.js (23KB) - заменен на ScrollManagerV2
✅ messageLoader.legacy.js (16KB) - заменен на MessageLoaderV2
✅ messageRenderer.legacy.js (18KB) - заменен на MessageRendererV2
✅ chatDetail.js (старая версия) - имел deprecated обертки
✅ chatDetailTest.js - тестовый файл

ПЕРЕИМЕНОВАНО:
✅ chatDetailV2.js → chatDetail.js (стал основным)

ПРЕИМУЩЕСТВА:
- Прямой импорт ChatControllerV2
- Нет deprecated оберток
- Поддержка lastReadTimestamp fallback
- Правильная загрузка вокруг lastRead
- Минус 57KB мертвого кода
2026-01-13 10:14:11 +03:00
7ad2cef7cc fix: исправлен критический баг - метод _loadAround не возвращал результат
ПРОБЛЕМЫ:
- chatDetailV2.js не передавал lastReadTimestamp в config
- метод _loadAround не имел return statement
- scrollIntoView скроллил родительские контейнеры

ИСПРАВЛЕНИЯ:
✅ Добавлен lastReadTimestamp в readConfig() chatDetailV2.js
✅ Добавлена передача lastReadTimestamp в ChatControllerV2
✅ Исправлен _loadAround - добавлен return loadResult
✅ Заменен scrollIntoView на ручной расчет scrollTop в _scrollToMessage
✅ Добавлено подробное логирование для отладки

РЕЗУЛЬТАТ:
- Чат загружается вокруг последнего прочитанного (16 сообщений вместо 30)
- Скролл к правильной позиции
- Header не прячется под navbar
- IntersectionObserver не срабатывает при инициализации
2026-01-13 10:11:21 +03:00
0fe736ede8 refactor: переключились на chatDetailV2.js (чистая архитектура)
- Прямой импорт ChatControllerV2 без промежуточных слоев
- Убраны deprecated обертки (window.messageRenderer, window.chatHistoryLoader)
- Меньше кода: 231 vs 264 строки
- Более явная архитектура
- Для тестирования работы в production
2026-01-13 10:03:54 +03:00
6a82ef7b80 fix: используем lastReadTimestamp как fallback для скролла к последнему прочитанному
- Проблема: lastReadMessageId часто равен 0/null
- Решение: используем lastReadTimestamp (API поддерживает оба формата)
- Добавлен this.lastReadTimestamp в ChatControllerV2
- Передаем оба параметра из chatDetail.js
- anchorValue = lastReadMessageId || lastReadTimestamp
- Исправлена поврежденная структура в chatControllerV2.js
2026-01-13 09:46:27 +03:00
103c3422a5 debug: добавлено логирование lastReadMessageId для диагностики автоскролла
- Логируем сырое значение из data-last-read-message-id
- Логируем решение загрузки (around vs latest)
- Поможет понять почему скролит в низ вместо последнего прочитанного
2026-01-13 09:42:57 +03:00
70cefe9dc0 fix: добавил флаг _isInitializing чтобы блокировать Observer во время инициализации
- проблема: Observer срабатывал сразу после setup даже с проверкой isNearBottom
- isNearBottom() возвращает false когда scrollTop=0 (пользователь вверху)
- решение: игнорируем события Observer в течение 500ms после init
- флаг _isInitializing снимается через setTimeout
- это гарантирует что автозагрузка не произойдет при первом рендере
2026-01-13 09:37:27 +03:00
e7ab9893e4 fix: добавил проверку isNearBottom в IntersectionObserver чтобы избежать ложного срабатывания
- проблема: Observer срабатывал сразу после init когда scrollTop=0
- первое сообщение было видимо → автоматическая загрузка истории
- решение: не загружаем историю если пользователь внизу (isNearBottom)
- это предотвращает ложное срабатывание при инициализации
2026-01-13 09:35:42 +03:00
041e905a44 fix: заменил scrollTo() на прямое присвоение scrollTop при инициализации
- scrollTo() НЕ работает при первичной загрузке (scrollTop остается 0)
- используется прямое присвоение scrollTop как в legacy коде
- тройной RAF для надежности
- это должно исправить проблему с автозагрузкой истории
2026-01-13 09:30:18 +03:00
6c4dc8cc12 fix: убрал плавный скролл из всех методов - теперь instant как в legacy
- scrollToBottom: использует scrollTop (мгновенно) вместо scrollTo smooth
- scrollToMessage: дефолт behavior изменен с 'smooth' на 'auto'
- это исправляет проблему с незавершенным плавным скроллом при инициализации
2026-01-13 09:28:12 +03:00
77423bfcbb fix: замена всех использований legacy классов на V2 2026-01-13 09:19:19 +03:00
7b57214fdd fix: исправлены импорты в messageEditing и chat/index 2026-01-13 09:18:25 +03:00
f7f73e7c50 refactor: переименовал устаревшие файлы в .legacy
- messageLoader.js → messageLoader.legacy.js
- scrollManager.js → scrollManager.legacy.js
- messageRenderer.js → messageRenderer.legacy.js

Теперь используются V2 версии этих модулей
2026-01-13 09:16:38 +03:00
fcee247256 fix(chat-v2): исправлена загрузка истории - silent mode + prepend
- ScrollManagerV2: использует prepend + height difference вместо полного ре-рендера
- MessageLoaderV2: фильтрует новые сообщения, возвращает только их
- MessageStoreV2: silent mode для загрузки истории (без событий)
- MessageRendererV2: детальное логирование для диагностики

Проблема: Store emit'ил события → appendMessage добавлял в конец → prependMessages пропускал дубликаты
Решение: silent mode отключает события → отрисовка только через prepend → сообщения в начало
2026-01-13 09:06:34 +03:00
0375337543 feat: implement Telegram-style badges system
- Created comprehensive badges-telegram-style.css (240 lines) based on Telegram Web K
- Updated all badge markup in templates (navbar, sidebar, chat_list, chat_detail, chat_title)
- Replaced Bootstrap badge classes with .badge-telegram classes
- Implemented Telegram specifications: 20px height, 10px radius, 11px font, 600 weight
- Added smooth animations: pulse (on update), animate-in (on mount), animate-out (on unmount)
- Updated JavaScript: replaced .d-none with style.display for badge visibility
- Updated 5 JS files: bottom-navbar, notification-manager, chatBadgeHandler, chatBadgeManager, chatListRealtime
- Added pulse animation on badge value increase
- Improved shadows and transitions with cubic-bezier easing
- Added badges-telegram-style.css to base.html for global availability
- Created documentation: TELEGRAM_BADGES_GUIDE.md, TELEGRAM_BADGES_UPDATE.md

Technical details:
- Research: Analyzed 50+ files from Telegram Web K GitHub repository
- Perfect circles: border-radius: 10px (not 50%)
- Spring animation: cubic-bezier(0.175, 0.885, 0.32, 1.275)
- Auto-hide: :empty and [data-count='0'] selectors
- Responsive design + dark theme support
2026-01-12 17:37:41 +03:00
6d76988cdd refactor: восстановлены старые стили пузырей сообщений, аватаров и разделителей (pre-redesign)
- Восстановлен мягкий цвет пузырей: color-mix(92%) вместо жесткого var(--bs-primary)
- Аватары: border-radius 9999px + grid layout для идеальных кругов
- Разделители: правильный spacing, font-weight 700, pointer-events, color-mix прозрачность
- Добавлены оптимизации скролла: rootMargin 300px, limit 50 сообщений (Telegram-стиль)
- Добавлены новые модули: messageLoader, scrollManager, chatUtils
- Рефакторинг логики загрузки сообщений для предотвращения дубликатов
- Создана документация по архитектуре и тестированию
2026-01-12 17:21:41 +03:00
1efbe8cd12 fix(messenger): полное устранение конфликтов прокрутки
ГЛУБОКИЙ АУДИТ выявил корневые причины прыжков:

НАЙДЕННЫЕ ПРОБЛЕМЫ:
1. chatMarkRead делал свою прокрутку ПОСЛЕ handleInitialMessages
   - mark.scrollIntoView() или autoscroll() в requestAnimationFrame
   - Конфликтовал с уже установленной прокруткой

2. Дублирование обработчика кнопки 'вниз':
   - chatMarkRead.js: btn.addEventListener
   - chat-detail-enhanced.js: scrollBtn.addEventListener
   - Два обработчика на одну кнопку!

3. Излишняя сложность в scrollToBottom():
   - Вызывал markReadApi.autoscroll() вместо прямой установки
   - Дополнительный уровень косвенности = источник багов

ИСПРАВЛЕНИЯ:
1. chatMarkRead НЕ скроллит при инициализации:
   - Divider создается, но не скроллится к нему
   - Прокрутка управляется ТОЛЬКО из handleInitialMessages
   - Единая точка ответственности

2. Убрано дублирование кнопки:
   - Удален обработчик из chat-detail-enhanced.js
   - Остался только в chatMarkRead.js

3. Упрощен scrollToBottom():
   - Прямая установка scrollTop вместо вызова markReadApi
   - Поддержка instant режима (без анимации)
   - Предсказуемое поведение

4. Добавлены комментарии и документация:
   - Пояснено почему НЕ скроллим в chatMarkRead
   - Описано назначение каждой функции прокрутки
   - Создан полный аудит в docs/completed/SCROLL_CONFLICTS_AUDIT.md

АРХИТЕКТУРА ПРОКРУТКИ:
✅ При загрузке: ТОЛЬКО handleInitialMessages
✅ Кнопка вниз: chatMarkRead.autoscroll()
✅ Новые сообщения: ТОЛЬКО если свое ИЛИ уже внизу
✅ Ввод текста: autoscroll() если внизу

РЕЗУЛЬТАТ:
✅ Нет прыжков - единая точка управления прокруткой
✅ Нет конфликтов - каждая функция делает одно
✅ Нет дублирования - один обработчик на событие
✅ Предсказуемость - прямые вызовы вместо косвенных

Файлы:
- userWebSocket.js: упрощен scrollToBottom
- chatMarkRead.js: убрана автопрокрутка при инициализации
- chat-detail-enhanced.js: убран дублирующий обработчик
- docs/completed/SCROLL_CONFLICTS_AUDIT.md: полный аудит
2026-01-12 11:11:02 +03:00
e1d27370c0 fix(messenger): исправление прыжков при загрузке и дублирования скриптов
ПРОБЛЕМЫ:
1. Видимые прыжки прокрутки при загрузке чата
2. Принудительный скролл при получении чужих сообщений
3. Дублирование загрузки chat-detail-enhanced.js

РЕШЕНИЯ:
1. Используем requestAnimationFrame для гарантии обновления DOM перед прокруткой
   - Скрываем контейнер → рендерим → ждем RAF → скроллим → показываем
   - Прокрутка происходит ДО показа контейнера = нет видимых прыжков

2. Убираем агрессивный автоскролл в handleNewMessage:
   - Скроллим только если это наше сообщение ИЛИ мы уже внизу
   - Предотвращаем прерывание чтения старых сообщений

3. Убираем дублирование chat-detail-enhanced.js в шаблоне:
   - Было: загружается ДО chatDetail.js
   - Стало: загружается ПОСЛЕ для правильного порядка инициализации

4. Улучшен порядок загрузки скриптов в chat_detail.html:
   - emoji-picker (третья сторона)
   - chatDetail.js (core инициализация)
   - chat-detail-enhanced.js (UI расширения)

РЕЗУЛЬТАТЫ:
✅ Нет видимых прыжков - чат открывается сразу в конце
✅ Не прерывается чтение старых сообщений при приходе новых
✅ Правильный порядок инициализации компонентов
✅ Убрано дублирование загрузки скриптов
2026-01-12 11:03:41 +03:00
17f818656d perf(messenger): оптимизация загрузки initial messages
Проблема: При открытии чата сначала загружались сообщения,
затем происходила видимая прокрутка вниз - плохой UX

Решение:
1. Скрываем контейнер (visibility: hidden) перед рендерингом
2. Используем DocumentFragment в renderMessages для батчевой вставки
3. Устанавливаем scrollTop ДО показа контейнера
4. Показываем контейнер - пользователь сразу видит конец диалога

Преимущества:
- Нет видимой прокрутки - сразу показывается конец чата
- Меньше reflow (1 вместо N при forEach)
- Быстрее рендеринг больших чатов (все элементы вставляются за раз)
- Лучший UX - нет "прыжков" при загрузке

Изменения:
- userWebSocket.js: добавлено скрытие/показ контейнера, прямая установка scrollTop
- messageRenderer.js: renderMessages использует DocumentFragment вместо множественных insertAdjacentHTML
2026-01-12 10:56:59 +03:00
1be2f3cdd4 refactor(messenger): Phase 3-4 - финализация рефакторинга
Фаза 3-4: Упрощение и документирование
- Улучшена структура initializeComponents() в chatDetail.js
  * Пронумерованные шаги (1-8) для четкого порядка
  * Улучшенное логгирование с ✓ маркерами
  * MessageRenderer создается первым
  * Экспорт всех API в window для отладки
- Добавлена подробная JSDoc документация
  * @fileoverview с описанием архитектуры
  * @param для всех функций
  * Описание порядка инициализации
- Обновлена документация MESSAGES_LOADING_REFACTORING.md
  * Отмечены все 4 фазы как завершенные
  * Добавлена финальная архитектура
  * Количественные и качественные показатели
  * Переведен в docs/completed/

Результаты рефакторинга:
✅ Удалено 540+ строк мертвого кода
✅ Унифицирован рендеринг через MessageRenderer
✅ Улучшена читаемость и поддерживаемость
✅ Исправлен баг infinite loader

Рефакторинг завершен успешно!
2026-01-12 10:52:44 +03:00
86791f7bf3 refactor(messenger): Phase 2 - унификация рендеринга сообщений
- Добавлен метод MessageRenderer.createMessageElement() для создания DOM элементов
- Обновлен chatComposer для использования MessageRenderer
- Обновлен chatHistoryLoader для использования MessageRenderer
- Обновлен chatDetail.js для передачи messageRenderer в модули
- Все модули теперь используют единый источник рендеринга
- Сохранена обратная совместимость через fallback на createMessageElement()

Phase 2 of 4: Rendering unification completed
2026-01-12 10:42:11 +03:00
3433886be3 refactor(chat): удалены неиспользуемые модули загрузки сообщений
- Удалён chatWebSocket.js (дублировал userWebSocket.js)
- Удалён initialMessagesLoader.js (не используется, загрузка через WS)
- Очищены импорты и закомментированный код в chatDetail.js
- Добавлен план рефакторинга в docs/in-progress/

Загрузка initial messages теперь происходит только через:
- userWebSocket.handleInitialMessages() - начальные сообщения
- chatHistoryLoader - подгрузка истории при скролле
2026-01-12 10:27:38 +03:00
003bbab1ff Добавлена нижняя навигационная панель для мобильных устройств
- Добавлена bottom navbar с 5 кнопками (Главная, Уведомления, Поиск, Календарь, Ещё)
- Панель отображается только на мобильных устройствах (до 768px)
- Использованы системные CSS переменные и стили
- Удалена кнопка гамбургера из верхней панели (дублирование функционала)
- Добавлена синхронизация бейджей уведомлений
- Поддержка светлой и темной темы
- Backdrop-filter для полупрозрачности в iOS-стиле
2026-01-12 08:32:16 +03:00
2b61564837 feat(communications): Реализация управления уведомлениями чатов и оптимизация
- Добавлен API endpoint для включения/выключения уведомлений чата
- Реализован frontend для управления уведомлениями через меню чата
- Обновлены сигналы для проверки настроек notifications_enabled
- Стандартизирована логика уведомлений для всех типов чатов
- Оптимизированы запросы к БД (1 запрос вместо N для ChatUserSettings)
- Переведены детальные логи с INFO на DEBUG уровень

Файлы:
- backend/api/v1/communications/views.py (новый endpoint)
- backend/api/v1/urls.py (новый маршрут)
- backend/static/js/components/chatMenuActions.js (полная реализация)
- backend/communications/notification_signals.py (проверка настроек + оптимизация)
- backend/notifications/services.py (оптимизация логирования)
2026-01-08 14:39:40 +03:00
2a76ffacab refactor: Web Push Phase 1 - Critical fixes for AbortError
✅ КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ:
1. Упростил _checkSubscription() - теперь ТОЛЬКО чтение
   - Убрана автоматическая синхронизация с сервером
   - Убрана автоматическая переподписка при ошибках
   - Метод не модифицирует состояние

2. Исправил subscribe() - убран принудительный unsubscribe
   - Браузер сам управляет существующими подписками
   - update_or_create на backend обновит запись
   - Избегаем конфликтов Push Service

3. Улучшен resetEverything() для recovery
   - Полная очистка: unsubscribe + unregister + localStorage
   - Задержка 2 сек для обработки Push Service
   - Подробное логирование каждого шага
   - Инструкции для пользователя

4. Добавлена детекция AbortError
   - Понятное сообщение в консоли
   - Инструкция по recovery
   - Ссылка на resetEverything()

�� Добавлен полный аудит:
- backend/docs/reports/WEB_PUSH_AUDIT_2026_01_06.md
- Детальный анализ всех компонентов
- План рефакторинга (4 фазы)
- Чек-листы для тестирования

Связано с: #AbortError #WebPush #VAPID
2026-01-06 08:26:50 +03:00
d36e9dfd7c feat: Auto-unsubscribe push on logout, force resubscribe on login
- Добавлена автоматическая отписка от Web Push при выходе
- При входе принудительно переподписываем пользователя
- Очищаем старую подписку из localStorage перед новой
- Это исправляет AbortError из-за старых подписок с другими VAPID ключами
2026-01-06 08:11:24 +03:00
fc6a6b0816 fix: Close catch block in _checkSubscription
Missing closing brace after catch block caused syntax error
2026-01-06 08:02:21 +03:00
62982fedb2 fix: Remove all DEBUG logs from push-notifications.js
- Clean up verbose console.log statements
- Keep only essential error/success logs
- Fix syntax error on line 177
2026-01-06 07:54:18 +03:00
dced7d3aa6 feat: Implement Web Push notifications with VAPID
- Split notification sending into separate WebSocket and Web Push channels
- Add Web Push support for offline users
- Configure VAPID keys for push authentication
- Add 'aud' field to VAPID claims for WNS compatibility
- Optimize subscription sync - only POST when endpoint changes
- Remove debug logs and minimize server logging
- Update Service Worker with improved error handling
- Add Service-Worker-Allowed header for proper scope

Web Push now works independently from WebSocket, enabling
notifications when browser is closed (requires HTTPS in production)
2026-01-06 07:48:04 +03:00
03b584769a static 2026-01-05 15:04:45 +03:00
158167b4b8 templates 2026-01-05 15:04:38 +03:00
73b082aae5 fix: Service Worker registration and API routing issues
- Move Service Worker to root (/sw.js) for proper scope registration
- Add route to serve sw.js from root with correct content-type
- Update push-notifications.js to register sw.js from root
- Fix all notification API URLs to use /api/v1/ prefix
- Update notificationsApi.js to use correct v1 endpoints
2026-01-05 14:38:06 +03:00
1587b5dffd fix: handle non-JSON error responses in requestCrudHandler 2026-01-05 14:35:19 +03:00
0d7c442b6b feat: implement Web Push notifications for offline browser notifications
- Add WebPushSubscription model for storing push subscriptions
- Generate VAPID keys for Web Push authentication
- Add API endpoints for push subscribe/unsubscribe
- Create Service Worker (sw.js) for handling push events
- Create JavaScript module for managing push subscriptions
- Integrate send_web_push_notification into NotificationService
- Add Service Worker registration to base.html
- Update requirements.txt with pywebpush package
2026-01-05 14:10:42 +03:00
fff16130f3 feat(department-roles): complete LDAP architecture redesign with RoleAssignment model
BREAKING CHANGES:
- Removed OU=Roles from LDAP structure, role groups now created directly in department OU
- Role groups use ROLE_<Name> naming convention (similar to DEP_, POS_)

New features:
- RoleAssignment model: allows assigning roles to ANY employee, not just department members
- New API endpoints: /assign/, /revoke/, /assignments/ on DepartmentRoleViewSet
- Permission system updated: has_dept_perm() checks RoleAssignment first
- Employee profile shows external roles with 'внешняя роль' badge
- Employee list filter includes role-only employees with department_relation field
- Role assignment modal now searches all employees via AJAX

LDAP changes:
- _ensure_role_group(): creates ROLE_<Name> group in department OU
- assign_role(), revoke_role(): manage RoleAssignment + LDAP sync
- rename_role_group(), delete_role_group(): full lifecycle support
- Removed all references to OU=Roles

Migrations:
- 0035: Create RoleAssignment model
- 0036: Data migration from EmployeeDepartment.role

Tests:
- 7 new tests for role assignment (all passing)

Docs:
- 9 detailed reports on architecture, models, API, LDAP, tests
2025-12-30 10:35:34 +03:00
a7d46c04f5 feat(requests): добавлены фильтры по сотруднику и периоду дат 2025-12-29 15:32:27 +03:00
cc261f13cb feat(requests): текст темы в списке заявлений теперь ссылка на страницу деталей 2025-12-29 14:47:13 +03:00
7e7a2b2f9b fix(requests): убрано двоеточие перед именем approver в списке заявлений 2025-12-29 14:40:45 +03:00
c433001c85 refactor(requests): показывать имя approver вместо кнопок действий для уже обработанных заявлений 2025-12-29 14:38:48 +03:00
002c1ffb55 fix(requests): исправлена отправка уведомлений при создании заявления
ПРОБЛЕМА: Уведомления не отправлялись при создании нового заявления

ПРИЧИНА: Сигнал post_save срабатывал ДО установки ManyToMany связей (recipients, cc_users)

РЕШЕНИЕ:
- Добавлен сигнал m2m_changed для отслеживания установки recipients/cc_users
- При создании заявления оно помечается как ожидающее отправки уведомлений
- После установки recipients через .set() срабатывает m2m_changed и отправляет уведомления
- Используется глобальный set _pending_new_requests для отслеживания

УЛУЧШЕНИЯ:
- Добавлено подробное логирование процесса создания и отправки уведомлений
- Разные эмодзи-иконки для разных типов получателей (� адресовано, � в копии, ✅ на согласование)
- Все типы используют notification_type='request_new' (существующий в БД)

Файлы:
- notification_signals.py: добавлены сигналы m2m_changed
- serializers.py: добавлено логирование создания и установки recipients
2025-12-29 11:56:56 +03:00