Corporate Directory/People Directory with SharePoint Search

Let’s look at how to create the corporate directory for SharePoint Search in this post. When we need to look for users across the entire firm, this will be helpful.

1. Copy the below HTML to the notepad and name it Item_Person_Custom.html

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> 
<head>
<title>People Item (Custom)</title>

<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:MasterPageDescription msdt:dt="string">Displays a result tailored for a person.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#SearchResults;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
<mso:CrawlerXSLFile msdt:dt="string"></mso:CrawlerXSLFile>
<mso:ManagedPropertyMapping msdt:dt="string">'WorkPhone':'WorkPhone','MobilePhone':'MobilePhone','AboutMe':'AboutMe','AccountName':'AccountName','BaseOfficeLocation':'BaseOfficeLocation','Department':'Department','HitHighlightedProperties':'HitHighlightedProperties','Interests':'Interests','JobTitle':'JobTitle','LastModifiedTime':'LastModifiedTime','Memberships':'Memberships','PastProjects':'PastProjects','Path':'Path','PictureURL':'PictureURL','PreferredName':'PreferredName','Responsibilities':'Responsibilities','Schools':'Schools','ServiceApplicationID':'ServiceApplicationID','SipAddress':'SipAddress','Skills':'Skills','UserProfile_GUID':'UserProfile_GUID','WorkEmail':'WorkEmail','WorkId':'WorkId','YomiDisplayName':'YomiDisplayName'</mso:ManagedPropertyMapping>
<mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded>
<mso:HtmlDesignStatusAndPreview msdt:dt="string">http://test.schneck.com/sites/search/_catalogs/masterpage/Display Templates/Search/Item_Person_FPS.html, Conversion successful.</mso:HtmlDesignStatusAndPreview>
<mso:HtmlDesignPreviewUrl msdt:dt="string"></mso:HtmlDesignPreviewUrl>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<body>
    <div id="Item_Person">
