Tuesday, September 12, 2023

How SharePoint handles DateTime stamps - and why it causes PnP Search Filter URLs to be offset

 

TimeZones and how SharePoint handles timestamps

We recently had an issue logged in the PnP Modern Search repository regarding why the date filter values were "wrong".

Actually, the date filter values were correct as they were offset to match the current users Time Zone, which can be pretty hard to understand, hence this summery:


Disclamer: I am in Denmark, currently in UTC+2 (summertime)

Each time a timestamp is saved in SharePoint it is saved in UTC0, so when I upload a document at 13.45 local time the timestamp saved in the backend will read 11.45.


But in the Document library it clearly shows 13.45, what gives?

Each time the SharePoint Front End displays a timestamp it is offset to the local timezone, so my colleague in Los Angeles looking at the same document will see the timestamp as 04.45 (9 hours behind my timezone).


However, when you get the timestamp from an API you get the time in UTC0 !!!!

So, if I am looking for documents that was created between 4 April and 10 April I must answer the question: from which timezone do I define when 4 April begins?

If I lived in New Zealand(UTC+12) 4 April starts a lot earlier than it does here in Denmark(UTC+2).

So, when somebody asks you to set up a PowerShell script to pull all Contracts (content type) created on 10 April, you have to ask is the offset should be based on the Time Zone of the requestor or something else.


In PnP Modern Search any time-based query is automatically offset to match the Time Zone of the current user. 
When I query for something created between 4 April and 10 April the query is changed to:
creased between 3 April 22h00m and 9 April 22h00m.
The reason is that when 4 April started in Denmark the time was 3 April 22h00m UTC0 which is the values in the backend.

You can find your current TimeZone info by navigating to a classic SP Page, hitting F12, go to the Console tab, enter _spPageContextInfo and hit Enter, look for webTimeZoneData:




Time Zones might be hard to deal with, but I guess it is there to stay :-)


Tuesday, June 6, 2023

Searching for phone numbers in the Employee Directory

 

Phone numbers search - where the answer is "It depends"


A question I get very often when assisting customers with People Search is why they can't search for phone numbers.


The answer is that they in most cases CAN search for phone numbers. However, it might not be as straightforward as they would like.

The primary reason searching for phone numbers is difficult is that we as humans prefer that phone numbers are displayed in a form that is easy to read and remember.

For instance, a US phone number will often be displayed as +1 980 555 0101, and those spaces really can mess up the search. More on this later.


In some cases, the KQL has been twisted in such a way that you can't search for phone numbers:


I searched for Joni, and copied her phone number.


But I get no results?


In this case the query is set up to search for FirstName only: FirstName:{subjectTerms}


I then update the query to: FirstName:{subjectTerms}  OR MobilePhone:{subjectTerms}

But still no results, what gives?


Checking the UPA reveals that Joni doesn't have a Mobile nor Home phone number.



OK, so the query should be like this perhaps: 

FirstName:{subjectTerms}  OR WorkPhone:{subjectTerms} 

Using the query text +1 980 555 0101 it returns no hits.

Looking at the query sent to the API reveals that it is transformed into 

FirstName:+1 980 555 0101  OR WorkPhone:+1 980 555 0101

 

Ouch, not a well-formed query.


The final query will in this case look like this:

(FirstName:({subjectTerms}) OR WorkPhone:({subjectTerms})*  )

and the resulting query in the API call like this:

(FirstName:(+1 980 555 0101) OR WorkPhone:(+1 980 555 0101)*  )


Another option is to abandon the specific search and use a more generic query: {subjectTerms}*  

(However, this might find matches in unexpected properties)


Query text                            resulting query                Hits

joni                                        joni*                                1

+1 980 555 0101                +1 980 555 0101*            1

+1 980                                +1 980*                            1

+1 9                                    +1 9*                                6

0101                                    0101*                               0


Sorry, SharePoint search can only handle "starts with" wildcards, not "ends with"


Yet another approach is to use the phone number properties for display purposes only, and create your own User Profile properties, like "WorkPhoneAsText" which contains the WorkPhone value stripped for spaces and prefixes. 

I have primarily used it with customers that used the last 4 digits like a local extension, and would therefore have a "LocalExtension" property in the UPA and a matching managed Property.







Sunday, March 12, 2023

Boost the person fields in your PnP Modern Search Layout

 

This rather generic SharePoint list is created by a self-service site provisioning setup, and it shows who is in change of any Site Collection.






On the front page on each of the Site Collections the customer requests that we insert a web part with some basic site information. In this case the People web part is not sufficient as some of the metadatea can change over time, such as e.g. the Site Owner.

The obvious choice is therefore a PnP Modern Search results web part using a query like 

Path:https://tcwlv.sharepoint.com/sites/SampleTeamSite/Lists/SiteCreationRequestList* basicProvisioningSiteUrlOWSTEXT:{Site.Url}

(basicProvisioningSiteUrlOWSTEXT is the internal name for the SiteUrl column as seen above)

This will give me the data in the list item having the SiteUrl that is the same as the current Site Collection. 


I looked in the People layout and found that the template used to display a person is a pnp-persona template and used it in the custom layout. It looks like this and has not hover card.



This is off cause better than nothing, but even the OOTB List has a hover card, so it needed an upgrade.

I asked the community on the PnP-modern-search discussions and @patrikhellgren provided an incredibly detailed sample using the mgt-person template. (Microsoft Graph Toolkit).

So, by updating the Layout to this I get a tree line Card and the hover card as well 😀

