From 3aefed4cf54ca93d9a0c3f69065eecadfc6d0945 Mon Sep 17 00:00:00 2001 From: Milan Holemans <11723921+milanholemans@users.noreply.github.com> Date: Sun, 12 Jun 2022 22:59:42 +0200 Subject: [PATCH 1/2] Adds extra parameters to Add-PnPPlannerTask --- documentation/Add-PnPPlannerTask.md | 89 +++++++++++++++- src/Commands/Planner/AddPlannerTask.cs | 125 ++++++++++++++++++----- src/Commands/Utilities/PlannerUtility.cs | 24 +---- 3 files changed, 187 insertions(+), 51 deletions(-) diff --git a/documentation/Add-PnPPlannerTask.md b/documentation/Add-PnPPlannerTask.md index 2842abfaf..05360796d 100644 --- a/documentation/Add-PnPPlannerTask.md +++ b/documentation/Add-PnPPlannerTask.md @@ -21,12 +21,18 @@ Adds a new task to a planner bucket ### By Group ```powershell -Add-PnPPlannerTask -Group -Plan -Bucket -Title [-AssignedTo ] +Add-PnPPlannerTask -Group -Plan -Bucket -Title +[-PercentComplete ] [-DueDateTime ] [-StartDateTime ] + [-AssignedTo ] [-Description ] + [] ``` ### By Plan Id ```powershell -Add-PnPPlannerTask -Bucket -PlanId -Title [-AssignedTo ] +Add-PnPPlannerTask -Bucket -PlanId -Title +[-PercentComplete ] [-DueDateTime ] [-StartDateTime ] + [-AssignedTo ] [-Description ] + [] ``` ## DESCRIPTION @@ -148,6 +154,85 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -StartDateTime +Defines the start date of the task. + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DueDateTime +Specify the due date. + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PercentComplete +Defines the percentage of completeness of the task. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Priority +Sets the priority of the task. Value should be a number between 0 and 10. +- values 0 and 1 are interpreted as _Urgent_ +- values 2, 3 and 4 are interpreted as _Important_ +- values 5, 6 and 7 are interpreted as _Medium_ +- values 8, 9 and 10 are interpreted as _Low_ + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Description +Sets the description (notes) of the task. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/src/Commands/Planner/AddPlannerTask.cs b/src/Commands/Planner/AddPlannerTask.cs index 30bb48472..7cb566ea0 100644 --- a/src/Commands/Planner/AddPlannerTask.cs +++ b/src/Commands/Planner/AddPlannerTask.cs @@ -1,10 +1,15 @@ -using System.Management.Automation; using PnP.PowerShell.Commands.Attributes; using PnP.PowerShell.Commands.Base; using PnP.PowerShell.Commands.Base.PipeBinds; +using PnP.PowerShell.Commands.Model.Planner; using PnP.PowerShell.Commands.Utilities; +using PnP.PowerShell.Commands.Utilities.REST; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; -namespace SharePointPnP.PowerShell.Commands.Graph +namespace PnP.PowerShell.Commands.Planner { [Cmdlet(VerbsCommon.Add, "PnPPlannerTask")] [RequiredMinimalApiPermissions("Group.ReadWrite.All")] @@ -28,53 +33,119 @@ public class AddPlannerTask : PnPGraphCmdlet [Parameter(Mandatory = true, ParameterSetName = ParameterAttribute.AllParameterSets)] public string Title; + [Parameter(Mandatory = false)] + public int PercentComplete; + + [Parameter(Mandatory = false)] + public int Priority; + + [Parameter(Mandatory = false)] + public DateTime DueDateTime; + + [Parameter(Mandatory = false)] + public DateTime StartDateTime; + + [Parameter(Mandatory = false)] + public string Description; + [Parameter(Mandatory = false, ParameterSetName = ParameterAttribute.AllParameterSets)] public string[] AssignedTo; + protected override void ExecuteCmdlet() { + PlannerTask createdTask; + var newTask = new PlannerTask + { + Title = Title + }; + + if (ParameterSpecified(nameof(PercentComplete))) + { + if (PercentComplete < 0 || PercentComplete > 100) + { + throw new PSArgumentException($"{nameof(PercentComplete)} value must be between 0 and 100.", nameof(PercentComplete)); + } + newTask.PercentComplete = PercentComplete; + } - if (ParameterSetName == ParameterName_BYGROUP) + if (ParameterSpecified(nameof(Priority))) { - var groupId = Group.GetGroupId(HttpClient, AccessToken); - if (groupId != null) + if (Priority < 0 || Priority > 10) { - var planId = Plan.GetIdAsync(HttpClient, AccessToken, groupId).GetAwaiter().GetResult(); + throw new PSArgumentException($"{nameof(Priority)} value must be between 0 and 10.", nameof(Priority)); + } + newTask.Priority = Priority; + } - if (planId != null) - { - var bucket = Bucket.GetBucket(HttpClient, AccessToken, planId); - if (bucket != null) - { - PlannerUtility.AddTaskAsync(HttpClient, AccessToken, planId, bucket.Id, Title, AssignedTo).GetAwaiter().GetResult(); - } - else - { - throw new PSArgumentException("Bucket not found", nameof(Bucket)); - } + if (ParameterSpecified(nameof(StartDateTime))) + { + newTask.StartDateTime = StartDateTime.ToUniversalTime(); + } - } - else + if (ParameterSpecified(nameof(DueDateTime))) + { + newTask.DueDateTime = DueDateTime.ToUniversalTime(); + } + + if (ParameterSpecified(nameof(AssignedTo))) + { + newTask.Assignments = new Dictionary(); + var chunks = AssignedTo.Chunk(20); + foreach (var chunk in chunks) + { + var userIds = BatchUtility.GetPropertyBatchedAsync(HttpClient, AccessToken, chunk.ToArray(), "/users/{0}", "id").GetAwaiter().GetResult(); + foreach (var userId in userIds) { - throw new PSArgumentException("Plan not found", nameof(Plan)); + newTask.Assignments.Add(userId.Value, new TaskAssignment()); } } - else + } + + // By Group + if (ParameterSetName == ParameterName_BYGROUP) + { + var groupId = Group.GetGroupId(HttpClient, AccessToken); + if (groupId == null) { throw new PSArgumentException("Group not found", nameof(Group)); } + + var planId = Plan.GetIdAsync(HttpClient, AccessToken, groupId).GetAwaiter().GetResult(); + if (planId == null) + { + throw new PSArgumentException("Plan not found", nameof(Plan)); + } + newTask.PlanId = planId; + + var bucket = Bucket.GetBucket(HttpClient, AccessToken, planId); + if (bucket == null) + { + throw new PSArgumentException("Bucket not found", nameof(Bucket)); + } + newTask.BucketId = bucket.Id; + + createdTask = PlannerUtility.AddTaskAsync(HttpClient, AccessToken, newTask).GetAwaiter().GetResult(); } - else if (ParameterSetName == ParameterName_BYPLANID) + // By PlanId + else { var bucket = Bucket.GetBucket(HttpClient, AccessToken, PlanId); - if (bucket != null) - { - PlannerUtility.AddTaskAsync(HttpClient, AccessToken, PlanId, bucket.Id, Title).GetAwaiter().GetResult(); - } - else + if (bucket == null) { throw new PSArgumentException("Bucket not found", nameof(Bucket)); } + + newTask.PlanId = PlanId; + newTask.BucketId = bucket.Id; + + createdTask = PlannerUtility.AddTaskAsync(HttpClient, AccessToken, newTask).GetAwaiter().GetResult(); + } + + if (ParameterSpecified(nameof(Description))) + { + var existingTaskDetails = PlannerUtility.GetTaskDetailsAsync(HttpClient, AccessToken, createdTask.Id, false).GetAwaiter().GetResult(); + PlannerUtility.UpdateTaskDetailsAsync(HttpClient, AccessToken, existingTaskDetails, Description).GetAwaiter().GetResult(); } } } diff --git a/src/Commands/Utilities/PlannerUtility.cs b/src/Commands/Utilities/PlannerUtility.cs index 2b54438e7..92b0c71dc 100644 --- a/src/Commands/Utilities/PlannerUtility.cs +++ b/src/Commands/Utilities/PlannerUtility.cs @@ -161,29 +161,9 @@ public static async Task GetTaskDetailsAsync(HttpClient http return taskDetails; } - public static async Task AddTaskAsync(HttpClient httpClient, string accessToken, string planId, string bucketId, string title, string[] assignedTo = null) + public static async Task AddTaskAsync(HttpClient httpClient, string accessToken, PlannerTask task) { - StringContent stringContent = null; - if (assignedTo != null) - { - var assignments = new Dictionary(); - var chunks = BatchUtility.Chunk(assignedTo, 20); - foreach (var chunk in chunks) - { - var results = await BatchUtility.GetPropertyBatchedAsync(httpClient, accessToken, chunk.ToArray(), "/users/{0}", "id"); - foreach (var userid in results.Select(r => r.Value)) - { - assignments.Add(userid, new Model.Planner.PlannerAssignedToUser()); - } - } - stringContent = new StringContent(JsonSerializer.Serialize(new { planId = planId, bucketId = bucketId, title = title, assignments = assignments })); - } - else - { - stringContent = new StringContent(JsonSerializer.Serialize(new { planId = planId, bucketId = bucketId, title = title })); - } - stringContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); - return await GraphHelper.PostAsync(httpClient, "v1.0/planner/tasks", stringContent, accessToken); + return await GraphHelper.PostAsync(httpClient, "v1.0/planner/tasks", task, accessToken); } public static async Task DeleteTaskAsync(HttpClient httpClient, string accessToken, string taskId) From 5bc323062ac6dc8ffbdf26d1c04c4e619f6aad73 Mon Sep 17 00:00:00 2001 From: Koen Zomers Date: Tue, 14 Jun 2022 14:06:57 +0200 Subject: [PATCH 2/2] Added changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ff71cab7..0f615e3b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added `Add-PnPListItemAttachment` cmdlet to provide ability to upload a file as an attachment to a SharePoint list item. [#1932](https://github.com/pnp/powershell/pull/1932) - Added `Remove-PnPListItemAttachment` cmdlet to provide ability to delete a list item attachment. [#1932](https://github.com/pnp/powershell/pull/1932) - Added `Get-PnPListItemAttachment` cmdlet to download the attachments from a list item. [#1932](https://github.com/pnp/powershell/pull/1932) +- Added `-PercentComplete`, `-Priority`, `-StartDateTime`, `-DueDateTime` and `-Description` to `Add-PnPPlannerTask` [#1964](https://github.com/pnp/powershell/pull/1964) ### Changed - Changed `Sync-PnPSharePointUserProfilesFromAzureActiveDirectory` to map users based on their Ids instead which should resolve some issues around user identities reporting not to exist. You can use the new `-IdType` option to switch it back to `PrincipalName` if needed. [#1752](https://github.com/pnp/powershell/pull/1752)