<!--#_ 
                    if(!$isNull(ctx.CurrentItem) && !$isNull(ctx.ClientControl)){
                        var id = ctx.ClientControl.get_nextUniqueId();
                        var itemId = id + Srch.U.Ids.item;
                        var hoverId = id + Srch.U.Ids.hover;
                        $setResultItem(itemId, ctx.CurrentItem);
                        var container_id = id + "_peopleContainer";
                        var hhProps = Srch.U.createXMLDocument("<root>" + ctx.CurrentItem.HitHighlightedProperties + "</root>");
                        var encodedPath = $urlHtmlEncode(ctx.CurrentItem.Path);
                        var has_pn = !$isEmptyString(ctx.CurrentItem.PreferredName);
                        var has_sip = !$isEmptyString(ctx.CurrentItem.SipAddress);
                        var has_email = !$isEmptyString(ctx.CurrentItem.WorkEmail);
                        var has_jt = !$isEmptyString(ctx.CurrentItem.JobTitle);
                        var has_dp = !$isEmptyString(ctx.CurrentItem.Department);
                        var has_abme = !$isEmptyString(ctx.CurrentItem.AboutMe);
                        var has_resp = !$isEmptyString(ctx.CurrentItem.Responsibilities);
                        var has_pp = !$isEmptyString(ctx.CurrentItem.PastProjects);
                        var has_ski = !$isEmptyString(ctx.CurrentItem.Skills);
                        var has_sch = !$isEmptyString(ctx.CurrentItem.Schools);
                        var has_int = !$isEmptyString(ctx.CurrentItem.Interests);
                        var has_vlm = !$isEmptyString(ctx.CurrentItem.ProfileViewsLastMonth);
                        var has_vlw = !$isEmptyString(ctx.CurrentItem.ProfileViewsLastWeek);
                        var has_query = !$isEmptyString(ctx.CurrentItem.ProfileQueriesFoundYou); 
                        var isSelfSrch = (has_vlm == true || has_vlw == true || has_query == true);
                        var delimiter = "";
                        var userPersonaId = $htmlEncode(id) + "_peopleUserPersona";
                        var uSip = ctx.CurrentItem.SipAddress;
                        var uEmail = ctx.CurrentItem.WorkEmail;
                        var uName = ctx.CurrentItem.PreferredName;
                        var uPicUrl = ctx.CurrentItem.PictureURL;
                        var hoverUrl = "~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Person_HoverPanel.js";
_#-->
                        <div id="_#= $htmlEncode(container_id) =#_" class="ms-srch-people-outerContainer ms-srch-resultHover">
                            <div id="_#= $htmlEncode(itemId) =#_" name="Item" class="ms-srch-people-item" onmouseover="EnsureScriptParams('SearchUI.js', 'HP.Init', event, '_#=$scriptEncode(itemId) =#_', '_#=$scriptEncode(hoverId) =#_', '_#=$scriptEncode(hoverUrl) =#_');" onmouseout="EnsureScriptParams('SearchUI.js', 'HP.Hide');">
                            <div id="_#= $htmlEncode(hoverId) =#_" class="ms-srch-hover-outerContainer"></div>
                                <div id="UserPersonaContainer">
                                    <div id="UserPersona">
                                        <div id="_#= userPersonaId =#_"></div>
                                    </div>
                                </div>
                                <div id="UserInfoContainer">
                                    <div id="ContactInfo">
                                        <div id="NameField">
<!--#_ 
                                            var encodedName = (has_pn == true) ? $htmlEncode(ctx.CurrentItem.PreferredName) : $htmlEncode(ctx.CurrentItem.YomiDisplayName);
                                            var displayName = Srch.U.getSingleHHXMLNodeValue(hhProps, "preferredname");
                                            if ($isEmptyString(displayName)) { displayName = encodedName }
_#-->
                                            <div id="NameValue" class="ms-srch-ellipsis ms-textLarge">
                                                <a clicktype="Result" id="NameFieldLink" href="_#= encodedPath =#_" title="_#= encodedName =#_">_#= displayName =#_</a>
                                            </div>
                                        </div>
<!--#_ 
                                        if(has_jt == true) {
_#-->
                                            <div id="JobTitleField">
<!--#_ 
                                                var encodedJtitle = $htmlEncode(ctx.CurrentItem.JobTitle);
                                                var displayJtitle = Srch.U.getSingleHHXMLNodeValue(hhProps, "jobtitle");
                                                if ($isEmptyString(displayJtitle)) { displayJtitle = encodedJtitle }
_#--> 
                                                <div id="JobTitleValue" class="ms-srch-ellipsis" title="_#= encodedJtitle =#_"> _#= displayJtitle =#_ </div>
                                            </div>
<!--#_ 
                                        }
_#-->
<!--#_ 
                                        if(has_dp == true) {
_#-->
                                            <div id="DepartmentField">
<!--#_ 
                                                var encodedDept = $htmlEncode(ctx.CurrentItem.Department);
                                                var displayDept = Srch.U.getSingleHHXMLNodeValue(hhProps, "department");
                                                if ($isEmptyString(displayDept)) { displayDept = encodedDept }
_#--> 
                                                <span class="label">Dept:</span><div id="DepartmentValue" class="ms-srch-ellipsis" title="_#= encodedDept =#_"> _#= displayDept =#_ </div>
                                            </div>
<!--#_ 
                                        }
_#-->

<!--#_ 
										var hasLocation = !$isEmptyString(ctx.CurrentItem.BaseOfficeLocation);
                                        if(hasLocation == true) {
_#-->
                                            <div id="LocationField">
<!--#_ 
                                                var encodedLocation = $htmlEncode(ctx.CurrentItem.BaseOfficeLocation);
                                                var displayLocation = Srch.U.getSingleHHXMLNodeValue(hhProps, "baseofficelocation");
                                                if ($isEmptyString(displayLocation)) { displayLocation = encodedLocation }
_#--> 
                                                <span class="label">Office:</span><div id="LocationValue" class="ms-srch-ellipsis" title="_#= encodedLocation =#_"> _#= displayLocation =#_ </div>
                                            </div>
<!--#_ 
                                        }
_#-->

<!--#_ 
										var hasWorkPhone = !$isEmptyString(ctx.CurrentItem.WorkPhone);
                                        if(hasWorkPhone == true) {
_#-->
                                            <div id="WorkPhoneField">
<!--#_ 
                                                var encodedWorkPhone = $htmlEncode(ctx.CurrentItem.WorkPhone);
                                                var displayWorkPhone = Srch.U.getSingleHHXMLNodeValue(hhProps, "workphone");
                                                if ($isEmptyString(displayWorkPhone)) { displayWorkPhone = encodedWorkPhone }
_#--> 
                                                <span class="label">Work Phone:</span><div id="WorkPhoneValue" class="ms-srch-ellipsis" title="_#= encodedWorkPhone =#_"> _#= displayWorkPhone =#_ </div>
                                            </div>
<!--#_ 
                                        }
_#-->


<!--#_ 
										var hasMobilePhone = !$isEmptyString(ctx.CurrentItem.MobilePhone);
                                        if(hasMobilePhone == true) {
_#-->
                                            <div id="MobilePhoneField">
<!--#_ 
                                                var encodedMobilePhone = $htmlEncode(ctx.CurrentItem.MobilePhone);
                                                var displayMobilePhone = Srch.U.getSingleHHXMLNodeValue(hhProps, "mobilePhone");
                                                if ($isEmptyString(displayMobilePhone)) { displayMobilePhone = encodedMobilePhone }
_#--> 
                                                <span class="label">Mobile Phone:</span><div id="MobilePhoneValue" class="ms-srch-ellipsis" title="_#= encodedMobilePhone =#_"> _#= displayMobilePhone =#_ </div>
                                            </div>
<!--#_ 
                                        }
_#-->


<!--#_ 
										var hasWorkEmail = !$isEmptyString(ctx.CurrentItem.WorkEmail);
                                        if(hasWorkEmail == true) {
_#-->
                                            <div id="WorkEmailField">
<!--#_ 
                                                var encodedWorkEmail = $htmlEncode(ctx.CurrentItem.WorkEmail);
                                                var displayWorkEmail = Srch.U.getSingleHHXMLNodeValue(hhProps, "workemaile");
                                                if ($isEmptyString(displayWorkEmail)) { displayWorkEmail = encodedWorkEmail }
_#--> 
                                                <span class="label"></span><div id="WorkEmailValue" class="ms-srch-ellipsis" title="_#= encodedWorkEmail =#_"><a href="mailto:_#= encodedWorkEmail =#_"> _#= displayWorkEmail =#_ </a></div>
                                            </div>
<!--#_ 
                                        }
_#-->


                                    </div>
<!--#_ 
                                    if(has_resp == true || has_ski == true || has_pp == true || has_int == true || has_sch == true) {
_#-->
                                        <div id="MoreInfoShort">
<!--#_ 
                                            if(has_resp == true) {
                                                var encodedVal = Srch.U.getMultipleHHXMLNodeValues(hhProps, "responsibilities", 3, delimiter);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Responsibilities, 3, delimiter))}
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <div id="ResponsibilitiesValue" class="ms-srch-ellipsis"> 
                                                        <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Responsibilities) =#_ </span>
                                                        _#= encodedVal =#_ 
                                                     </div>
