Браузер больше не ходит на chat.* с portal.* — REST идёт через Django с PAT;
WS backoff без бесконечных 403; utilities.js ждёт DOMContentLoaded.
Co-authored-by: Cursor <cursoragent@cursor.com>
ЛС/групповые в Mattermost не архивируются (delete_at=0) — «закрытие» это
пользовательская preference (direct_channel_show/group_channel_show = "false").
Тянем /users/me/preferences и скрываем именно закрытые пользователем разговоры
по умолчанию; галочка «Показувати закриті розмови» их показывает. Архивные
каналы (delete_at>0) по-прежнему учитываются.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Строка поиска перенесена наверх страницы (над всем чатом), результаты
по-прежнему открываются в области сообщений
- В списке ЛС у собеседников-ботов рядом выводится метка «бот»
- Закрытые/архивные разговоры (delete_at>0) скрыты по умолчанию, показываются
только по галочке «Показувати закриті розмови» (тянем include_deleted=true)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mattermost search per-team — опрашиваем все команды пользователя параллельно
и сливаем результаты с дедупликацией по id. ЛС/групповые попадают в выдачу
любой команды. Сбой одной команды не валит весь поиск.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Захватываем is_bot при резолве пользователей (/users/ids), рядом с именем
отправителя показываем компактную подпись «бот». Также распознаём вебхуки
(props.from_bot / from_webhook). Свои сообщения и обычных юзеров не помечаем.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Порядок каналов/ЛС — по реальному времени последнего поста (тянем per-channel,
т.к. last_post_at из списка каналов ненадёжен), архивные (delete_at>0) — вниз
- Непрочитанные: счётчик по websocket, бейдж на строке + жирное имя, префикс
«(N)» в тайтле, браузерное уведомление; сброс при открытии канала
- Кнопка «Написати в чат» на карточке сотрудника → /chat/?dm=<mm_id>,
чат открывает/создаёт ЛС с этим человеком (идемпотентный /channels/direct)
- Тесты кнопки чата в EmployeeDetailTests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Единый скролл вместо жёсткого max-height:35% на ЛС и flex:1 на каналах
(убран пустой провал под каналами)
- Секции-заголовки — компактные uppercase-подписи в стиле портала
- Строки ЛС и каналов выровнены по единому левому краю (0.75rem)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Списки каналов и ЛС сортируются по last_post_at (свежие сверху)
- При открытии чата автоматически выбирается самая свежая розмова — сразу
видны последние сообщения, а не пустой экран
- Поиск сообщений через Mattermost /teams/{id}/posts/search: строка поиска
над лентой, результаты списком (кто/канал/время/текст), клик открывает канал
- Выход из поиска при открытии канала и смене команды
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Аватар співрозмовника напроти особистого повідомлення (лівий список):
chatBuildChannelRow отримав опцію avatar; id співрозмовника ЛС резолвиться
в chatResolveDmLabel і підвантажує фото (chatApplyAvatar). Групові ЛС —
без фото, з ініціалами.
- Верхній перемикач «кімнат» — команди Mattermost (Офіс / Аптеки / Склад):
chatRenderTeamSwitcher/chatSelectTeam; chatRenderChannelList фільтрує канали
за обраною командою; за замовчуванням — перша команда. ЛС показуються завжди.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- chatApplyAvatar(el, userId): подгружает фото из Mattermost
/users/{id}/image (работает и для сотрудников, и для ботов) и накладывает
на кружок-аватар; до загрузки/при ошибке остаются инициалы. Кэш по userId.
- Применено в сообщениях (chatBuildMessageEl) и в пикере коллег
(chatRenderDmPickerList)
- Переиспользует существующий chatApiFetchBlob (Bearer-токен)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>