Pages

Wednesday, May 10, 2017

Convert uploaded file to array buffer


I would like to share some code snippet which will convert uploaded file to array buffer which we used mostly when upload something to SharePoint using JavaScript. Below is the code snippet for conversion,

var imageAsArrayBuffer;

//Get files from upload control 
var files = document.getElementById("picturefile").files;

fileData = new Blob([files[0]]);
var promise = new Promise(getBuffer);
promise.then(function(data) {       
     imageAsArrayBuffer = data;
}).catch(function(err) {
       alert('Error: ',err);
});

function getBuffer(resolve) {
var reader = new FileReader();
reader.readAsArrayBuffer(fileData);
reader.onload = function() {
 var arrayBuffer = reader.result
 //var bytes = new Uint8Array(arrayBuffer);
 resolve(arrayBuffer);
}

}

SharePoint Online - Update current user profile picture using JavaScript


I would like to share my recent experience to update current logged-in user profile picture programmatically using SharePoint OOTB REST API service SetMyProfilePicture as shown in below code example,

function setProfilePicture(imageAsArrayBuffer)
{
var output = false;
    var endpoint = _spPageContextInfo.webAbsoluteUrl + "/_api/SP.UserProfiles.PeopleManager/SetMyProfilePicture";    
    $.when($.ajax({
        url: endpoint,
type: "POST",
data: imageAsArrayBuffer,
processData: false,
headers: {
   "accept": "application/json;odata=verbose",
   "X-RequestDigest": $("#__REQUESTDIGEST").val(),
   "content-length": imageAsArrayBuffer.byteLength
},
success: function (data) {
alert("picture uploaded!");
},
error: function (data) {  
}
    })).done(function(data) {        
    });
    return output;
}

Need to convert the uploaded image to array buffer and provide it to data property of rest api service. Please search my blog to convert uploaded image to array buffer.

SharePoint Online - Update user profile properties using JavaScript


As SharePoint Online allows only JavaScript based code to do any updates, below example will show the way to update SharePoint Online user profile properties from site using SharePoint JavaScript object modal,

function startUpdate(){
          SP.SOD.executeFunc("sp.js", "SP.ClientContext", function(){
SP.SOD.registerSod("sp.userprofiles.js", SP.Utilities.Utility.getLayoutsPageUrl("sp.userprofiles.js"));
SP.SOD.executeFunc("sp.userprofiles.js", "SP.UserProfiles.PeopleManager", updateUserProfile);
});
}

var userProfileProperties;
function updateUserProfile(){
    //Get Current Context
    var clientContext = SP.ClientContext.get_current();
   
    //Get Instance of People Manager Class
    var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
   
    //Get properties of the current user
    userProfileProperties = peopleManager.getMyProperties();
   
    //Get only the accountname instead of all the properties.
    clientContext.load(userProfileProperties, "AccountName");
   
    //Execute the Query.
    clientContext.executeQueryAsync(function(){
    var currentUserAccountName = userProfileProperties.get_accountName();

    //Couple of properties for example
peopleManager.setSingleValueProfileProperty(currentUserAccountName, "CellPhone", mval);
peopleManager.setSingleValueProfileProperty(currentUserAccountName, "SPS-HireDate", hval);
//Birthday date format must be month name & date (October 19)
peopleManager.setSingleValueProfileProperty(currentUserAccountName, "SPS-Birthday", bval);
   
clientContext.executeQueryAsync(function(){
alert("Updated!");
},
function(sender,args){
alert(args.get_message());
});
   
    }, function(sender,args){
alert(args.get_message());
});
}

Powershell to sync exchange online to SharePoint Profiles


This articles talks about steps to update data from exchange online to SharePoint Online user profiles. Below script will do below steps part of sync,

1. Connect to Exchange Online by opening session.
2. Connect to SharePoint Online Admin Centre
3. Connect to SharePoint Online site collection. As SharePoint Online allows update to User Profiles through site collection.
4. Read through each profile from exchange online and will try to find the user available in SharePoint Online user profiles.
5. If user profile available, it will update.

Below script sample retrieving mobile number from exchange online and update to SharePoint Online user profiles,

Import-Module 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll'
Import-Module 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll'

#Admin User Principal Name
$admin = <admin email address>

#Get Password as secure String
$password =  convertto-securestring <Password of above admin account> -asplaintext -force

#Authenticate
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $admin, $password

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $credentials -Authentication Basic -AllowRedirection
Import-PSSession $Session
$Users = Get-User -ResultSize unlimited -RecipientType UserMailbox
$Users.Count

#Mysite URL
$site = 'https://<SharePoint Online Domain>-admin.sharepoint.com/' # This needs to be the "admin" site.
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin,$password)
#Get the Client Context and Bind the Site Collection
$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$context.Credentials = $Creds

#Create an Object [People Manager] to retrieve profile information
$people = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($context)

$siteurl = 'https://<SharePoint Online Domain>.sharepoint.com/'
$sitecontext = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
$sitecontext.Credentials = $Creds