<!--#_ 
                                                }
_#-->
<!--#_ 
                                            } else if(has_ski == true) {
                                                var encodedVal = Srch.U.getMultipleHHXMLNodeValues(hhProps, "skills", 3, delimiter);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Skills, 3, delimiter))}
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <div id="SkillsValue" class="ms-srch-ellipsis"> 
                                                        <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Skills) =#_ </span>
                                                        _#= encodedVal =#_ 
                                                    </div>
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_pp == true) {
                                                var encodedVal = Srch.U.getMultipleHHXMLNodeValues(hhProps, "pastprojects", 3, delimiter);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.PastProjects, 3, delimiter))}
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <div id="PastProjectsValue" class="ms-srch-ellipsis"> 
                                                        <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_PastProjects) =#_ </span>
                                                        _#= encodedVal =#_ 
                                                    </div>
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_int == true) {
                                                var encodedVal = Srch.U.getMultipleHHXMLNodeValues(hhProps, "interests", 3, delimiter);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Interests, 3, delimiter))}
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <div id="InterestsValue" class="ms-srch-ellipsis"> 
                                                        <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Interests) =#_ </span>
                                                        _#= encodedVal =#_ 
                                                    </div>
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_sch == true){
                                                var encodedVal = Srch.U.getMultipleHHXMLNodeValues(hhProps, "schools", 3, delimiter);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Schools, 3, delimiter))}
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <div id="SchoolsValue" class="ms-srch-ellipsis"> 
                                                        <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Schools) =#_ </span>
                                                        _#= encodedVal =#_ 
                                                    </div>
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } 
_#-->
                                        </div>
<!--#_ 
                                    } 
_#-->
<!--#_ 
                                    if(has_abme == true || has_ski == true || has_pp == true || has_int == true) {
_#-->                                
                                        <div id="MoreInfoLong">
<!--#_ 
                                            if(has_abme == true) {
                                                var encodedVal = Srch.U.getTrimmedProcessedHHXMLString(Srch.U.getSingleHHXMLNodeValue(hhProps, "aboutme"), 125);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getTrimmedString(ctx.CurrentItem.AboutMe, 125)) }
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    _#= encodedVal =#_ 
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_ski == true && has_resp == true) {
                                                var encodedVal = Srch.U.getTrimmedProcessedHHXMLString(Srch.U.getMultipleHHXMLNodeValues(hhProps, "skills", 3, delimiter), 125);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getTrimmedString(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Skills, 3, delimiter), 125)) }
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Skills) =#_ </span> 
                                                    _#= encodedVal =#_ 
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_pp == true && (has_ski == true || has_resp == true)) {
                                                var encodedVal = Srch.U.getTrimmedProcessedHHXMLString(Srch.U.getMultipleHHXMLNodeValues(hhProps, "pastprojects", 3, delimiter), 125);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getTrimmedString(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.PastProjects, 3, delimiter), 125)) }
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_PastProjects) =#_ </span>
                                                    _#= encodedVal =#_ 
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } else if(has_int == true && (has_pp == true || has_ski == true || has_resp == true)) {
                                                var encodedVal = Srch.U.getTrimmedProcessedHHXMLString(Srch.U.getMultipleHHXMLNodeValues(hhProps, "interests", 3, delimiter), 125);
                                                if (Srch.U.e(encodedVal)) { encodedVal = $htmlEncode(Srch.U.getTrimmedString(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.Interests, 3, delimiter), 125)) }
                                                if (!Srch.U.e(encodedVal)) {
_#-->
                                                    <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_Interests) =#_ </span>
                                                    _#= encodedVal =#_
<!--#_ 
                                                } 
_#-->
<!--#_ 
                                            } 
_#-->
                                        </div>
<!--#_ 
                                    } 
