feat: чат по заявке через комментарии к строке списка
Tests / frontend-test (pull_request) Successful in 1m16s
Tests / frontend-test (pull_request) Successful in 1m16s
Обсуждение заявки поверх штатных комментариев SharePoint (PnPjs item.comments) — без новых колонок и провижининга, права на переписку раздаёт сам SharePoint по правам на элемент. Встроено в ApproveFeature и EditFeature (единственные входы в просмотр заявки для всех типов), поэтому доступно автору, всем согласующим (включая уже решивших и ещё не дошедших до своего шага) и исполнителям, а не только текущему шагу маршрута, как DecisionPanel. Автора комментария всегда ставит реальная учётка — отладочная подмена личности на запись в SharePoint не влияет, в UI есть предупреждение.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { ICommentSource, toChatMessages } from './chatMessages';
|
||||
|
||||
const ME = 'ivan@tnsu.kz';
|
||||
|
||||
function comment(over: Partial<ICommentSource>): ICommentSource {
|
||||
return {
|
||||
id: '1',
|
||||
text: 'Сообщение',
|
||||
createdDate: '2026-08-21T09:00:00Z',
|
||||
author: { name: 'Иванов Иван', email: ME },
|
||||
...over
|
||||
};
|
||||
}
|
||||
|
||||
describe('toChatMessages', () => {
|
||||
it('сортирует от старых к новым — свежие в чате внизу', () => {
|
||||
const messages = toChatMessages(
|
||||
[
|
||||
comment({ id: '2', createdDate: '2026-08-21T10:00:00Z', text: 'второе' }),
|
||||
comment({ id: '1', createdDate: '2026-08-21T09:00:00Z', text: 'первое' })
|
||||
],
|
||||
ME
|
||||
);
|
||||
|
||||
expect(messages.map((m) => m.text)).toEqual(['первое', 'второе']);
|
||||
});
|
||||
|
||||
it('свои сообщения помечаются по email автора, регистр не важен', () => {
|
||||
const messages = toChatMessages(
|
||||
[
|
||||
comment({ id: '1', author: { name: 'Иванов Иван', email: 'IVAN@TNSU.KZ' } }),
|
||||
comment({ id: '2', author: { name: 'Петров Пётр', email: 'petr@tnsu.kz' } })
|
||||
],
|
||||
ME
|
||||
);
|
||||
|
||||
expect(messages[0].isOwn).toBe(true);
|
||||
expect(messages[1].isOwn).toBe(false);
|
||||
});
|
||||
|
||||
it('без текущего пользователя своих сообщений нет (а не все свои)', () => {
|
||||
const messages = toChatMessages([comment({})], '');
|
||||
expect(messages[0].isOwn).toBe(false);
|
||||
});
|
||||
|
||||
it('пустые комментарии отбрасываются — пустой «пузырь» показывать нечего', () => {
|
||||
const messages = toChatMessages(
|
||||
[comment({ id: '1', text: '' }), comment({ id: '2', text: ' ' }), comment({ id: '3' })],
|
||||
ME
|
||||
);
|
||||
|
||||
expect(messages).toHaveLength(1);
|
||||
expect(messages[0].id).toBe('3');
|
||||
});
|
||||
|
||||
it('дата без часового пояса читается как UTC, а не как местное время', () => {
|
||||
const withZone = toChatMessages([comment({ createdDate: '2026-08-21T09:00:00Z' })], ME);
|
||||
const withoutZone = toChatMessages([comment({ createdDate: '2026-08-21T09:00:00' })], ME);
|
||||
|
||||
expect(withoutZone[0].createdAt.getTime()).toBe(withZone[0].createdAt.getTime());
|
||||
});
|
||||
|
||||
it('автор без ФИО подписывается email, без email — заглушкой', () => {
|
||||
const messages = toChatMessages(
|
||||
[
|
||||
comment({ id: '1', author: { email: 'petr@tnsu.kz' } }),
|
||||
comment({ id: '2', author: undefined })
|
||||
],
|
||||
ME
|
||||
);
|
||||
|
||||
expect(messages[0].authorName).toBe('petr@tnsu.kz');
|
||||
expect(messages[1].authorName).toBe('Неизвестный автор');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user