feat: в чате заявки можно отметить тех, кому открыты «Все заявки» этого типа
Tests / frontend-test (pull_request) Successful in 2m4s
Tests / frontend-test (pull_request) Successful in 2m4s
Они открывают любую заявку типа и пишут в её чат — теперь попадают и в подсказку «@». Список берётся из админки approval-route (request-type-access), ФИО — из кадрового справочника. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,7 @@ export {
|
||||
getRequestTypeAccessEmails,
|
||||
resolveRoute
|
||||
} from './approvalRoute.service';
|
||||
export { hasRequestTypeAccess, accessibleAllRequestsTypes } from './requestTypeAccess';
|
||||
export { hasRequestTypeAccess, accessibleAllRequestsTypes, emailsForType } from './requestTypeAccess';
|
||||
export { useAccessibleAllRequestsFormKeys } from './useAccessibleAllRequestsFormKeys';
|
||||
export {
|
||||
initListPartitions,
|
||||
|
||||
@@ -9,7 +9,12 @@ import { effectiveUserEmail } from '../impersonation';
|
||||
// кешируется, чтобы временный сбой сети не «залип» на весь сеанс.
|
||||
const cache = new Map<number, Promise<string[]>>();
|
||||
|
||||
function emailsForType(context: WebPartContext, requestTypeId: number): Promise<string[]> {
|
||||
/**
|
||||
* Кому выдан доступ видеть ВСЕ заявки этого типа (раздел «Все заявки»). Кешируется
|
||||
* на сеанс. Нужен не только для проверки доступа: эти люди могут писать в чат
|
||||
* любой заявки типа, значит, их можно и отмечать в нём (см. shared/chat).
|
||||
*/
|
||||
export function emailsForType(context: WebPartContext, requestTypeId: number): Promise<string[]> {
|
||||
let pending = cache.get(requestTypeId);
|
||||
if (!pending) {
|
||||
pending = getRequestTypeAccessEmails(context, requestTypeId).catch((e) => {
|
||||
|
||||
@@ -7,7 +7,11 @@ import { IChatMessage } from './models/IChatMessage';
|
||||
import { buildCommentText, hasAttachments, toChatMessages } from './chatMessages';
|
||||
import { chatFilesFolderUrl, uploadChatFiles } from './chatFiles.service';
|
||||
import { IChatParticipant } from './chatMentions';
|
||||
import type { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { approvalServiceFor } from '../approval/approvalServiceFactory';
|
||||
import { getRequestTypeIdByPageUrl } from '../approval/approvalRoute.service';
|
||||
import { emailsForType } from '../approval/requestTypeAccess';
|
||||
import { getEmployeeOrganizations } from '../dictionary';
|
||||
|
||||
/**
|
||||
* Чат по заявке ПОВЕРХ штатных комментариев к строке списка.
|
||||
@@ -84,10 +88,34 @@ export interface IChatRequestInfo {
|
||||
code: string;
|
||||
title: string;
|
||||
initiator: IChatParticipant;
|
||||
/** Инициатор и все из маршрута (согласующие и исполнители), как есть — фильтрует buildParticipants. */
|
||||
/**
|
||||
* Инициатор, все из маршрута (согласующие и исполнители) и те, кому открыты
|
||||
* «Все заявки» этого типа, — как есть, повторы убирает buildParticipants.
|
||||
*/
|
||||
people: IChatParticipant[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Люди с доступом ко «Всем заявкам» этого типа (админка approval-route): они
|
||||
* открывают любую заявку типа и пишут в её чат, значит, их можно и отметить.
|
||||
* ФИО — из кадрового справочника, не нашлось — показываем почту. Любой сбой —
|
||||
* просто без них: отметки участников маршрута от этого не страдают.
|
||||
*/
|
||||
async function allRequestsViewers(context: WebPartContext, formKey: RequestTypeId): Promise<IChatParticipant[]> {
|
||||
try {
|
||||
const typeId = await getRequestTypeIdByPageUrl(context, formKey);
|
||||
const emails = await emailsForType(context, typeId);
|
||||
return await Promise.all(
|
||||
emails.map(async (email) => {
|
||||
const records = await getEmployeeOrganizations(context, email).catch(() => []);
|
||||
return { name: records[0]?.fio || email, email };
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициатор — автор строки списка данных: заявку создаёт он сам (подмена
|
||||
* личности на автора записи не влияет, см. RequestChat). Участники — строки
|
||||
@@ -95,18 +123,20 @@ export interface IChatRequestInfo {
|
||||
* просто отметить можно только инициатора.
|
||||
*/
|
||||
export async function getChatRequestInfo(
|
||||
context: WebPartContext,
|
||||
formKey: RequestTypeId,
|
||||
itemId: number,
|
||||
listId: string | undefined
|
||||
): Promise<IChatRequestInfo> {
|
||||
const [item, matrix] = await Promise.all([
|
||||
const [item, matrix, viewers] = await Promise.all([
|
||||
resolveDataList(formKey, listId)
|
||||
.items.getById(itemId)
|
||||
.select('Title', 'RequestUniqueCode', 'Author/Title', 'Author/EMail')
|
||||
.expand('Author')() as Promise<Record<string, unknown>>,
|
||||
approvalServiceFor(formKey, listId)
|
||||
.getMatrixForRequest(itemId)
|
||||
.catch(() => [])
|
||||
.catch(() => []),
|
||||
allRequestsViewers(context, formKey)
|
||||
]);
|
||||
const author = item.Author as { Title?: string; EMail?: string } | undefined;
|
||||
const initiator = { name: author?.Title || '', email: author?.EMail || '' };
|
||||
@@ -114,6 +144,6 @@ export async function getChatRequestInfo(
|
||||
code: (item.RequestUniqueCode as string) || '',
|
||||
title: (item.Title as string) || '',
|
||||
initiator,
|
||||
people: [initiator, ...matrix.map((r) => ({ name: r.who, email: r.email }))]
|
||||
people: [initiator, ...matrix.map((r) => ({ name: r.who, email: r.email })), ...viewers]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export function useRequestChat(
|
||||
React.useEffect(() => {
|
||||
let alive = true;
|
||||
setInfo(undefined);
|
||||
getChatRequestInfo(formKey, itemId, listId)
|
||||
getChatRequestInfo(context, formKey, itemId, listId)
|
||||
.then((loaded) => {
|
||||
if (alive) setInfo(loaded);
|
||||
})
|
||||
@@ -77,7 +77,7 @@ export function useRequestChat(
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, [formKey, itemId, listId]);
|
||||
}, [context, formKey, itemId, listId]);
|
||||
|
||||
// В режиме проверки себя тоже можно отметить — отсекаем «себя» по пустому адресу.
|
||||
const participants = React.useMemo(
|
||||
|
||||
Reference in New Issue
Block a user