Monday, November 25, 2019

Speaking at SharePoint Saturday Oslo 2019

I'm looking forward to speaking at SharePoint Saturday in Oslo on December 7, 2019.

SPS Oslo will be superb and very special since Jeff Teper and Omar Shahine will give the keynote! In addition, top speakers (international and local) will fill the rest of the agenda. As you can see, there will be a lot of people to meet and a lot of knowledge to acquire. I've attended to several SharePoint/Office 365 events in the past and I've never met Jeff Teper or Omar Shahine in a community event before! It is amazing to have you here. Thanks for joining us 👍

In my session, I'll cover different topics around SharePoint Site Designs and Site Scripts. I've been blogging, using and speaking about this topic and I'm very happy to share my knowledge about it with the attendees! I'm looking forward to seeing you there 😀

I am very happy to be a part of the speakers team! It’s going to be my third speech at a SharePoint/Office 365 Saturday event. Let's get in touch if you're also going to participate in SPS Oslo!

Oslo, I'm coming 😉


Event information:

Home page - http://www.spsevents.org/city/oslo/oslo2019
Schedule - http://www.spsevents.org/city/Oslo/Oslo2019/schedule
Registration - https://www.eventbrite.com/e/sharepoint-saturday-oslo-2019-tickets-72991217697

Tuesday, November 19, 2019

Adding dynamic references to default components of an Office 365 Group using SharePoint Site Designs

How nice would it be to have links visible to users to the default Planner, Calendar and Team in the quick launch of an Office 365 group from the beginning? Let me answer that for you: That would be awesome 🥳. By default, we already have in an Office 365 group links to the group’s document library, default notebook and mailbox. But what about the other components? I’ve seen many questions about this topic either during my speaker sessions about Site Designs or in Github. I've started looking for a better way to solve that problem and finally I’ve found a very elegant way to implement a solution without the need of unique identifiers. What!? No IDs?

Once again, Site Design offers the easiest way to solve this problem since by default it supports the capability of adding links to the SharePoint navigation through the addNavLink action. This action supports references to web relative links which is very helpful if you don’t know unique identifiers in advance, such as site collection URL or group ID. Therefore, I chose Site Designs as the base of this implementation. The rest of the job is done by the "_layouts/15/groupstatus.aspx?target=<target> URL. Combined to the Office 365 group URL, this URL refers to Office 365 default components such as Planner, Calendar, Team, Documents, Notebook, Members and so on. Checkout Yannick Reekmans blog post if you want detailed information about this URL and its functionality. Since addNavLink supports web relative URL, you can image how simple it is to create those dynamic links using Site Designs.

In this blog post, I will answer three questions:

How to reference to default Planner of an Office 365 group using SharePoint Site Designs?

The solution is to reference to "/_layouts/15/groupstatus.aspx?target=planner" url. This url points to the default planner of the Office 365 group. This is what the site script looks like:

{
    "verb""addNavLink",
    "url""/_layouts/15/groupstatus.aspx?target=planner",
    "displayName""Planner",
    "navComponent":"QuickLaunch",
    "isWebRelative"true
}


How to reference to default Calendar of an Office 365 group using SharePoint Site Designs?

The solution is to reference to "/_layouts/15/groupstatus.aspx?target=calendar" URL. This URL points to the default calendar of the Office 365 group. This way you don’t need to provide values such as group mail nickname or tenant name since these values are required in the default calendar URL:

https://outlook.office365.com/calendar/group/<TenantName>.onmicrosoft.com/<GroupMailNickname>

This is what the site script looks like:

{
    "verb""addNavLink",
    "url""/_layouts/15/groupstatus.aspx?target=calendar",
    "displayName""Calendar",
    "navComponent":"QuickLaunch",
    "isWebRelative"true
}


How to reference to associated Microsoft Team of an Office 365 group using SharePoint Site Designs?

The solution is to reference to "/_layouts/15/groupstatus.aspx?target=team" URL. This URL points to the associated Microsoft Team of the Office 365 group. This way you don’t need to provide values such as channel ID or tenant ID since these values are required in the team URL:

https://teams.microsoft.com/l/team/19:03d807810bd337748477d9965c215359@thread.skype/conversations?tenantId=b62a7921-3425-42b6-8a86-123eeff26f32

This is what the site script looks like:

{
    "verb""addNavLink",
    "url""/_layouts/15/groupstatus.aspx?target=team",
    "displayName""Team",
    "navComponent":"QuickLaunch",
    "isWebRelative"true
}

Note that the associated team must exist, otherwise that link won’t work properly and the end user will end up with an exception message.


Site Design and Site Script

