Skip to content

Commit 56c8c01

Browse files
Merge pull request #1357 from kadu-jr/dev
Added 'associatedsites' and 'hubsiteId' parameters to SitePicker to have option to show only sites associated with the hub. + infinite loop prevention when fetching sites
2 parents 5dfe5bb + 5730033 commit 56c8c01

File tree

4 files changed

+71
-10
lines changed

4 files changed

+71
-10
lines changed

src/common/Interfaces.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { SPHttpClient } from '@microsoft/sp-http';
22
import { PageContext, SPField } from '@microsoft/sp-page-context';
33
import { ListViewAccessor } from "@microsoft/sp-listview-extensibility";
44
import { ISPField } from './SPEntities';
5+
import { INavNodeInfo } from '@pnp/sp/navigation/types';
56

67
/**
78
* Customizer context interface.
@@ -27,3 +28,23 @@ export interface IFields {
2728
export interface IProps {
2829
context: IContext;
2930
}
31+
32+
export interface IHubSiteData {
33+
headerEmphasis: string;
34+
hideNameInNavigation: boolean;
35+
isNavAudienceTargeted: boolean;
36+
isSameTenantInstance: boolean;
37+
logoFileHash: number;
38+
logoUrl: string;
39+
megaMenuEnabled: boolean;
40+
name: string;
41+
navigation: INavNodeInfo[];
42+
parentHubSiteId: string;
43+
relatedHubSiteIds: string[];
44+
requiresJoinApproval: boolean;
45+
siteDesignId: string;
46+
tenantInstanceId: string;
47+
themeKey: string;
48+
url: string;
49+
usesMetadataNavigation: boolean;
50+
}

src/controls/sitePicker/ISitePicker.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ export interface ISitePickerProps {
2727
*/
2828
multiSelect?: boolean;
2929
/**
30-
* Defines what entities are available for selection: site collections, sites, hub sites.
30+
* Defines what entities are available for selection: site collections, sites, hub sites, sites inside hub.
3131
*/
32-
mode?: 'site' | 'web' | 'hub';
32+
mode?: 'site' | 'web' | 'hub' | 'associatedsites';
3333

3434
/**
3535
* Specifies if the options should be limited by the current site collections. Taken into consideration if selectionMode is set to 'web'
@@ -88,4 +88,11 @@ export interface ISitePickerProps {
8888
* Applicable if mode is set to site or web.
8989
*/
9090
additionalQuery?: string;
91+
92+
/**
93+
* If provided will be used in the search for all sites in a hub.
94+
* Applicable if mode is set to associatedsites.
95+
* If mode is set to associatedsites and no hubsiteId is provided, the current site's hub ID will be used.
96+
*/
97+
hubsiteId?: string;
9198
}

src/controls/sitePicker/SitePicker.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as React from 'react';
1010

1111
import * as telemetry from '../../common/telemetry';
1212
import { toRelativeUrl } from '../../common/utilities/GeneralHelper';
13-
import { getAllSites, getHubSites, ISite } from '../../services/SPSitesService';
13+
import { getAllSites, getHubSites, ISite, getAssociatedSites } from '../../services/SPSitesService';
1414
import { ISitePickerProps } from './ISitePicker';
1515

1616
const styles = mergeStyleSets({
@@ -73,7 +73,8 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
7373
className,
7474
selectedSites,
7575
trimDuplicates,
76-
additionalQuery
76+
additionalQuery,
77+
hubsiteId
7778
} = props;
7879

7980
const [isLoading, setIsLoading] = React.useState<boolean>();
@@ -233,11 +234,18 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
233234
setFilteredSites([]);
234235

235236
let promise: Promise<ISite[]>;
236-
if (mode === 'hub') {
237-
promise = getHubSites(context);
238-
}
239-
else {
240-
promise = getAllSites(context, mode !== 'site', limitToCurrentSiteCollection, trimDuplicates === true, additionalQuery);
237+
switch (mode) {
238+
case 'hub':
239+
promise = getHubSites(context);
240+
break;
241+
242+
case 'associatedsites':
243+
promise = getAssociatedSites(context, trimDuplicates === true, hubsiteId);
244+
break;
245+
246+
default:
247+
promise = getAllSites(context, mode !== 'site', limitToCurrentSiteCollection, trimDuplicates === true, additionalQuery);
248+
break;
241249
}
242250

243251
promise.then(newSites => {

src/services/SPSitesService.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BaseComponentContext } from '@microsoft/sp-component-base';
22
import { SPHttpClient } from '@microsoft/sp-http';
3+
import { IHubSiteData } from '../common/Interfaces';
34

45
export interface ISite {
56
/**
@@ -36,6 +37,7 @@ const getAllSitesInternal = async (ctx: BaseComponentContext, queryText: string,
3637
let startRow = 0;
3738
const rowLimit = 500;
3839
let totalRows = 0;
40+
let currentRows = 0;
3941
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4042
const values: any[] = [];
4143

@@ -69,8 +71,9 @@ const getAllSitesInternal = async (ctx: BaseComponentContext, queryText: string,
6971
values.push(...relevantResults.Table.Rows);
7072
totalRows = relevantResults.TotalRows;
7173
startRow += rowLimit;
74+
currentRows = relevantResults.Table.Rows?.length;
7275

73-
} while (values.length < totalRows);
76+
} while (values.length < totalRows && currentRows !== 0);
7477

7578
// Do the call against the SP REST API search endpoint
7679

@@ -161,3 +164,25 @@ export const getSiteWebInfo = async (ctx: BaseComponentContext, webUrl: string):
161164
siteId: siteInfoResult.Id
162165
};
163166
}
167+
168+
export const getAssociatedSites = async (ctx: BaseComponentContext, trimDuplicates: boolean, hubSiteId?: string): Promise<ISite[]> => {
169+
if (!hubSiteId){
170+
171+
const requestUrl = `${ctx.pageContext.site.absoluteUrl}/_api/web/HubsiteData`;
172+
const response = await ctx.spHttpClient.get(requestUrl, SPHttpClient.configurations.v1);
173+
const json = await response.json();
174+
175+
const hubsiteData: IHubSiteData = JSON.parse(json.value);
176+
177+
if (hubsiteData === null)
178+
return [];
179+
180+
hubSiteId = hubsiteData.relatedHubSiteIds[0];
181+
182+
}
183+
184+
const queryText = `(contentclass:STS_Site DepartmentId:${hubSiteId})`;
185+
186+
187+
return getAllSitesInternal(ctx, queryText, trimDuplicates);
188+
};

0 commit comments

Comments
 (0)