feat: Update version to 1.0.2 and enhance profile retrieval with People Picker integration

This commit is contained in:
Torsten Brendgen
2026-08-24 14:13:08 +02:00
parent 83dd10f255
commit 4e5dafabfc
4 changed files with 89 additions and 3 deletions
@@ -29,6 +29,17 @@ interface ITreeLoadState {
visited: { [account: string]: boolean };
}
interface IPeoplePickerEntityData {
AccountName?: string;
Email?: string;
}
interface IPeoplePickerEntity {
EntityData?: IPeoplePickerEntityData;
IsResolved?: boolean;
Key?: string;
}
export class OrganizationChartDataService {
private static cache: { [account: string]: IProfileCacheEntry } = {};
@@ -49,7 +60,7 @@ export class OrganizationChartDataService {
visited: {}
};
const rootRequest: Promise<IUserProfile> = account
? this.getProfile(account, cacheMinutes)
? this.getConfiguredProfile(account, cacheMinutes)
: this.getMyProfile(cacheMinutes);
return rootRequest
.then((profile: IUserProfile): Promise<IOrganizationNode> =>
@@ -83,6 +94,79 @@ export class OrganizationChartDataService {
return this.requestProfile(url, key, cacheMinutes);
}
private getConfiguredProfile(accountName: string, cacheMinutes: number): Promise<IUserProfile> {
return this.resolveAccountNames(accountName)
.catch((): string[] => [accountName])
.then((accounts: string[]): Promise<IUserProfile> =>
this.getFirstAvailableProfile(accounts, cacheMinutes, 0));
}
private getFirstAvailableProfile(
accounts: string[],
cacheMinutes: number,
index: number,
previousError?: Error
): Promise<IUserProfile> {
if (index >= accounts.length) {
return Promise.reject(previousError || new Error('The configured user could not be resolved.'));
}
return this.getProfile(accounts[index], cacheMinutes)
.catch((error: Error): Promise<IUserProfile> =>
this.getFirstAvailableProfile(accounts, cacheMinutes, index + 1, error));
}
private resolveAccountNames(accountName: string): Promise<string[]> {
const url: string = this.webUrl +
'/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser';
const body: string = JSON.stringify({
queryParams: {
__metadata: { type: 'SP.UI.ApplicationPages.ClientPeoplePickerQueryParameters' },
AllowEmailAddresses: true,
AllowMultipleEntities: false,
AllUrlZones: false,
MaximumEntitySuggestions: 10,
PrincipalSource: 15,
PrincipalType: 1,
QueryString: accountName
}
});
const headers: any = { // tslint:disable-line:no-any
'Accept': 'application/json;odata=verbose',
'Content-Type': 'application/json;odata=verbose',
'OData-Version': '3.0'
};
return this.context.spHttpClient.post(url, SPHttpClient.configurations.v1, { headers: headers, body: body })
.then((response: SPHttpClientResponse): Promise<any> => { // tslint:disable-line:no-any
if (response.ok) { return response.json(); }
return response.text().then((text: string): Promise<any> => // tslint:disable-line:no-any
Promise.reject(new Error('People Picker request failed (' + response.status + '): ' + text)));
}).then((payload: any): string[] => { // tslint:disable-line:no-any
const data: any = payload && payload.d !== undefined ? payload.d : payload; // tslint:disable-line:no-any
const serialized: string = String(
data && data.ClientPeoplePickerSearchUser !== undefined
? data.ClientPeoplePickerSearchUser
: (data && data.value !== undefined ? data.value : '[]')
);
let entities: IPeoplePickerEntity[] = [];
try { entities = JSON.parse(serialized) as IPeoplePickerEntity[]; } catch (error) { entities = []; }
const input: string = normalizeAccount(accountName).toLowerCase();
const matching: IPeoplePickerEntity[] = entities.filter((entity: IPeoplePickerEntity): boolean => {
const account: string = normalizeAccount(entity.EntityData && entity.EntityData.AccountName).toLowerCase();
const email: string = normalizeAccount(entity.EntityData && entity.EntityData.Email).toLowerCase();
const key: string = normalizeAccount(entity.Key).toLowerCase();
return entity.IsResolved !== false && (account === input || email === input || key === input);
});
const selected: IPeoplePickerEntity[] = matching.length ? matching : (entities.length === 1 ? entities : []);
const candidates: string[] = [];
selected.forEach((entity: IPeoplePickerEntity): void => {
candidates.push(normalizeAccount(entity.Key));
candidates.push(normalizeAccount(entity.EntityData && entity.EntityData.AccountName));
});
candidates.push(normalizeAccount(accountName));
return uniqueAccounts(candidates, '', candidates.length || 1);
});
}
private requestProfile(url: string, cacheKey: string, cacheMinutes: number): Promise<IUserProfile> {
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1, { headers: this.headers })
.then((response: SPHttpClientResponse): Promise<any> => { // tslint:disable-line:no-any