Inquisitive M365 https://thomasdaly.net Yet another SharePoint / Office 365 blog Tue, 17 Jun 2025 00:29:47 +0000 en-US hourly 1 116451836 Sort Your SharePoint Site Directory Alphabetically https://thomasdaly.net/2025/02/02/sorting-your-sharepoint-site-directory-by-title-with-pnp-search/ https://thomasdaly.net/2025/02/02/sorting-your-sharepoint-site-directory-by-title-with-pnp-search/#comments Sun, 02 Feb 2025 21:53:07 +0000 https://thomasdaly.net/?p=3339 In my previous article, Build a Site Directory with PnP Search Web Parts, I walked through how to create a dynamic site directory using PnP Modern Search. While that setup provides a powerful and flexible way to display SharePoint sites, you may have noticed a limitation—SharePoint doesn’t allow sorting by the Site Title property out of the box.

This article covers the extra step needed to sort your site directory alphabetically by title. The trick? Leveraging RefinableString fields to make the Site Title sortable. It’s a simple process with just a few tweaks, and by the end of this guide, you’ll have a properly sorted site directory in no time. Let’s dive in.

Updating the Search Schema

Navigate to the SharePoint Admin Center

Expand ‘Advanced’ then click ‘More Features’ and finally click ‘Open’ under the ‘Search’ group

Next click ‘Manage Search Schema’

Next enter ‘RefinableString’ in the search box and click the green button

Hover over any of the available properties and find the drop down, then click ‘Edit Map Property’

It’s not critical on what number refinable string you choose

Scroll all the way to the bottom and click ‘Add a Mapping’

Enter ‘display’ and click ‘Find’, then select Basic:displaytitle and click O

Verify the mapped managed property and click ‘OK’

This completed the Search Schema changes. These can take quite some time to take effect so be patient. It could be a day before you see it working.

Next navigate to the SharePoint page with the PnP Search Web Part configured as a Site Directory

NOTE: The following steps are only necessary if you have customized the Custom template.

  1. Edit the page and open the web part properties of the Search Results web part
  2. On the second page, click on the curly braces { }
  3. Take a copy of the entire

Change the template to Debug. This is so that you can visually see the property to ensure that the search property has taken effect.

Go back to the first page of the web part properties, enter the name of the RefinableString## you modified and hit Enter.

The result should appear on the left hand site – most likely it will read null to begin with. It will eventually populate. It can appear at any time but at least wait 8 hours or a full day. Recheck the steps in the search config but at this point there is not much more to do but wait.

What to do if the site title will no show up?

If it’s just not showing for a few sites

  • Update the Site Title of the site. Change it temporarily and then change it back
  • Trigger a reindex on the 1 site

If it’s not showing up for many sites

Recrawling puts strain on the service as a whole so it’s not meant to be run over and over as it can take weeks to finish on very large sites.

After the crawl property appears move on to the next step.

Apply the Sort

Navigate back to the Search web part page and edit the web part properties

Click ‘Edit sort settings’

Type in your RefinableString## into the Field name box, click Default Sort and then click ‘Add and save’

The sorting is now set to alphabetical order from A-Z by default.

Next go to the second page of the web part properties

Set the template back to what it previously was. In our case Custom and then click on the { } to edit the custom template

Copy / Paste in the template, Save and Republish.

The final result should be in order by site title.

Wrap Up

Sorting your SharePoint site directory by title might not be possible out of the box, but with a little creativity—leveraging RefinableString fields—it becomes a straightforward solution. By following these steps, you can ensure your directory is organized in a way that makes finding sites easier for users.

This small but impactful tweak enhances usability and keeps your directory structured exactly how you need it. If you’re already using PnP Search Web Parts, this is a great optimization to implement. Have questions or run into issues? Drop a comment—I’d love to hear how this worked for you!

]]>
https://thomasdaly.net/2025/02/02/sorting-your-sharepoint-site-directory-by-title-with-pnp-search/feed/ 2 3339
Build a Site Directory with PnP Search Web Parts https://thomasdaly.net/2025/01/20/build-a-site-directory-with-pnp-search-web-parts/ https://thomasdaly.net/2025/01/20/build-a-site-directory-with-pnp-search-web-parts/#comments Tue, 21 Jan 2025 04:07:34 +0000 https://thomasdaly.net/?p=3324 This article will demonstrate how PnP Search Web Parts can be used to build a comprehensive Site Directory that not only enhances navigation but also improves the overall user experience by providing a centralized resource for accessing various sites within your organization.

Pre-Requisites

PnP Modern Search – Search Web Parts – v4

From your SharePoint site

Instructions

Create a new Page

Edit the Page

Add the PnP Search Results Web Part

Next click ‘Configure’

Next click ‘SharePoint Search’

Next click ‘Customize’ under ‘Layouts slots’

Add SiteUrl — mapped to SPSiteUrl, click ‘Save’

Edit the Query Template, using this as my base. It will show all ‘Sites’ and not the app catalog or my sites.

contentclass:STS_Site -"{TenantUrl}/sites/contenttypehub" -"{TenantUrl}/sites/appcatalog" -SiteTemplate:SPSPERS

** Thanks Kasper Larsen for the comment and suggestion to use the tokens for more resuability! **

Make sure to hit Apply to save the query.

Scroll down to the Paging Options

For our example we want to show as many sites as possible.

Set the number of items per page to 500

Click ‘Next’ to go to the second page of the property pane

Click ‘Custom’ Template and then {}

