3

他のバグ追跡システムの問題に取り組んでいる場合、作成者のユーザー名と入力された日付で明確にマークされているアイテムにメモを追加する方法があります。TFS の作業項目で同様の機能を探しています。そのような機能はありますか?

現在、ホットキーを押して現在の時刻とユーザー名を複数行のテキスト フィールドに貼り付けることができるシステムを使用しています。すべてのユーザーは、入力した情報の上にその情報を貼り付けることを知っています。これは手動ですが、受け入れられ、簡単です。例えば:

2009/5/1 午前 1:20:00 - AManagr-
次のバージョンに延期されました。その理由は次のとおりです...

2009 年 4 月 24 日午前 1:20:00 - ADev -
QA マシンに古い XYZ ギズモ コンポーネントがありました。これが発生する可能性のある複雑な方法は次のとおりです...何とか何とか...これを修正するのは困難です。

2009 年 4 月 22 日午前 1:20:00 - QAGuy -
レポートを PDF ファイルに保存できません。

私が使用した他のツール (Mantis かな?) には「メモ」機能が組み込まれていました。そのため、コメントに自分の名前を付けることを忘れたり、新しいメモがフィールドの上部または下部に表示されるかどうかを知ることができませんでした。 ..

名前と日付/時刻を手動で入力することは (良い) オプションではありません。ただし、単一のキーまたはツールバーのボタンを押すだけで問題ありません。

このような長い形式の「メモ」を複数の特定の個々のフィールドに分解することについてアドバイスを求めているわけではありません。また、作業項目の履歴タブについては認識していますが、これでは十分ではありません。誰が、いつ、何を書いたのかを明確にし、テキストと同じビューにする必要があります。

アップデート

何人かのチーム メンバーが問題を調査していると想像してください。それらはすべて作業項目に情報を追加し、それぞれが同じフィールドにさらにテキストを追加します。誰がどの部分を追加したかをどのように簡単に知ることができますか?

履歴ログには、各ユーザーの変更の行が表示され、フィールドの変更も表示されます。しかし、それは別の画面上にあり、表示されるデータを精神的に解析するのは困難です。

テキストの各部分に「署名」することはできますが、ツールの助けがなければこれは苦痛です。

Stackoverflows のコメント機能も良い例かもしれません。

4

2 に答える 2

3

はい、できます。TFS ワークアイテムはカスタマイズ可能です。私がこのバージョンで望むほどではありませんが、やりたいことはできます。

次のフィールド定義で試してみましょう。Notes Date と Notes Author は読み取り専用で、システムからデフォルト値を取得します。Notes フィールドは HTML であり、そこには何でも入れることができます。これは、TFS プロセス エディターで行うことができます。

 <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>

もちろん、フォームにコントロールを追加する必要があります。

もう 1 つ試すことができるのは、Notes フィールドのみを保持して WorkItemChanged イベントに登録し、Web サービスを作成して Notes フィールドを Date と Author で更新することです。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);
           }
       }
    }
 }

これは、既存のコードからのコピーと貼り付けで簡単に汚れているため、タイプミスが発生していないことを確認するために慎重に確認してください。

于 2009-05-13T21:04:49.050 に答える