_#-->
<!--#_ 
                                    if(isSelfSrch == true) {
_#-->
                                        <hr class="ms-srch-people-item-separator" />
                                        <div id="SelfSearchInfo">
                                            <div id="Heading">
                                                <a id="EditProfileLink" href="_#= $urlHtmlEncode(ctx.CurrentItem.EditProfileUrl) =#_"> _#= $htmlEncode(Srch.Res.item_People_EditProfileLink) =#_ </a>
                                            </div>
                                            <div id="Frequency">
                                                <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_SelfSearchFrequency) =#_ </span>
                                                <ul id="FrequencyCard">
                                                    <li id="MonthlyViews">
<!--#_ 
                                                        var encodedVal = (ctx.CurrentItem.ProfileViewsLastMonth == 1) ? $htmlEncode(String.format(Srch.Res.item_People_SelfSearchFrequency_ViewsMonths_Singular, ctx.CurrentItem.ProfileViewsLastMonth)) : 
                                                            $htmlEncode(String.format(Srch.Res.item_People_SelfSearchFrequency_ViewsMonths_Plural, ctx.CurrentItem.ProfileViewsLastMonth));
_#-->
                                                           _#= encodedVal =#_  
                                                    </li>
                                                    <li id="DailyViews">
<!--#_ 
                                                        var encodedVal = (ctx.CurrentItem.ProfileViewsLastWeek == 1) ? $htmlEncode(String.format(Srch.Res.item_People_SelfSearchFrequency_ViewsWeeks_Singular, ctx.CurrentItem.ProfileViewsLastWeek)) :
                                                            $htmlEncode(String.format(Srch.Res.item_People_SelfSearchFrequency_ViewsWeeks_Plural, ctx.CurrentItem.ProfileViewsLastWeek));
_#-->
                                                        _#= encodedVal =#_  
                                                    </li>
                                                </ul>
                                            </div>
<!--#_ 
                                            if(has_query == true) {
_#-->                                        
                                                <div id="Keywords">
                                                    <span id="FieldTitle" class="ms-soften"> _#= $htmlEncode(Srch.Res.item_People_SelfSearchKeywords) =#_ </span>
<!--#_ 
                                                    var encodedVal = $htmlEncode(Srch.U.getTrimmedString(Srch.U.getUnEncodedMultiValuedResults(ctx.CurrentItem.ProfileQueriesFoundYou, 5, delimiter), 84));
                                                    if (!Srch.U.e(encodedVal)) {
_#-->
                                                        _#= encodedVal =#_
<!--#_ 
                                                    } 
_#-->
                                                </div>    
<!--#_ 
                                            } 
_#-->
<!--#_
                                            if(!Srch.U.n(ctx.CurrentItem.LastModifiedTime))
                                            {
                                                var lastModifiedTime = ctx.CurrentItem.LastModifiedTime;
                                                var encodedLastModifiedTimeId = $htmlEncode(id + "_lastModifiedTime");
                                                AddPostRenderCallback(ctx, function()
                                                {
                                                    Srch.U.renderFriendlyTimeIntervalString(lastModifiedTime, encodedLastModifiedTimeId);
                                                });
_#-->
                                                <div id="LastModifiedTime"> 
                                                    <span class="ms-textSmall">_#= $htmlEncode(Srch.Res.item_People_LastModified) =#_</span>
                                                    <span id="_#= encodedLastModifiedTimeId =#_" class="ms-textSmall ms-srch-ellipsis"></span>
                                                </div>
<!--#_
                                            }
_#-->
                                        </div>
<!--#_ 
                                    } 
_#-->
                                </div> 
                            </div>
                        </div>
<!--#_
                    AddPostRenderCallback(ctx, function(){
                        EnsureScriptFunc("clienttemplates.js", "RenderUserFieldWorker", function() {
                            var getUserPersona = function() {
                                var renderCtx = new ContextInfo();
                                renderCtx.Templates = {};
                                renderCtx.Templates["Fields"] = {};
                                var fieldSchemaData = { "PictureOnly":"1", "PictureSize": "Size_72px"};
                                var listSchema = {"EffectivePresenceEnabled": "1", "PresenceAlt": Srch.Res.item_People_NoPresenceAvailable};
                                var userData = {"title": uName, "email": uEmail, "picture": uPicUrl, "sip": uSip};
                                var personaControlElement = document.getElementById(userPersonaId);
                                if (!Srch.U.n(personaControlElement))
                                {
                                    personaControlElement.innerHTML = RenderUserFieldWorker(renderCtx, fieldSchemaData, userData, listSchema);
                                }
                                if(typeof(ctx.EnqueueImnRequest) == "undefined") { ctx.EnqueueImnRequest = false; }
                                if (ctx.EnqueueImnRequest == false) {
                                    ctx.ClientControl.add_oneTimeResultRendered(function(){ if (typeof(ProcessImn) != "undefined") { ProcessImn(); } });
                                    ctx.EnqueueImnRequest = true;
                                 }
                            };
                            getUserPersona();
                        });
                    });
_#-->                        
<!--#_ 
                } 
_#-->
    </div>
</body>
</html>

2. Copy the above file to the site settings ->master pages and page layouts ->Display templates->Search folder in SharePoint