Replace this CSS

 /* Insert your CSS overrides here */
       .example-themePrimary a {
            color: {{@root.theme.palette.themePrimary}};
        }

        .site-logo {
            width: 35px;
            margin-right: 10px;
        }

        .icon {
            width: 20px;
            height: 16px;
        }

        ul.template--custom {
            list-style: none;
            padding-left: 5px;
	 columns: 4;
        }

        ul.template--custom li {
            display: flex;
            padding: 8px;
        }
        
        .site-link {
            line-height: 20px;
        }
        
        .site-link > a {
            display: flex;
            align-items: center;
        }
        
        .site-link, .site-link a, .site-link a:visited, .site-link a:hover, .site-link a:link {
            color: #000 !important;
            text-decoration: none;
        }

Next replace the item template

<template id="content">

 {{#> resultTypes item=item}}
                            {{!-- The block below will be used as default item template if no result types matched --}}
                            <li class="site-link">
                                <a href="{{slot item @root.slots.SiteUrl}}">
                                   <img class="site-logo" src="{{slot item @root.slots.SiteUrl}}/_api/siteiconmanager/getsitelogo?type='1'"/>
                                   <span class="site-name">{{slot item @root.slots.Title}}</span>
                                </a>
                            </li>
                        {{/resultTypes}}

                    </template>

Click ‘Save’

Click Republish

Your page should now look something like this

Conclusion

This is the first step toward making a Site Directory with all the sites you have access to. You could easily extend this to use a search box to filter these items down or change the KQL query to show only certain types of sites. You might also notice that the sites are not in order. In the next article I’ll walk you through the process of implementing the sort on the Site Name.

]]>
https://thomasdaly.net/2025/01/20/build-a-site-directory-with-pnp-search-web-parts/feed/ 4 3324
SharePoint Site – Automatically Apply Site Templates on Site Creation https://thomasdaly.net/2024/02/20/sharepoint-site-automatically-apply-site-templates-on-site-creation/ https://thomasdaly.net/2024/02/20/sharepoint-site-automatically-apply-site-templates-on-site-creation/#comments Wed, 21 Feb 2024 04:17:16 +0000 https://thomasdaly.net/?p=3313 Applying a consistent site template across newly created SharePoint sites is essential for maintaining uniformity, particularly for departmental sites. While designing and creating templates is straightforward, the application process—requiring manual site visits or PowerShell script executions—is less efficient. This gap underscores the need for automation, eliminating the need for manual interventions or technical scripting. In this article, we introduce a streamlined method to automate site template applications, ensuring consistency and efficiency across your SharePoint environment.

Leverage Power Automate for Seamless SharePoint Site Template Applications

Unlock the power of automation with Power Automate by setting up a new flow using a SharePoint administrator account. Here’s how to streamline your process:

  1. Initiate your Flow: Select the ‘When an item is created’ SharePoint trigger to start your automation whenever a new site is created.
  2. Configure Site Address: Input the custom URL of your Admin site in the format https://{domain}-admin.sharepoint.com to specify where your flow should monitor for new site creations.
  3. Specify the List Name: Enter DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS as the list name. This special list captures all newly created sites, ensuring no site, including those associated with Microsoft Teams, is overlooked.

By following these steps, you establish a foundation for applying templates automatically to every new SharePoint site, including those created for Microsoft Teams, enhancing consistency and efficiency across your digital workspace.

Streamlining Site Template Application with Power Automate and Azure Functions

Once a new SharePoint site is created, the flow initiates, albeit with a slight delay. This delay is a small trade-off for the automation benefits you gain. At this stage, your flow can send a message to a queue, including crucial site details such as the ‘SiteUrl’.

Important Note: The activation of this flow is not immediate. There may be a brief waiting period before the flow triggers. Despite this, it remains the most efficient automation method I’ve encountered for this purpose.

Next Steps: Leveraging Azure Functions

The automation journey continues with the creation of an Azure Function, specifically designed to respond to queue messages. This function, triggered by the queue, grants you the power to programmatically adjust your SharePoint site, including the application of the desired site template.

For guidance on creating an Azure Function to apply a site template, please consult the Microsoft documentation. This resource provides comprehensive steps and best practices:

Microsoft Documentation on Creating Azure Functions for Site Templates

This link directs you to detailed instructions for leveraging PnP provisioning with Azure Functions, facilitating the application of site templates in SharePoint.

]]>
https://thomasdaly.net/2024/02/20/sharepoint-site-automatically-apply-site-templates-on-site-creation/feed/ 1 3313
Updating Web Part Properties via Azure Function & PowerShell PnP + Searchable Content https://thomasdaly.net/2024/01/06/updating-web-part-properties-via-azure-function-powershell-pnp-searchable-content/ https://thomasdaly.net/2024/01/06/updating-web-part-properties-via-azure-function-powershell-pnp-searchable-content/#respond Sun, 07 Jan 2024 03:31:52 +0000 https://thomasdaly.net/?p=2901 I’ve been working on an SPFx web part that allows users to edit content on the page without being a Contributor on the site. It’s basically a remake of the Out of the Box Text webpart but putting it all together had some interesting challenges that I want to share.

The focus of this blog is not on the exact solution for the text editor but on how the web part calls an Azure function to update it’s properties AND make the information that is displayed searchable.

What are the major problems?

The users using this web part are visitors. Visitors cannot update edit pages or list items. This web part allows them to edit the content of the web part BUT they can’t actually edit the page and they can’t actually edit update page content or list items.

This is why we need to incorporate the Azure Function. The Azure Function will perform the update using elevated privileges. This allows visitors to edit content on the page without having rights to do so normally.

Architecture

Below is the architecture used in the scenario. The Azure Function in this case is using a Azure AD app permissions, Sites.ReadWrite.All and authenticating via a certificate to access the SharePoint site and make the necessary changes.

SPFx Web Part

On the client side there is a standard SPFx web part that will call an Azure Function with a POST request and a body. This body will contain the content of the web part text. In order for the web part to maintain this information it needs to store this in the Web Part Properties. The web part contains a Web Part Property called Content that is a string value. This is what the web part displays.

Azure Function – PnP PowerShell

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