ForEach($User in $Users)
{
    $userprofile = $people.GetPropertiesFor("i:0#.f|membership|" + $User.UserPrincipalName)
    $context.Load($userprofile)
    $context.ExecuteQuery()

    $mobileno = Get-User $User.UserPrincipalName | fl MobilePhone | Out-String
    if($mobileno.ToString().Trim().Length -gt 13)
    {
        $people.SetSingleValueProfileProperty("i:0#.f|membership|" + $User.UserPrincipalName,"CellPhone", $mobileno.ToString().Trim().Substring(14))
        $context.ExecuteQuery()        
    }        
}


SharePoint Online Current User Properties


As SharePoint Online will not allow any server side code, we have to depend on SharePoint JavaScript Client Side Object Modal. We may not have all the features we get at server side but now a days Microsoft enhancing the SharePoint Client object modal a lot to support most the things while work lists, libraries, items, documents and user profiles.

There is one global object available while working with JavaScript in SharePoint Online and that is _spPageContextInfo. You can access all current logged in user related properties as mentioned below,

Display Name - _spPageContextInfo.userDisplayName
User Id - _spPageContextInfo.userId
Email - _spPageContextInfo.userEmail
Login Name - _spPageContextInfo.userLoginName
Is site admin - _spPageContextInfo.isSiteAdmin

Also current site details,

Current site collection URL - _spPageContextInfo.siteAbsoluteUrl
Current Site collection relative URL - _spPageContextInfo.siteServerRelativeUrl
Current web site relative URL - _spPageContextInfo.webServerRelativeUrl
Current web site URL - _spPageContextInfo.webAbsoluteUrl
Current Site Culture name - _spPageContextInfo.currentCultureName
Current Site Language LCID - _spPageContextInfo.currentLanguage

SharePoint Online Search Content Crawling


From my experience about search crawling/indexing of SharePoint Online content after add/update/delete content in to lists/libraries. Usually SharePoint Online takes up to 15 min. time to crawl the content to make it available in search results. This time may increase based on content size of the site which will take to process them part of continuous crawling. Office 365 & SharePoint Online not provided any explicit option to start the crawl by end users and that will be maintained by Microsoft.

Also couple of things related to search in SharePoint Online below for developers who do not have idea,

1. We can use custom site columns data part of search result. SharePoint Online creates crawled properties of site columns by default and only we need to map them with managed properties. Go to site settings --> Site Collection Administration --> Search Schema, click on crawled properties and search with your site column, that will be appeared in the results and you can map that with managed property. After couple of hours, the managed property become available to use in search display templates.



2. Refiner/Sort - To refine/filter or sort search results based on particular site column, cannot do with our own managed properties. There are predefined managed properties available and those are started with Refinable (with different data types). These managed properties will be available to filter/sort when we use content search web part and search results web part. Only we need to map crawled properties to it.


Tuesday, May 9, 2017

Create a publishing page using custom page layout programmatically


Recently, I have got requirement to create a publishing page programmatically using JavaScript in SharePoint Online. Below are the steps details and example code snippet,

function createPage(){
$.getScript(_spPageContextInfo.webServerRelativeUrl + "/_layouts/15/" + "SP.Publishing.js", function(){
SP.UI.ModalDialog.showWaitScreenWithNoClose("Creating Page", "Please wait");    
   clientContext = new SP.ClientContext.get_current();  
   oSite = clientContext.get_site();
   oWeb = oSite.get_rootWeb();  

            //Get the client context,web and list object of Master Page Gallery
   var oList = oWeb.get_lists().getByTitle('Master Page Gallery');  

   //Get the page layout by ID using which we will create a publishing page       
   pageLayoutitem = oList.getItemById(pagelayoutid); 

   clientContext.load(oWeb); 
   clientContext.load(pageLayoutitem);  
   clientContext.executeQueryAsync(QuerySuccess, QueryFailure);
    });
}
function QuerySuccess() {  
    //Create Publishing Page using PublishingPageInformation object   
    var curContext = new SP.ClientContext.get_current(); 
    var cWeb = curContext.get_web();
    var newPublishingPage = SP.Publishing.PublishingWeb.getPublishingWeb(curContext, cWeb);  
    var pageInfo = new SP.Publishing.PublishingPageInformation();  
    pageInfo.set_name("sample.aspx");  
   
    pageInfo.set_pageLayoutListItem(pageLayoutitem);  
    newPage = newPublishingPage.addPublishingPage(pageInfo);  
    //Load the new page object to the client context   
    clientContext.load(newPage);  
    clientContext.executeQueryAsync(SecondQuerySuccess, SecondQueryFailure);  
}  

function QueryFailure(sender, args) {  
    console.log('Request failed' + args.get_message());
    SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.Cancel);
    alert("Something went wrong, refresh and try again");  
}  

function SecondQuerySuccess(sender, args) {  
    console.log("Publishing page created successfully.");
    var pageItem = newPage.get_listItem();
        pageItem.get_file().checkIn("", 0);
        clientContext.load(pageItem);
        clientContext.executeQueryAsync(function () {
            //Open publishing page which is created     
    window.open(pageItem.get_item('FileRef'), '_blank');
   }, SecondQueryFailure);
        }, Function.createDelegate(this, SecondQueryFailure));       
}  
function SecondQueryFailure(sender, args) {  
    SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.Cancel);
     alert("Something went wrong, refresh and try again");
}

Make sure SP.Publishing.js file loaded before execute above script.