3. Copy the following CSS and save it as people-search.css under site contents -> style library

.ms-srch-people-outerContainer {
  width: 200px;
  height: 200px;
  display: inline-block;
  border: 1px solid #e1e1e1;
  margin: 0 15px 15px 0;
  padding: 10px;
  vertical-align: top;
}

.ms-srch-people-outerContainer .ms-srch-people-item {
  width: auto;
  padding: 0;
  min-height: none;
  overflow: visible;
}

.ms-srch-people-outerContainer #UserPersonaContainer {
  text-align: center;
  width: 100%;
  margin-bottom: 5px;
}

.ms-srch-people-outerContainer #UserPersonaContainer #UserPersona .ms-table {
  margin: 0 auto;
}

.ms-srch-people-outerContainer #UserInfoContainer {
  width: 100%;
  margin: 0;
  float: none;
}

.ms-srch-people-outerContainer #UserInfoContainer .label {
  font-weight: bold;
  margin: 0 5px 0 0;
  width: auto;
}

.ms-srch-people-outerContainer #UserInfoContainer #NameField {
  text-align: center;
}

.ms-srch-people-outerContainer #UserInfoContainer #NameField a, .ms-srch-people-outerContainer #UserInfoContainer #NameField a:link, .ms-srch-people-outerContainer #UserInfoContainer #NameField a:visited {
  font-size: 18px;
  color: #005a84;
}

.ms-srch-people-outerContainer #UserInfoContainer #NameField a:hover {
  color: #13b5ea;
}

.ms-srch-people-outerContainer #UserInfoContainer #JobTitleField {
  text-align: center;
  font-style: italic;
  padding-top: 0;
}

.ms-srch-people-outerContainer #UserInfoContainer #DepartmentField {
  margin-top: 10px;
}

.ms-srch-people-outerContainer #UserInfoContainer #MobilePhoneField,
.ms-srch-people-outerContainer #UserInfoContainer #MoreInfoShort,
.ms-srch-people-outerContainer #UserInfoContainer #MoreInfoLong,
.ms-srch-people-outerContainer #UserInfoContainer #SelfSearchInfo,
.ms-srch-people-outerContainer #UserInfoContainer
.ms-srch-people-item-separator {
  display: none;
}

.alpha-controls {
  overflow: hidden;
  margin: 10px 0;
}

.alpha-controls .letter {
  float: left;
  min-width: 16px;
  text-align: center;
  margin-right: 10px;
  padding: 6px 10px;
  cursor: pointer;
  background-color: #005a84;
  color: #fff;
  text-transform: uppercase;
}

.alpha-controls .letter:hover, .alpha-controls .letter.active {
  background-color: #13b5ea;
}

Add the CSS reference in Site Settings-> Master page-> Alternate CSS URL from the style library path

4. Copy the below HTML as alpha.html and place it in the same location. site contents->style library

<div class="alpha-controls" id="alpha-controls">
	<div class="letter" id="see-all" onclick="alpha.search('');">See All</div>
	<div class="letter" id="letter-a" onclick="alpha.search('a');">a</div>
	<div class="letter" id="letter-b" onclick="alpha.search('b');">b</div>
	<div class="letter" id="letter-c" onclick="alpha.search('c');">c</div>
	<div class="letter" id="letter-d" onclick="alpha.search('d');">d</div>
	<div class="letter" id="letter-e" onclick="alpha.search('e');">e</div>
	<div class="letter" id="letter-f" onclick="alpha.search('f');">f</div>
	<div class="letter" id="letter-g" onclick="alpha.search('g');">g</div>
	<div class="letter" id="letter-h" onclick="alpha.search('h');">h</div>
	<div class="letter" id="letter-i" onclick="alpha.search('i');">i</div>
	<div class="letter" id="letter-j" onclick="alpha.search('j');">j</div>
	<div class="letter" id="letter-k" onclick="alpha.search('k');">k</div>
	<div class="letter" id="letter-l" onclick="alpha.search('l');">l</div>
	<div class="letter" id="letter-m" onclick="alpha.search('m');">m</div>
	<div class="letter" id="letter-n" onclick="alpha.search('n');">n</div>
	<div class="letter" id="letter-o" onclick="alpha.search('o');">o</div>
	<div class="letter" id="letter-p" onclick="alpha.search('p');">p</div>
	<div class="letter" id="letter-p" onclick="alpha.search('q');">q</div>
	<div class="letter" id="letter-r" onclick="alpha.search('r');">r</div>
	<div class="letter" id="letter-s" onclick="alpha.search('s');">s</div>
	<div class="letter" id="letter-t" onclick="alpha.search('t');">t</div>
	<div class="letter" id="letter-u" onclick="alpha.search('u');">u</div>
	<div class="letter" id="letter-v" onclick="alpha.search('v');">v</div>
	<div class="letter" id="letter-w" onclick="alpha.search('w');">w</div>
	<div class="letter" id="letter-x" onclick="alpha.search('x');">x</div>
	<div class="letter" id="letter-y" onclick="alpha.search('y');">y</div>
	<div class="letter" id="letter-z" onclick="alpha.search('z');">z</div>