$cert = "$($TriggerMetadata.FunctionDirectory)\\cert.pfx"
$cert_password = (ConvertTo-SecureString -String $env:CERT_PASSWORD -AsPlainText -Force)

# Parameters for the Webpart update 
$SiteURL = $Request.Query.SiteURL
$Page = $Request.Query.Page
$WebPartIdentity = $Request.Query.WebPartIdentity
$PropertyKey = $Request.Query.PropertyKey
$PropertyValue = $Request.Query.PropertyValue

$v = (Get-Module "PnP.PowerShell").Version
Write-Host $v

$SiteURL = $Request.Body.SiteURL
if (-not $SiteURL) {
    $errorMessage = "SiteURL parameter can not be empty. "
}
$Page = $Request.Body.Page
if (-not $Page) {
    $errorMessage += "Page parameter can not be empty. "
}
$WebPartIdentity = $Request.Body.WebPartIdentity
if (-not $WebPartIdentity) {
    $errorMessage += "WebPartIdentity parameter can not be empty. "
}
$PropertyKey = $Request.Body.PropertyKey
if (-not $PropertyKey) {
    $errorMessage += "PropertyKey parameter can not be empty. "
}
$PropertyValue = $Request.Body.PropertyValue
if (-not $PropertyValue) {
    $errorMessage += "PropertyValue parameter can not be empty. "
}
 
Write-Host "Request Data is ... "

if (-not $errorMessage) {
    try {
        Connect-PnPOnline -Url $SiteURL -ClientId $env:APP_CLIENT_ID -CertificatePath $cert -CertificatePassword $cert_password -Tenant $env:APP_TENANT_ID
        Write-Host "Successfully connected"
        $web = Get-PnPWeb
        $webTitle = $web.Title
        Write-Host "Web: $webTitle"

        $page = Get-PnPPage -Identity $page.Substring($page.LastIndexOf("/") + 1)

        $controls = $page.Controls | Where-Object { $WebPartIdentity -eq $_.Title -or $WebPartIdentity -eq $_.WebPartId -or $WebPartIdentity -eq $_.InstanceId }    

        $controls | ForEach-Object {                        
            Write-Host "Updating web part, Title: " $($_.Title) ", InstanceId: " $($_.InstanceId)
            try {
                $webpartJsonObj = ConvertFrom-Json $_.PropertiesJson

                if ($PropertyKey -and $PropertyValue) {
                    # Check if both PropertyKey and PropertyValue are arrays of the same length
                    if ($PropertyKey.Count -eq $PropertyValue.Count) {
                        for ($i = 0; $i -lt $PropertyKey.Count; $i++) {
                            $webpartJsonObj | Add-Member -MemberType NoteProperty -Name $PropertyKey[$i] -Value $PropertyValue[$i] -Force
                        }
                    }
                    else {
                        # Handle the case where the arrays have different lengths
                        $errorMessage = "PropertyKey and PropertyValue arrays must have the same number of elements. $($PropertyKey.Count) $($PropertyValue.Count)" 
                    }
                }
                else {
                    $errorMessage = "PropertyKey and PropertyValue parameters must be provided as arrays."
                }

                if (-not $errorMessage) {
                    $_.PropertiesJson = $webpartJsonObj | ConvertTo-Json
                    Write-Host "Web part properties updated!" -ForegroundColor Green
                    $body = "Web part properties updated!"
                }
                else {
                    Write-Host $errorMessage -ForegroundColor Red
                    $body = $errorMessage
                }
            }
            catch {       
                $errorMessage += "Failed updating web part, Title: $($_.Title), InstanceId: $($_.InstanceId), Error: $($_.Exception)"                    
                Write-Host "Failed updating web part, Title: $($_.Title), InstanceId: $($_.InstanceId), Error: $($_.Exception)"
            }
        }

        # Save the changes and publish the page
        Write-Host "Saving Page"
        $page.Save()
        $page.Publish()
        Write-Host "Saved Page"

        try {
            $item = Get-PnPListItem -Id $page.PageListItem.Id -List $page.PagesLibrary.Id -Fields "CanvasContent1"
            $canvasContent = $item["CanvasContent1"]
            
            # Load the HTML document using AngleSharp
            $parser = [AngleSharp.Html.Parser.HtmlParser]::new() 
            $document = $parser.ParseDocument($canvasContent)

            # Define the target element selector
            $targetElementSelector = "div[data-sp-webpartdata*='$($WebPartIdentity)'] div[data-sp-htmlproperties='']"

            # Find the target element
            $targetElement = $document.QuerySelector($targetElementSelector)

            $index = $PropertyKey.IndexOf("searchableTextString")
            if ($index -ne -1) {
                # Create a new div element
                $newDiv = $document.CreateElement("div")
                $newDiv.SetAttribute("data-sp-prop-name", "searchableTextString")
                $newDiv.SetAttribute("data-sp-searchableplaintext", "true")
                $newDiv.TextContent = $PropertyValue[$index]

                # Remove all child nodes from the target element
                if ($targetElement.Children.Length -ge 1) {
                    $targetElement.Children.Remove()
                }

                # Append the new div element to the target element
                $targetElement.AppendChild($newDiv)
            }  
            
            # Get the updated HTML content as a string
            $updatedHtmlContent = $document.DocumentElement.OuterHtml

            # Encode special characters
            $encodedString = $updatedHtmlContent -replace '{', '{' -replace '}', '}' -replace ':', ':' -replace [char]0x00A0, " "

            # Update the CanvasContent1 property with the encoded string
            $item["CanvasContent1"] = $encodedString

            $item.SystemUpdate()
            Invoke-PnPQuery
        }
        catch {
            $status = [HttpStatusCode]::BadRequest   
            $errorMessage += $_.Exception.Message
            Write-Host $_.Exception.Message
        }

        Write-Host "$($_) saved and published." -ForegroundColor Green 
        $body += " Page saved and published." 
        $status = [HttpStatusCode]::OK
    }
    catch {
        $status = [HttpStatusCode]::BadRequest   
        $errorMessage += $_.Exception.Message
        Write-Host $_.Exception.Message
    }
}

