Friday, 7 February 2020

SharePoint Online - Declare / Undeclare Item as a record using Powershell CSOM



A - OBJECTIVE: 

During process automation in SharePoint Online, Powershell script can be considered to programmatically declare (or undeclare) items and files as a record .

The manual steps that can be automated for multiple items are as follows:





B - ARCHITECTURE:

1. The site collection feature "In Place Records Management" must be activated; then, at each individual list / library settings (Record declaration settings), we need to configure the manual records management settings.




2. Field Value _vti_ItemHoldRecordStatus (int) can be used to identify the record status of the item (reference 3): 

  • _vti_ItemHoldRecordStatus = 0 : a normal document / item
  • _vti_ItemHoldRecordStatus = 273 : a record
  • _vti_ItemHoldRecordStatus = 4353: an item on hold


3. Field Value _vti_ItemDeclaredRecord (datetime) is set to the current date time soon after the associated item is set as a record; and this value is cleared once the item is undeclared as a record.

4. The functions DeclareItemAsRecord / UndeclareItemAsRecord (using ClientRuntimeContext) in the assembly Microsoft.SharePoint.Client.RecordsRepository.Records of the library Microsoft.Office.Client.Policy.dll is used to declare / undeclare a record:

#declare the record
if($DocItem.FieldValues["_vti_ItemHoldRecordStatus"] -eq 0)
{
[Microsoft.SharePoint.Client.RecordsRepository.Records]::DeclareItemAsRecord($clientRuntimeContext,$DocItem)
}

#undeclare the record
if($DocItem.FieldValues["_vti_ItemHoldRecordStatus"] -eq 273)
{
[Microsoft.SharePoint.Client.RecordsRepository.Records]::UndeclareItemAsRecord($clientRuntimeContext,$DocItem)
}

5. The declared item has a LOCK icon at the file type and the datetime value in the column Declared Record:





C - SOLUTION:

1. Powershell tool must be Windows Powershell or Windows Powershell ISE. The script does not work in SharePoint Online Management Shell at the moment (Microsoft.Online.SharePoint.PowerShell version 16.0.7414.0) , and it will throw an error:

Cannot convert argument "context", with value: "Microsoft.SharePoint.Client.ClientContext", for "IsRecord" to type "Microsoft.SharePoint.Client.ClientRuntimeContext": "Cannot convert the "Microsoft.SharePoint.Client.ClientContext" value of type "Microsoft.SharePoint.Client.ClientContext" to type "Microsoft.SharePoint.Client.ClientRuntimeContext"." ---> System.Management.Automation.PSInvalidCastException: Cannot convert the "Microsoft.SharePoint.Client.ClientContext" value of type "Microsoft.SharePoint.Client.ClientContext" to type "Microsoft.SharePoint.Client.ClientRuntimeContext".

2. SharePoint Online Client Components SDK (link here): the latest version should be installed and referenced to in the Powershell script:

Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"

Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"


Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.Office.Client.Policy.dll"

3. DLL version must be 16+ (i.e. the version 15.x is not recommended)




4. The function IsRecord does not return a proper value as expected in this DLL version; hence, we should use the field value $DocItem.FieldValues["_vti_ItemHoldRecordStatus"]

[Boolean] $isRecord = [Microsoft.SharePoint.Client.RecordsRepository.Records]::IsRecord($clientRuntimeContext,$DocItem)

D - SOURCE CODE:


#region Load SharePoint Client Assemblies
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.Office.Client.Policy.dll"
#endregion

# Document Library
$libRequestDocs = "Request Documents"

# Connection Credetials 
$UserName = "admin@nhn.onmicrosoft.com"
$PASSWORD = "YourPassword"
$SecurePassword = ConvertTo-SecureString -String $PASSWORD -AsPlainText -Force

# Target environment
$SiteUrl = "https://nhn.sharepoint.com/sites/records"

# Global variables
$archivedIDs = [System.Collections.ArrayList]@()

### Connection to SP Online Archive subsites to get the reference
Try
{
    #connect/authenticate to SharePoint Online and get ClientContext object..        
    $clientContextArchive = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl) 
 
 [Microsoft.SharePoint.Client.ClientRuntimeContext]$clientRuntimeContext=[Microsoft.SharePoint.Client.ClientRuntimeContext]$clientContextArchive.Site.Context
 
    $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword) 
    $clientContextArchive.Credentials = $credentials
 
 $clientContextArchive.Load($clientContextArchive.Web)
 $clientContextArchive.ExecuteQuery()
  
    Write-Host "Connected to SharePoint Online site: " $SiteUrl"/Archive001/" -ForegroundColor Green
}
Catch
{
    $SPOConnectionException = $_.Exception.Message
    Write-Host ""
    Write-Host "Connection Error:" $SPOConnectionException -ForegroundColor Red
    Write-Host ""
    Break
}

