Saturday, February 25, 2023

Creating a Planner tab in Teams, including a number of Tasks, in an Azure Function

( Updated 1 March 2023)

As part of an update to a provisioning tool I was looking into creating a Planner, a Bucket and a handful of tasks and finally connecting the Planner to a tab in one of the channels in my Teams Team.   




The tools of choice is an Azure Function running PnP.PowerShell ( version 1.12 )  as this combo allows both us and the client to alter existing functions and create new ones without having to hire a hardcore developer. Quite a few consultants and IT administrators knows enough PowerShell to work with these fairly simple scripts.  💪

Creating the Planner, the bucket and the tasks goes like this: (draft version , not ready for product yet)



$localConn = Connect-PnPOnline -Url $siteUrl -ClientId $ClientId -thumbprint $thumbprint -Tenant $TenantName -ReturnConnection -erroraction stop

$PlannerPlan = Get-PnPPlannerPlan -Group $groupId -Identity $PlannerName -Connection $localConn

if(-not $PlannerPlan)
{
    $PlannerPlan = New-PnPPlannerPlan -Group $groupId -Title $PlannerName -Connection $localConn
}

$bucket = Add-PnPPlannerBucket -Group $groupId -Plan $PlannerPlan.Id -Name "Tasks" -Connection $localConn

$newTask = Add-PnPPlannerTask -Group $groupId -Plan $PlannerPlan.Id -Bucket $bucket.Id -Title "Task A" -Connection $conn

$newTask = Add-PnPPlannerTask -Group $groupId -Plan $PlannerPlan.Id -Bucket $bucket.Id -Title "Task B" -Connection $conn

$newTask = Add-PnPPlannerTask -Group $groupId -Plan $PlannerPlan.Id -Bucket $bucket.Id -Title "Task C" -Connection $conn

$newTask = Add-PnPPlannerTask -Group $groupId -Plan $PlannerPlan.Id -Bucket $bucket.Id -Title "Task D" -Connection $conn

$plannerChannel = Get-PnPTeamsChannel -Team $groupId -Connection $conn | Where-Object {$_.DisplayName -eq "RFP"}

However, connecting the Planner to the tab in Teams proved to be a challange as the Add-PnPTeamsTab looks like this:


Prefect, as one of the options in the Type enum is "Planner" this should do the trick:

Add-PnPTeamsTab -Team $groupId -Channel $teamsChannel -DisplayName "RFP" -Type Planner -ContentUrl $contentUrl


But no. Error : Add-PnPTeamsTab: A parameter cannot be found that matches parameter name 'ContentUrl'.


Later in the day I saw that @PaoloPia (Paolo Pialorsi) had released a YouTube video : "Learn how to use Graph to automate provisioning of Planner plans, buckets, and tasks". In that video Paolo was using MS Graph to create the tab and connect it to the Planner.

When I added a comment on Twitter that I most likely was going to use the same approach as the Add-PnPTeamsTab approach apparently didn't work.

Gautam Sheth (@gautamdsheth) saw this and answered that I should use -type "Custom" instead as this would allow me to set the ContentUrl.

This will create a Planner tab to your channel:

$teamsTab = Add-PnPTeamsTab -Team $groupId -Channel $plannerChannel -DisplayName "RFP" -Type Custom -TeamsAppId "com.microsoft.teamspace.tab.planner" -Connection $conn -ContentUrl "https://tasks.office.com/[TenantName].onmicrosoft.com/Home/PlannerFrame?page=7&planId=$($PlannerPlan.Id)"


So thanks to a comment on Twitter and to Paolo and Gautam I learned something new, got the function to work using PnP.PowerShell exclusively. 

In order to ensure that this option reaches a broader audience the documentation for Add-PnPTeamsTab has been updated with a example like the code above.

  
Update 1 March 2023:

Gautam has updated the Cmdlet and I have updated the documentation with this example:
No need to use -Type Custom anymore ✌




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.