if (-not $errorMessage) {
    $message = @{
        message = $body | ConvertTo-Json -Compress
    }
} else {
    $message = @{
        message = $errorMessage | ConvertTo-Json -Compress
    }
    $status = [HttpStatusCode]::BadRequest
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $status 
    Body       = $message | ConvertTo-Json -Compress
})

Issue – Updating Web Part Properties from the backend (PnP PowerShell) won’t make the content searchable

There is a bit of magic that happens when you edit a page through the UI. When you edit the page and publish, SharePoint will update a page property called CanvasContent1. In this property it contains web part properties for all web parts on the page as well as the content of the webparts. This holds key information in searchable text strings. All this magic happens when you use the product as designed but when you make an update via PnP PowerShell the CanvasContent1 will not be automagically updated.

This sample code demonstrates a method to update the web part and render a new CanvasContent1. By creating a new CanvasContent1 your content would now be searchable.

]]>
https://thomasdaly.net/2024/01/06/updating-web-part-properties-via-azure-function-powershell-pnp-searchable-content/feed/ 0 2901
Community Days / Sessionize Key Deep Dive https://thomasdaly.net/2023/11/25/community-days-sessionize-key-deep-dive/ https://thomasdaly.net/2023/11/25/community-days-sessionize-key-deep-dive/#respond Sat, 25 Nov 2023 23:32:19 +0000 https://thomasdaly.net/?p=3040 Intro

In the previous article, we discussed creating a basic JSON-formatted API endpoint in Sessionize to integrate your event content, including Speakers, Sessions, and Schedule, into your Community Days event listing.

In this article, we’ll delve into each section in more detail and examine how it affects your event listing on Community Days.

Read First: Creating a Sessionize Key for Community Days

Section Highlights:

Sessionize API Endpoint

Let’s get started – in the following sections we cover the items near the bottom of the page, more specifically the Schedule Grid, Sessions, and Speakers options.

Schedule Grid & Sessions Section

RECOMMENDATION: keep these sections in sync with each other

Parts of the API utilize the Schedule Grid, while others rely on Sessions. To ensure the most consistent experience, maintain the same options for both sections.

NOTE: Your submission fields will be specific to your event. Jump to the Submission Fields / Filter Fields section for more info.

For Hybrid / Virtual events

  • Check Live icon with Link – this will add the link of the session in Community Days for easy access
  • Video Recording Link [optional if available]

NOTE: Live links will be displayed only before the event; they won’t be shown once the event is over.

Result

In Community Days, you can find this on the Sessions Tab.

In Community Days, you can access this on the Speakers Tab.

In Community Days, you can find this information on the Schedule Tab.

Adding Live Links

You can add Live Links to either your Sessions directly or to Rooms. Adding Live Links to Rooms will automatically apply to any Session scheduled in that Room.

Rooms Live Stream Links

Result

The result will be the same as in the previous sections. All Sessions scheduled in that Room will receive the Live Stream Link.

Session Live Stream Links

From the Sessionize left menu, Click Session, then Click the edit button on the Session you wish to add a Live Stream Link to.

Enter the ‘Live stream link’ and optionally the ‘Video recording link’, then click ‘Save changes’.

Result

The result will be the same as in the previous sections. That specific Session will now display a Live Stream Link.

NOTE: If you have added both a Room Live Stream link and a Session Live Stream link, the Session Live Stream link will take priority.

Submission Fields / Filter Fields

This section will show the fields that you can filter by on Community Days, Session Tab. Each event would have different options.

Example: On this call for Speakers page we ask the speakers to provide the Session Format & Track they are applying for.

On the API page we want to include Track so that attendees can filter by this option.

Result

On Community Days, on the event page, Sessions Tab – we now have the option to filter Sessions by Track.

Service Sessions – Registration, Breaks, Lunch, etc..

Service Sessions are blocks of time allocated for Registration, long breaks, Lunch or non-speaker sessions such as Opening, Closing or Network related sessions.

RECOMMENDATION: It’s highly recommended to Include Service Sessions on your Schedule. This lets attendees know about expected breaks so that they can better plan their day and you can set expectations in regard to the event timeline.

Adding Service Sessions

In the left Sessionize Menu – Click Schedule, then Schedule Builder

Click ‘+ Add Service Session’

Enter Detailed Information on this Service Session

Add Service Session to Schedule

Click and drag the Service Session into the Schedule

Click Save Changes

Result

On Community Days, on the event page, Sessions Tab – we now have the new Service Sessions included.

On Community Days, on the event page, Schedule Tab – we now have the new Service Sessions included.

Speakers

This section will show how the Speaker options can add detail to your Speaker listing in Community Days

Links

Community Days will read in and display the following links:

  • Twitter / X
  • LinkedIn
  • Blog
  • Company Website
  • Sessionize

Result

On Community Days, on the event page, Sessions Tab or Speakers Tab, clicking a Speaker will show their provided links.

Show Top Speakers first

Community Days will automatically showcase Top Speakers if they are marked Top Speakers / Featured.

It is recommended to check this option to Show Top Speakers first in the mobile App.

As stated in the previous section, Community Days will always show Top Speakers as Featured Speakers

How to Enable a Top / Feature Speaker

From the Sessions left Menu, Click Speakers, then Click on the Edit button on the Speaker you wish to turn into a Top / Featured Speaker

Check ‘Is top speaker of this event?’, then Click ‘Save changes’

Result

The selected Speaker(s) will be displayed at the top of the Speaker Tab in your event listing.

Conclusion

