SPFx-MSGraph Toolkit FileList Control

Introduction

Hi friends, in one of my previous post I walk you through the steps on how you can leverage MSGraph Toolkit components in SharePoint Framework project with minimal configuration. Now let us see how we can use the FileList control from MSGraph Toolkit in action, its properties and how we can customize the control.

Focus on the Code

Let us start by creating a new web part project using yeoman SharePoint generator, before that create a folder where you want to create the web part. Navigate to that folder and run the below command.

yo @microsoft/sharepoint

The generator will asks you couple of questions,

  • Enter the webpart name as your solution name, and then select Enter.
  • Select Create a subfolder with solution name for where to place the files.
  • Select N to allow the solution to be deployed to all sites immediately.
  • Select N on the question if solution contains unique permissions.
  • Enter the webpart name
  • Enter the webpart description
  • Choose the framework as ‘React

NoteI have used @microsoft/generator-sharepoint version 1.12.1

Once the project is created, make sure the web part is running without any issue. Its better to actually run the vanilla web part once it is created. Once the verification is done, install the below packages

Once the above packages are installed, you should have the package.json file like the below

{
    "name": "graph-toolkit-demo",
    "version": "0.0.1",
    "private": true,
    "main": "lib/index.js",
    "scripts": {
        "build": "gulp bundle",
        "clean": "gulp clean",
        "test": "gulp test"
    },
    "dependencies": {
        "@microsoft/mgt-react": "^2.3.0",
        "@microsoft/mgt-spfx": "^2.3.0",
        "@microsoft/sp-core-library": "1.12.1",
        "@microsoft/sp-lodash-subset": "1.12.1",
        "@microsoft/sp-office-ui-fabric-core": "1.12.1",
        "@microsoft/sp-property-pane": "1.12.1",
        "@microsoft/sp-webpart-base": "1.12.1",
        "office-ui-fabric-react": "7.156.0",
        "react": "16.9.0",
        "react-dom": "16.9.0"
    },
    "devDependencies": {
        "@types/react": "16.9.36",
        "@types/react-dom": "16.9.8",
        "@microsoft/sp-build-web": "1.12.1",
        "@microsoft/sp-tslint-rules": "1.12.1",
        "@microsoft/sp-module-interfaces": "1.12.1",
        "@microsoft/sp-webpart-workbench": "1.12.1",
        "@microsoft/rush-stack-compiler-3.7": "0.2.3",
        "gulp": "~4.0.2",
        "ajv": "~5.2.2",
        "@types/webpack-env": "1.13.1"
    }
}

Here I have named my web part as graph-toolkit-demo.

Now we have to update our code to authenticate to Microsoft Identity to access the Microsoft Graph API. There is no complication and nothing to worry on the authentication or setup, all are taken care by the providers which comes with the package that we installed above. We just need to use the right providers. Since we are using SPFx, we need to use the SharePoint Provider. This can be achieved with just a single line of code which is shown below. Update your <webpart>.ts file with the below code.

import { Providers, SharePointProvider } from '@microsoft/mgt-spfx';
protected async onInit() {
    if (!Providers.globalProvider) {
        Providers.globalProvider = new SharePointProvider(this.context);
    }
}

So with the above code, the authentication is set. Now we can see how we can use the components in our <webpart>.tsx file. Before modifying the web part file, we need to create some folders and files which makes it easy for maintaining the controls and for re-usability.

Create a folder named ToolkitControl in the src folder. Add the following files

  • Graph.FileList.tsx
  • controlStyles.module.scss

The style class is common for all the controls and for each control you can create a separate tsx file and implement the business logic.

Update Graph.FileList.tsx with the below code

import * as React from 'react';
import { FC } from 'react';
import { useState } from 'react';
import styles from './controlStyles.module.scss';
import { FileList } from '@microsoft/mgt-react/dist/es6/spfx';
import { CacheService } from '@microsoft/mgt-spfx';
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';

export const GraphFileList: FC<{}> = (props) => {
    const [selFileInfo, setSelFileInfo] = useState<any>(undefined);

    const _onFileClick = (e: any) => {
        console.log(e);
        if (e.detail) {
            let fileInfo: any = {
                Editor: e.detail.lastModifiedBy.user.displayName,
                Modified: e.detail.lastModifiedDateTime,
                ItemId: e.detail.remoteItem.sharepointIds.listItemId,
                FileUrl: e.detail.remoteItem.webDavUrl,
                FilePrevUrl: e.detail.remoteItem.webUrl
            };
            setSelFileInfo(fileInfo);
        }
    };

    const _onClearCache = () => {
        CacheService.clearCaches();
    };

    return (
        <div className={styles.filesList}>
            <p>My Onedrive files</p>
            <FileList fileListQuery="/me/drive/recent" pageSize={5} itemClick={_onFileClick} />
            <div>
                <p>Selected file info</p>
                {selFileInfo &&
                    <div className={styles.fileInfo}>
                        <div><p>Last Modified By:</p> {selFileInfo.Editor}</div>
                        <div><p>Last Modified Time:</p> {selFileInfo.Modified}</div>
                        <div><p>List Item Id:</p> {selFileInfo.ItemId}</div>
                        <div><p>File Url:</p> {selFileInfo.FileUrl}</div>
                        <div><p>File Preview Url:</p> {selFileInfo.FilePrevUrl}</div>
                    </div>
                }
            </div>
            <p>File Upload</p>
            <FileList enableFileUpload={true} maxUploadFile={2}></FileList>
            <PrimaryButton onClick={_onClearCache} text="Clear Cache" />
            <div className={styles.customFileList}>
                <p>Custom Style</p>
                <FileList fileListQuery="<siteid/libraryid/root/children" />
            </div>
        </div>
    );
};