<template id="content">

    {{#> resultTypes item=item}}
        {{!-- The block below will be used as default item template if no result types matched --}}
       
       
        <div class="contactheader">
        Primary Contact
        </div>
       
        <mgt-person
            user-id="{{getUserEmail (slot item @root.slots.Owner)}}"
            view='threelines'
            show-presence="true"
            person-card="hover"
            avatar-size="large"
        />
        </mgt-person>
        <br><br>
    Template: "{{slot item @root.slots.Template}}"

    {{/resultTypes}}
</template>






As an additional bonus I am pretty sure (not verified yet), that the photo comes from AAD and not the User Profile Application, a service that have provided several headaches over the years, especially related to the employee photo ;-)













Monday, February 20, 2023

Microsoft search : using a DateTime field in your Result Types

In one of our products, we are using a Generic SharePoint list to store some information that is required to be visible within a specific timeslot ( beginDate & EndDate).

In the ol' days we could easily exclude those listitems in a data source derived from the LocalSharePointResults data source using a Date variable.


But these days we are dealing with Microsoft Search and a different set of rules.


 Since Microsoft Search will display those list items by default we have a few options:

Option 1: Create two Result Types and use e.g. ContentTypeId and the RefinableDates to handle the items that should be show and not shown respectively.



 Well, this is as far down that path that I got. Date fields in the Result type builder does NOT have any date variables, and according to a very reliable source with Microsoft there are no plans to offer this option.


So, we are left with Option 2 or 3.

Option 2: For each relevant Search Vertical we must add a filter to hide any item outside the range.
(risky as this rule might be forgotten and not implemented in a Vertical added at a letter date)


Option 3: Use the Result Type without any date filter and set up the Adaptive Card to hide any item outside the range.

I am not happy about having "business logic" in the GUI/Display layer but I guess we will go with Option 3 for now.

Wednesday, December 21, 2022

Yeah, SharePoint custom Search Display Templates are back*



Once upon a time (before SharePoint Modern mode, circa 2016) we were able to create  custom display templates for search results. This was a great option when your search query was returning a specific Content Type and you could display the various fields in a way that fit the content e.g. showing a red traffic light for expired content.

However when SharePoint Modern appeared on our tenants Microsoft decided not to provide any option to customize the out of the box search, a decision that is hard to understand.

Luckily for Microsoft and us the M365 Community rose to the challenge and the PnP Modern Web Parts project was born.

 

As of today, you can add additional MS Search Vertical on the Site and Tenant level, and we can only hope that one day we will be able to assign an Audience to a Vertical in order to ensure the relevancy for the end user. (hint hint)

 

And NOW (public preview late Dec 22 and complete mid Jan 23) we can create custom item display templates in the shape of Result types with associated Adaptive Cards:

 

 


 

Please note that the Rules is using KQL so all the old queries you have been using for years still works !!!

 


And the skill set required for beautiful looking Adaptive Cards is on my wish list for X-mas but at least I can cheat and learn from the masters at https://github.com/pnp/AdaptiveCards-Templates

 





(Hey it works
😊 )

Thursday, February 3, 2022

Don't pay more for SharePoint Storage than you have to :-)



This blog post will walk you through the potential challenges related the SharePoint Storage, and a few suggestions how to minimize your costs.


Even though most of us likes Microsoft, on some days more than others, there are no reason why we should pay more than necessary.

As you might know each tenant is born with a 1 TB SharePoint Storage allowance. On top of that you get 10 GB per licensed user.

Unless you already have a retention policy or similar in place that will delete the content of your SharePoint Site Collections as the time goes by, you will eventually run out of free SharePoint Storage. At the time of writing additional SharePoint Storage is available in the admin center at $0.20 per GB per month.

First of all it is important to know how the total SharePoint Storage is calculated. In the screen shot below you see the version history of a fairly typical file. It has been updated and reviewed a few times and currently we have a total of 25 versions.

It has been difficult to find any documentation from Microsoft confirming this, but as far as I know Microsoft calculate the Storage for this file as each version multiplied by its size. So in this case our file is roughly 25 * 39 MB towards the Storage allowance. That is a lot. 

So what can we do about it?

As usually there are a fair number of options:

A) Set up a Rentention policy that will delete some of the content. For some organizations this is not an option as per their Governance policies or fear that the policy might delete too much. 

B) Reduce the number of document versions saved  ( the default is 500 major versions). This will  often require that you have some kind of provision tools in place that will change the default value. The downside of this option is that you might be in a situation where you wish to restore an older version, but that version does not exist anymore.

C) Monitor the Site Collections for activity and enforce that the Owners of a Site Collection deletes any non essential documents once the Site Collection is no longer active. This Governance approach might work in some organizations, but I have yet to see it.

D) Monitor the Site Collections for activity and once it is no longer active the Archiving process starts. Depending on the requirements that could be something like:    





Step number 2 can be omitted but is there to ensure that it will be possible to locate any version of a given document should the need arise.

The reason for not deleting the entire Site Collection once the documents have been copied to cheaper storage is to ensure that the organization will still able to see the Site Collection and the content. Often the Site Collection was used in a project or similar and the organization needs to store that fact that this project once existed.

There is also possible to extend the process by deleting the Read Only Site Collection after a few months or years.  


If you are thinking "Well this might save us some SharePoint Storage, but I have no idea how to verify it", the PnP Script Samples is the place to go:

storage savings report


This script will output a report showing how much Storage you can save per site collection.


#SharingIsCaring