This concludes this guide on the various options in Sessionize and how they tie into Community Days. If you need more help please leave me a comment or head over to CommunityDays.org and fill out our feedback form.

]]>
https://thomasdaly.net/2023/11/25/community-days-sessionize-key-deep-dive/feed/ 0 3040
Creating a Sessionize Key for Community Days https://thomasdaly.net/2023/11/25/creating-a-sessionize-key-for-community-days/ https://thomasdaly.net/2023/11/25/creating-a-sessionize-key-for-community-days/#comments Sat, 25 Nov 2023 23:02:11 +0000 https://thomasdaly.net/?p=3027 In this walkthrough, we’ll guide you through the steps to create a Sessionize key, which is required by Community Days for integrating your event’s Speakers, Sessions, and Schedule.

Community Days leverages the event content you have on Sessionize.com. By using Sessionize.com, Community will handle displaying your event content in a consistent and user-friendly manner.

Before we begin, please ensure that you have a Sessionize account and an existing event that has been approved on Sessionize.com.

Quick Start – Creating JSON Sessionize Endpoint

Click on your event from the event Dashboard

Next Click on API / Embed

On the API Dashboard you should see 1 Default endpoint. If you look at the Format column you will see ‘Styled Html’. This is used to embed into your existing website. Community Days does not support this format. We use the JSON format and in the next few steps we will walk through the process of creating a new key.  

In the API Dashboard, start by clicking on the ‘Create new endpoint’ button

Next, provide a name for the endpoint, such as ‘Community Days.’ Then, make sure to check the following options:

  • Enabled
  • JSON (coding required)

It’s recommended to include Sessions with the status ‘Accepted and Informed and Confirmed.’ This will display speakers and sessions that have been notified that their content was selected and have confirmed the notice. The default value is ‘Accepted and Informed,’ which will show speakers who have not yet confirmed the selection of their sessions.

Advanced Options

It is recommended to keep the default options here.

This option will only show information on Scheduled sessions. If you do not plan to use Sessionize to build a schedule you may want to change this.

Recommended Options

If you prefer a quick recommendation, refer to the following image and choose the corresponding options. For more advanced information check out: Community Days / Sessionize Key Deep Dive

Finishing Up

Click ‘Create endpoint’

Copy / Paste your Sessionize Key for later use in Community Days and you are all set!

Conclusion

This concludes the basic steps to get your Sessionize content integrated with Community Days.

In the next article, we’ll review each section individually and discuss its impact on the display in Community Days.

Next Article: Community Days / Sessionize Key Deep Dive

]]>
https://thomasdaly.net/2023/11/25/creating-a-sessionize-key-for-community-days/feed/ 1 3027
Azure Web App Deployment Issues https://thomasdaly.net/2022/02/12/azure-web-app-deployment-issues/ https://thomasdaly.net/2022/02/12/azure-web-app-deployment-issues/#comments Sat, 12 Feb 2022 04:56:15 +0000 https://thomasdaly.net/?p=2653 I’ve been having major troubles when I am deploying my Node.js application. It will often get stuck deploying in the Azure Web App b/c of the oryx build process. This is highly frustrating because it already takes close to 10 minutes to produce the build and deploy the web app. These deployments stick regardless of push via Visual Studio Code or through Azure DevOps Pipeline. They don’t stick all the time but when they do it’s seemingly permanent. In this blog I’ll cover the issue that happens and what you can do to revive it.

You’ll know it’s stuck when the deployment takes forever and you check the deployment logs in the Deployment Center and the output is the same each time.

You’ll also know it’s stuck if you try another deployment and you get this error

Error Type 409. “Error: There is a deployment currently in progress. Please try again when it completes.”

Option 1) Delete the web app and recreate it

If you’ve done some research on these you’ll see some issues or forum posts on the topic. Most people have just given up and deleted the entire web app and recreate it from a clean slate. This will work but the package will get stuck again and you’ll soon find that it will become too much work to do all that.

Option 2) Delete the deployment lock files

I literally just started rummaging around the file system when I noticed the deployments folder with some lock files. I cleared that folder, restarted the web app and was able to redeploy again.

These two options will help you get past the stuck in deploying for the current moment. I’m now on the hunt for the cause of the issue. I know this doesn’t happen with the same app deployed to the windows container. It’s somewhat isolated to a Linux container, node.js, and the oryx build. If I figure that out I’ll be sure to post that in a future blog.

]]>
https://thomasdaly.net/2022/02/12/azure-web-app-deployment-issues/feed/ 2 2653
Adding Font Awesome to SPFx React project https://thomasdaly.net/2022/01/20/adding-font-awesome-to-spfx-react-project/ https://thomasdaly.net/2022/01/20/adding-font-awesome-to-spfx-react-project/#comments Thu, 20 Jan 2022 18:39:00 +0000 https://thomasdaly.net/?p=2688 Introduction

I love the FontAwesome library and use it on many projects. I was a huge fan of FontAwesome 4.0 and had a little struggle moving over to using 5.0 + 6.0 in my projects. I was use to the old way of including the link to the CSS files and using the class names. You can still do that if you wish but this article shows using the React component approach. It’s simple once you’ve done it a few times.

Install React Font Awesome

npm i –save @fortawesome/react-fontawesome

Install the Core Packages [required]

npm i --save @fortawesome/fontawesome-svg-core

Install the Icon Packages, use only the ones you need. If you only use solid icons then choose that. If you are not sure right now then you can include them all and remove them later.

npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/free-brands-svg-icons

Go Find a Fonthttps://fontawesome.com/icons

Keep in mind that you only have the free library so you can only use those unless you buy the pro license

If you pick an icon and it says ‘Start Using this Pro Icon’ then you need to choose something else or purchase a license

You can filter the free ones by clicking this on the left.

I’ve selected the fish icon, next you need to take note of the type ‘Solid’ or ‘Regular’

