在处理其他错误跟踪系统中的问题时,可以通过多种方式向明确标有作者用户名和输入日期的项目添加注释。我正在寻找 TFS 工作项中的类似功能。 有这样的功能吗?
我们目前使用的系统允许我们点击热键将当前时间和用户名粘贴到多行文本字段中。所有用户都知道将该信息粘贴到他们键入的内容上方。虽然这是手动的,但它是可以接受的并且很容易。例如:
5/1/2009 1:20:00 am - AManagr- Defered to next version, and here's why... 4/24/2009 1:20:00 am - ADev - QA machine had out of date XYZ gizmo component. Here's the convoluted way this can happen... blah blah... This is difficult to fix. 4/22/2009 1:20:00 am - QAGuy - I can't save reports to PDF files.
我用过的其他工具(也许是 Mantis?)内置了“注释”功能。所以我不会忘记在评论中写上我的名字,或者知道新注释是放在字段的顶部还是底部等等……
手动输入您的姓名和日期/时间不是一个(好的)选项。但是,点击一个键或工具栏按钮就可以了。
我不是在寻找有关将像这样的长格式“注释”分解为多个特定的单独字段的建议。此外,我知道工作项上的历史记录选项卡,但这还不够。谁写了什么,什么时候写的,需要清楚并与文本保持一致。
更新
想象几个团队成员正在研究一个问题。它们都将信息添加到工作项,每个都将更多文本附加到同一字段。您如何轻松知道谁添加了什么部分?
历史日志为每个用户的更改显示一行,甚至显示字段的更改。但那是在另一个屏幕上,很难在头脑中解析它显示的数据。
他们可以“签署”文本的每个部分 - 但如果没有工具的帮助,这会很痛苦。
也许 Stackoverflows 的评论功能也是一个很好的例子。
最佳答案
是的,你可以。 TFS 工作项是可定制的。在这个版本中没有我想要的那么多,但你可以做你想做的。
让我们用下面的字段定义来尝试一下。 Notes Date 和 Notes Author 是只读的,并从系统中获取它们的默认值。 Notes 字段是 HTML,您可以在其中放置任何您想要的内容。您可以在 TFS Process Editor 中执行此操作.
<FIELD reportable="dimension" type="DateTime" name="Notes Date" refname="System.VSTS.Notes.Date">
<DEFAULT from="clock" />
<READONLY not="[Global]\Team Foundation Administrators" />
</FIELD>
<FIELD reportable="dimension" type="String" name="Notes Author" refname="System.VSTS.Notes.Author">
<DEFAULT from="currentuser" />
<READONLY not="[Global]\Team Foundation Administrators" />
</FIELD>
<FIELD type="HTML" name="Notes" refname="System.VSTS.Notes" />
</FIELDS>
当然,您仍然需要向表单添加控件。
您可以尝试的另一件事是仅保留 Notes 字段并注册一个 WorkItemChanged 事件并编写一个 web 服务以使用日期和作者更新注释字段。 Changed BY 和 Changed Date 字段将为您提供此信息。您可以在 Brian A. Randell 撰写的这篇文章中了解可用事件以及如何订阅它们 - Team Foundation System Event Service
[WebService(Namespace = "http://mynamespace.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class UpdateWorkItem : System.Web.Services.WebService
{
private static TeamFoundationServer _Tfs;
private static WorkItemStore _WorkItemStore;
private static List<WorkItem> _ChangedWorkItems = new List<WorkItem>();
[SoapDocumentMethod(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
[WebMethod]
public void Notify(string eventXml, string tfsIdentityXml)
{
EventLog.WriteEntry("TFS Services", "Log Started: Notify Webmethod");
// Load the recieved XML into a XMLDocument
XmlDocument eventXmlDoc = new XmlDocument();
eventXmlDoc.LoadXml(eventXml);
XmlElement eventData = eventXmlDoc.DocumentElement;
// Validate event data
if (eventData != null)
{
// Get Work Item id from event data
int id = GetWorkItemId(eventData);
//EventLog.WriteEntry("TFS Services", String.Format("eventXmlDoc {0}", eventXmlDoc.InnerXml));
EventLog.WriteEntry("TFS Services", String.Format("Got Id {0}", id));
string changedby = GetWorkItemChangedBy(eventData);
EventLog.WriteEntry("TFS Services", String.Format("Got changedby {0}", changedby));
if (changedby != "TFSSERVICE")
{
//Add a 15 second delay in order to make sure all workitems are saved first before starting to update them
Thread.Sleep(15000);
EventLog.WriteEntry("TFS Services", "Calling UpdateWorkItemInternal");
UpdateWorkItemInternal(id);
}
}
}
private int GetWorkItemId(XmlElement eventData)
{
return Convert.ToInt32(eventData.SelectSingleNode("CoreFields/IntegerFields/Field[ReferenceName='System.Id']/NewValue").InnerText);
}
private string GetWorkItemChangedBy(XmlElement eventData)
{
return Convert.ToString(eventData.SelectSingleNode("CoreFields/StringFields/Field[ReferenceName='System.ChangedBy']/NewValue").InnerText);
}
private static void UpdateWorkItemInternal(int id)
{
//Connect To TFS Server
EventLog.WriteEntry("TFS Services", string.Format("Updating Work Item {0}", id));
_Tfs = TeamFoundationServerFactory.GetServer("TeamServer");
_WorkItemStore = (WorkItemStore)_Tfs.GetService(typeof(WorkItemStore));
WorkItem workItem = _WorkItemStore.GetWorkItem(id);
switch ((string)workItem.Fields["System.WorkItemType"].Value)
{
case "Bug":
UpdateNotes(workItem);
break;
default:
break;
}
foreach (WorkItem item in _ChangedWorkItems)
{
if (item.IsDirty)
{
foreach (Field field in item.Fields)
{
if (!field.IsValid)
{
Console.Write("Not valid");
}
}
EventLog.WriteEntry("TFS Services", string.Format("Saving WorkItem: {0}", item.Id));
try
{
item.Save();
}
catch (Exception ex)
{
}
}
}
_ChangedWorkItems.Clear();
}
private static void UpdateNotes(WorkItem workItem)
{
Field notes = workitem.Fields["System.VSTS.Notes"];
if (notes != null)
{
notes = string.Format("{0} - {1}", workItem.ChangedDate, workItem.ChangedBy);
}
if (workItem.IsDirty)
{
if (!_ChangedWorkItems.Contains(workItem))
{
_ChangedWorkItems.Add(workItem);
}
}
}
}
这只是从我现有的代码中复制和粘贴的一些快速和肮脏的,所以仔细检查它以确保我没有引入拼写错误。
关于tfs - 如何跟踪谁在 TFS 工作项上输入了评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/860237/