From 8f934eff0e1363559042dd431c4ea0b4b5289b19 Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Fri, 1 Oct 2021 17:19:38 +0200 Subject: [PATCH 1/7] Added filter for Microsoft 365 Group to PeoplePicker --- .../docs/controls/PeoplePicker.md | 11 +++- src/controls/peoplepicker/IPeoplePicker.ts | 7 +-- .../peoplepicker/PeoplePickerComponent.tsx | 3 +- src/services/PeopleSearchService.ts | 53 ++++++++++++++++--- .../controlsTest/ControlsTestWebPart.ts | 24 ++++++--- .../ControlsTest_SingleComponent.tsx | 15 +++--- 6 files changed, 87 insertions(+), 26 deletions(-) diff --git a/docs/documentation/docs/controls/PeoplePicker.md b/docs/documentation/docs/controls/PeoplePicker.md index ff9430f9c..56c3e9ac3 100644 --- a/docs/documentation/docs/controls/PeoplePicker.md +++ b/docs/documentation/docs/controls/PeoplePicker.md @@ -61,7 +61,7 @@ The People picker control can be configured with the following properties: | context | BaseComponentContext | yes | Context of the current web part. | | | titleText | string | no | Text to be displayed on the control | | | groupName | string | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupName and groupId specified groupName takes precedence. | _none_ | -| groupId | number | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupId and groupName specified groupName takes precedence. | _none_ | +| groupId | number \| Guid | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupId and groupName specified groupName takes precedence. If Guid is specified, Microsoft 365 Group is used | _none_ | | personSelectionLimit | number | no | Defines the limit of people that can be selected in the control | 1 | | required | boolean | no | Set if the control is required or not | false | | disabled | boolean | no | Set if the control is disabled or not | false | @@ -93,4 +93,13 @@ The `PrincipalType` enum can be used to specify the types of information you wan | SecurityGroup | 4 | | SharePointGroup | 8 | + + ## MSGraph Permissions required + +This control requires the following scopes if groupId is of type Guid: + +at least : GroupMember.Read.All, + + ![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/PeoplePicker) + diff --git a/src/controls/peoplepicker/IPeoplePicker.ts b/src/controls/peoplepicker/IPeoplePicker.ts index 8577d6e68..f9cc78e20 100644 --- a/src/controls/peoplepicker/IPeoplePicker.ts +++ b/src/controls/peoplepicker/IPeoplePicker.ts @@ -1,4 +1,5 @@ import { BaseComponentContext } from '@microsoft/sp-component-base'; +import { Guid } from '@microsoft/sp-core-library'; import { DirectionalHint } from "office-ui-fabric-react/lib/common/DirectionalHint"; import { IPersonaProps } from "office-ui-fabric-react/lib/components/Persona/Persona.types"; import { PrincipalType } from "."; @@ -29,10 +30,10 @@ export interface IPeoplePickerProps { */ groupName?: string; /** - * Id of SharePoint Group + * Id of SharePoint Group (Number) or Office365 Group (Guid) */ - groupId?: number; - /** + groupId?: number | Guid; + /** * Maximum number of suggestions to show in the full suggestion list. (default: 5) */ suggestionsLimit?: number; diff --git a/src/controls/peoplepicker/PeoplePickerComponent.tsx b/src/controls/peoplepicker/PeoplePickerComponent.tsx index d9966a5ce..244b273f6 100644 --- a/src/controls/peoplepicker/PeoplePickerComponent.tsx +++ b/src/controls/peoplepicker/PeoplePickerComponent.tsx @@ -12,6 +12,7 @@ import { IPersonaProps } from "office-ui-fabric-react/lib/components/Persona/Per import FieldErrorMessage from '../errorMessage/ErrorMessage'; import isEqual from 'lodash/isEqual'; import uniqBy from 'lodash/uniqBy'; +import { Guid } from '@microsoft/sp-core-library'; /** * PeoplePicker component @@ -19,7 +20,7 @@ import uniqBy from 'lodash/uniqBy'; export class PeoplePicker extends React.Component { private peopleSearchService: SPPeopleSearchService; private suggestionsLimit: number; - private groupId: number; + private groupId: number | Guid; constructor(props: IPeoplePickerProps) { super(props); diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index f59239042..83d93d1ef 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -1,10 +1,13 @@ import { ISPHttpClientOptions, SPHttpClient } from '@microsoft/sp-http'; -import { Environment, EnvironmentType } from '@microsoft/sp-core-library'; +import { Environment, EnvironmentType, Guid } from '@microsoft/sp-core-library'; import { BaseComponentContext } from '@microsoft/sp-component-base'; import { MockUsers, PeoplePickerMockClient } from './PeoplePickerMockClient'; import { PrincipalType, IPeoplePickerUserItem } from "../PeoplePicker"; import { IUsers, IUserInfo } from "../controls/peoplepicker/IUsers"; import { cloneDeep, findIndex } from "@microsoft/sp-lodash-subset"; +import { sp, PrincipalSource, PrincipalType as SPPrincipalType } from '@pnp/sp'; +import "@pnp/sp/sputilities"; +import "@pnp/sp/webs"; /** * Service implementation to search people in SharePoint @@ -62,7 +65,7 @@ export default class SPPeopleSearchService { /** * Search person by its email or login name */ - public async searchPersonByEmailOrLogin(email: string, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number = null, ensureUser: boolean = false): Promise { + public async searchPersonByEmailOrLogin(email: string, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | Guid = null, ensureUser: boolean = false): Promise { if (Environment.type === EnvironmentType.Local) { // If the running environment is local, load the data from the mock const mockUsers = await this.searchPeopleFromMock(email); @@ -76,7 +79,7 @@ export default class SPPeopleSearchService { /** * Search All Users from the SharePoint People database */ - public async searchPeople(query: string, maximumSuggestions: number, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number = null, ensureUser: boolean = false): Promise { + public async searchPeople(query: string, maximumSuggestions: number, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | Guid = null, ensureUser: boolean = false): Promise { if (Environment.type === EnvironmentType.Local) { // If the running environment is local, load the data from the mock return this.searchPeopleFromMock(query); @@ -162,7 +165,7 @@ export default class SPPeopleSearchService { /** * Tenant search */ - private async searchTenant(siteUrl: string, query: string, maximumSuggestions: number, principalTypes: PrincipalType[], ensureUser: boolean, groupId: number): Promise { + private async searchTenant(siteUrl: string, query: string, maximumSuggestions: number, principalTypes: PrincipalType[], ensureUser: boolean, groupId: number | Guid): Promise { try { // If the running env is SharePoint, loads from the peoplepicker web service const userRequestUrl: string = `${siteUrl || this.context.pageContext.web.absoluteUrl}/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser`; @@ -183,11 +186,49 @@ export default class SPPeopleSearchService { searchBody.queryParams["SharePointGroupID"] = 0; } - // Check if users need to be searched in a specific group - if (groupId) { + // Check if users need to be searched in a specific SharePoint Group + if (groupId && typeof(groupId) === 'number') { searchBody.queryParams["SharePointGroupID"] = groupId; } + // Check if users need to be searched in a specific Office365 Group + else if(groupId && Guid.isValid(groupId.toString())) { + const graphUserRequestUrl = `https://graph.microsoft.com/v1.0/groups/${groupId.toString()}/members?$count=true&$search="displayName:${query}" OR "mail:${query}"`; + const graphClient = await this.context.msGraphClientFactory.getClient(); + const graphUserResponse = await graphClient.api(graphUserRequestUrl).header('ConsistencyLevel', 'eventual').get(); + + if(graphUserResponse.value && graphUserResponse.value.length > 0) { + + // Get user loginName from user email + const _users = []; + const batch = sp.web.createBatch(); + for (const value of graphUserResponse.value) { + sp.utility.inBatch(batch).resolvePrincipal(value.mail, SPPrincipalType.User, PrincipalSource.All, true, false, true) + .then(p => _users.push(p)); + } + + await batch.execute(); + + let userResult: any[] = _users.map(user => { + return { + id: ensureUser ? user.PrincipalId : user.LoginName, + loginName: user.LoginName, + imageUrl: this.generateUserPhotoLink(user.Email), + imageInitials: this.getFullNameInitials(user.DisplayName), + text: user.DisplayName, // name + secondaryText: user.Email, // email + tertiaryText: '', // status + optionalText: '' // anything + } as IPeoplePickerUserItem + }); + + return userResult; + } + + //Nothing to return + return []; + } + const httpPostOptions: ISPHttpClientOptions = { headers: { 'accept': 'application/json', diff --git a/src/webparts/controlsTest/ControlsTestWebPart.ts b/src/webparts/controlsTest/ControlsTestWebPart.ts index 148cca944..8fcb47fc4 100644 --- a/src/webparts/controlsTest/ControlsTestWebPart.ts +++ b/src/webparts/controlsTest/ControlsTestWebPart.ts @@ -19,6 +19,8 @@ import { ThemeProvider, } from "@microsoft/sp-component-base"; import ControlsTest from './components/ControlsTest'; +import ControlsTest_SingleComponent from './components/ControlsTest_SingleComponent'; +import { sp } from '@pnp/sp'; /** * Web part to test the React controls */ @@ -27,7 +29,7 @@ export default class ControlsTestWebPart extends BaseClientSideWebPart { - + sp.setup(this.context); this._themeProvider = this.context.serviceScope.consume( ThemeProvider.serviceKey ); @@ -78,18 +80,28 @@ export default class ControlsTestWebPart extends BaseClientSideWebPart = React.createElement( - ControlsTest, - { + // ControlsTest, + // { - themeVariant: this._themeVariant, + // themeVariant: this._themeVariant, + // context: this.context, + // description: this.properties.description, + // title: this.properties.title, + // displayMode: this.displayMode, + // updateProperty: (value: string) => { + // this.properties.title = value; + // }, + // totalPages: this.properties.totalPages + // } + ControlsTest_SingleComponent, + { context: this.context, description: this.properties.description, title: this.properties.title, displayMode: this.displayMode, updateProperty: (value: string) => { this.properties.title = value; - }, - totalPages: this.properties.totalPages + } } ); diff --git a/src/webparts/controlsTest/components/ControlsTest_SingleComponent.tsx b/src/webparts/controlsTest/components/ControlsTest_SingleComponent.tsx index 1e4e1d0a1..96fcbe7fc 100644 --- a/src/webparts/controlsTest/components/ControlsTest_SingleComponent.tsx +++ b/src/webparts/controlsTest/components/ControlsTest_SingleComponent.tsx @@ -15,7 +15,7 @@ import { ListPicker } from '../../../ListPicker'; import { IFrameDialog } from '../../../IFrameDialog'; import { IFramePanel } from '../../../IFramePanel'; import { PanelType } from 'office-ui-fabric-react/lib/Panel'; -import { Environment, EnvironmentType, DisplayMode } from '@microsoft/sp-core-library'; +import { Environment, EnvironmentType, DisplayMode, Guid } from '@microsoft/sp-core-library'; import { SecurityTrimmedControl, PermissionLevel } from '../../../SecurityTrimmedControl'; import { SPPermission } from '@microsoft/sp-page-context'; import { PeoplePicker, PrincipalType } from '../../../PeoplePicker'; @@ -460,15 +460,12 @@ export default class ControlsTest extends React.Component - { console.log('Cancelled'); }} - onSubmitted={async (listItem) => { console.log(listItem); }}> - - + onChange={users => console.log(users)} + ensureUser + groupId={2} + /> ); } From 5408ea9f9bc5e3376265b7dad52ce83fd9fc1683 Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Fri, 1 Oct 2021 17:39:38 +0200 Subject: [PATCH 2/7] Added missing semicolon --- src/services/PeopleSearchService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index 83d93d1ef..f605ace9f 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -219,7 +219,7 @@ export default class SPPeopleSearchService { secondaryText: user.Email, // email tertiaryText: '', // status optionalText: '' // anything - } as IPeoplePickerUserItem + } as IPeoplePickerUserItem; }); return userResult; From c6991191e7dc41e86dc79bc22d3c97512e8c27c7 Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Mon, 4 Oct 2021 11:15:21 +0200 Subject: [PATCH 3/7] Changed groupId from Guid to String --- src/controls/peoplepicker/IPeoplePicker.ts | 5 ++--- src/controls/peoplepicker/PeoplePickerComponent.tsx | 3 +-- src/services/PeopleSearchService.ts | 12 ++++++------ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/controls/peoplepicker/IPeoplePicker.ts b/src/controls/peoplepicker/IPeoplePicker.ts index f9cc78e20..bff933b4e 100644 --- a/src/controls/peoplepicker/IPeoplePicker.ts +++ b/src/controls/peoplepicker/IPeoplePicker.ts @@ -1,5 +1,4 @@ import { BaseComponentContext } from '@microsoft/sp-component-base'; -import { Guid } from '@microsoft/sp-core-library'; import { DirectionalHint } from "office-ui-fabric-react/lib/common/DirectionalHint"; import { IPersonaProps } from "office-ui-fabric-react/lib/components/Persona/Persona.types"; import { PrincipalType } from "."; @@ -30,9 +29,9 @@ export interface IPeoplePickerProps { */ groupName?: string; /** - * Id of SharePoint Group (Number) or Office365 Group (Guid) + * Id of SharePoint Group (Number) or Office365 Group (String) */ - groupId?: number | Guid; + groupId?: number | string; /** * Maximum number of suggestions to show in the full suggestion list. (default: 5) */ diff --git a/src/controls/peoplepicker/PeoplePickerComponent.tsx b/src/controls/peoplepicker/PeoplePickerComponent.tsx index 244b273f6..3fb908481 100644 --- a/src/controls/peoplepicker/PeoplePickerComponent.tsx +++ b/src/controls/peoplepicker/PeoplePickerComponent.tsx @@ -12,7 +12,6 @@ import { IPersonaProps } from "office-ui-fabric-react/lib/components/Persona/Per import FieldErrorMessage from '../errorMessage/ErrorMessage'; import isEqual from 'lodash/isEqual'; import uniqBy from 'lodash/uniqBy'; -import { Guid } from '@microsoft/sp-core-library'; /** * PeoplePicker component @@ -20,7 +19,7 @@ import { Guid } from '@microsoft/sp-core-library'; export class PeoplePicker extends React.Component { private peopleSearchService: SPPeopleSearchService; private suggestionsLimit: number; - private groupId: number | Guid; + private groupId: number | string; constructor(props: IPeoplePickerProps) { super(props); diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index f605ace9f..55d959c4b 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -1,5 +1,5 @@ import { ISPHttpClientOptions, SPHttpClient } from '@microsoft/sp-http'; -import { Environment, EnvironmentType, Guid } from '@microsoft/sp-core-library'; +import { Environment, EnvironmentType } from '@microsoft/sp-core-library'; import { BaseComponentContext } from '@microsoft/sp-component-base'; import { MockUsers, PeoplePickerMockClient } from './PeoplePickerMockClient'; import { PrincipalType, IPeoplePickerUserItem } from "../PeoplePicker"; @@ -65,7 +65,7 @@ export default class SPPeopleSearchService { /** * Search person by its email or login name */ - public async searchPersonByEmailOrLogin(email: string, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | Guid = null, ensureUser: boolean = false): Promise { + public async searchPersonByEmailOrLogin(email: string, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | string = null, ensureUser: boolean = false): Promise { if (Environment.type === EnvironmentType.Local) { // If the running environment is local, load the data from the mock const mockUsers = await this.searchPeopleFromMock(email); @@ -79,7 +79,7 @@ export default class SPPeopleSearchService { /** * Search All Users from the SharePoint People database */ - public async searchPeople(query: string, maximumSuggestions: number, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | Guid = null, ensureUser: boolean = false): Promise { + public async searchPeople(query: string, maximumSuggestions: number, principalTypes: PrincipalType[], siteUrl: string = null, groupId: number | string = null, ensureUser: boolean = false): Promise { if (Environment.type === EnvironmentType.Local) { // If the running environment is local, load the data from the mock return this.searchPeopleFromMock(query); @@ -165,7 +165,7 @@ export default class SPPeopleSearchService { /** * Tenant search */ - private async searchTenant(siteUrl: string, query: string, maximumSuggestions: number, principalTypes: PrincipalType[], ensureUser: boolean, groupId: number | Guid): Promise { + private async searchTenant(siteUrl: string, query: string, maximumSuggestions: number, principalTypes: PrincipalType[], ensureUser: boolean, groupId: number | string): Promise { try { // If the running env is SharePoint, loads from the peoplepicker web service const userRequestUrl: string = `${siteUrl || this.context.pageContext.web.absoluteUrl}/_api/SP.UI.ApplicationPages.ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser`; @@ -192,8 +192,8 @@ export default class SPPeopleSearchService { } // Check if users need to be searched in a specific Office365 Group - else if(groupId && Guid.isValid(groupId.toString())) { - const graphUserRequestUrl = `https://graph.microsoft.com/v1.0/groups/${groupId.toString()}/members?$count=true&$search="displayName:${query}" OR "mail:${query}"`; + else if(groupId && typeof(groupId) === 'string') { + const graphUserRequestUrl = `https://graph.microsoft.com/v1.0/groups/${groupId}/members?$count=true&$search="displayName:${query}" OR "mail:${query}"`; const graphClient = await this.context.msGraphClientFactory.getClient(); const graphUserResponse = await graphClient.api(graphUserRequestUrl).header('ConsistencyLevel', 'eventual').get(); From e6cef8ea94ae31a902f2276df1437cb8147a28ea Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Mon, 4 Oct 2021 11:37:57 +0200 Subject: [PATCH 4/7] Added groupId string property to documentation --- docs/documentation/docs/controls/PeoplePicker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/documentation/docs/controls/PeoplePicker.md b/docs/documentation/docs/controls/PeoplePicker.md index 56c3e9ac3..cb094bcac 100644 --- a/docs/documentation/docs/controls/PeoplePicker.md +++ b/docs/documentation/docs/controls/PeoplePicker.md @@ -61,7 +61,7 @@ The People picker control can be configured with the following properties: | context | BaseComponentContext | yes | Context of the current web part. | | | titleText | string | no | Text to be displayed on the control | | | groupName | string | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupName and groupId specified groupName takes precedence. | _none_ | -| groupId | number \| Guid | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupId and groupName specified groupName takes precedence. If Guid is specified, Microsoft 365 Group is used | _none_ | +| groupId | number \| string | no | Group from which users are fetched. Leave it blank if need to filter all users. When both groupId and groupName specified groupName takes precedence. If string is specified, Microsoft 365 Group is used | _none_ | | personSelectionLimit | number | no | Defines the limit of people that can be selected in the control | 1 | | required | boolean | no | Set if the control is required or not | false | | disabled | boolean | no | Set if the control is disabled or not | false | From c5d9e817054924a126cfc483f7e7f932f10bae79 Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Wed, 6 Oct 2021 08:27:35 +0200 Subject: [PATCH 5/7] Added null-check on retreived users --- docs/documentation/docs/controls/PeoplePicker.md | 2 +- src/services/PeopleSearchService.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/documentation/docs/controls/PeoplePicker.md b/docs/documentation/docs/controls/PeoplePicker.md index cb094bcac..402ac8c1d 100644 --- a/docs/documentation/docs/controls/PeoplePicker.md +++ b/docs/documentation/docs/controls/PeoplePicker.md @@ -96,7 +96,7 @@ The `PrincipalType` enum can be used to specify the types of information you wan ## MSGraph Permissions required -This control requires the following scopes if groupId is of type Guid: +This control requires the following scopes if groupId is of type String: at least : GroupMember.Read.All, diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index 55d959c4b..c96385bf4 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -209,8 +209,13 @@ export default class SPPeopleSearchService { await batch.execute(); - let userResult: any[] = _users.map(user => { - return { + let userResult: IPeoplePickerUserItem[] = []; + for (const user of _users) { + if(user['odata.null']) { + continue; + } + + userResult.push({ id: ensureUser ? user.PrincipalId : user.LoginName, loginName: user.LoginName, imageUrl: this.generateUserPhotoLink(user.Email), @@ -219,8 +224,8 @@ export default class SPPeopleSearchService { secondaryText: user.Email, // email tertiaryText: '', // status optionalText: '' // anything - } as IPeoplePickerUserItem; - }); + }); + } return userResult; } From e8cca66dd2a45590e28f16d22320728919af1afa Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Thu, 7 Oct 2021 10:30:09 +0200 Subject: [PATCH 6/7] Changed resolvePrincipal to ensureUser --- src/services/PeopleSearchService.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index c96385bf4..764aef3b6 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -8,6 +8,7 @@ import { cloneDeep, findIndex } from "@microsoft/sp-lodash-subset"; import { sp, PrincipalSource, PrincipalType as SPPrincipalType } from '@pnp/sp'; import "@pnp/sp/sputilities"; import "@pnp/sp/webs"; +import "@pnp/sp/site-users/web"; /** * Service implementation to search people in SharePoint @@ -203,24 +204,19 @@ export default class SPPeopleSearchService { const _users = []; const batch = sp.web.createBatch(); for (const value of graphUserResponse.value) { - sp.utility.inBatch(batch).resolvePrincipal(value.mail, SPPrincipalType.User, PrincipalSource.All, true, false, true) - .then(p => _users.push(p)); + sp.web.inBatch(batch).ensureUser(value.userPrincipalName).then(u => _users.push(u.data)); } await batch.execute(); let userResult: IPeoplePickerUserItem[] = []; for (const user of _users) { - if(user['odata.null']) { - continue; - } - userResult.push({ - id: ensureUser ? user.PrincipalId : user.LoginName, + id: ensureUser ? user.Id : user.LoginName, loginName: user.LoginName, imageUrl: this.generateUserPhotoLink(user.Email), - imageInitials: this.getFullNameInitials(user.DisplayName), - text: user.DisplayName, // name + imageInitials: this.getFullNameInitials(user.Title), + text: user.Title, // name secondaryText: user.Email, // email tertiaryText: '', // status optionalText: '' // anything From aab47aeba951d496c9ad5390c03111dd6a126cc7 Mon Sep 17 00:00:00 2001 From: Andreas Omayrat Date: Mon, 11 Oct 2021 15:19:13 +0200 Subject: [PATCH 7/7] Bugfix: Could not execute batch from Site Pages, only on Home Page --- src/services/PeopleSearchService.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/services/PeopleSearchService.ts b/src/services/PeopleSearchService.ts index 764aef3b6..9e4e250a5 100644 --- a/src/services/PeopleSearchService.ts +++ b/src/services/PeopleSearchService.ts @@ -5,8 +5,9 @@ import { MockUsers, PeoplePickerMockClient } from './PeoplePickerMockClient'; import { PrincipalType, IPeoplePickerUserItem } from "../PeoplePicker"; import { IUsers, IUserInfo } from "../controls/peoplepicker/IUsers"; import { cloneDeep, findIndex } from "@microsoft/sp-lodash-subset"; -import { sp, PrincipalSource, PrincipalType as SPPrincipalType } from '@pnp/sp'; +import { sp } from '@pnp/sp'; import "@pnp/sp/sputilities"; +import { Web } from "@pnp/sp/webs"; import "@pnp/sp/webs"; import "@pnp/sp/site-users/web"; @@ -202,7 +203,7 @@ export default class SPPeopleSearchService { // Get user loginName from user email const _users = []; - const batch = sp.web.createBatch(); + const batch = Web(this.context.pageContext.web.absoluteUrl).createBatch(); for (const value of graphUserResponse.value) { sp.web.inBatch(batch).ensureUser(value.userPrincipalName).then(u => _users.push(u.data)); }