Now import the FontAwesomeIcon component and the icon you want from the correct package

This fish icon is in the Solid package.

If I wanted to use something from the regular package like this icon

This font is in ‘Regular’ package you would import it from that package instead

There is intellisense inside visual studio to help get the correct name of the icon

Now the result

If you wanted to use the brand icons you would follow the same approach. I believe that all the brands icons are free.

I love FontAwesome library of icons and use them in many projects. The PRO version unlocks so many more fonts and customizations that it’s worth buying if you plan to use them and want to support this project.

]]>
https://thomasdaly.net/2022/01/20/adding-font-awesome-to-spfx-react-project/feed/ 2 2688
Azure Community Bootcamp 2021 https://thomasdaly.net/2021/11/20/azure-community-bootcamp-2021/ https://thomasdaly.net/2021/11/20/azure-community-bootcamp-2021/#respond Sat, 20 Nov 2021 03:53:29 +0000 https://thomasdaly.net/?p=2635

Introduction

After an event I like to wrap up some of my thoughts on how the event started and some of the lessons learned. This post will be broken out into the two parts of the story on the event and then some of the lessons that come with running an event. For those that don’t know me I run many community events in the NY/NJ/PA area and involved with helping other events either get started or with supporting them by volunteering my skills, time or helping them reach people.

The Back Story

Each year I host a local Azure event in New Jersey as part of the Global Azure Bootcamp. It’s a 1 day event held on a Saturday at the local Microsoft office in Iselin, NJ. It’s been a very successful event with about 90 out of a possible 100 that can fit in that office safely. In our area we’ve seen a demand for Azure training and information grow drastically over the past 3 years. Due to the local office being closed for public events we’ve had to spread our wings and take to the cloud.

This year was our first virtual Azure event on our own. Alone in the sense of no major support from a company. It would be a grassroots event where we would have to push this out to the public to gather sponsors, speakers and attendees with little visibility / marketing. Events like this cannot happen alone. You need a solid team to help and that’s something that I knew I had in my pocket.

It start with a phone call from Rajaniesh Kaushikk who was an attendee at the 3rd Global Azure Bootcamp. He reached out to me and said we haven’t had an Azure event since the pandemic, would it be possible to run one before the end of the year. If it wasn’t for his push, I would probably never have run this event. Raj’s energy had set the spark for me to gather the team. Jason Rivera who runs M365 Philly events like the User Group and M365 Saturdays. Manpreet Singh from the Tech Platform who always helps out with NY/NJ/PA events and many other events within the community.

The bootcamp was initially planned to have 4 speakers and short and quick, easy to manage. What would be a small event with a few people, no stress, easy to manage. We put out some feelers but launching a call for speakers on Sessionize.com. We were a bit overwhelmed with the response. Speakers from around the globe were applying to our little event from regular people wanting to share their experience, seasoned professionals, Microsoft Certified Trainers and even Microsoft Azure MVPs. We had 34 sessions and 22 speakers to choose from which included 8 Microsoft MVPs, a handful of C# Corner MVPS, Bloggers, Speakers, YouTubers. Quickly our event gained some momentum at least from the speaker community. We ultimately settled on 18 speakers, although we knew that would be a handful to deal with in just 1 day. We had to have 2 tracks and run longer than we’d like to. It was a virtual event, so our focus wasn’t on just EST time, we knew we’d have audience in attendance from other areas.

As I just mentioned the event was planned around EST time. This created some challenges for speakers from around the globe. We had some dedicated speakers! Eric Cheng from Sydney, Australia presented his session from 3am his time. Any many others presenting at 9pm their time. I was blown away by the commitment of the speakers and they were so appreciative of the opportunity to speak at this event.

Running the Event

Prep Work

There is a lot of work that goes into these events. There’s a ton that goes into prior to anything you might even see from the outside. I’ll shed some light into some of the major areas.

Team – you need a solid team of people to do actual work. You don’t want to end up doing everything yourself. I am known for taking on too many things and doing everything myself. You need to form a team and be able to plan, delegate, track, and keep that ball rolling. This is always challenging in a community ‘free’ event. Watch out for volunteers that simply volunteer to put their name on it. You need grunts and you need influencers. It’s very common for other MVPs to come along and offer to help but those typically aren’t the ones that put in the real work. They might help your event get some notoriety or help with promotions, but they aren’t the ones building the website or making slides [typically]. Get a balanced team – with some people that are motivated to help and do work. If you’re the leader then you need to be sure to lead and delegate. Give people tasks and check in and follow up weekly / bi-weekly.

Graphics – no event can happen without some great graphics. You need catchy event graphics, speaker promotions, sponsor promotions and more. You could sub this out to fiverr but if you can link up with someone that can use Canva or even better Photoshop then you’ll be set. I used to do all the graphics but for this event I was able to get help from Omer at SoHo Dragon.

Social Media Promotion – no event can happen without promotion. You won’t be seen or noticed without a social media presence. We failed in this event to secure an Azure Community Bootcamp twitter profile, so everything went out from my personal account or M365 NYC account. I’m sure people were not thrilled to be getting tons of promotions from my personal twitter and LinkedIn, but I didn’t care that much. Mute me. The point is that you need to get the word out. Involved the speakers, sponsors and organizers in the promotion. It’s everyone’s job. If you can create a game for attendees to promote, then do that as well. Our primary methods of promotion were LinkedIn and Twitter. We posted our event on Eventbrite which has some built in traffic that can also help. We also cross posted on the NJ & PA user groups on Meetup.com. In hindsight I should have reached out across the USA to the Azure meetups. I would have if I had more time.

