- Changed Modal component to support render prop pattern (children as function)
- Modal children can now receive isFullscreen state as parameter
- Changed modal size from 'xl' to 'lg' for compact default view
- Thumbnail now only shows when modal is in fullscreen mode
- In normal mode: single column with metadata and 'Open file' button
- In fullscreen mode: two columns with metadata (left) and thumbnail (right)
- Provides progressive disclosure: compact view first, expanded view on demand
- Left column: metadata and information (2/3 width)
- Right column: document thumbnail preview (1/3 width)
- Thumbnail supports: images (direct display), PDFs (iframe), other files (icon placeholder)
- Added 'Open in full size' button in thumbnail section
- Removed separate file open button from main content
- Sticky positioning for thumbnail on scroll
- Responsive: single column on mobile, two columns on large screens
- Changed modal size from 'lg' to 'xl' for better layout
- Added metadata grid with author, creation date, file info, and file size
- Added folder location section with FolderOpen icon
- Enhanced recipients section with departments and individual recipients
- Added visual indicators with colored icon badges
- Improved layout with better spacing and visual hierarchy
- File open button now full-width for better visibility
- Shows up to 10 individual recipients with overflow indicator
The max-h-[90vh] class was duplicated:
- Once in the hard-coded className
- Once in modalSizeClass variable
Now it only comes from modalSizeClass, avoiding CSS duplication
Changes to match existing modal patterns:
- Update z-index from z-50 to z-[100] for consistency
- Add backdrop-blur-sm to backdrop for modern glass effect
- Change shadow-2xl to shadow-xl (project standard)
- Move max-h-[90vh] to container level (not content div)
- Move overflow-y-auto to container for proper scrolling
- Update close button from rounded-lg to rounded-full
- Change button padding from p-2 to p-1 for tighter look
- Remove border-b from header, use mb-4 instead
- Change h2 to h3 for header title (semantic hierarchy)
- Add bottom padding div for proper spacing
Style now matches CalendarModal, EventModal, and ViewEventDetailsModal patterns
New features:
- Create reusable Modal component with animations
- Add useModal hook for common modal behaviors
- Add useClickOutside hook for backdrop clicks
- Implement ESC key handling for all modals
- Add focus trap to prevent focus escaping modals
- Add body scroll locking when modals are open
- Add fullscreen toggle option for modals
- Add fade-in/scale animations for smooth transitions
Modal improvements:
- Upload modal: converted to use new Modal component
- Document details modal: converted to use new Modal component
- Create folder modal: converted to use new Modal component
- Acknowledgements report: enhanced with modal hooks
Technical details:
- Modal sizes: sm, md, lg, xl, full
- Configurable close behavior (ESC, click outside, close button)
- Automatic scrollbar width compensation
- Focus restoration after modal close
- Accessible with ARIA attributes and keyboard navigation
Backend improvements:
- Add document_count annotation to FolderViewSet queryset
- Add document_count field to FolderSerializer
Frontend improvements:
- Add folder_path display in document cards with folder icon
- Add document count badges in folder tree
- Add breadcrumbs navigation showing current folder path
- Improve folder selector button to show selected folder name
- Add clear filter button (X) to folder selector
- Add highlighted style for selected folder in selector
- Update Document interface to include folder and folder_path fields
UI enhancements:
- Folder path shown in sky-blue color with FolderOpen icon in cards
- Document count displayed in gray badge next to folder names
- Breadcrumbs allow quick navigation back to root
- Selected folder highlighted with sky-blue background
- Visual feedback for folder selection state
Backend changes:
- Add acknowledgement_required field to Document model (migration 0009)
- Add FolderViewSet with CRUD endpoints for folder management
- Add folder_id filtering support in DocumentViewSet.get_queryset()
- Register folders endpoint in API router
Frontend changes:
- Add DocumentAcknowledgementsReport component for viewing acknowledgement status
- Add folder_id parameter to getDocuments API method
- Add currentFolderId prop to DocumentUploadForm
- Update document creation to save to selected folder
- Add folder filtering in documents list view
- Fix PDF worker loading (use local worker instead of CDN)
- Lock pdfjs-dist version to 5.4.296 to prevent conflicts
- Add postinstall script to copy PDF worker to public/
Features:
- Hierarchical folder structure with parent-child relationships
- Filter documents by selected folder
- Upload documents to specific folders
- View acknowledgement statistics with search and export
- Local PDF worker for reliable document preview
MAJOR UPDATE: Complete documents page overhaul with all advanced features!
Frontend Integration:
- Created FolderTree component (hierarchical folder navigation)
- Added sidebar with folders and quick navigation
- Integrated Dashboard view (toggle between Documents/Dashboard)
- Added Advanced Search toggle (simple/advanced modes)
- Integrated BulkActionsToolbar with multi-select checkboxes
- Added EnhancedPDFViewer for PDF files
- Select All checkbox for bulk operations
- Folder filtering support
New Components:
- FolderTree: Expandable tree with CRUD actions
- Sidebar: Folders + Quick navigation menu
- View Modes: Documents | Dashboard tabs
Updated documents/page.tsx:
- 2-column layout: Sidebar + Main content
- Bulk selection with useDocumentSelection hook
- Enhanced PDF preview for .pdf files
- Regular preview for other files
- Folder-based filtering
- Toggle sidebar visibility
- All Phase 4 components integrated
Features Now Available:
✅ Hierarchical folder navigation
✅ Bulk operations (select all, multi-select)
✅ Enhanced PDF viewer with zoom/rotate/search
✅ Advanced search with filters
✅ Dashboard with analytics
✅ Document acknowledgements (already present)
✅ Workflow buttons
✅ Status filtering
What Users Can Now See:
1. Folder tree in sidebar
2. Documents with checkboxes
3. Bulk actions toolbar when items selected
4. Advanced search option
5. Dashboard tab
6. Enhanced PDF viewer for PDFs
7. Select all functionality
Branch: feature/django-filer-documents
Phase 4 Advanced Features complete!
- Created BulkActionsToolbar component with features:
* Multi-select documents with checkboxes
* Batch actions: move to folder, add tags, change status, delete
* Real-time progress tracking for batch operations
* Undo notification with 5-second timeout
* useDocumentSelection hook for state management
- Created DocumentsDashboard component with features:
* Statistics cards: total docs, my docs, approved, activity
* Line chart: uploads over last 30 days (recharts)
* Pie chart: document type distribution
* Bar chart: document status distribution
* Activity feed: recent uploads, edits, status changes
* Quick access sections: Recent, Favorites, My Documents
* Responsive grid layout
Total Phase 4 Deliverables:
1. ✅ Client-side processing integration into upload form
2. ✅ Enhanced PDF Viewer with zoom, rotate, page navigation
3. ✅ Advanced Search with filters and saved searches
4. ✅ Batch Operations with progress tracking
5. ✅ Dashboard & Analytics with charts
- Updated DocumentUploadForm to use processDocument utility
- Added real-time progress tracking with visual feedback
- Display extracted text in editable textarea
- Support compressed file upload
- Added extracted_text field to API client and backend serializer
- Auto-process PDFs, DOCX, and images on file selection
Created comprehensive document processing library:
� src/lib/document-utils/
├── processor.ts - Главный процессор (интеллектуальная обработка)
├── ocr.ts - OCR через Tesseract.js (rus+eng)
├── pdf.ts - PDF операции (extract text, thumbnail, split, merge, rotate)
├── docx.ts - DOCX извлечение текста (mammoth.js)
├── image.ts - Image processing (compress, crop, rotate, thumbnail)
└── index.ts - Экспорты
Возможности:
✅ Автоматическое определение типа файла
✅ OCR для изображений (client-side, не нагружает сервер)
✅ Извлечение текста из PDF и DOCX
✅ Сжатие изображений перед загрузкой
✅ Генерация thumbnails
✅ Progress callbacks для UI
✅ Оценка времени обработки
✅ TypeScript типы для всех функций
Преимущества перед server-side:
- Моментальная обратная связь
- Не нагружает backend
- Приватность (файл не уходит на сервер до загрузки)
- Экономия трафика (сжатие до отправки)
- Можно показать preview extracted text ДО upload
Phase 2 & 3 Complete!
- Добавлена закрывающая скобка } в onClick handler
- Добавлено содержимое кнопки с иконкой Eye
- Удален блок отображения document_type (поле не существует в модели)
- Убраны поля document_type и tags из DocumentUploadForm
- Обновлен API клиент: createDocument и updateDocument без этих полей
- Обновлены TypeScript типы в api.ts
- Убраны document_type и tags из отображения в documents/page.tsx
- Форма теперь принимает только: title, description, file
- Добавлена проверка Array.isArray() в NotificationCenter
- Добавлена защита от non-array в useNotifications хук
- Исправлен импорт date-fns/locale для версии 4+
- В случае ошибки API устанавливается пустой массив []
Frontend:
- Установлен Sonner для toast уведомлений
- Создан Service Worker (public/sw.js) для Web Push
- Реализован хук useWebPush для управления подписками
- Добавлены утилиты Web Push (lib/push.ts)
- Создан компонент NotificationCenter с UI
- Интегрирован в AppShell (header desktop + mobile)
- Добавлен Toaster в Providers
API методы:
- getVapidPublicKey() - получение VAPID ключа
- subscribePush() - создание подписки
- unsubscribePush() - удаление подписки
- getPushSubscriptions() - список подписок
Возможности:
- � Web Push (работают даже когда вкладка закрыта)
- � NotificationCenter с badge и историей
- � Toast уведомления (Sonner)
- ⚙️ Настройки push подписок
- � Респонсивный дизайн
Документация: frontend/NOTIFICATIONS_IMPLEMENTATION.md
- Добавлены 5 новых моделей в watson search:
* ProcurementRequest (заявки на закупку)
* Equipment (оборудование)
* Document (документы)
* Notification (уведомления)
* Event из django-scheduler (расписание)
- Backend API: форматтеры для новых типов моделей
- Frontend: добавлены иконки и названия для новых типов
- Тесты: исправлены фикстуры, все 13 тестов проходят
- Индексы: 3895 записей проиндексировано
Итого: 12 моделей доступны для полнотекстового поиска
Backend:
- Created REST API endpoint /api/v1/search/
- Added SearchResultSerializer and SearchResponseSerializer
- Implemented search_api_view with model formatters (employee, department, post, request, chat, message, event)
- Registered search endpoint in api/v1/urls.py
- Added permission check for requests (HR can see all, users only their own)
Frontend:
- Added SearchResponse, SearchResult, SearchModelType types
- Added apiClient.search() method in lib/api.ts
- Completely rewrote search/page.tsx:
* Single API call instead of 6 parallel requests
* Cleaner UI with icons for each result type
* Real-time search with loading states
* Meta information display (email, phone, status, etc.)
* Better performance and UX
Benefits:
- Frontend: 220 lines → 178 lines (19% reduction)
- 1 API request instead of 6 (83% less network calls)
- Server-side full-text search via watson (better relevance)
- Unified search results with metadata
Testing:
- API endpoint verified at /api/v1/search/?q=test
- Returns JSON with query, results, counts, total
- Requires authentication (IsAuthenticated decorator)
- Удалено поле last_read_at из ChatReadState, используется только last_read_message FK
- Исправлена логика автоотметки: отмечается последнее ЗАГРУЖЕННОЕ сообщение, а не последнее в чате
- Убран вызов chat.mark_read() при WebSocket open_chat (отмечал последнее в чате вместо загруженного)
- Добавлен signal для мониторинга изменений ChatReadState
- Исправлена логика скролла: убран автоскролл при дозагрузке вниз
- Добавлена проверка разрывов при WebSocket сообщениях (предотвращает пропуск сообщений)
- Реализована автоотметка WebSocket сообщений (только если пользователь внизу)
- Асимметричная загрузка: 24 контекста + 6 новых сообщений
- Добавлен ScrollableMessageList компонент для корректной работы скролла
- Миграции: 0028 (удаление last_read_at), 0029 (индекс на last_read_message)
- Добавлены API методы в api.ts:
* getChats, getChat, createChat
* getChatMessages, sendMessage, sendMessageWithFiles
* updateMessage, deleteMessage
* markChatAsRead, togglePinChat, toggleChatNotifications
- Создан компонент NewChatModal:
* Поиск и выбор сотрудников
* Поддержка приватных и групповых чатов
* Автоматическое название для групп
- Интегрирована кнопка 'Новый чат' в Chatscope UI
- При создании чата автоматически открывается диалог
- Установлены пакеты @chatscope/chat-ui-kit-react и @chatscope/chat-ui-kit-styles
- Создана новая страница /messages-chatscope с полнофункциональным мессенджером
- Добавлен пункт 'Мессенджер (NEW)' в навигационное меню
- Реализована интеграция с существующим Django API
- Добавлена поддержка WebSocket для real-time сообщений
- Список чатов с поиском и аватарами
- Отображение сообщений с датами и вложениями
- Индикатор 'печатает...' через WebSocket
- Extract CalendarCard to separate component (467 lines)
- Create calendarService for API and caching (156 lines)
- Add useCalendarEvents hook (96 lines)
- Create CalendarSidebar wrapper component (29 lines)
- Reduce AppShell.tsx from 1277 to 634 lines (-50%)
- Implement proper separation of concerns
- Move global cache to service layer
- Improve code maintainability and testability
- Реализована возможность конвертации повторяющегося события в обычное:
* При снятии галочки 'Повторяющееся событие' rule_id сбрасывается в null
* Событие становится одиночным, все occurrence исчезают
- Добавлен метод updateRule() в apiClient:
* Позволяет обновлять существующие правила повторения
* Изменения применяются ко всем occurrence события
* Использует PUT запрос к /api/v1/schedule/rules/{id}/
- Исправлено использование repeatMode:
* Заменен устаревший useCount на repeatMode ('until' | 'count' | 'forever')
* Корректная обработка end_recurring_period только для режима 'until'
- Добавлена универсальная функция normalizeByweekday():
* Решена проблема с разными форматами byweekday с backend:
- Массив: [0, 4] ✓
- Строка: '0,4' ✓
- Число: 4 ✓
* Функция используется во всех компонентах:
- EventModal: авто-выбор дней, отображение кнопок, сохранение
- ViewEventDetailsModal: отображение дней недели
* Исправлены ошибки '.map is not a function' и '.includes is not a function'
- Улучшена логика handleSave() в EventModal:
* Проверка необходимости сброса rule при снятии галочки
* Разделение логики создания и обновления правил
* Нормализация byweekday перед отправкой на backend
Closes: полная поддержка CRUD операций для повторяющихся событий
- Заменен boolean useCount на enum repeatMode: 'until' | 'count' | 'forever'
- Добавлен третий radio button 'Бесконечно' в UI
- При выборе 'forever' count и end_recurring_period = undefined
- Для бесконечного режима показывается пояснение вместо input
- loadRule() правильно определяет repeatMode при загрузке правила
- При включении isRecurring по умолчанию repeatMode = 'until'
Проблема: нельзя было создать событие без ограничений по дате или количеству.
Решение: RFC 5545 RRULE поддерживает бесконечное повторение (без count/until).
- Убрана блокировка редактирования для существующих повторяющихся событий
- loadRule() теперь заполняет поля формы параметрами из Rule:
* frequency, interval, byweekday, count
* isRecurring = true
* useCount устанавливается если есть count
- Удален readonly блок с информацией о повторении
- Редактируемые поля теперь доступны для всех событий
- При сохранении будет обновлен Rule через API
Проблема: нельзя было изменять параметры повторения (частота, дни недели, count).
Решение: все occurrences используют общий Rule - просто редактируем его параметры.
Backend:
- Добавлено поле rule_data в EventSerializer
- get_rule_data() возвращает частоту, параметры и описание правила
- Использует rule.get_params() для получения распарсенных параметров
Frontend:
- Добавлены константы FREQUENCY_LABELS и WEEKDAY_LABELS для русификации
- Новый блок с детальной информацией о повторении в синем фоне
- Отображается частота (WEEKLY, MONTHLY и т.д.)
- Дни недели для еженедельных событий (ПН, ВТ, СР...)
- Количество повторений (count)
- Дата окончания повторения (end_recurring_period)
- Подсказка о невозможности редактирования параметров
Проблема: пользователь не видел детали повторяющихся событий.
Решение: красивый информационный блок с полной информацией о правиле.
- Добавлено поле color_event в тип SidebarCalendarEvent
- Добавлен цветной индикатор (h-2 w-2 rounded-full) перед названием события
- Используется fallback: color_event || color || #3498db
- Индикатор отображается рядом с названием события
Проблема: в списке 'На этой неделе' не было визуальных индикаторов цвета события.
Решение: добавлен цветной кружок перед названием каждого события.
- Изменена логика eventDays для учета всех дней многодневного события
- Теперь перебираются все дни от start до end включительно
- Добавлена обработка событий без end (однодневные)
- Сброс времени для корректного сравнения дат
Проблема: точки-индикаторы отображались только в день начала события.
Решение: добавление всех дней из диапазона [start, end] в Set eventDays.
- Убран вызов useCalendar() из AppShell (вызывался до создания CalendarProvider)
- Добавлен state currentSelectedCalendarId в AppShell
- selectedCalendarId передается через props и синхронизируется через useEffect
- onCalendarChange callback передается в Calendar -> CalendarCard
- CalendarCard синхронизирует selectedCalendarId с родительским компонентом
Проблема: useCalendar вызывался в AppShell до того, как CalendarProvider был создан.
Решение: передача selectedCalendarId через props вместо прямого вызова хука.
- Добавлена проверка selectedCalendarId при создании события из мини-календаря
* Теперь при попытке создать событие без выбранного календаря появляется предупреждение
* selectedCalendarId передается в новое событие вместо null
* Добавлен useCalendar() хук в AppShell для доступа к selectedCalendarId
- Исправлено отображение многодневных событий в ViewDayEventsModal
* Изменена логика фильтрации событий: теперь проверяется диапазон [start, end]
* Многодневные события отображаются для всех промежуточных дней, не только для начала/конца
* Исправлена проблема, когда события не показывались в промежуточные дни
Проблема: в большом календаре проверка была, в мини-календаре - нет.
Решение: унификация логики создания события с проверкой выбранного календаря.
- Исправлен RuleSerializer для корректной конвертации params между форматами:
* Frontend отправляет dict/JSON: {"byweekday": [0, 4], "interval": 1}
* Backend сохраняет в формате django-scheduler: "byweekday:0,4;interval:1"
* Добавлен универсальный парсер _parse_params_input() для всех форматов
- Добавлен UX в стиле Apple Calendar для еженедельных событий:
* Авто-выбор дня начала при включении WEEKLY
* Информационный баннер с датой первого события если начальный день не выбран
* Защита от перезаписи выбора пользователя через useRef
- Рефакторинг и очистка кода:
* Удалены все отладочные console.log() и print()
* Улучшены docstrings с примерами
* Добавлена константа VALID_FREQUENCIES
- Исправлена загрузка событий в режиме "Все события":
* Убрана блокировка для selectedCalendarId === null
* События и occurrences загружаются корректно для всех календарей
Closes: повторяющиеся события теперь генерируются только в выбранные дни недели
Новые компоненты:
- ViewDayEventsModal: показывает все события в выбранный день
- Список событий с временем и описанием
- Кнопка "Создать событие на этот день"
- Клик на событие → ViewEventDetailsModal
- ViewEventDetailsModal: детали события (read-only)
- Все поля события (время, описание, участники)
- Индикаторы повторяющихся событий �
- Кнопки "Редактировать" и "Удалить"
Изменения в BigCalendar:
- handleSelectSlot: клик на дату → открывает ViewDayEventsModal вместо прямого создания
- handleSelectEvent: клик на событие → открывает ViewEventDetailsModal вместо прямого редактирования
- Добавлены обработчики переходов между модалами
Изменения в AppShell:
- handleOpenEventModal: логика маршрутизации модалов (дата/событие/создание)
- Добавлены обработчики для новых модалов
- sidebarEvents: состояние для передачи событий в ViewDayEventsModal
- Интеграция в CalendarCard для обоих календарей (desktop + mobile)
Преимущества UX:
- Пользователь видит контекст перед действием
- Предотвращение случайных дубликатов событий
- Логичный flow: Просмотр → Действие (create/edit/delete)
- Особенно полезно для повторяющихся событий
Frontend:
- Добавлена опция "� Все события" в выбор календаря (BigCalendar и AppShell)
- selectedCalendarId === null теперь показывает все события пользователя
- Изменена логика loadEvents: при null используется apiClient.getMyEvents()
- CalendarContext: по умолчанию selectedCalendarId === null (не выбирается первый календарь)
- UX улучшение: пользователь видит все свои события сразу при загрузке страницы
Backend:
- Расширен get_queryset в ScheduleEventViewSet: теперь пользователь видит события где он участник (EventRelation), даже если не имеет доступа к календарю
- Добавлен action my-events для получения только событий участника
- Исправлена архитектурная проблема: участники событий теперь могут видеть свои события
Frontend:
- Добавлен метод apiClient.getMyEvents() для получения событий пользователя
- Добавлена подсказка в EventModal о логике начала/конца для повторяющихся событий
- Улучшен UX: пользователи понимают что начало/конец применяются ко всем повторениям
- Добавлен useEffect для очистки временных состояний при isOpen=false
- Сбрасываются: showAddParticipants, selectedEmployeeIds, pendingParticipantIds, searchQuery, availableEmployees
- Исправлена проблема с сохранением состояния между открытиями модала
- Добавлена функция toLocalDateTimeString для корректной конвертации UTC в локальное время
- Исправлено отображение времени в модальном окне событий (было 21:00 UTC вместо 00:00 MSK)
- Упрощена логика datetime-local inputs (удалена сложная условная логика)
- Добавлен allDayAccessor в react-big-calendar для корректного отображения событий
- Унифицирован EventModal для обоих календарей (~718 строк удалено)
- Добавлен CustomToolbar для BigCalendar со стрелками навигации
- Выпадающий список для выбора вида календаря
- Management command для создания тестовых пользователей и календарей
- Создано 3 тестовых пользователя (anna_ivanova, petr_petrov, maria_sidorova)
- Создано 5 календарей с 11 событиями
- Убраны подписки (они для старой системы calendar_app)
- Исправлены стили тулбара BigCalendar
- Модалы календаря рендерятся на корневом уровне AppShell