feat: в письме о сообщении чата — строка «Прикреплены файлы: …»
Tests / frontend-test (pull_request) Failing after 28s

Иначе сообщение из одного файла приходило письмом с пустым текстом.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
gorbenko.pavel
2026-10-14 14:36:39 +05:00
parent 53535e4180
commit 2bcfb9f6f4
3 changed files with 29 additions and 3 deletions
@@ -50,6 +50,15 @@ describe('buildChatNotifyBody', () => {
expect(self?.mentionedEmails).toEqual(['petrova@tnsu.kz']); expect(self?.mentionedEmails).toEqual(['petrova@tnsu.kz']);
}); });
it('файлы — строкой в тексте письма, и при пустом сообщении тоже', () => {
expect(buildChatNotifyBody({ ...base, fileNames: ['акт.pdf', 'скан.jpg'] })?.messageText).toBe(
'Текст\n\nПрикреплены файлы: акт.pdf, скан.jpg'
);
expect(buildChatNotifyBody({ ...base, messageText: '', fileNames: ['акт.pdf'] })?.messageText).toBe(
'Прикреплены файлы: акт.pdf'
);
});
it('нет ни инициатора, ни отметок — поток не вызываем', () => { it('нет ни инициатора, ни отметок — поток не вызываем', () => {
expect(buildChatNotifyBody({ ...base, initiatorEmail: '' })).toBeUndefined(); expect(buildChatNotifyBody({ ...base, initiatorEmail: '' })).toBeUndefined();
}); });
@@ -23,6 +23,8 @@ export interface IChatNotifyInput {
authorName: string; authorName: string;
authorEmail: string; authorEmail: string;
messageText: string; messageText: string;
/** Имена приложенных файлов, как их выбрал пользователь (без складского префикса). */
fileNames?: string[];
requestCode: string; requestCode: string;
requestUrl: string; requestUrl: string;
requestTitle: string; requestTitle: string;
@@ -32,6 +34,17 @@ export interface IChatNotifyInput {
const sameEmail = (a: string, b: string): boolean => a.toLowerCase() === b.toLowerCase(); const sameEmail = (a: string, b: string): boolean => a.toLowerCase() === b.toLowerCase();
/**
* Текст для письма: сообщение и строка о файлах. Без неё сообщение из одного
* файла пришло бы письмом с пустым текстом. Сами файлы в письмо не кладём —
* они в библиотеке, открываются по ссылке на заявку.
*/
function letterText(text: string, fileNames: string[]): string {
if (fileNames.length === 0) return text;
const files = `Прикреплены файлы: ${fileNames.join(', ')}`;
return text ? `${text}\n\n${files}` : files;
}
/** /**
* Собрать тело запроса к потоку или undefined, если писать некому. * Собрать тело запроса к потоку или undefined, если писать некому.
* *
@@ -62,7 +75,7 @@ export function buildChatNotifyBody(input: IChatNotifyInput): IChatNotifyBody |
initiatorEmail, initiatorEmail,
mentionedEmails: mentioned, mentionedEmails: mentioned,
authorName: input.authorName, authorName: input.authorName,
messageText: input.messageText, messageText: letterText(input.messageText, input.fileNames || []),
RequestUniqueCode: input.requestCode, RequestUniqueCode: input.requestCode,
requestUrl: input.requestUrl, requestUrl: input.requestUrl,
requestTitle: input.requestTitle requestTitle: input.requestTitle
@@ -126,7 +126,7 @@ export function useRequestChat(
// Письмо о сообщении — после записи комментария и без ожидания: сбой потока // Письмо о сообщении — после записи комментария и без ожидания: сбой потока
// не должен выглядеть как неудачная отправка (см. notifyChatMessage). // не должен выглядеть как неудачная отправка (см. notifyChatMessage).
const notifyAboutMessage = React.useCallback( const notifyAboutMessage = React.useCallback(
(text: string): void => { (text: string, fileNames: string[]): void => {
if (!info) return; if (!info) return;
const body = buildChatNotifyBody({ const body = buildChatNotifyBody({
initiatorEmail: info.initiator.email, initiatorEmail: info.initiator.email,
@@ -134,6 +134,7 @@ export function useRequestChat(
authorName: currentUserName, authorName: currentUserName,
authorEmail: currentUserEmail, authorEmail: currentUserEmail,
messageText: text, messageText: text,
fileNames,
requestCode: info.code, requestCode: info.code,
requestUrl: requestLinkOnPage(PORTAL_PAGE_URL, formKey, itemId, listId), requestUrl: requestLinkOnPage(PORTAL_PAGE_URL, formKey, itemId, listId),
requestTitle: info.title || info.code, requestTitle: info.title || info.code,
@@ -163,7 +164,10 @@ export function useRequestChat(
await addChatMessage(formKey, itemId, listId, trimmed, files); await addChatMessage(formKey, itemId, listId, trimmed, files);
setError(undefined); setError(undefined);
reload(); reload();
notifyAboutMessage(trimmed); notifyAboutMessage(
trimmed,
files.map((f) => f.name)
);
return true; return true;
} catch (e) { } catch (e) {
setError(`Не удалось отправить сообщение: ${friendlyErrorMessage(e)}`); setError(`Не удалось отправить сообщение: ${friendlyErrorMessage(e)}`);