List Out Office 365 Groups With SPFx

Overview

 
MS Graph APIs offer a wide range of capabilities. It can be effectively used to list Office 365 groups from SharePoint Framework solutions. An SPFx web part can be a useful asset to list all Office 365 groups, instead of navigating to Office 365 admin center.
 
During this article, we will develop a practical scenario to list all Office 365 groups using MS Graph.
 

Develop SPFx Web Part

 
Open a command prompt. Create a directory for the SPFx solution.
  1. md spfx-list-o365-groups  
Navigate to the above created directory.
  1. cd spfx-list-o365-groups  
Run the Yeoman SharePoint Generator to create the solution.
  1. yo @microsoft/sharepoint  
Yeoman generator will present you with the wizard by asking questions about the solution to be created.
 
List Out Office 365 Groups With SPFx
 
Yeoman generator will perform the scaffolding process to generate the solution. The scaffolding process will take a significant amount of time.
 
Once the scaffolding process is completed, lock down the version of the project dependencies by running below command.
  1. npm shrinkwrap  
In the command prompt type below command to open the solution in the code editor of your choice.
  1. code .  

NPM Packages Dependency

 
Microsoft Graph TypeScript types
 
The typings will help in providing IntelliSense while writing the code.
 
On the command prompt, run the below command to include the npm package.
  1. npm install @microsoft/microsoft-graph-types --save-dev  

Set Permission Scopes

 
To consume MS Graph or any third-party REST APIs, the permissions need to be explicitly set in the solution manifest.
 
