首先自然是先介绍一下Planner。Planner是Office 365的组件之一,用于团队任务管理。
Planner通过在内部搜集管理任务来帮助团队进行自我管理和快速开始新项目。Planner提供跟踪进度的能力、提供会话的功能,并能将报告状态以不同的图表呈现。Microsoft Planner是Office 365生态系统的一部分,自然Microsoft Graph中具有Planner相关的API。如果读者想要了解更多关于服务自身的内容,微软建议大家查看详细的介绍。总之今天我们介绍的内容是如何利用Microsoft Graph的API去自动化和集成Planner的一些内容。
Plans是Planner的起点,也就是基础单元。它是一个任务、设置和其他内容的逻辑容器。现阶段,plans必须创建在Office 365组的下面,一个组可以包含多个plans。用户可以通过Planner(tasks.office.com)和Microsoft Teams(添加标签页时)创建plans。作为开发者,我们可以通过planner/plans终结点去创建新的plans。有两点要注意:plans也遵从安全设置;plan的owner属性必须设置为其关联的组的Id。
我们今天要演示的就是用代码创建plans。
Buckets,直译是桶的意思,它实际上是plan中的一个逻辑容器,也可以理解为Planner的第二级容器。Buckets帮助用户组织他们的任务,如基于步骤、状态、分类和所有权等,这取决于团队要如何使用。每个Bucket在Planner中展示为垂直的一列。
作为开发者,我们可以利用Microsoft Graph去创建/更新/删除buckets。这在我们想要模板化plans时很有用。试想假设我们为一家提供市场服务的咨询公司工作,其中大多数的广告活动项目都遵从相同的模式:一些属于设计者的任务,一些属于网站长的任务,一些属于社区管理者的任务和一些印刷层的任务等。我们完全可以想象得到,创建新项目和plans的自动化,包含了一些默认的buckets用来分工。buckets终结点可以帮助我们实现它。
任务就不需要过多解释了,因为它就是任务……是指一个项目中想要完成的单元工作以推进项目的顺利进行。通过tasks终结点我们可以创建/读取/更新/删除任务及其相关的细节信息,包括分类、进度、受理人、讨论区等。
继续上面提到的那个例子,向模板里继续添加默认的tasks并指派给相关的人员,这使得模板更加丰富了。
现阶段,跟Planner交互需要Groups.Read.All或Groups.ReadWrite.All权限。我们这次代码演示的内容会向Planner写数据,因此需要Groups.ReadWrite.All权限,同时需要查询租户内的用户,也需要User.ReadBasic.All权限。
介绍完了该说代码了。
Step 1. 更新应用程序注册权限
前面介绍了,不多说了,如果还没有所需的权限就更新一下,记得选择托管权限。
Step 2. 确保要使用的用户属于某个Office 365组
为了用于演示,其实最简单的方式就是用我们的用户创建一个新组。
Step 3. 为你的应用启用设备码流支持
可以参考上一篇。
本文的示例需要设备码流进行认证。
Step 4. 代码实现
在Helpers文件夹中创建一个新类PlannerHelper.cs,并替换为以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Graph;
namespace GraphDemo
{
public class PlannerHelper
{
private readonly GraphServiceClient _graphClient;
public PlannerHelper(GraphServiceClient graphClient)
{
_graphClient = graphClient ?? throw new ArgumentNullException(nameof(graphClient));
}
public async Task PlannerHelperCall()
{
//Getting the first group we can find to create a plan
var groupId = (await _graphClient.Me.GetMemberGroups(false).Request().PostAsync()).FirstOrDefault();
if (groupId != null)
{
var users = await _graphClient.Users.Request(new List {
new QueryOption("$top", "3")
}).GetAsync();
var planId = await GetAndListCurrentPlans(groupId) ?? await CreatePlannerPlan(users, groupId);
}
}
private async Task GetAndListCurrentPlans(string groupId)
{
//Querying plans in current group
var plans = await _graphClient.Groups[groupId].Planner.Plans.Request(new List
{
new QueryOption("$orderby", "Title asc")
}).GetAsync();
if (plans.Any())
{
Console.WriteLine($"Number of plans in current tenant: {plans.Count}");
Console.WriteLine(plans.Select(x => $"-- {x.Title}").Aggregate((x, y) => $"{x}\n{y}"));
return plans.First().Id;
}
else
{
Console.WriteLine("No existing plan");
return null;
}
}
private async Task CreatePlannerPlan(IEnumerable users, string groupId)
{
// Getting users to share the plan with
var sharedWith = new PlannerUserIds();
users.ToList().ForEach(x => sharedWith.Add(x.Id));
// Creating a new planner plan
var createdPlan = await _graphClient.Planner.Plans.Request().AddAsync(
new PlannerPlan
{
Title = $"My new Plan {Guid.NewGuid().ToString()}",
Owner = groupId,
Details = new PlannerPlanDetails
{
SharedWith = sharedWith,
CategoryDescriptions = new PlannerCategoryDescriptions
{
Category1 = "my first category",
Category2 = "my second category"
},
}
}
);
Console.WriteLine($"Added a new plan {createdPlan.Id}");
return createdPlan.Id;
}
}
}
扩展Program类去列出存在的Plans
在Program类中更新Main方法,添加以下两行代码用于获取plans:
var plannerHelper = new PlannerHelper(graphClient);
plannerHelper.PlannerHelperCall().GetAwaiter().GetResult();
下面我们继续添加Bucket和Task的操作支持。
添加Bucket
在PlannerHelper类中添加CreatePlannerBucket方法,代码如下:
private async Task CreatePlannerBucket(string groupId, string planId)
{
// Creating a new bucket within the plan
var createdBucket = await _graphClient.Planner.Buckets.Request().AddAsync(
new PlannerBucket
{
Name = "my first bucket",
OrderHint = " !",
PlanId = planId
}
);
Console.WriteLine($"Added new bucket {createdBucket.Name} to plan");
return createdBucket.Id;
}
在PlannerHelperCall方法的末尾添加代码:
var bucketId = await CreatePlannerBucket(groupId, planId);
添加Task
在PlannerHelper类中添加CreatePlannerTask方法,代码如下:
private async Task CreatePlannerTask(IEnumerable users, string groupId, string planId, string bucketId)
{
// Preparing the assignment for the task
var assignments = new PlannerAssignments();
users.ToList().ForEach(x => assignments.AddAssignee(x.Id));
// Creating a task within the bucket
var createdTask = await _graphClient.Planner.Tasks.Request().AddAsync(
new PlannerTask
{
DueDateTime = DateTimeOffset.UtcNow.AddDays(7),
Title = "Do the dishes",
Details = new PlannerTaskDetails
{
Description = "Do the dishes that are remaining in the sink"
},
Assignments = assignments,
PlanId = planId,
BucketId = bucketId
}
);
Console.WriteLine($"Added new task {createdTask.Title} to bucket");
}
注意:在添加Task时我们的代码是查询当前租户中的前三个用户作为受理人添加的,如果我们的Plan是新建的,需要把这三个用户添加进来作为成员,否则在添加完Task之后我们在界面上看到Task的受理人处会显示前成员。
在PlannerHelperCall方法的末尾继续添加一行代码:
await CreatePlannerTask(users, groupId, planId, bucketId);