9cc5d52bab
По дате выхода удобнее планировать подготовку рабочих мест. Даты для сортировки дочитываются для всего списка пачками (предел длины URL), заявки без даты — всегда в конце. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
70 lines
3.0 KiB
TypeScript
70 lines
3.0 KiB
TypeScript
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
|
import '@pnp/sp/webs';
|
|
import '@pnp/sp/lists';
|
|
import '@pnp/sp/items';
|
|
import { spForSite } from '../../shared/pnp/pnpjs';
|
|
import { traced } from '../../shared/perfTrace';
|
|
import { IMyRequest } from './models/IMyRequest';
|
|
|
|
// Сколько Id в одном $filter: при сортировке по дате выхода дочитывается весь
|
|
// список типа (сотни заявок), а «Id eq … or …» на сотни Id упирается в предел
|
|
// длины URL.
|
|
const IDS_PER_REQUEST = 50;
|
|
|
|
/**
|
|
* Проставляет startDate — дату выхода сотрудника (колонка StartDate списка
|
|
* данных). Обычно для видимой страницы, при сортировке по дате выхода — для
|
|
* всего списка (см. fetchRefinedPage в RequestsTableView). Группировка по
|
|
* партиции строки, как в hydrateAuthors: в другой партиции тот же Id — чужая
|
|
* заявка. Мутирует строки.
|
|
*/
|
|
export async function hydrateStartDates(context: WebPartContext, rows: IMyRequest[]): Promise<void> {
|
|
if (rows.length === 0) return;
|
|
return traced('дата выхода (REST)', () => hydrateStartDatesInner(context, rows));
|
|
}
|
|
|
|
async function hydrateStartDatesInner(context: WebPartContext, rows: IMyRequest[]): Promise<void> {
|
|
const byPartition = new Map<string, { siteUrl: string; listId: string; typeName: string; ids: number[] }>();
|
|
rows.forEach((r) => {
|
|
const bucket = byPartition.get(r.listId.toLowerCase()) || {
|
|
siteUrl: r.siteUrl,
|
|
listId: r.listId,
|
|
typeName: r.requestTypeName,
|
|
ids: [],
|
|
};
|
|
bucket.ids.push(r.id);
|
|
byPartition.set(r.listId.toLowerCase(), bucket);
|
|
});
|
|
|
|
const requests: Array<{ siteUrl: string; listId: string; typeName: string; ids: number[] }> = [];
|
|
byPartition.forEach((bucket) => {
|
|
for (let i = 0; i < bucket.ids.length; i += IDS_PER_REQUEST) {
|
|
requests.push({ ...bucket, ids: bucket.ids.slice(i, i + IDS_PER_REQUEST) });
|
|
}
|
|
});
|
|
|
|
const byKey = new Map<string, string>();
|
|
await Promise.all(
|
|
requests.map(async ({ siteUrl, listId, typeName, ids }) => {
|
|
try {
|
|
const sp = spForSite(siteUrl, context);
|
|
const dataRows = (await sp.web
|
|
.getList(listId)
|
|
.items.filter(ids.map((id) => `Id eq ${id}`).join(' or '))
|
|
.select('Id', 'StartDate')
|
|
.top(ids.length)()) as Array<Record<string, unknown>>;
|
|
dataRows.forEach((r) => byKey.set(`${listId.toLowerCase()}-${r.Id as number}`, (r.StartDate as string) || ''));
|
|
} catch (e) {
|
|
console.error(
|
|
`[Все заявки] Не удалось дочитать дату выхода для «${typeName}» (${listId}):`,
|
|
(e as Error).message
|
|
);
|
|
}
|
|
})
|
|
);
|
|
|
|
rows.forEach((r) => {
|
|
r.startDate = byKey.get(`${r.listId.toLowerCase()}-${r.id}`) ?? '';
|
|
});
|
|
}
|