45 lines
2.2 KiB
TypeScript
45 lines
2.2 KiB
TypeScript
import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';
|
|
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
|
import { APPROVAL_API_CLIENT_ID, DICTIONARY_API_BASE_URL } from '../config';
|
|
import { IProject, IProjectListResponse } from './models/IProject';
|
|
|
|
// GET /Project — справочник проектов. Ответ обёрнут в { items: [...] } и
|
|
// ПАГИНИРОВАН, поэтому тянем ВСЕ страницы (иначе проекты за пределами первой
|
|
// страницы не находятся в поиске пикера). Авторизация та же (AadHttpClient +
|
|
// APPROVAL_API_CLIENT_ID, SSO текущего пользователя).
|
|
const PAGE_SIZE = 500;
|
|
const MAX_PAGES = 50; // страховка от бесконечного цикла (до 25 000 проектов)
|
|
|
|
async function fetchProjects(context: WebPartContext): Promise<IProject[]> {
|
|
const client = await context.aadHttpClientFactory.getClient(APPROVAL_API_CLIENT_ID);
|
|
const all: IProject[] = [];
|
|
for (let page = 1; page <= MAX_PAGES; page++) {
|
|
const response: HttpClientResponse = await client.get(
|
|
`${DICTIONARY_API_BASE_URL}/Project?page=${page}&pageSize=${PAGE_SIZE}&includeDeleted=false`,
|
|
AadHttpClient.configurations.v1
|
|
);
|
|
if (!response.ok) {
|
|
throw new Error(`Project (page ${page}): ${response.status} ${response.statusText}`);
|
|
}
|
|
const body: IProjectListResponse = await response.json();
|
|
const items = body.items ?? [];
|
|
all.push(...items);
|
|
// Последняя страница — вернулось меньше запрошенного размера.
|
|
if (items.length < PAGE_SIZE) break;
|
|
}
|
|
return all;
|
|
}
|
|
|
|
// Справочник в рамках сессии не меняется — грузим один раз и отдаём тот же
|
|
// промис повторным вызовам (как в departments.service).
|
|
let cache: Promise<IProject[]> | undefined;
|
|
export function getProjects(context: WebPartContext): Promise<IProject[]> {
|
|
if (!cache) {
|
|
cache = fetchProjects(context).catch((e) => {
|
|
cache = undefined;
|
|
throw e;
|
|
});
|
|
}
|
|
return cache;
|
|
}
|