Showing posts with label SPFx. Show all posts
Showing posts with label SPFx. Show all posts

Saturday 25 May 2019

Accessing SharePoint Data with SPFx User Tokens via Service Layers - Part II

We are looking at getting user tokens retrieved from SPFx solutions, and leveraging the tokens on Azure service layers to access the SharePoint data on behalf of user.

So far, we have seen [link]
  • Creating SPFx solution by mapping necessary permissions to the package-solution.json file. 
  • Tuning the code, to get the access code for Microsoft Graph resources.

Here, by end of this reading, you will get to know how to use the token on Azure service to get access to SharePoint data.


Deploy & Approve Permissions:


Open the created SPFx solution and deploy the solution, before even testing the code on workbench. As the component requires permissions for accessing the data on SharePoint, the permissions requested should be approved before accessing. Once the component is deployed, the required permissions will be listed for approval under admin portal’s API management section.

In my case, the admin portal URL for approving necessary permissions will be
https://nakkeerann-admin.sharepoint.com/_layouts/15/online/AdminHome.aspx#/webApiPermissionManagement

Tuesday 21 May 2019

Accessing SharePoint Data with SPFx User Tokens via Service Layers - Part I

Let us have a detailed look at using the SharePoint SPFx user tokens, outside the SharePoint environments.

Why is it necessary to use the user tokens? To get to access the SharePoint data from third party services with user context. The scenario is explained below.

Usecase/Scenario: 

SPFx component accessing the SharePoint data via service layers with same user context : Weird scenario? Yes, it is very much needed in some cases like chat bot implementations or in other business processes. Say, You are working on the SharePoint component, and you need to pull data from SharePoint, but via other service like Azure services (See, we are not accessing SharePoint data directly from SharePoint component). In this case, your Azure service needs to authenticate with the SharePoint tenant, on behalf of you. That could be done by passing the oAuth tokens from SPFx to Azure service.

The flow will be as follows.
  • Create SPFx solution and map the necessary permissions on the package file.
  • Develop SPFx code, that communicates with AAD token provider and acquires the user token.
  • Pass the token to service layers like Azure Services. [This is not explained in this post. Based on the requirements, the service layer call could change. For example, if it is endpoint accessible using the endpoint, the normal REST call could be sufficient to get it working]
  • Azure service accesses the SharePoint data using the token available.
  • Azure service responds back to SPFx component with relevant data. [This is not explained in this post]

Thursday 11 April 2019

Restrict Permissions on Editing SharePoint SPFx Property Pane Configurations

Let us look, how the SPFx web part property configurations changes can be controlled by user permissions.

Let us assume a scenario, where administrators can only change the SPFx web part property values.

The following steps helps achieving the requirement.
  • The permissions of logged in user details could be identified using the context/page context.
  • While rendering the property pane configurations, the current user permissions could be checked.
  • So the properties could be enabled based on the permissions, i.e., properties will be editable, if user has admin access to the site.

This could be achieved, using the WebpartContext property and SPPermission class.

The object is initialized, using the current user permission details, and then site permission is checked for user.
    let permission = new SPPermission(this.context.pageContext.web.permissions.value);
    let isAdmin = permission.hasPermission(SPPermission.manageWeb);

Sunday 7 April 2019

Using MS Graph API and Adaptive Cards for Search/Render User Details with SPFx solutions

In this article, we will learn how to develop SPFx webparts for Office 365 SharePoint site and Microsoft Team, that leverages Microsoft Graph to search users and adaptive cards for rendering the user data effectively.

The sample used here uses the adaptive card, which has a very minimal UI. The sample used, shows how effectively UI could be changed by users. But complex custom UI could be built using the adaptive cards.

Adaptive Cards:

Let us use the adaptive card on our SPFx component for displaying user details. The following provides you the basic understanding.
  • Introduced recently, a new way for developers to render content in a consistent way, which is a open framework. 
  • It is providing options for developers, to design the UI for the specific component, using schema or visually.
  • https://adaptivecards.io/designer
  • Primarily targeted for BOT frameworks, Teams, Cortona, and windows notifications.
The following snapshot showing the UI built for our sample. This snapshot has 2 container sets for displaying 2 user details. In the schema mentioned later in the article, the single container is used, which could iterated using for loops for building containers for the required user set.

Adaptive Card Visual Interface for building component with UI
Adaptive Card Visual Interface for building component with UI

Monday 1 April 2019

Using Azure Devops & Github to Automate SPFx solution Packaging Processes for MS Teams and SharePoint

In this article, we will understand how SPFx solutions built for MS Teams and SharePoint portals, could be automatically packaged and uploaded into app catalog portals. This automation is achieved with the help of Azure Devops and Github version control systems. Using devops ensures us the continuous delivery of changes onto the target platforms.
  
Remember, we will be targeting the webparts of this solution for SharePoint and as tabs for Microsoft Teams. Let us use github repositories as a version control tool for storing the solution. You will understand, how github could be easily integrated with Azure Devops for automating the packaging processes in this article. 