Ticketing – mentioned above we used Eventbrite for our ticketing which can help with some promotion sales. It takes a good amount of time to setup the Eventbrite for an event. It’s not difficult but you should be asking questions and gathering the correct information of the attendees. You want to think about collecting information if you are sharing with sponsors. Important things like company, location, phone. You must also ask if you can share the information. I highly suggest an option to be added to the mailing list. Building a mailing list is critical for building an audience.

Website – you will need a website. Hopefully someone on your team can make one or you could use a wix.com site. We’d prefer to have a custom site, but we started out with no site. Ultimately, we decided we needed a site to look like a legit event. Legit in the eyes of the world you at least need a website. Not a meetup.com event, not a Eventbrite event. You need a place on the internet that you can see the event, the schedule, the speakers, etc. We went with wix.com because we could have a site up and running within a few hours. Another requirement is that it needs to be mobile accessible. Using wix it was easy enough for volunteers to help update and did not need to know programming languages or anything else. Just use the web interface to make changes. We also used Sessionize embed for the speaker / sessions / schedule which was a bonus since we did not have to build that integration. You can check it out here – https://www.azurecommunitybc.com/

Speaker Call – having a formal speaker call allows potential speakers to submit their information to you for evaluation. Sessionize.com works great for FREE events. ** Sessionize is a pay service BUT is FREE for a FREE event. You must apply when you host a free event to get it for free **. You can use the speaker call to bring in speakers. You can customize the form with custom questions. The platform allows you to invite content members to help select speakers. You can accept / deny speakers from the platform easily. You can build the schedule inside the platform with rooms and time slots. You can email out all the speakers from it to communicate event updates. Most importantly you can use all the information from Sessionize to embed into another website. You do not need to recreate the schedule, sessions or speaker lists on your site. You can simply use the embed code to post the information. If your feeling frisky you can even customize the CSS to style it as you wish.

Sponsors Call – Community events I run are free, but we do need sponsors to help. Sponsors help pay for website costs, domain names, email accounts, and some other misc fees. Once you run an LLC for a User Group you’ll see. You need to file taxes, have accounting software and whatnot. Even though I keep those at the bare minimum there are other expenses. Plus, you want to have a great event with some giveaways. Normally the sponsor dollars cover food which is not happening at the moment, so they cover the web hosting fees + giveaways. It’s the truth that someone pays for a free event. I’ve covered many a user group pizza night on my own dime. It’s fine because I am able and willing to do so. You understand when you run a user group. My insight here is keep the sponsorships to a normal amount and make it fair. We didn’t solicit sponsors for money for this event, I just wasn’t prepared to ask for money not knowing the outcome. I felt that big sponsors wouldn’t be interested in such a small event [turned out to not so small]. Our sponsors have donated resources like time from their employees or services. We thank SoHo Dragon and the Tech Platform for their support this year. Both of those sponsors help out with ALL of my events no matter how big or small.

Tech Challenges

Meeting Platform – we chose MS Teams Live Events to run the meetings. There are some pros and cons to this approach.

Pros #1 it’s easy, you run 1 long event for each track and you are done. No need to have attendees drop in and out of sessions. This was a huge draw since we did not have a huge moderator team. #2 you can’t see the live attendees – if there are no attendees the speaker doesn’t know so they don’t act differently. Present without the concept of an audience. We’ve seen / attended and even presented to teams events with 1 or 2 people and it’s just not fun. [not this event but with others]

Cons #1 you can’t see the live attendees – The speaker doesn’t know who is in the session or how many people attend. This can throw speakers off if they plan to have Q/A or interactive sessions. It just doesn’t work in this format without planning [using surveys or forms for questions and circling back], #2 there is a delay – this causes disconnect between the presenter and the audience. If you are asking questions, it just doesn’t work great. It can take a minute or so before the audience hears the question and then replies.

Tech Check – Always do a tech check with MS Teams. Make sure the users can log in and share their screen on the same computer they will do it live. It verifies that the account can get in with no issues. We’ve seen people attend the tech checks and then not able to join because they are using a different computer or different account. We’ve seen people have issues b/c their session is about teams and they need to be logged in to present and also log into teams. They need to use a VM in that case to be part of the live event and show another MS Teams tenant. Also if you get any last minute speakers always do a tech check [got us this time]. We’ve seen people use gmail accounts and then have difficulties logging into MS Teams because it needs a MS based account like hotmail/outlook.

Time Check – send out the schedule in your time zone. Don’t depend on the web or Sessionize to convert it correctly. We had some speakers at the wrong time because they saw online at some point it say something else. Make sure to send the print out / email of the schedule with the time in your time zone.

Multiple Presenters – MS Teams multiple presenters is a problem. One event I moderated had 3 presenters that I would be constantly changing the web cam for. Teams can only show 1 webcam at a time. This is a problem for us in the wrap up session. We want to have all of our organizers on to say their last words about the event. We use streamyard.com to create a live event on youtube and forward our attendees there for the last sessions [the wrap up]. We still don’t know who shows up but it allows up to wrap up the event with a little behind the scenes footage. We give our take and thank everyone involved. Sometimes we raffle items off in there as the close out and if not we just use that as the organizer platform to speak our minds.

Communication – over communication is never a problem. Stay in touch frequently with your speakers and attendees. Let them know about the event at least once a week when you are in the final month. Attendees need to know how to easily access the sessions. Give them multiple ways to get in – post is in the email, use the web, blast it out on social media. It’s never a problem to over communicate how to attendee the event. Same with the speakers – let them know about event changes with the schedule or format. Give them access to a OneDrive folder with the content for promotion materials, slide decks or whatever else you might have for them.

Moderators – have enough moderators for each session. The purpose of the moderator is the welcome the speaker and inform them of any last minute changes, how to share screen, let the speaker know that nothing is sharing, how to turn on subtitles and remind them when time is up and to show the event slides / feedback slide. Have a dedicated moderator for each session and 1 backup so that people can switch out. Never let someone moderate [alone] that hasn’t moderated before. Put a moderator schedule out ahead of time so everyone can confirm that they will be on the watch for their session.