Below are done in the above code

  • We have imported the correct reference to the FileList component from ‘@microsoft/mgt-react/dist/es6/spfx
  • We have also imported CacheService from ‘@microsoft/mgt-spfx‘. (This has to be referenced from mgt-spfx and not mgt-react because you will face some issues if you had referenced using mgt-react)
  • Declared a state variable to store some of the file info..
  • Declared a method _onFileClick which will be invoked each time when the user click on the file item.
  • Declared a method _onClearCache which will clear the cache and will tell the component to get the files from the source location.
  • Render the FileList control with different properties. I have used thrice to show you how you can use the control properties and custom styles.

Note: The links to the documentation is mentioned in the reference section below.

Update controlStyles.module.scss file

@import '~office-ui-fabric-react/dist/sass/References.scss';

.filesList {
    p {
        color: black;
        font-size: 15px;
        font-weight: bold;
    }
    .fileInfo {
        color: black;
        div {
            word-break: break-word;
        }
        div > p {
            margin: 3px 0px;
            font-size: 13px;
            display: contents;
        }
    }
    .customFileList {
        mgt-file-list {
            --font-family: 'Segoe UI';
            --font-size: 14px;
          
            --file-list-background-color: #ffffff;
            --file-list-border: 1px solid "[theme:themePrimary]";
            --file-list-box-shadow: none;
            --file-list-padding: 4px 0;
            --file-list-margin: 0;
          
            --file-item-background-color--hover: "[theme:themeTertiary]";
            --file-item-background-color--active: rgba(0, 0, 0, 0.05);
            --file-item-border-radius: 2px;
            --file-item-margin: 0 4px;
          
            --file-item-border-top: none;            
            --file-item-border-left: none;
            --file-item-border-right: none;
            --file-item-border-bottom: none;
          
            --show-more-button-background-color: "[theme:themeLighter]";
            --show-more-button-background-color--hover: "[theme:themeLight]";
            --show-more-button-font-size: 12px;
            --show-more-button-padding: 10px;
            --show-more-button-border-bottom-right-radius: 4px;
            --show-more-button-border-bottom-left-radius: 4px;
          
            --file-upload-border: 4px dotted #ffbdc3;
            --file-upload-background-color: rgba(255, 0, 0, 0.1);
            --file-upload-button-float: left;
            --file-upload-button-color: "[theme:themeWhite]";
            --file-upload-button-background-color: "[theme:themeSecondary]";
            --file-upload-dialog-content-background-color: #ffe7c7;
            --file-upload-dialog-primarybutton-background-color: #ffe7c7;
            --file-upload-dialog-primarybutton-color: #323130;
          }
    }
}

The control is ready and now we can render the control in the actual webpart.tsx file. Update the file with the required import and the control inside the render method.

import { GraphFileList } from '../../../ToolkitControls/Graph.FileList';
public render(): React.ReactElement<IGraphToolkitDemoProps> {
    return (
        <div className={styles.graphToolkitDemo}>
            <div className={styles.container}>
                <div className={styles.row}>
                    <div className={styles.column}>
                        <GraphFileList />
                    </div>
                </div>
            </div>
        </div>
    );
}

Now the last and the most important for the Graph API to access the data. I think you figured it out, its the scopes. We have to define the scopes that are used by the control in the package-solution.json file.

"webApiPermissionRequests": [
            {
                "resource": "Microsoft Graph",
                "scope": "Files.ReadWrite.All"
            },
            {
                "resource": "Microsoft Graph",
                "scope": "Files.Read.All"
            },
            {
                "resource": "Microsoft Graph",
                "scope": "Sites.ReadWrite.All"
            },
            {
                "resource": "Microsoft Graph",
                "scope": "Sites.Read.All"
            }
 ]

Thats it. You are done with the coding part and now comes the fun part. Execute the code and see how it renders. Make sure you approve the API requests in the SharePoint Admin Center.

Video

Coming soon…

Reference Links

Happy Coding…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s