</div>

<script>
(function() {

window.alpha = window.alpha || {};

alpha.globals = {
	"alphaControlsId": "alpha-controls",
	"alphaActiveLetterAttr": "data-active-letter"
}

alpha.clearSelectedLetter = function () {
	var alphaControls = document.getElementById(alpha.globals.alphaControlsId);
	var activeLetterId = alphaControls.getAttribute(alpha.globals.alphaActiveLetterAttr);
	if(activeLetterId) {
		var activeLetter = document.getElementById(activeLetterId);
		if(activeLetter) {
			activeLetter.className = activeLetter.className.split(' ')[0];	
		}
	}
};

alpha.search = function(letter) {
	var alphaControls = document.getElementById(alpha.globals.alphaControlsId);
	
	var currentLetterId = "letter-" + letter;
	var activeLetterId = alphaControls.getAttribute(alpha.globals.alphaActiveLetterAttr);
	
	var searchKeyword, searchKeywordDefaultValue, searchFilter, searchBoxInput, updateParts, filter;

	alpha.clearSelectedLetter();

	if(letter === "" || letter.length === 0 || currentLetterId === activeLetterId) {
		filter = "";
		alphaControls.setAttribute(alpha.globals.alphaActiveLetterAttr, "");
	}
	else {
		//if not the same letter - set a new letter
		var currentLetter = document.getElementById(currentLetterId);
		currentLetter.className = currentLetter.className + " active";
		alphaControls.setAttribute(alpha.globals.alphaActiveLetterAttr, currentLetterId);
		filter = "LastName:" + letter + "*";
	}

    updateParts = { k: filter, s: "" };
    ajaxNavigate.update(null, updateParts);
}

})();
</script><html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"><head>
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:i0352c37ab274162b438da5dfcdbe0a6 msdt:dt="string">Project Documentation|4d0ce455-6d67-44a6-90b4-85260c7c194c</mso:i0352c37ab274162b438da5dfcdbe0a6>
<mso:TaxCatchAll msdt:dt="string">5;#Project Documentation|4d0ce455-6d67-44a6-90b4-85260c7c194c</mso:TaxCatchAll>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>

5. Add a new site page, add a content editor web part and map the HTML file from the library to have alphabets for a search like below.

6. Add search results web part, search text box web part, and refiners if you need them as well

7. For the Search Results web part, choose local people results in the change query setting

8. Under Display Templates settings, choose the people item(custom) as the display template

9. Under Refiners web part properties, choose the required refiners like below

10. Finally, Save and close the page. The page should look like below. You can customize the template as required in the associated HTML, Script, and display template code.

Using HTTP Call/ Rest API from SharePoint Designer workflow to create list

In this post, i will show how to call http/rest API using SharePoint Designer workflow to create new task List.

Open SharePoint Designer.

Create a workflow and add the below steps.

  1. Set variable RESTUrl of type string with value as workflow context – current site url and append _api/web/lists.http8
  2. Build Dictionary, add two string variables(Accept – Type String – Value as application/json;odata=verbose) and Content-Type as another variable with type string and value as application/json;odata=verbosehttpcall1output to variable requestHeaders.
  3. Add one more step, build dictionary, add variable name as type and type as String with value SP.List as below.httpcall2output variable to metadata.
  4. Add another Dictionary with variables below.httpcall3.PNGoutput variable to parameters.
  5. add variable like __metadata of type dictionary and choose workflow variable and choose variable metadata.httpcall3
  6. note: metadata variable should have two underscores, BaseTemplate as type Integer with value 107. In my case 107 is task list check for others if you want to create other list types, Description as type string and value as some description. Title as type string as per your need.
  7. Add step call http web service as below and change the variable like below.
  8. http4
  9. right click on the step and choose properties and change as needed. change request type to POST
  10. http5
  11. http6http7
  12. Log response code to see if any error comes out. Now trigger the workflow.

Make sure that you have enough permissions to run the workflow. if you face access related errors activate the feature workflow can use app permissions and register the workflow like below

https://docs.microsoft.com/en-us/sharepoint/dev/general-development/create-a-workflow-with-elevated-permissions-by-using-the-sharepoint-workflo 

Thats all.

Integrate Microsoft Sway with SharePoint Online

In this post, I’m going to show how to integrate Microsoft Sway with SharePoint Online site.

Its just as simple as it is.

Create your Sway with your own design.

Design SwayDesign sway1

Once designed, click on share button for options. choose get embed code and copy to notepad.

Get Embed code

 

embeded code

Go to SharePoint Online site, Add Content Editor web part to any of the pages, choose source code and paste the above embed code in that. That’s all

Sharepoint_Content Editor

 

Item level permissions using Microsoft Flow

Microsoft Flow is a licensing tool which is used to automate the tasks and workflows.

In this post, as a beginner, I will tell you how to set item level permissions on SharePoint List and make it recurrence to run daily over a period of time.

One of the most interesting feature is we can set recurrence/trigger the flow and make it run like a timer job to run/schedule sequence of steps where as using SharePoint Designer we cannot set the timer and need an action (add/edit) to execute the workflow.

