From ff9b094dd7f3b138dcb1f22a1564b0096f569bad 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: Mon, 8 Dec 2025 12:09:32 +0300 Subject: [PATCH] fix: improve recipient picker - load all users with avatars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RecipientPicker (заявления): - Added pagination support to load ALL users (not just first page) - Added avatar images from media URLs instead of base64 - Falls back to initials when no avatar available - Loads users in batches of 100 per page RecipientPickerHandler (чаты): - Added pagination support for full user list - Keeps existing avatar display logic - Loads 100 users per page when not searching - Limits to 20 results when searching CSS improvements: - Added styles for avatar images (.user-avatar-img) - Added placeholder styles for initials - Proper object-fit and border-radius for avatars --- .../static/css/components/recipientPicker.css | 22 ++++++++ .../static/js/components/recipientPicker.js | 56 +++++++++++++++---- .../js/components/recipientPickerHandler.js | 34 ++++++++--- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/backend/static/css/components/recipientPicker.css b/backend/static/css/components/recipientPicker.css index 23a94928..a3a21889 100644 --- a/backend/static/css/components/recipientPicker.css +++ b/backend/static/css/components/recipientPicker.css @@ -182,6 +182,28 @@ font-weight: 600; font-size: 0.75rem; flex-shrink: 0; + overflow: hidden; +} + +/* Изображение аватара */ +.user-avatar-img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 50%; +} + +/* Плейсхолдер с инициалами */ +.user-avatar-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: var(--bs-primary); + color: white; + font-weight: 600; + font-size: 0.75rem; } /* Информация о пользователе */ diff --git a/backend/static/js/components/recipientPicker.js b/backend/static/js/components/recipientPicker.js index 27299484..86cc0100 100644 --- a/backend/static/js/components/recipientPicker.js +++ b/backend/static/js/components/recipientPicker.js @@ -52,16 +52,11 @@ export class RecipientPicker { async loadData() { this.state.loading = true; try { - const [usersRes, deptsRes] = await Promise.all([ - fetch(this.options.apiUsersUrl), - fetch(this.options.apiDepartmentsUrl) - ]); - - if (usersRes.ok) { - const usersData = await usersRes.json(); - this.users = usersData.results || usersData; - } - + // Загружаем пользователей с пагинацией (все страницы) + this.users = await this.loadAllUsers(); + + // Загружаем отделы + const deptsRes = await fetch(this.options.apiDepartmentsUrl); if (deptsRes.ok) { const deptsData = await deptsRes.json(); this.departments = deptsData.results || deptsData; @@ -73,6 +68,37 @@ export class RecipientPicker { } } + /** + * Загрузка всех пользователей с автоматической обработкой пагинации + */ + async loadAllUsers() { + const allUsers = []; + let nextUrl = this.options.apiUsersUrl + '?page_size=100&active=true'; + + while (nextUrl) { + try { + const response = await fetch(nextUrl); + if (!response.ok) break; + + const data = await response.json(); + const users = data.results || data; + + if (Array.isArray(users)) { + allUsers.push(...users); + } + + // Проверяем наличие следующей страницы + nextUrl = data.next || null; + } catch (error) { + console.error('RecipientPicker: Error loading users page:', error); + break; + } + } + + console.log(`RecipientPicker: Loaded ${allUsers.length} users`); + return allUsers; + } + render() { this.container.innerHTML = `
@@ -255,9 +281,17 @@ export class RecipientPicker { const displayName = `${user.last_name} ${user.first_name}`; const subtitle = user.position || user.email || ''; + // Аватар или инициалы + let avatarHtml; + if (user.avatar) { + avatarHtml = `${displayName}`; + } else { + avatarHtml = `
${this.getInitials(user)}
`; + } + return `