Try {
    #Get the Document Library
    $libDocs =$clientContextArchive.Web.Lists.GetByTitle($libRequestDocs)
    $clientContextArchive.Load($libDocs)
 $clientContextArchive.ExecuteQuery()
 
    #Define CAML Query to Get All Files    
    $queryCommand = " 
  
   
  
  1000
 "
 
    $DataCollection = @() 
 $Count = 1;
 $position = $null
 
 $queryCAML = New-Object Microsoft.SharePoint.Client.CamlQuery
 $queryCAML.ViewXml = $queryCommand
 
 #handle large library with more than 5000 items
 Do
 {
  Try{
   #powershell sharepoint online list all documents
   $currentDocCollection = $libDocs.GetItems($queryCAML)
   $clientContextArchive.Load($currentDocCollection)
   $clientContextArchive.ExecuteQuery()
   
   $queryCAML.ListItemCollectionPosition = $currentDocCollection.ListItemCollectionPosition 
   
   Write-host -f Green "Collection Index " $currentDocCollection.ListItemCollectionPosition.pagingInfo 
   
   #Iterate through each document in the library
   ForEach($DocItem in $currentDocCollection)
   {
    $clientContextArchive.Load($DocItem)
    $clientContextArchive.Load($DocItem.File)
    $clientContextArchive.ExecuteQuery()
    
    #this function does not return expected results
    [Boolean] $isRecord = [Microsoft.SharePoint.Client.RecordsRepository.Records]::IsRecord($clientRuntimeContext,$DocItem)
    $clientContextArchive.ExecuteQuery()
    
    Write-host -f Green "Doc:" $DocItem.FieldValues
    Write-host -f Green "[Record Details] _vti_ItemHoldRecordStatus: " $DocItem.FieldValues["_vti_ItemHoldRecordStatus"]
    Write-host -f Green "[Record Details] _vti_ItemDeclaredRecord: " $DocItem.FieldValues["_vti_ItemDeclaredRecord"]
    
    #undeclare the record
    if($DocItem.FieldValues["_vti_ItemHoldRecordStatus"] -eq 273){
     [Microsoft.SharePoint.Client.RecordsRepository.Records]::UndeclareItemAsRecord($clientRuntimeContext,$DocItem)

     try
     {
      $clientRuntimeContext.ExecuteQuery()  
      Write-Host "...Item has been undeclared a record" -ForegroundColor Green
      Write-host -f Blue "Doc:" $DocItem.FieldValues
     }
     catch
     {
      Write-Host "...Item could not be undeclared a record" -ForegroundColor Red
      write-host -f Red "Error Level 3:" $_.Exception
     }       
    }
    
    #declare the record
    if($DocItem.FieldValues["_vti_ItemHoldRecordStatus"] -eq 0){
     [Microsoft.SharePoint.Client.RecordsRepository.Records]::DeclareItemAsRecord($clientRuntimeContext,$DocItem)

     try
     {
      $clientRuntimeContext.ExecuteQuery()  
      Write-Host "...Item has been declared a record" -ForegroundColor Green
      Write-host -f Blue "Doc:" $DocItem.FieldValues
     }
     catch
     {
      Write-Host "...Item could not be declared a record" -ForegroundColor Red
      write-host -f Red "Error Level 3:" $_.Exception
     }       
    }   
   }
  }
  Catch{
   write-host -f Red "Error Level 2:" $_.Exception
  }
 }
 While($queryCAML.ListItemCollectionPosition -ne $null)
}
Catch {
    write-host -f Red "Error Level 1:" $_.Exception.Message
}

REFERENCE:

1. https://gallery.technet.microsoft.com/office/SharePoint-Online-f6bae254/view/Discussions#content

2. https://www.sharepointpals.com/post/check-whether-a-document-is-already-a-record-or-not-isrecord-in-sharepoint-office-365-programmatically-using-c-csom/


3. A sample of a file's field values (or properties):