Open “config\package-solution.json” and add below permission scope.
  1. {  
  2.   "$schema""https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",  
  3.   "solution": {  
  4.     "name""spfx-list-o365-groups-client-side-solution",  
  5.     "id""5d134841-70c0-47a5-a838-217b6fd79c55",  
  6.     "version""1.0.0.0",  
  7.     "includeClientSideAssets"true,  
  8.     "isDomainIsolated"false,  
  9.     "webApiPermissionRequests": [  
  10.       {  
  11.         "resource""Microsoft Graph",  
  12.         "scope""Group.Read.All"  
  13.       },  
  14.       {  
  15.         "resource""Microsoft Graph",  
  16.         "scope""Group.ReadWrite.All"  
  17.       }  
  18.     ]  
  19.   },  
  20.   "paths": {  
  21.     "zippedPackage""solution/spfx-list-o365-groups.sppkg"  
  22.   }  

Define State

 
Define a state to represent O365 group creation information.
 
Step 1
 
Add a file IListO365GroupsState.ts file under folder “src\webparts\listO365Groups\components\IListO365GroupsState.ts”.
  1. export interface IGroup {  
  2.     id: string;  
  3.     displayName: string;  
  4.     description?: string;  
  5.     visibility?: string;  
  6. }  
  7.   
  8. export interface IGroupCollection {  
  9.     value: IGroup[];  
  10. }  
  11.   
  12. export interface IListO365GroupsState {  
  13.     filterText?: string;  
  14.     groups?: IGroup[];  
  15. }  

Implement O365 Groups Service

 
Implement a service to perform operations against O365 groups.
 
Step 1
 
Under src, create a folder named "services".
 
Step 2
 
Add a file O365GroupService.ts file under it.
  1. import { MSGraphClient } from "@microsoft/sp-http";  
  2. import { WebPartContext } from "@microsoft/sp-webpart-base";  
  3. import { IGroup, IGroupCollection } from "../models";  
  4.   
  5. export class O365GroupService {  
  6.   public context: WebPartContext;  
  7.   
  8.   public setup(context: WebPartContext): void {  
  9.     this.context = context;  
  10.   }  
  11.   
  12.   .  
  13.   .  
  14.   .  
  15.   
  16. const GroupService = new O365GroupService();  
  17. export default GroupService;  
Step 3
 
Implement a method to get all O365 groups.
  1. public getGroups(): Promise<IGroup[]> {  
  2.     return new Promise<IGroup[]>((resolve, reject) => {  
  3.       try {  
  4.         // Prepare the output array  
  5.         var o365groups: Array<IGroup> = new Array<IGroup>();  
  6.   
  7.         this.context.msGraphClientFactory  
  8.           .getClient()  
  9.           .then((client: MSGraphClient) => {  
  10.             client  
  11.               .api("/groups?$filter=groupTypes/any(c:c eq 'Unified')")  
  12.               .get((error: any, groups: IGroupCollection, rawResponse: any) => {  
  13.                 // Map the response to the output array  
  14.                 groups.value.map((item: any) => {  
  15.                   o365groups.push({  
  16.                     id: item.id,  
  17.                     displayName: item.displayName,  
  18.                     description: item.description,  
  19.                     visibility: item.visibility  
  20.                   });  
  21.                 });  
  22.   
  23.                 resolve(o365groups);  
  24.               });  
  25.           });  
  26.       } catch (error) {  
  27.         console.error(error);  
  28.       }  
  29.     });  
  30.   }  
  31. }  
Step 4
 
Implement a method to get the O365 group link.
  1. public getGroupLink(groups: IGroup): Promise<any> {  
  2.     return new Promise<any>((resolve, reject) => {  
  3.       try {  
  4.         this.context.msGraphClientFactory  
  5.           .getClient()  
  6.           .then((client: MSGraphClient) => {  
  7.             client  
  8.               .api(`/groups/${groups.id}/sites/root/weburl`)  
  9.               .get((error: any, group: any, rawResponse: any) => {  
  10.                 resolve(group);  
  11.               });  
  12.           });  
  13.       } catch (error) {  
  14.         console.error(error);  
  15.       }  
  16.     });  
  17.   }  
Step 5
 
Implement a method to get the O365 group thumbnail.
  1. public getGroupThumbnail(groups: IGroup): Promise<any> {  
  2.     return new Promise<any>((resolve, reject) => {  
  3.       try {  
  4.         this.context.msGraphClientFactory  
  5.           .getClient()  
  6.           .then((client: MSGraphClient) => {  
  7.             client  
  8.               .api(`/groups/${groups.id}/photos/48x48/$value`)  
  9.               .responseType('blob')  
  10.               .get((error: any, group: any, rawResponse: any) => {  
  11.                 resolve(window.URL.createObjectURL(group));  
  12.               });  
  13.           });  
  14.       } catch (error) {  
  15.         console.error(error);  
  16.       }  
  17.     });  
  18.   }  
Step 6
 
Under the services folder, add a file index.ts.
  1. export * from './O365GroupService';   

Consume service from the web part

 
Step 1
 
Open web part file at “src\webparts\listO365Groups\ListO365GroupsWebPart.ts”
 
Step 2
 
Import the service.
  1. import O365GroupService from './services/O365GroupService';  
Step 3
 
Implement onInit() method to set up the service.
  1. protected onInit(): Promise<void> {  
  2.   return super.onInit().then(() => {  
  3.     O365GroupService.setup(this.context);  
  4.   });  
  5. }   

Implement the ListO365Groups React Component

 
Step 1
 
Open the React component at src\webparts\listO365Groups\components\ListO365Groups.tsx
 
Step 2
 
Add the below imports.
  1. import { FocusZone, FocusZoneDirection } from 'office-ui-fabric-react/lib/FocusZone';  
  2. import { TextField } from 'office-ui-fabric-react/lib/TextField';  
  3. import { Image, ImageFit } from 'office-ui-fabric-react/lib/Image';  
  4. import { Icon } from 'office-ui-fabric-react/lib/Icon';  
  5. import { List } from 'office-ui-fabric-react/lib/List';  
  6. import { ITheme, mergeStyleSets, getTheme, getFocusStyle } from 'office-ui-fabric-react/lib/Styling';  
  7. import { IGroup, IGroupCollection } from "../models/IGroup";  
  8. import O365GroupService from '../services/O365GroupService';  
Step 3
 
Use the React state.
  1. import { IListO365GroupsState } from './IListO365GroupsState';  
  2.   
  3. export default class ListO365Groups extends React.Component<IListO365GroupsProps, IListO365GroupsState> {  
  4.   constructor(props: IListO365GroupsProps) {  
  5.     super(props);  
  6.   
  7.     this.state = {  
  8.       groups: []  
  9.     };  
  10.   }  
  11. .  
  12. .  
  13. .  
  14. }  
Step 4
 
As we are using Office 365 UI Fabric List, let us initialize the display of it.
  1. interface IGroupListClassObject {  
  2.   itemCell: string;  
  3.   itemImage: string;  
  4.   itemContent: string;  
  5.   itemName: string;  
  6.   itemIndex: string;  
  7.   chevron: string;  
  8. }  
  9.   
  10. const theme: ITheme = getTheme();  
  11. const { palette, semanticColors, fonts } = theme;  
  12.   
  13. const classNames: IGroupListClassObject = mergeStyleSets({  
  14.   itemCell: [  
  15.     getFocusStyle(theme, { inset: -1 }),  
  16.     {  
  17.       minHeight: 54,  
  18.       padding: 10,  
  19.       boxSizing: 'border-box',  
  20.       borderBottom: `1px solid ${semanticColors.bodyDivider}`,  
  21.       display: 'flex',  
  22.       selectors: {  
  23.         '&:hover': { background: palette.neutralLight }  
  24.       }  
  25.     }  
  26.   ],  
  27.   itemImage: {  
  28.     flexShrink: 0  
  29.   },  
  30.   itemContent: {  
  31.     marginLeft: 10,  
  32.     overflow: 'hidden',  
  33.     flexGrow: 1  
  34.   },  
  35.   itemName: [  
  36.     fonts.xLarge,  
  37.     {  
  38.       whiteSpace: 'nowrap',  
  39.       overflow: 'hidden',  
  40.       textOverflow: 'ellipsis'  
  41.     }  
  42.   ],  
  43.   itemIndex: {  
  44.     fontSize: fonts.small.fontSize,  
  45.     color: palette.neutralTertiary,  
  46.     marginBottom: 10  
  47.   },  
  48.   chevron: {  
  49.     alignSelf: 'center',  
  50.     marginLeft: 10,  
  51.     color: palette.neutralTertiary,  
  52.     fontSize: fonts.large.fontSize,  
  53.     flexShrink: 0  
  54.   }  
  55. });  
Step 5
 
Implement render method to add the UI controls.
  1. public render(): React.ReactElement<IListO365GroupsProps> {  
  2.   const { groups = [] } = this.state;  
  3.   const resultCountText = groups.length === this._originalItems.length ? '' : ` (${groups.length} of ${this._originalItems.length} shown)`;  
  4.   
  5.   return (  
  6.     <FocusZone direction={FocusZoneDirection.vertical}>  
  7.       <TextField label={'Filter by name' + resultCountText} onChange={this._onFilterChanged} />  
  8.       <List items={groups} onRenderCell={this._onRenderCell} />  
  9.     </FocusZone>  
  10.   );  
  11. }  
Step 6
 
Implement the event handlers for UI controls.
  1. private _onFilterChanged = (_: any, text: string): void => {  
  2.     this.setState({  
  3.       filterText: text,  
  4.       groups: text ? this._originalItems.filter(item => item.displayName.toLowerCase().indexOf(text.toLowerCase()) >= 0) : this._originalItems  
  5.     });  
  6.   
  7.     this._getGroupLinks(this.state.groups);  
  8.   }  
  9.   
  10.   private _onRenderCell(group: IGroup, index: number | undefined): JSX.Element {  
  11.     return (  
  12.       <div className={classNames.itemCell} data-is-focusable={true}>  
  13.         <Image className={classNames.itemImage} src={group.thumbnail} width={50} height={50} imageFit={ImageFit.cover} />  
  14.         <div className={classNames.itemContent}>  
  15.           <div className={classNames.itemName}>  
  16.             <a href={group.url} target="_blank">{group.displayName}</a>  
  17.           </div>  
  18.           <div className={classNames.itemIndex}>{group.visibility}</div>  
  19.           <div>{group.description}</div>  
  20.         </div>  
  21.       </div>  
  22.     );  
  23.   }  
Step 7
 
Implement the helper methods.
  1. public _getGroups = (): void => {  
  2.   O365GroupService.getGroups().then(groups => {  
  3.     console.log(groups);  
  4.     this._originalItems = groups;  
  5.   
  6.     this.setState({  
  7.       groups: groups  
  8.     });  
  9.   
  10.     this._getGroupLinks(groups);  
  11.   });  
  12. }  
  13.   
  14. public _getGroupLinks = (groups: any): void => {  
  15.   groups.map(groupItem => (  
  16.     O365GroupService.getGroupLink(groupItem).then(groupUrl => {  
  17.       if (groupUrl !== null) {  
  18.         this.setState(prevState => ({  
  19.           groups: prevState.groups.map(group => group.id === groupItem.id ? { ...group, url: groupUrl.value } : group)  
  20.         }));  
  21.       }  
  22.     })  
  23.   ));  
  24.   
  25.   this._getGroupThumbnails(groups);  
  26. }  
  27.   
  28. public _getGroupThumbnails = (groups: any): void => {  
  29.   groups.map(groupItem => (  
  30.     O365GroupService.getGroupThumbnail(groupItem).then(grouptb => {  
  31.       console.log(grouptb);  
  32.       this.setState(prevState => ({  
  33.         groups: prevState.groups.map(group => group.id === groupItem.id ? { ...group, thumbnail: grouptb } : group)  
  34.       }));  
  35.     })  
  36.   ));  
  37. }  

Deploy the SPFx Package to SharePoint App Catalog

 
Follow the below steps to deploy the SPFx package (.sppkg) to the SharePoint app catalog.
 
Build minified assets
 
On the command prompt, type the below command.
  1. gulp bundle --ship  
Prepare the package
 
On the command prompt, type the below command.
  1. gulp package-solution --ship  
The .sppkg package will be available inside the “sharepoint\solution” folder.
 

Upload package to the app catalog

 
Step 1
 
Open the SharePoint app catalog site.
 
Step 2
 
Upload the package to the app catalog.
 
List Out Office 365 Groups With SPFx 
 

API Management

 
After deploying the web part, follow the below steps to approve API requests.
  1. Open SharePoint Admin Center (https://[tenant]-admin.sharepoint.com).
  2. From left navigation, click “API Management”.
  3. Approve the pending requests.
List Out Office 365 Groups With SPFx 

Test the WebPart

  1. On the command prompt, type “gulp serve”.
  2. Open SharePoint site.
  3. Navigate to /_layouts/15/workbench.aspx
  4. Locate and add the web part (named O365 Groups Listing) to page.
List Out Office 365 Groups With SPFx
 

Summary

 
Microsoft Graph offers a wide range of APIs to access the content and services provided by Office 365. Listing all O365 groups by using MS Graph API is one of the business cases supporting it.