I have a requirement for a SharePoint Tasks list items to lock down /set read only permissions over items based on date created. so, Lets start how to achieve this using Microsoft Flow.

  1. Login to the MS Flow (https://us.flow.microsoft.com)
  2. Under MyFlows choose create from blank.Flow from blank
  3. search for Recurrence and add Schedule Recurrence step and name the flow.add a trigger.png
  4. Add a schedule as per your need.recurrence step
  5. Add Get Items steps and provide the details below to get items from the SharePoint Site and List with optional Filter Query. In my case I just added Created date less than or equal to today date. you can still add more expressions/dynamic content.filter query
  6. Add apply to each step by click more with ellipses button.apply to each step
  7. choose value as output and one condition in apply to each choose dynamic conditions if any as per your need. I have added ID is greater than 1 condition just for example.value
  8. Under yes branch, add HTTP Condition. For this you need few parameters from the tenant along with App Registration.
  9. Just follow this link for getting those parameters using PostMan.
  10. After getting all the parameters,Get Access Token
  11. Parse the json code from the access token reply. Add this step. Choose the Data Operations action – Parse JSON. add the dynamic condition Body from the requestParse JSON from Get Access Token
  12. Copy this to schema.
     
    
    {
    "type": "object",
    "properties": {
    "token_type": {
    "type": "string"
    },
    "expires_in": {
    "type": "string"
    },
    "not_before": {
    "type": "string"
    },
    "expires_on": {
    "type": "string"
    },
    "resource": {
    "type": "string"
    },
    "access_token": {
    "type": "string"
    }
    }
    }
  13. Add one more step of HTTP to get access token as below.
  14. get token
  15. Add Parse JSON step, paste this script under schema
  16. {
    "type": "object",
    "properties": {
    "odata.metadata": {
    "type": "string"
    },
    "odata.type": {
    "type": "string"
    },
    "odata.id": {
    "type": "string"
    },
    "odata.editLink": {
    "type": "string"
    },
    "Id": {
    "type": "number"
    },
    "IsHiddenInUI": {
    "type": "boolean"
    },
    "LoginName": {
    "type": "string"
    },
    "Title": {
    "type": "string"
    },
    "PrincipalType": {
    "type": "number"
    },
    "Email": {
    "type": "string"
    },
    "IsEmailAuthenticationGuestUser": {
    "type": "boolean"
    },
    "IsShareByEmailGuestUser": {
    "type": "boolean"
    },
    "IsSiteAdmin": {
    "type": "boolean"
    },
    "UserId": {
    "type": "object",
    "properties": {
    "NameId": {
    "type": "string"
    },
    "NameIdIssuer": {
    "type": "string"
    }
    }
    }
    }
    }
  17. Add HTTP condition for Breaking Permissions.
  18. break permission
  19. Add another HTTP Condition to set permission.
  20. set permission
    Permissions level Role ID
    Full Control 1073741829
    Contribute 1073741827
    Read 1073741826
  21. Thats all save your flow and test the flow. verify your list items permission by selecting the item ECB Menu.

Please feel free to comments if you have any doubts.

Information Management Policy Settings / Retention Stage not working for SharePoint Online

Check for “Library and Folder Based Retention” feature under top level site features and activate.

You can enable and add retention stage over List/Library under settings to schedule policy and action over a period of time. for eg, after 30 days of creation date, you can start the workflow to trigger, move to recylcebin, permanently delete the document/list etc.

There are two timer jobs behind the scenes which will run on weekly basis.

For SharePoint On Premise, restart the below timer jobs to make it working.

  1. Expiration Policy.
  2. Information management policy.

For SPO/SharePoint Online we don’t have control over this timer jobs to restart rather need to wait till timer job executes and no other way and will run weekly mostly Monday or Tuesday and depends on timezone.

You can check the last execution date of these timer jobs using SharePoint Designer.

Open the root SharePoint Online site and check for dates for the below two properties from top Ribbon Site Options.

dlc_policyupdatelastrun

dlc_expirationlastrun

Site Options

Column ContentType does not exist.It may have been deleted by another user while adding/updating the list item

I have taken the list template from SharePoint 2007. Edited the Product version in order to use this template in SharePoint Online similar to this.

After creating the list from template, I tried to add edit list items and facing this error saying that column ContentType does not exist. It may have been deleted by another user while adding/updating the list item.

To overcome this,

I have created single line of text column with name “ContentType”.

After which, I’m able to add and edit the list items.

 

Microsoft SharePoint Foundation version 3 templates are not supported in this version of the product

This kind of error occurs when you try to create a list using a template which is taken from SharePoint 2007.

version 3 templates error As a workaround, you can still you the template in SharePoint Online but with few/limited settings.

Steps:

  1. Save the list as template from Source Site (2007) with name CustomList.stp
  2. Rename CustomList.stp to CustomList.cab.
  3. Extract the files using winrar to Physical Location e.g., D:\Temp\CustomList.
  4. Edit the manifest.xml with notepad and change the Product Version from <ProductVersion>3</ProductVersion> to <ProductVersion>4</ProductVersion>
  5. Open a command prompt and change to the directory that the manifest.xml and CustomList.cab files are located by using cd (D:\Temp\CustomList)
  6. Run the below command
  7. D:\Temp\CustomList>makecab manifest.xml CustomList.cab
  8. Rename it back to CustomList.stp
  9. Go to Destination Site – List Templates upload the CustomList and create the List from this template.

You may face editing or updating the list items that i will cover in other post.

Migration from SharePoint 2007 to SharePoint Online/Office 365

Recently I had to move existing SharePoint 2007/WSS Site On Premise to SharePoint Online/ Office 365 Site and that led me to this post.

When it comes to Migration, each Migration and approach will vary depending on several factors and based on the content.

Our role is to identify and go for the best migration approach.

I have done quick analysis on Migration options.

Points to be considered before any Migration or check list:

  1. Check the Site Hierarchy and determine the Site Inventory in terms of available Sites/Sub sites/ Lists/ Libraries/ Pages etc in excel sheet.
  2. Check on the volume of the content to be migrated and come to an idea in terms of size.
  3. Check on Lists, Libraries that having Lookup, Content Types, Workflows, Permissions etc.
  4. Check on User and Groups.
  5. Determine whether to maintain or preserve Meta Data Properties.
  6. Check for Managed Meta Data.
  7. Clean up unused Content(Lists and Libraries)
  8. Re structure Lists and Libraries on Destination site if unorganized.

Migration Approach:

  1. Third Party Tools:

I prefer to use any of the famous Third Party Tools such as Share-gate / Meta Logix /Doc Ave etc.

Pros of going for the third party tools are

Hassle – free

Reports can be generated.

can run pre-upgrade check for dependencies.

Individual Lists/Libraries can also be moved.

Maintain same site hierarchy

Preserve Meta Data Properties like Created Date, Modified Date, Created By and Modified By columns.

Cons

Cost effective and Licensed.

2. Power-Shell:

You can go with SharePoint Online Management Shell for Migration of Content from SharePoint On Premise to SharePoint Online.

Involves custom development of PowerShell script.

Efficient way to move Documents from Windows File Share/ Network Drive.

File Meta Data can be preserved or updated using PowerShell Script.

3. SharePoint Migration Tool:

It is a free tool provided by Microsoft for Migration of content from various sources.

Sources can be

SharePoint on-premise

File Share

CSV File

It requires

Office 365 Subscription

Azure subscription

Cons:

Only Date Modified column can be preserved.

4. Manual Migration:

Last but not least you can go for Manual Migration.

Windows Explorer View:

You can use Windows Explorer View for Libraries(On Premise Site) in Internet Explorer to Copy the Documents and Paste them in Window Explorer View of Destination Site(Office 365).

File Meta Data Properties cannot be retained or Preserved.

For Lists, You can save the list as a template with data if data is not exceeding the SharePoint List Limit and move the templates to the Destination site and restore them. You may face templates are not supported in this version of the product error. I have workaround for that probably will cover in other post. However, will have few limitations in terms of list settings may not work.

If the lists are having lookup mapped to other columns those columns may need to recreated and filled up manually.

You can even save the site as template without content and then create the site in destination from the template. That way you can have mapped lists/library and site structure. Later for Lists you can export the the list to excel file and the re import from the list choosing the exported file.

Overall, each migration approach has their set of Pros and Cons and entirely depends upon the content and clients budget.

 

 

Server side activities have been updated. You need to restart SharePoint Designer to use updated version of activities

While Opening SharePoint Designer and trying to create new SharePoint Designer workflow or open existing Designer Workflows, you may come across this kind of error saying “Server-side activities have been updated. You need to restart SharePoint Designer to use updated version of activities” message.

server side activities error

As a workaround, do

Clear SharePoint Designer Cache:

  1. Close SharePoint Designer 2013
  2. Delete everything at %USERPROFILE%\AppData\Local\Microsoft\WebsiteCache
  3. Delete everything at %APPDATA%\Microsoft\Web Server Extensions\Cache
  4. Go to SPD2013 options –> General –> Application Options –> Uncheck the “Cache site data across SharePoint Designer sessions”
  5. Restart the SharePoint Designer and open/create the workflow.

Update SharePoint Designer:

Update the SharePoint Designer to the latest package available and check to see if this resolves your problem.

If still problem exists try to Open the SharePoint/Office 365 Site probably in some other system/machine and check to see if the problem still exists.

In my case I’m able to open the site/workflow from another machine.

 

Change Sub Site Master page without enabling Publishing Feature

At times you may need to change or apply different master page for sub sites that are inheriting permissions/ inheriting site master page from parent site.

If publishing feature is not activated, you will not be available with Master Page setting under Site Settings.

To make the link available you may need to activate the publishing feature and Site Collection Features and Site Features.

Here is tip/trick to change the master page without activating the features.

Just browse to https://<Site URL>/_layouts/15/ChangeSiteMasterPage.aspx and change the system/site master page as per your wish.

No Publishing Feature

changesubsitemasterpage.png