[ID, 1638][ContentTypeId, 0x010100A5FD4705EF695745935DCFF362D96FD9002FFDDFEEE3A428488245399665244602][Created, 31/01/2020 3:55:24 AM][Author, Microsoft.SharePoint.Client.FieldUserValue][Modified, 31/01/2020 3:55:24 AM][Editor, Microsoft.SharePoint.Client.FieldUserValue][_HasCopyDestinations, ][_CopySource, ][_ModerationStatus, 3][_ModerationComments, ][FileRef, /sites/ourbriefings-test/Archive001/RequestDocuments/BAC-100/ArchiveFlagNHN-2020-01-31.txt][FileDirRef, /sites/ourbriefings-test/Archive001/RequestDocuments/BAC-100][Last_x0020_Modified, 2020-01-31T03:55:24Z][Created_x0020_Date, 2020-01-31T03:55:24Z][File_x0020_Size, 11228][FSObjType, 0][SortBehavior, Microsoft.SharePoint.Client.FieldLookupValue][CheckedOutUserId, Microsoft.SharePoint.Client.FieldLookupValue][IsCheckedoutToLocal, 0][CheckoutUser, Microsoft.SharePoint.Client.FieldUserValue][FileLeafRef, ArchiveFlagNHN-2020-01-31.txt][UniqueId, df9fe88c-4a14-47ca-a8ae-20bbcfc2a680][SyncClientId, Microsoft.SharePoint.Client.FieldLookupValue][ProgId, ][ScopeId, {8024A1D9-532B-4461-BF67-F2A53DE8A3B9}][VirusStatus, Microsoft.SharePoint.Client.FieldLookupValue][CheckedOutTitle, Microsoft.SharePoint.Client.FieldLookupValue][_CheckinComment, ][Modified_x0020_By, i:0#.f|membership|anthony.nguyen@an.com][Created_x0020_By, i:0#.f|membership|anthony.nguyen@an.com][File_x0020_Type, txt][HTML_x0020_File_x0020_Type, ][_SourceUrl, ][_SharedFileIndex, ][MetaInfo, SendEmailToAuthors:SW|Send Emailvti_parserversion:SR|16.0.0.19708vti_previewinvalidtime:TX|31 Jan 2020 03:55:22 -0000vti_author:SR|i:0#.f|membership|anthony.nguyen@an.comvti_dbschemaversion:SR|16.0.204.0vti_sprocsschemaversion:SR|16.0.452.0CBSStatus:SW|DraftIconOverlay:SW||txt|lockoverlay.pngecm_ItemDeleteBlockHolders:SW|ecm_InPlaceRecordLockvti_writevalidationtoken:SW|GQIq0B5WkD/F3Wg7yUVPfqvtYLk=DocumentSetDescription:SW|vti_modifiedby:SR|i:0#.f|membership|anthony.nguyen@an.comecm_RecordRestrictions:SW|BlockDelete, BlockEditvti_foldersubfolderitemcount:IR|0ContentTypeId:SW|0x010100A5FD4705EF695745935DCFF362D96FD9002FFDDFEEE3A428488245399665244602ecm_ItemLockHolders:SW|ecm_InPlaceRecordLockvti_folderitemcount:IR|0_vti_ItemDeclaredRecord:SW|2020-01-30T19:56:26Z_vti_ItemHoldRecordStatus:IW|273HideFromDelve:BW|true][_Level, 2][_IsCurrentVersion, True][ItemChildCount, 0][FolderChildCount, 0][Restricted, ][OriginatorId, ][NoExecute, 0][ContentVersion, 1][_ComplianceFlags, ][_ComplianceTag, ][_ComplianceTagWrittenTime, ][_ComplianceTagUserId, ][BSN, Microsoft.SharePoint.Client.FieldLookupValue][_ListSchemaVersion, ][_Dirty, 0][_Parsable, 0][_StubFile, 0][AccessPolicy, 0][_VirusStatus, ][_VirusVendorID, ][_VirusInfo, ][_CommentFlags, ][_CommentCount, ][_LikeCount, ][_RmsTemplateId, ][_IpLabelId, ][_DisplayName, ][_IpLabelAssignmentMethod, ][AppAuthor, ][AppEditor, ][SMTotalSize, Microsoft.SharePoint.Client.FieldLookupValue][SMLastModifiedDate, 2020-01-31T03:56:27Z][SMTotalFileStreamSize, 11228][SMTotalFileCount, Microsoft.SharePoint.Client.FieldLookupValue][owshiddenversion, 2][_UIVersion, 1][_UIVersionString, 0.1][InstanceID, ][Order, 163800][GUID, f5cb7fe8-1bc2-4a25-b164-614d2feb94d4][WorkflowVersion, 1][WorkflowInstanceID, ][ParentVersionString, Microsoft.SharePoint.Client.FieldLookupValue][ParentLeafName, Microsoft.SharePoint.Client.FieldLookupValue][DocConcurrencyNumber, 2][ParentUniqueId, {E14CB12D-6970-45C6-8452-8B2C50A6F25F}][StreamHash, 0x0219022AD01E56903FC5DD683BC9454F7EABED60B9][ComplianceAssetId, ][Title, ][TemplateUrl, ][xd_ProgID, ][xd_Signature, ][_ShortcutUrl, ][_ShortcutSiteId, ][_ShortcutWebId, ][_ShortcutUniqueId, ][CBSStatus, Draft][CBSDocComments, ][CBSDueBy, ][CBSDocType, ][CBSFileName, ][CBSReviewersContributors, ][SendEmailToAuthors, Send Email][RequestID, ][DocumentSetDescription, ][Send_x0020_Email_x0020_To_x0020_Reviewer, ][Update_x0020_Request_x0020_Number, ][UpdateDo, ][UpdateNe, ][MediaServiceMetadata, ][MediaServiceFastMetadata, ][Send_x0020_Email_x0020_To_x0020_Reviewer_x0028_1_x0029_, ][Update_x0020_Request_x0020_number0, ][UpdateDo0, ][UpdateNe0, ][MediaServiceAutoTags, ][MediaServiceOCR, ][Document_x0020_Status, ][UploadedBy, ][CBSDocumentType, ][CBSAuthor, ][CBSComments, ][CBSDocStatus, ][CBSDocDueDate, ][CBSSendToAuthor, ][CBSRepeaterDocID, ][FileUpdate, ][MediaServiceDateTaken, ][SharedWithUsers, ][SharedWithDetails, ][MediaServiceGenerationTime, ][MediaServiceEventHashCode, ][RequestTitle, ][TaskDueDate, ][Status, ][MediaServiceLocation, ][HideFromDelve, True][RequestNumber, ][RequestNumber_x003a_Current_x0020_Status, ][_vti_ItemDeclaredRecord, 30/01/2020 8:56:26 AM][_vti_ItemHoldRecordStatus, 273]





Monday, 2 December 2019

SharePoint Online - Azure WebJob

A - OBJECTIVE: to schedule a timer job for SharePoint Online using Azure App Services.

B - PROBLEMS :

In SharePoint Online, we need to schedule a "timer job" without any server or Virtual Machines, and Azure WebJob is the best option to schedule a SharePoint task to run automatically based on a pre-defined schedule.

C - SOLUTION:

High-level approach:
  1. Download & install Visual Studio (to create a Console Application .NET Framework)
  2. Subscribe to Azure App Services to enable the feature
  3. Develop a console application (.NET Framework) using C# to programmatically manipulate the SharePoint list and library using CSOM.
  4. Publish the solution to Azure
  5. Schedule a CRON job.




D - SOURCE CODE:

The following details are to create a sample:  

1. In the newly created project, right-click to select "Manage NuGet Packages...", then add the package "AppForSharePointOnlineWebToolkit", and ensure that the 2 files "SharePointContext.cs" and "TokenHelper.cs" is generated automatically in the project.






2. Configure all configurable keys in the file App.config




3. Set up a connection from the console application to SharePoint Online: reference to Microsoft Dev #1 below.

4. To query a large list (more than 5,000 items):

        private static List<ListItem> LoadLargeList(ClientContext context, string listName)
        {
            List loadedList = context.Web.Lists.GetByTitle(listName);
            context.Load(loadedList);
            context.ExecuteQuery();

            var listItemCollection = new List<ListItem>();
            ListItemCollectionPosition position = null;

            do
            {
                CamlQuery camlQuery = new CamlQuery();
                camlQuery.ViewXml =
                    @"<View Scope='Recursive'>
                        <Query></Query>
                        <RowLimit>5000</RowLimit>
                    </View>";
                camlQuery.ListItemCollectionPosition = position;

                ListItemCollection listItems = loadedList.GetItems(camlQuery);
                context.Load(listItems);
                context.ExecuteQuery();

                position = listItems.ListItemCollectionPosition;

                foreach(ListItem item in listItems)
                {
                    listItemCollection.Add(item);
                }
            } 
            while (position != null);

            return listItemCollection;

        }

5. To get all files in a document library which has many folders:

                        //handle the Document Library
                        FolderCollection allRequestDocSets = context.Web
                            .GetFolderByServerRelativeUrl(ConfigurationManager.AppSettings["SPLibRequestDocsRelativeURL"])
                            .Folders;

                        context.Load(allRequestDocSets);
                        context.ExecuteQuery();

                        int countArchivedDocSets = 0;
                        Global.allArchivedFiles = new List<File>();

                        foreach (Folder docset in allRequestDocSets)
                        {
                            //Console.WriteLine("DocSet Processing : " + docset.Name);

                            if (!String.IsNullOrEmpty(docset.Name) && docset.Name.Split('-').Length == 2)
                            {
                                int requestID = Int32.Parse(docset.Name.Split('-')[1].Trim());
                                if (archivedIDs.Contains(requestID))
                                {
                                    countArchivedDocSets++;
                                    context.Load(docset.Files);
                                    context.ExecuteQuery();
                                    FileCollection archivedFileCollection = docset.Files;
                                    foreach (File file in archivedFileCollection)
                                    {
                                        Global.allArchivedFiles.Add(file);
                                    }
                                }
                            }

                        }

6. The console application can be published directly to Azure App Service



7. Lastly, you can use App Service Editor to modify the schedule




Note: a license is required to schedule a webjob.

REFERENCE:

1. Microsoft Dev: 
https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/getting-started-with-building-azure-webjobs-for-your-office365-sites

2. CSOM: https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-client-library-code

Thursday, 20 December 2018

SharePoint Online - Custom Applications & Forms with React


A - OBJECTIVE: to highlight several important notes required for custom developments at SharePoint Online using React

1. Useful third-party products: Nintex Forms (limited) and Nintex Workflows for Office 365

2. Useful framework & libraries

  • React (with the concept of components, which can be rendered as a control, a section, or a whole webpart).
  • State management with Mobx (or Redux): Mobx is preferred because the custom application at SharePoint Online is not a large-scaled application, and Mobx is more straightforward.
  • Form controls (e.g. People Picker, Textbox, etc): Office UI Fabric React/Angular can be considered together with PnP SPFx Controls.
  • Data Create/Read/Edit/Delete actions: SharePoint PnP Framework is a good option, or you can write your own ajax API calls (reference here).

3. Visual Studio Code is recommended as a code editor to develop custom applications.

Note: SharePoint 2010/2013 Designer Workflow (free of charge) can be used to some extent (apart from the commercial Nintex workflow) if you want to trigger special action automatically (e.g. send email).


B - PROBLEMS & SOLUTIONS:

To list all potential or encountered technical errors or operational issues:

1. Nintex Forms: if your form has a number of controls (e.g. > 30 controls) and business rules (e.g. > 50 rules), Nintex Forms will probably take about 10+ seconds to load as at December 2018 (hopefully Nintex will improve this matter in future). Therefore, a custom form (e.g. using React) is a good alternative.

2. Library Version: it is recommended to fix the UI Fabric version (in package.json) because the automatically updated version can lead to a conflict in your control code later.

e.g. npm install mobx@3.1.2 --save









3. Real-time Code Error Notification: you should always run gulp serve in the terminal so that the code editor (i.e. Visual Studio Code) can highlight any error immediately soon after you save the code.  

4. Set State (default React webpart) does not support multiple setState in the default React webpart (i.e. only the first setState call takes place). Therefore, we need to use an additional library (i.e. Mobx) to address this matter.

5. Caching (PnP Caching) can be simply used by adding .usingCaching() in the PnP functions and this temporary data can be saved in either local storage (i.e. local caching - to store all configuration data) or session (to store user credentials). However, this caching can cause an issue if the form needs to refresh data frequently (e.g. cascading dropdown list may not be updated as expected).
.

C - DEVELOPMENT & DEBUGGING:

Debugging:

a. React Extension is available at Chrome and is useful to debug the Typescript files.



b. Hosted Workbench can be configured to run and test your code at SharePoint Online workbench (separated from the deployed solution):


c. Debugging can be done from the code editor (i.e. simple mark the breakpoint and use F5):


Development:

1. Reusable modules (e.g. repeater, custom cascading dropdown, etc) should be packaged as a component which will used in the main component.

2. All declared and dependent libraries used in your code can be installed once using the command npm install in the integrated terminal.

3. When Mobx is used, the tag @action must be added if an observable object/variable is updated to keep track of the observable item.

4. ReactDOM is a useful library to manipulate DOM elements in React approach:



5. Real-time value update for a certain control in the form requires a React function componentDidMount():


Note: this React summary is useful as a reference.

D - DEPLOYMENT: 

1. During production deployment, it is best to clean the package to generate a small solution 



2. The solution is packaged as follows in the Terminal:
gulp bundle --ship
(wait)
gulp package-solution --ship


3. The SharePoint solution package .sppkg must be deployed to the library sites/AppCatalog and all users who use the solution must have the access right to the AppCatalog.



Friday, 27 April 2018

SharePoint Framework (SPFx) Introduction

A - OBJECTIVE: 

This article is to provide a summary of Microsoft guidelines about SharePoint Framework for developers at SharePoint Online (SPO).

B - PREPARATION :

           I. Installation: 

To prepare for the development you will need: 

1. A SharePoint Online tenant: developers can request for a 1-year trial at Office 365 (including SPO) at this link

2. SharePoint Online Management Shell: to be installed to your laptop to connect to SPO and run Powershell scripts that can automate your tasks.

3. Visual Studio Code (Free): a kind of development tool for your custom web-parts & extensions.

           II. Programming Language: 

Moving forwards, to develop custom solutions at SPO, Typescript (a superset of Javascript) is the main programming language you should get yourself familiar with.

           III. Deployment: 

Option 1 - to troubleshoot the code and work on the development at local browser (link here). 

Option 2 - to deploy the custom solutions (webparts or extensions) to SPO (link here).

Note:

* The deployment should be done via Command Prompt, for example:
gulp trust-dev-certgulp serve --nobrowsergulp bundle --shipgulp package-solution --ship

* Apart from the deployed package, you can host the associated files (e.g. css or js) to an Office 365 Content Delivery Network CDN (e.g. for webpart at this link here , or for extension at this link here), or Azure CDN (link here).

C - MAIN POINTS:

The custom solutions (webpart or extension) are designed into several blocks as follows:




1. Configuration: it's basically first level of a webpart design where you can preconfigure (link here) or validate the webpart properties (link here).

2. Properties: including the required settings for the webpart/extension properties

  • *.manifest.json: to specify the default values of the properties
  • interface NameWebpartProps
  • protected getPropertyPaneConfiguration

3. Resources: such as language settings (example of a localised webpart), or styling

  • mystring.d.ts
  • en-us.js
  • NameWebpart.Module.scss
4. Main Content: the function to render the webpart/extension content.

5. External Libraries:
     - A detailed guide is at this link.
     - External JS frameworks: must be installed to the solution using CMD (e.g. npm install --save jqueryui). 

In code view, we have these blocks as follows:




Let's go through some Microsoft tutorials here:

           I. Webparts:

1. Properties: 

- Webparts are allowed to be configurable (link here), and webpart icon can be updated.

- SharePoint content can be pre-loaded to the webpart properties (link here), or you can have a cascading dropdown among the properties (link here).

2. Javascript frameworks: Developing on top of other Javascript frameworks (e.g. jQuery, AngularJS, etc) is possible:

  • jQuery:
    • To incorporate UI to the webpart content (e.g. jQuery UI Accordion - link here).
    • DataTables (link here): to build powerful data overviews of data from SPO & external APIs.
    • FullCalendar (link here): to display data in a calendar view.
  • AngularJS: 
    • To migrate AngularJS to SPFx: https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/migrate-angular-1-x-applications-to-sharepoint-framework
    • To develop a custom AngularJS application at SPO: https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/build-client-side-web-parts-with-angular-1-x
  • JSOM: the example used here loads information about SPO lists in the current site after selecting a button.

3. Connected webparts: Client-side webparts can share data between each other (link here).

           II. Extensions: 

As of April 2018, there are 3 types of Extensions:

  • Application Customizer: e.g. to extend or change the GUI of a SPO site (link here).
  • Field Customizer: e.g. to customise the display of a column in a SPO list (link here), with an example of migration project here.
  • ListView Command Set (aka Context Menu): e.g. to add an additional command to the list menu (link here), with an example of migration project here.

Similar to webparts, extensions have icons which can be customised (link here).


D - USEFUL RESOURCE: 

1. SPFx Microsoft https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant

2. SharePoint Online Powershell scripts (useful functions): http://www.sharepointfire.com/2016/01/get-sharepoint-online-web-templates-powershell/

3. Typescript Key Notes: https://blog.mariusschulz.com/series/typescript-evolution