The site script below contains all the above navigation entries. Here is what the site script looks like:

{
    "$schema""schema.json",
    "actions": [
        {
            "verb""addNavLink",
            "url""/_layouts/15/groupstatus.aspx?target=planner",
            "displayName""Planner",
            "navComponent":"QuickLaunch",
            "isWebRelative"true
        },
        {
            "verb""addNavLink",
            "url""/_layouts/15/groupstatus.aspx?target=calendar",
            "displayName""Calendar",
            "navComponent":"QuickLaunch",
            "isWebRelative"true
        },
        {
            "verb""addNavLink",
            "url""/_layouts/15/groupstatus.aspx?target=team",
            "displayName""Team",
            "navComponent":"QuickLaunch",
            "isWebRelative"true
        }        
    ],
    "bindata": { },
    "version"1
}

In order to create a Site Script based on that script, you need to run the following PowerShell command (instead of PowerShell you could also use CSOM or REST for instance). Note that the Site Script response will be stored in a variable in order to reuse it during Site Design creation:


$siteScript = Add-SPOSiteScript -Title "Dynamic References" -Content (Get-Content "C:\Temp\DynamicReferences.json" -Raw)


The next PowerShell command creates the Site Design. Here is what it looks like:

Add-SPOSiteDesign -Title "Dynamic References" -WebTemplate 64 -SiteScripts $siteScript.Id


Id                  : 12c6f045-8b61-459e-85d5-2a68224e24f7
Title               : Dynamic References
WebTemplate         : 64
SiteScriptIds       : {acab2014-71a1-48a8-b49d-442b8c276384}
Description         :
PreviewImageUrl     :
PreviewImageAltText :
IsDefault           : False
Version             : 1
DesignPackageId     : 00000000-0000-0000-0000-000000000000

Note that WebTemplate equals 64 represents Modern Team sites.


The end result

Applying the Site Design that we’ve just created, results in a left navigation that contains three new links to the default Planner plan, Calendar and associated Team. Here is what the navigation looks like:



I hope you enjoyed reading this blog postSee you on the next post! Follow me on twitter and keep up-to-date!

Tuesday, November 12, 2019

Extracting a site collection using SharePoint Site Designs (Get-SPOSiteScriptFromWeb)

At Microsoft Ignite 2019, Microsoft announced that the capability of extracting a SharePoint site collection using Site Designs will be available soon 🥳 Lucky me, because it is already working on my Office 365 tenant which run as targeted release 😀 In this blog post, I want to show you how you can extract a site using Site Designs. In addition, I will also show what is supported when extracting the site.


Short feature overview:

Site Designs was enhanced by the capability of extracting a site as a Site Script. It means that you can reuse an existing site collection to create copies of that. This process supports additional parameters which you can use to define what will be extracted.


What can I extract?

Comparing to other extraction tools like PnP or Sites.asmx service, Site Designs is still very limited in terms of the supported components. Nevertheless, it is a good alternative to existing tools, especially if the scope of components to be extracted is small.

The Site Designs feature for extracting site collections can be enhanced by supportive parameters. These parameters define the components to be extracted. During extraction, these parameters will be converted to Site Script actions/verbs which make the extracted output very easy to be reused. Below I've listed all the supported parameters:

IncludeBranding: Supports extracting the branding of a site collection. Here is what the output of this parameter looks like:

"verb""setSiteBranding",
"navigationLayout""Megamenu",
"headerLayout""Standard",
"headerBackground""None",
"showFooter"true

IncludeTheme: Supports extracting the custom theme of a site collection. The output of this parameter depends if the site is themed or not. If the site is not themed, you will end up with either an exception or a warning message:

Exception: No actions could be successfully exported. Additional information: This site is not
themed. Please apply a theme to the site before exporting the theme.

Warning: This site is not themed. Please apply a theme to the site before exporting the theme.

Here is the output if the site is themed. Note that I shorted the output of the palette property in order to improve readability.

"verb""applyTheme",
"themeJson": {
"version""2",
"isInverted"false,
"palette": {
    "neutralPrimaryAlt""#ff4b4b4b",
    "themeLighterAlt""#fff1faf0",
    "black""#ff1d1d1d",
    "themeTertiary""#ff55ae48",
    "primaryBackground""#ffffffff",
    ...
    }   
}

Very interesting here is the themeJson property! The applyTheme action has been supporting only the themeName property. Now you can use the themeJson property to enter a theme based on its JSON definition instead of its name. That makes the extraction very flexible, since it supports applying this script to another tenant which doesn't have a theme by name.

IncludeRegionalSettings: Supports extracting the regional settings. Here is how the output of this parameter looks:

"verb""setRegionalSettings",
"timeZone"13,
"locale"1033,
"sortOrder"25,
"hourFormat""12"

IncludeSiteExternalSharingCapability: Supports extracting the external sharing capability. Here is how the output of this parameter looks:

"verb""setSiteExternalSharingCapability",
"capability""ExternalUserAndGuestSharing"

IncludeLinksToExportedItems: Supports extracting links from the quick launch. There is a logical dependency between a navigation link and a list. Therefore, this parameter must be used along with the IncludedLists parameter. When using this parameter without the IncludedLists parameter, I ended up with the following exception:

"No actions could be successfully exported. Additional information: No QuickLaunch links
suitable for export could be found. In order to export navigation links pointing to lists, the list needs to be included in the site script as well."

I was testing this parameter also with custom links like "www.microsoft.com", but it didn't extract that. I did also try to extract the link to the Shared Document library but it didn't work. During my tests, this parameter has stopped outputting the link when used correctly. I assume that Microsoft is still working on it 😀

This is what the output looks like if the parameter is used/work correctly:

{
    "verb""createSPList",
    "listName""Project Activities",
    "templateType"100,
    "subactions": [
        ...
    ]
},
{
    "verb""addNavLink",
    "url""/Lists/Project Activities",
    "displayName""Project Activities",
    "isWebRelative"true,
    "navComponent""QuickLaunch"
}

IncludedLists: Supports extracting one or more SharePoint lists. Here is what the output of this parameter looks like:

"verb""createSPList",
"listName""Project Activities",
"templateType"100,
"subactions": [
  {
    "verb""addSPView",
    "name""All Items",
    "viewFields": [
      "LinkTitle"
    ],
    "query""",
    "rowLimit"30,
    "isPaged"true,
    "makeDefault"true,
    "addLink""Project Activities"
  }
]


What kind of site collections are supported?

I tested the Get-SPOSiteScriptFromWeb command with the site collections that my customers have been mostly using. I tried to extract the regional settings, the branding, the theme, the sharing capability and the shared documents library of the corresponding site collections. No matter which site collection I've used, Site Designs was always able to extract the content according to my specifications. Of course, the extraction output depends on the site collection type. For instance, IncludeBranding parameter will always return footer as false for a modern team site (Office 365 group) since a modern team site doesn't support editing the footer area by default. I listed below the site collections that I've used for testing:

- Communication Site
- Modern Team Site (Office 365 Group)
- Classic Team Site
- Modern Team Site without Group


Extract a SharePoint site in different ways:

The extraction of a site collection using Site Design can be done with PowerShell, REST or CSOM. I demonstrated below how to extract a site collection using PowerShell, REST and CSOM:

PowerShell:

Get-SPOSiteScriptFromWeb 
-WebUrl https://example.sharepoint.com/sites/template 
-IncludeBranding 
-IncludeTheme 
-IncludeRegionalSettings 
-IncludeSiteExternalSharingCapability 
-IncludeLinksToExportedItems 
-IncludedLists ("Protocols""Lists/Project Activities")

REST:

POST: https://example-admin.sharepoint.com/
_api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.GetSiteScriptFromWeb


   "webUrl":"https://example.sharepoint.com/sites/template",
   "info":{ 
      "IncludeBranding":true,
      "IncludedLists":[ 
         "Clients",
         "MyList"
      ],
      "IncludeRegionalSettings":true,
      "IncludeSiteExternalSharingCapability":true,
      "IncludeTheme":true,
      "IncludeLinksToExportedItems":true
   }
}

CSOM: 

var tenant = new Tenant(ctx);

var info = new TenantSiteScriptSerializationInfo()
{
    IncludeBranding = true,
    IncludeTheme = true,
    IncludeRegionalSettings = true,
    IncludeLinksToExportedItems = true,
    IncludeSiteExternalSharingCapability = true,
    IncludedLists = new[] {"Protocols""Lists/Project Activities"}
};

var response = tenant.GetSiteScriptFromSite("https://example.sharepoint.com/sites/template/", info);

ctx.ExecuteQueryRetry();

Note that in CSOM the method to extract the site collection is called GetSiteScriptFromSite! In PowerShell and REST it is called ...FromWeb. So, don't get confused when extracting sites using PowerShell, REST or CSOM 😀


Summary:

The capability of extracting a site using Site Designs is definitely a feature that SharePoint admins have been waiting for since it supports reusing the work already done. The scope of supportive parameters is still very small, but I believe that Microsoft will be publishing other parameters over the time.

I hope you enjoyed reading this blog post. See you on the next post! Follow me on twitter and keep up-to-date!