Create the SPFx solution, that is compatible for SharePoint online portals. The SPFx solution (available on the github https://github.com/nakkeerann/globalspfxsoln) contains, the azure-pipeline configuration file template for setting up the build pipelines. The following snapshot shows the configurations for creating SPFx solution. 

Push the code into Github using the git commands. For example, below commands are used for my repository.
git initgit add .git commit -m "first commit"git remote add origin https://github.com/nakkeerann/globalspfxsoln.gitgit push -f origin master


Install the Azure Pipelines to your Github account https://github.com/marketplace/azure-pipelines . Select the repositories required to install pipelines. Authorize azure pipelines. 

Thursday 26 October 2017

Removing Web Part from SPFx Solution

You would have seen adding web parts to the SharePoint framework solutions. Here, let us see how to remove the web part from the SharePoint framework solution manually.

Web Part Files:

  • Navigate to your SPFx solution and the web parts folder inside it. (\src\webparts\)
  • Locate your web part folder and delete it. (This will delete all the files created for your web part)

Configuration File Entries:

  • Next, web part bundle needs to be removed from the config file (config.json).
  • In the config.json, locate your web part entry and remove the same. 
  • Similarly remove the localization file entry from the config file. 
For example, helloworld web part entry will look like,



Library Files:

  • Corresponding files should also be removed from the library folder.
  • Navigate to /lib/webparts/ folder in the solution. Locate your web part and delete the same.



Thursday 12 January 2017

Working With Cascading Dropdowns In SPFx Webpart Propeties

In this post, you will learn how to populate cascading drop down options in SharePoint Framework web part properties pane.
You will see how to populate cascading dropdown fields with dynamic SharePoint list content. I have used two dropdowns in this sample.

Declare Drop down Fields/Properties 


The drop down values appended to the field is of type IPropertyPaneDropdownOption. The variables "listDropDownOptions" and "itemDropDownOptions" of same type are declared inside the class.
The below snippet shows the property declaration.
  1. private listDropDownOptions: IPropertyPaneDropdownOption[] =[];  
  2. private itemDropDownOptions: IPropertyPaneDropdownOption[] = [];   

Define Properties 


The properties are defined using propertyPaneSettings() method. The below snippet shows the properties defined.
  1. protected get propertyPaneSettings(): IPropertyPaneSettings {  
  2.   
  3.   return {  
  4.     pages: [  
  5.       {  
  6.         header: {  
  7.           description: strings.PropertyPaneDescription,  
  8.         },  
  9.         groups: [  
  10.           {  
  11.             groupName:"Lists",  
  12.             groupFields:[  
  13.               PropertyPaneDropdown('listDropDown',{  
  14.                 label: "Select List To Display on the page",  
  15.                 options:this.listDropDownOptions,  
  16.                 isDisabled: false  
  17.               }),  
  18.               PropertyPaneDropdown('ItemsDropDown',{  
  19.                 label: "Select Item to display",  
  20.                 options: this.itemDropDownOptions,  
  21.                 isDisabled: false  
  22.   
  23.               })  
  24.             ]  
  25.           }  
  26.         ]  
  27.       }  
  28.     ]  
  29.   };  
  30. }  
Note - There are two properties defined. One dropdown is for list source and the other dropdown is for listing down the items of the list. As you can see, the values are not appended directly, rather variable of type IPropertyPaneDropdownOption is assigned. 

Load First Dropdown (List Dropdown) 


Initially, on the property pane load, all the lists available in the SharePoint site should be listed in the list dropdown. Next, we need to load the list names on the dropdown field dynamically.
To load the values, onPropertyPaneConfigurationStart method is used. It loads only when the property pane is opened. So, this method will be used in the current sample.
The below snippet shows the methods to load the list names into list dropdown. The custom function is written to load the SharePoint list names into the dropdown property. Here, this.listDropDownOptions property is loaded with the list names, which will reflect in the list dropdown property.
  1. protected onPropertyPaneConfigurationStart(): void {  
  2.   // loads list name into list dropdown  
  3.   this.GetLists();  
  4.   
  5. }  
  6.   
  7. private GetLists():void{  
  8.   // REST API to pull the list names  
  9.   let listresturl: string = this.context.pageContext.web.absoluteUrl + "/_api/web/lists?$select=Id,Title";  
  10.   
  11.   this.LoadLists(listresturl).then((response)=>{  
  12.     // Render the data in the web part  
  13.     this.LoadDropDownValues(response.value);  
  14.   });  
  15. }  
  16.   
  17. private LoadLists(listresturl:string): Promise<spLists>{  
  18.   // Call to site to get the list names  
  19.   return this.context.httpClient.get(listresturl).then((response: Response)=>{  
  20.     return response.json();  
  21.   });  
  22. }  
  23.   
  24. private LoadDropDownValues(lists: spList[]): void{  
  25.   lists.forEach((list:spList)=>{  
  26.     // Loads the drop down values  
  27.     this.listDropDownOptions.push({key:list.Title,text:list.Title});  
  28.   });  
  29. }   


Load Second Dropdown (Items Dropdown)  


Then, once the list name is selected, the items dropdown property should be populated. This can be done by overriding onPropertyChange method. The method takes two parameters (property path and new value). The function should be executed only when the list dropdown property is changed.
The below snippet shows the methods to load the items (item Title field) into list dropdown. The custom function is written to load the SharePoint item titles into the items dropdown property. Here, this.itemsDropDownOptions property is loaded with the item titles, which will reflect in the item dropdown property.
  1. protected onPropertyChange(propertyPath: string, newValue: any):void{  
  2.   if(propertyPath === "listDropDown"){  
  3.     // Change only when drop down changes  
  4.     super.onPropertyChange(propertyPath,newValue);  
  5.     // Clears the existing data  
  6.     this.properties.ItemsDropDown = undefined;  
  7.     this.onPropertyChange('ItemsDropDown'this.properties.ItemsDropDown);  
  8.     // Get/Load new items data  
  9.     this.GetItems();  
  10.   }  
  11.   else {  
  12.     // Render the property field  
  13.     super.onPropertyChange(propertyPath, newValue);  
  14.   }  
  15. }  
  16.   
  17. private GetItems(): void{  
  18.   // Retrives Items from SP List  
  19.   if(this.properties.listDropDown != undefined){  
  20.     let url: string = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getbytitle('"+this.properties.listDropDown+"')/items?$select=ID,Title,Created,Author/Title&$expand=Author";  
  21.   
  22.     this.GetItemsDropDown(url).then((response)=>{  
  23.       // Loads in to drop down field  
  24.       this.LoadItemsDropDown(response.value);  
  25.     });  
  26.   }  
  27. }  
  28.   
  29. private GetItemsDropDown(listresturl:string): Promise<spListItems>{  
  30.   // Call to list to get the items  
  31.   return this.context.httpClient.get(listresturl).then((response: Response)=>{  
  32.     return response.json();  
  33.   });  
  34. }  
  35.   
  36. private LoadItemsDropDown(listitems: spListItem[]): void{  
  37.   // Populates drop down values  
  38.   this.itemDropDownOptions = [];  
  39.   if(listitems != undefined){  
  40.     listitems.forEach((listItem:spListItem)=>{  
  41.       this.itemDropDownOptions.push({key:listItem.ID,text:listItem.Title});  
  42.     });  
  43.   }  
  44. }   


Render Web Part  


The data displayed on the web part is rendered using render method. The web part should be rendered based on the values selected from two drop downs. The custom functions are written inside render() method to display the list items based on the list name and items selected from the drop downs.
The below snippet shows the functions to render the data on the web part.
  1. public render(): void {  
  2.   // Render the items in tabular format  
  3.   this.domElement.innerHTML = `  
  4.     <div class="${styles.listItemsForm}">  
  5.       <div class="${styles.Table}">  
  6.         <div class="${styles.Heading}">  
  7.           <div class="${styles.Cell}">Title</div>  
  8.           <div class="${styles.Cell}">Created</div>  
  9.           <div class="${styles.Cell}">Author</div>  
  10.         </div>  
  11.       </div>  
  12.     </div>`;  
  13.     console.log("Render");  
  14.   
  15.     this.LoadData();  
  16. }  
  17.   
  18. private LoadData(): void{  
  19.   if(this.properties.listDropDown != undefined && this.properties.ItemsDropDown != undefined){  
  20.     let url: string = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getbytitle('"+this.properties.listDropDown+"')/items?$select=Title,Created,Author/Title&$expand=Author&$filter=ID eq "+this.properties.ItemsDropDown;  
  21.     this.GetListData(url).then((response)=>{  
  22.       // Render the data in the web part  
  23.       this.RenderListData(response.value);  
  24.     });  
  25.   }  
  26. }  
  27.   
  28. private GetListData(url: string): Promise<spListItems>{  
  29.   // Retrieves data from SP list  
  30.   return this.context.httpClient.get(url).then((response: Response)=>{  
  31.      return response.json();  
  32.   });  
  33. }  
  34.   
  35. private RenderListData(listItems: spListItem[]): void{  
  36.   let itemsHtml: string = "";  
  37.   // Displays the values in table rows  
  38.   listItems.forEach((listItem: spListItem)=>{  
  39.     itemsHtml += `<div class="${styles.Row}">`;  
  40.     itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Title}</p></div>`;  
  41.       itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Created}</p></div>`;  
  42.       itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Author.Title}</p></div>`;  
  43.   
  44.     itemsHtml += `</div>`;  
  45.   });  
  46.   this.domElement.querySelector("."+styles.Table).innerHTML +=itemsHtml;  
  47. }  


Interfaces  


The interfaces required for the sample can be found below.
  1. export interface spListItems{  
  2.   value: spListItem[];  
  3. }  
  4. export interface spListItem{  
  5.   Title: string;  
  6.   ID: string;  
  7.   Created: string;  
  8.   Author: {  
  9.     Title: string;  
  10.   };  
  11. }  
  12.   
  13. export interface spList{  
  14. Title:string;  
  15. id: string;  
  16. }  
  17. export interface spLists{  
  18.   value: spList[];  
  19. }  
The below snapshot shows the web part with the cascading dropdown fields on SPFx web part properties pane.


Summary 


Thus, you have learned how to build the cascading dropdown and populate the values dynamically on the SharePoint Framework web part properties pane.