Physical Challenges

Time Management – running events is a full day affair. If your involved, you’ll likely have to take off work. There’s no room to concentrate on the event and try to take a meeting. That means be aware of business owners / CEOs or CTOs on your team. They would likely get pulled away with some emergency. You need reliable sources to help the event.

Real Life – If you have kids let the team know when you won’t be available because you’ll need to focus if you want to do a proper job. My kids are young, so they don’t really listen when I say play quietly. To them that means check out who’s on the camera, draw behind me on the whiteboard, rip my office apart, play with loud toys or just fight because I can’t stop them. They might have made an appearance in this event.

Bio Breaks – you can’t be moderating all sessions on two computers. Sure, it’s possible for a short time but not all day. Make sure you have back up and let the speakers know that you’ll be in the session to help out but popping in and out every 10 minutes. This gives you are free minute to use the bathroom or stretch your legs. It’s impossible to sit at the computer the entire day without leaving. You need to program in some breaks for your person.

Summary

What a day, what a day. The experience of running a virtual event doesn’t even come close to a live event. Live events you get that instant satisfaction of meeting people and hearing about their experience. Virtual events you get to read about it from the few that bother to fill out our the feedback form. If you know me then you know I’m not a huge fan of virtual events, but I know that they are important to keeping the community alive during this time. Despite some of our challenges above I would consider the 2021 Azure Community Event a success. We did it, we held a unique online event that reached 100’s of people and I’m happy with that. We held an event that hosted 18 speakers of high caliber, with 2-3 moderators, 4 organizers, no monetary sponsorships, 1 day, 10 hours, 2 tracks, planned within 2.5 months.

You can visit the event website here – https://www.azurecommunitybc.com/ . We’ll be posted the recordings from the event within the next week. Leave me a comment, let me know if you have questions about running an event in your area or online.

** At the time of this writing I have not yet read any event feedback from our attendees. **

]]>
https://thomasdaly.net/2021/11/20/azure-community-bootcamp-2021/feed/ 0 2635
Alerts Header – SPFx project https://thomasdaly.net/2021/10/10/alerts-header-spfx-project/ https://thomasdaly.net/2021/10/10/alerts-header-spfx-project/#comments Sun, 10 Oct 2021 21:24:00 +0000 https://thomasdaly.net/?p=2660

Introduction

This new project is a nice little feature that you can easily add to your SharePoint site to enable site messages or alerts. Having the ability to display site alerts is one of the top 10 most requested features to enhance SharePoint. This customization is built as an SPFx application customizer, with a little bit of UI hacking. This project can be used as-is or as a starting point for you to extend and create your own combinations of notifications, icons and colors.

  • Git Repo
  • Pre-Build SPPKG
  • Overview

    The Alerts Header solution contains an SPFx application customizer and a list schema for the alerts messages. The list will automatically be created for you when the app is added to your site. Currently the app displays messages from the site it’s in but could be easily modified to pull notifications from another site. Initially this was designed to be deployed the the entire intranet and activated on each site. Each site had the option to display ‘local’ alerts, alerts contained within the site and remote alerts, alerts contained at the root site collection “/”. The remote alert functionality has been commented out for simplicity in the Git Hub repo but could be reenabled with just a little effort.

    Implementation

    The List

    The solution installs an ‘Alerts’ list in your site. This list contains a number of required fields to properly display the alerts.

    Title – The first part of the text that is displayed

    Description – The second part of the text that is displayed. The description will fill the reminder of the space and truncate with ‘…’

    Alert Type – The icon that is displayed. Warning, Actionable or Info as show below from top to bottom.

    Link – The navigation url and the text that will be displayed

    Start Date / Time – The date and time that the alert will be displayed

    End Date / Time – The date and time that the alert will no longer be displayed

    Items will immediately start to show up once they are added to the list and hit the duration between the start and end date.

    The Web Part

    This view below shows the alerts application customizer with all three types of alerts and active.

    Icons – The icons used are from the Font Awesome 5.0 free library. You could easily update the code to change out the icons.

    Expand / Collapse – If the alert has a long description it will be truncated once it fills the available screen space. The up / down arrow will allow the user to expand and collapse the alert to read the full description.

    Dismiss / Close – The alert has and close icon at the far right to dismiss the alert. The alert will no longer show during that session. A new session will display the alert again. New Tabs are equivalent to new sessions.

    SharePoint UI Hack – I hinted earlier that I’ve included a bonus UI Hack for free, haha. Take a peek at the picture below. The normal location of an application customizer is at the very top of the page. I did not want the alerts to show up there so I opted to move them to the bottom of the header. This is a non supported customization according to Microsoft. I’m pointing this out for transparency.

    Responsive / Mobile Friendly – The web part was designed with the intention of working across all devices and screen sizes. The functionality is somewhat different on the mobile. Once the item is expanded it can only be closed. I’ve do it this way to intentionally close them out to regain the screen real estate back on the small devices.

    Customizations

    The web part comes with a few notification types. You can add more types directly to the list or to the list schema. After you add new Alert Types you would then need to do a few more updates

    IAlerts.types.ts – Add your new Alert Types to the enumeration

    AltertItem.tsx – Add new conditions for the new Alert Types and the icon you want to use

    AlertItem.module.scss – Copy / Paste an existing Alert Type combination and change the colors to meet your needs.

    Conclusion

    Site Alerts are one of the top 10 features requested from clients and customers to build. I’m happy to be able to post this feature to share even though it’s not 100% Microsoft compliant. The tiny UI hack positions this feature in the location where I felt it belongs. I hope and wish that Microsoft would give us more Zones in which we could target in the application customizers.

    ]]>
    https://thomasdaly.net/2021/10/10/alerts-header-spfx-project/feed/ 13 2660