Reading Time: 4 minutes
Update: Source code is also available on the official GitHub of Microsoft SharePoint PnP
https://github.com/SharePoint/sp-dev-fx-webparts/tree/master/samples/react-teams-tabs-pnpjs 
5/12/2019 SharePoint Framework Community Call Recording with my live demo is now available
If you want you can see the registration here :)

Hi guys,
today we’ll talk about a new SPFx sample webpart I made using one of my favorite technology, SharePoint Framework!

General needs

The requirement is to show in a WebPart the hierarchy of Channels and Tabs of the Team connected to the SharePoint Modern Team site, directly on the site, so that it is possible to access the Tabs without necessarily having to open MS Teams app (or web app), saving the step of having to find the team and the desired channel: they are already on a site connected to a Team, I would like to be able to access directly.
The result is therefore a fast track towards the Teams Tabs, so that their access is even quickly.

First of all, we need to understand what are SharePoint Online Modern Team site.

Modern Team sites are Team Sites integrated with Office 365 groups and it provides options to collaborate better than before. When you create a modern team site in SharePoint Online, it automatically creates the O365 group, group email address, and ability to identify whether this site will contain sensitive data (privacy) and more new features.

What are Modern Team Sites?

Why is it so interesting know there is an Office 365 group connected to a Modern Team Site?

When you create a new team in Microsoft Teams, on the backend, you’re creating an Office 365 Group and the associated SharePoint document library and OneNote notebook, along with ties into other Office 365 cloud applications. If the person creating the team is an owner of an existing Office 365 Public or Private Group, they can add Teams functionality to the group if it has less than 5000 people and has never been added to Teams. This creates one default General channel in which chat messages, documents, OneNote, and other objects reside. Viewing the document library for the channel will reveal the General folder representing the channel in the team. More importantly, if you create your own folder structure within a document library it does not propagate to Teams as a channel; for now, it only flows from Teams into SharePoint.

How Office 365 Groups work

How are Modern Team sites connected to Teams?

There is a property bag named GroupId inside SharePoint Team Site, you can easly verify using CSOM, Powershell or SharePoint Online Client Browser

Prerequisites

You can start from a Team inside MS Teams, and open the connected Modern Team Sites

react-teams-tabs-pnpjs: components and features

Landing into the home page, the WebPart will shows the list of all channels of the Modern Team Sites linked teams. Nested inside Channels list, you will find Tabs link.

In order to render Channels and Tabs nested, I used Fabric UI Nav component

the interesting side is that the webpart contextualizes itself on the current site, going to retrieve the information through the api graphs from the teams connected to the site.

Microsoft Graph API calls are wrapped from @pnp/graph/teams package. Internally they use two specifics calls.

Get all Channels from a Team, using GroupId

GET /teams/{id}/channels

Get all Tabs from a Channel

GET /teams/{id}/channels/{id}/tabs

react-teams-tabs-pnpjs in action!

Code deep-dive

The solution is pushed in my GitHub repository, but I would like to focus on three snippets

Get GroupID using @pnp/sp

public static async getGroupId(): Promise<string> {

    var id: string = "";

    var props: any = await sp.web.select("AllProperties")
      .expand("AllProperties")
      .get();

    if (props.AllProperties["GroupId"] != null) {
      id = props.AllProperties["GroupId"];
    }
    return id;
  }

Get GroupID using current context

(Update 06/12/2019) Ehy! Do we really need to make an explicit call to  retrieve GroupID? 
Actually not! This information is already in the context of the page, so we can retrieve it 
directly, saving a call. It is interesting to know how to do it with PnPJS, but if an 
information is already in the context there is no need to make a specific call ;)  
Thanks for the hint to Markus Möller, mate and Avanade colleague!
public static async getGroupId(): Promise<string> {

    var id: string = "";

    // Retreive GroupID
    id=this.context.pageContext.legacyPageContext['groupId']);

    return id;
  }

Get Channels and Tabs using @pnp/graph/teams

public static async getChannels(groupId: string): Promise<any[]> {

    var channels: any[]= [];

    channels = await graph.teams.getById(groupId).channels.get();

    return channels;
  }


  public static async getTabsFromChannel(groupId: string, channelId: string): Promise<any[]> {

    var tabs: any[] = [];

    tabs = await graph.teams.getById(groupId).channels.getById(channelId)
      .tabs
      .get();

    return  tabs;
  }

Add web API permission requests to the SPFx solution

If you want to use @pnp/graph in order to retrive Channels and Tabs, you should provide permission request for corresponding APIs. In our case we need to add Group.Read.All, Group.ReadWrite.All scope. Add below code in your package-solution.json, under “solution” node:

 "webApiPermissionRequests": [
      {
        "resource": "Microsoft Graph",
        "scope": "Group.ReadWrite.All"
      }
    ]

Hope you enjoy my new code contribution!
Cheers
Federico

One thought on “react-teams-tabs-pnpjs: show Channels and Tabs from a Modern Team Site connected to MS Teams”

Leave a Reply

Your email address will not be published. Required fields are marked *