有没有办法在TFS2017下的列表中显示Release下的任务工作项的父PBI?
下面的屏幕截图显示了与Release-3相关的两个任务。在这里,我希望能够为每个人显示父PBI。通过扩展它们或仅显示包含父PBI链接的附加列
感谢您的帮助
编辑: 我知道有可能在TFS上创建查询。问题是我需要在父工作项上显示与特定版本相关的信息,以便用户可以使用它们进行报告。我试图为此目的创建一个查询,但我找不到基于Release的过滤选项,所以我认为可能启用一些额外的列,或者可能有一个扩展,但我无法弄清楚如何这样做..
答案 0 :(得分:1)
通过扩展实现该目标的步骤:
有一些简单的扩展代码可以获取特定版本的工作项,您可以参考:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Custom widget</title>
<meta charset="utf-8" />
<script src="node_modules/vss-web-extension-sdk/lib/VSS.SDK.js"></script>
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformStyles:true
});
VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/TestManagement/RestClient", "TFS/WorkItemTracking/RestClient", "TFS/Build/RestClient", "VSS/Service", "VSS/Identities/Contracts", "VSS/Identities/RestClient", "VSS/Authentication/Services"], function (WidgetHelpers, TFS_Test_WebApi, TFS_Work_WebApi, TFS_Build_Client, VSS_Service, idContracts, idRest, VSS_Auth_Service) {
WidgetHelpers.IncludeWidgetStyles();
VSS.register("WidgetStarain", function () {
var authHeader = "none";
var vstsAccount = "none";
var projectName = "none";
var releaseRestAPIPrex = "none"
var getReleaseWorkItems= function (widgetSettings) {
var c = VSS.getWebContext();
vstsAccount = c.account.name;
projectName = c.project.name;
releaseRestAPIPrex="https://" + vstsAccount + ".vsrm.visualstudio.com/DefaultCollection/" + projectName + "/_apis/release"
VSS.getAccessToken().then(function (token) {
authHeader = VSS_Auth_Service.authTokenManager.getAuthorizationHeader(token);
$.ajax({
type: 'GET',
url: releaseRestAPIPrex+'/definitions?api-version=3.0-preview.1',
cache: false,
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", authHeader);
},
}).done(function (data) {
var v = data.value;
$("#releaseDefList").empty();
$("#releaseDefList").append('<option value="select">select</option>');
$.each(v, function (index, value) {
$("#releaseDefList").append('<option value="' + value.id + '">' + value.name + '</option>');
});
}).error(function (e) {
var s = "ss";
});
});
};
$("#releaseDefList").change(function () {
var str = "";
$("#releaseList").empty();
$("#releaseList").append('<option value="select">select</option>');
$("#releaseDefList option:selected").each(function () {
var releaseDefId = $(this).val();
if (releaseDefId != "select") {
$.ajax({
type: 'GET',
url: releaseRestAPIPrex+'/releases?definitionId=' + releaseDefId + '&api-version=3.0-preview.2',
cache: false,
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", authHeader);
},
}).done(function (data) {
var v = data.value;
$.each(v, function (index, value) {
$("#releaseList").append('<option value="' + value.id + '">' + value.name + '</option>');
});
}).error(function (e) {
var s = "ss";
});
}
});
});
$("#releaseList").change(function () {
var str = "";
$("#releaseList option:selected").each(function () {
var releaseId = $(this).val();
if (releaseId != "select") {
$.ajax({
type: 'GET',
url: releaseRestAPIPrex+'/release/releases/' + releaseId + '?api-version=3.0-preview.2',
cache: false,
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", authHeader);
},
}).done(function (data) {
var artifacts = data.artifacts;
$.each(artifacts, function (index, value) {
var buildId = value.definitionReference.version.id;
TFS_Build_Client.getClient().getBuildWorkItemsRefs(projectName, buildId).then(function (workitemRefs) {
var workItemIds = new Array();
$.each(workitemRefs, function (index, value) {
workItemIds.push(value.id);
});
var workitemString = "";
TFS_Work_WebApi.getClient().getWorkItems(workItemIds,null,null,"All").then(function (workitems) {
$.each(workitems, function (index, value) {
workitemString += "ID: " + value.id + "; Title: " + value.fields["System.Title"];
});
$("#workitems").text(workitemString);
});
});
});
}).error(function (e) {
var s = "ss";
});
}
});
});
return {
load: function (widgetSettings) {
getReleaseWorkItems(widgetSettings);
return WidgetHelpers.WidgetStatusHelper.Success();
}
}
});
VSS.notifyLoadSucceeded();
});
</script>
</head>
<body>
<div class="widget">
<h2 class="title">widgets starain</h2>
<div class="token">none</div>
<select id="releaseDefList">
<option id="select">select</option>
</select>
<select id="releaseList">
<option id="select">select</option>
</select>
<div id="workitems">
none workitem
</div>
</div>
</body>
</html>
VSS-extension.json:
{
"manifestVersion": 1,
"id": "sample-extension",
"version": "0.5.34",
"name": "My test extension",
"description": "my test extension description",
"publisher": "Starain",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"icons": {
"default": "Images/logo.png"
},
"scopes": [
"vso.work",
"vso.build",
"vso.build_execute",
"vso.test",
"vso.test_write",
"vso.release"
],
"contributions": [
{
"id": "WidgetStarain",
"type": "ms.vss-dashboards-web.widget",
"targets": [ "ms.vss-dashboards-web.widget-catalog", "Starain.sample-extension.WidgetStarainConfiguration" ],
"properties": {
"name": "widget starain",
"description": "custom widget",
"catelogIconUrl": "Images/iconProperty.png",
"previewImageUrl": "Images/iconProperty.png",
"uri": "WidgetStarain.html",
"supportedSizes": [
{
"rowSpan": 1,
"columnSpan": 2
}
],
"supportedScopes": [ "project_team" ]
}
}
],
"files": [
{
"path": "node_modules/vss-web-extension-sdk/lib",
"addressable": true
},
{
"path": "Images",
"addressable": true
},
{
"path": "Scripts",
"addressable": true
},
{
"path": "WidgetStarain.html",
"addressable": true
}
]
}