TFS Timesheets is now on CodePlex

One of the key weaknesses (in my opinion) with Team Foundation Server work items at present is the difficulty to record time spent against a project. Sure you can track time in the ‘Work Completed’ field and can even report on what changes were made to this field over time. The difficulty is that this still assumes that developers will always update the work items on the correct day and fails to give simple visibility of how much time different team members have spent on a given work item.

Some time back I created a small timesheet utility for Team Foundation Server 2010. This was partly driven out of a requirement to be able to track this level of detail for a project I was working on, but also to serve as a sample project for my previous blog posts about creating custom work item controls;

At the moment the code posted is far from perfect and I haven’t had a lot of time for updating the sample since the posts, but as a number of people have requested access to either view or contribute to the source code I’ve decided to post it to CodePlex ‘warts and all’ so to speak. If you are interested in the code for this component it can now be found at the following location.

We’ve used this control on a couple of projects now and have found that it has helped to keep the work remaining / work completed values up to date by creating visibility of how much time team members are logging against work items on any given day. There are definitely some improvements that can be made (especially in terms of reporting) – so if you do happen to try out this component please drop me a note to let me know what you think, or if you have any ideas for how it could be improved!

Advertisements

TFS 2010 Beta 2 – Custom Work Item Controls. Step 2, Work Item Setup

Overview

[Edit: Source code for the control discussed in this post can be found here: TFS TimeSheets (Codeplex).]

In the first post (Step 1, Getting Started) in this series I looked at how to create a basic Work Item Custom Control for Team Foundation Server 2010, and went through the process of configuring and installing the custom control for use on the Task work item.

Today I’m looking at setting up the Task Work item definition to allow create a new field for our custom work item control to persist time sheet data to.

The screen shot below depicts my goals for the control; however this post focuses more on how to create and configure the control than the actual time sheeting ability itself. Yes, I know this one isn’t going to win any prizes for prettiness … but that can be fixed later 🙂

As we are restricted within Team Foundation Server to a non-relational structure for our work item data, my current thinking is that time sheet data will be stored as XML within a new field configured on the work item. The other option I considered was looking at the ‘History’ field type … but a bit of investigation suggests that the way the work item history control works is to look at the various revisions of the work item, rather than store a collection of values.

Prerequisites:

Before getting started, the following prerequisite setup should be completed:

  • Visual Studio 2010 Beta 2 (for development)
  • Visual Studio 2010 Team Explorer Beta 2 (for testing)
  • Team Foundation Server 2010 Beta 2
  • The output from the project setup in Step 1.
  • A new reference added to our custom control library to Microsoft.TeamFoundation.Client
  • A new reference added to our custom control library to Microsoft.TeamFoundation.WorkItemTracking

Modify the Work Item Template

Using the following command the existing work item template for the Task work item can be extracted from the Team Foundation Server.

C:\>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin.exe” exportwitd /collection:localhost\defaultcollection /p:”{ExistingProject}” /n:Task /f:Task.xml

If you haven’t worked with the work item template in the past, at this stage it’s worth having a good read through the documentation. For the purposes of the changes today we are only going to need to add a new field; however there is a lot of value in understanding some of the other features available within the schema.

The first thing we need to do is declare a new field to store the time sheet data. The XML fragment below shows the new field definition is black bold font. It should be noted that the refname is unique across the entire Team Foundation Server collection database, so be sure to apply a suitable name at this stage. I tend to prefix all my custom fields with ‘Custom’ just to make them easier to identify.


<FIELD name=Authorized As refname=System.AuthorizedAs type=String syncnamechanges=true />
<FIELD name=”TimesheetRawData” refname=”Custom.Timesheets.TimesheetRawData” type=”PlainText” />
</FIELDS>

We also need to add the FieldName attribute to the control definition for the WorkItemTimeSheetControl:

<Tab Label=TimeSheets>
<Control Type=WorkItemTimeSheetControl LabelPosition=Top FieldName=”Custom.Timesheets.TimesheetRawData” />
</Tab>

The modified work item can then be imported back into TFS 2010 using the following command:

C:\TFS>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin.exe” importwitd /collection:localhost\defaultcollection /p:”{ExistingProjectName}” /f:Task.xml

Using the IWorkItemControl Members

The Work Item Custom Control we created earlier implemented the IWorkItemControl interface. Using this interface we can get access to the currently loaded work item, and manipulate its values programmatically.

The full documentation for the interface can of course be found on MSDN, but below are my additional notes on the usage of some of the members.

WorkItemDataSource A reference to the work item is provided to the user control via the WorkItemDataSource property. The property itself is defined as an object, but so far I’ve found that this reference can be safely typecast to a stronger type of Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem.
WorkItemFieldName If the work item control has been setup with a fieldname value then this will be provided to the custom control via the WorkItemFieldName field.
InvalidateDataSource The InvalidateDataSource method is called during the loading (and unloading) of a work item. This method should be used to populate the fields of the Work Item Custom Control with their persisted values, or default values for a new work item.

Writing to the Work Item using the Object Model

A small number of standard properties may be set via strongly typed properties on the Work Item … however the majority of the Work Item data must be accessed from within the Fields collection.

CurrentWorkItem.Fields[WorkItemFieldName].Value = TimeSheet.Serialize(TimeSheet);

Whenever any data is changed within the Fields collection the work item interface automatically detects that the work item is ‘dirty’ and sets it to appear modified in the user interface with the * next to the work item name.

The one gotcha I did come across on the way was how to obtain the name of the current user in the context of the connection to Team Foundation Server. It turns out this can be retrieved from the following property:

CurrentWorkItem.Store.TeamFoundationServer.AuthorizedIdentity.DisplayName;

The changes I’ve made to the control at this point have been very basic. I’ve added a couple of user input controls to the form, and setup the add button handler to add a new time sheet entry entity to a time sheet list, then serialize the resulting list back to the work item based on the WorkItemFieldName.

At a high level, the functionality implemented is:

  • Ability to enter a new timesheet entry
  • Ability to view all timesheet entries associated to the work item
  • The value of Remaining Work is decreased automatically based on the minutes entered
  • The value of the Completed Work is increased automatically based on the minutes entered

Testing the Changes …

As before, it is necessary to reopen the testing instance of Visual Studio 2010 – otherwise the old work item definition may still be cached.

If we reopen Visual Studio then create a new Task work item our custom control should be displayed under the TimeSheets tab, and loading / saving Task work items should result in our changes being persisted to the database.

References

While working through this investigation process I’ve found the following resources very useful, and my thanks go to their authors:

TFS 2010 Beta 2 – Custom Work Item Controls. Step 1, Getting Started

Overview

A few months ago I spent a week or so getting my head around the Custom Work Item Controls in Team Foundation Server 2008. At the time it was obvious that a lot of value could be added to our development teams if we could add some additional custom work item functionality to our processes.

My original intent at the time was to build a work item explorer that could navigate through work items based on their relationships … but that is fairly redundant now that we have proper work item hierarchies in TFS 2010. This time my intention is to have a look at how we can improve the way we record our time against tasks within Team Foundation Server.

This post (Step 1, Getting Started) will cover the process of setting up the required project and setup files, creating a basic ‘Hello World’ custom work item control and loading that control into the work item interface.

Prerequisites:

  • Visual Studio 2008 or 2010 (for development)
  • Visual Studio 2010 Team Explorer Beta 2 (for testing)
  • Team Foundation Server 2010 Beta 2

Visual Studio Project Setup

Creating Custom Work Items Controls is much like creating any other control library in Visual Studio. The control itself is based on the standard UserControl base class, and should be setup within a .NET Class Library Project.

Before going any further, we’re going to need to add a reference to the TFS Work Item Tracking Controls assembly. This is installed as part of Visual Studio 2010, and can be found in the following folder:

C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

At a minimum, we’ll also need the following artefacts in our solution:

  • One User Control (WorkItemTimeSheetControl)
  • One Work Item Custom Control definition file (.wicc). Note that it is important to set the Build Action for this file to ‘Content’ on from the properties window.

Create the User Control

There is nothing overly special about a user control housed within a Work Item form – except that it implements the IWorkItemControl interface. For the moment the goal is only to create a user control and embed it within the Work Item form, so the control itself contains nothing more than the compulsory ‘Hello World’ label in bold 24pt black font.

We’ll setup the various members of the IWorkItemControl interface in more detail in a future post – for the moment a basic implementation with the default NotImplementedExceptions removed will do the job. Just create basic backing variables for any of the properties that need to be defined.

Create the Work Item Custom Control definition (WICC)

The .wicc file is an XML file that defines the custom control to be loaded within a work item. When a Custom Control is referenced within a Work Item Template, Visual Studio will look within the custom controls folder for a .wicc definition file that matches the name of the required custom control. In the case of current custom control, Visual Studio will be looking for a file named WorkItemTimeSheetControl.wicc.

The following XML is the contents of the WorkItemTimeSheetControl.wicc file:

<?xml
version=1.0
encoding=utf-8 ?>

<CustomControl
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema>

<Assembly>TimeSheetControl.dll</Assembly>

<FullClassName>TimeSheetControl.WorkItemTimeSheetControl</FullClassName>

</CustomControl>

Create the Windows Installer

Unfortunately the runtime for a Work Item Custom Control is not defined on the Team Foundation Server instance, but rather must be installed on every Visual Studio client machine that will be interacting with the work item.

The one gotcha for the setup folder is that all the output must be installed on within the custom controls folder on the client machine. On Vista, this is located at C:\ProgramData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\10.0 … though this will vary depending on the OS.

  1. Create a new Setup Project within the solution
  2. Add a new ‘Custom Folder’ named CommonAppDataFolder to the output of the setup project.
  3. In the properties window for the new custom folder, set the Default Location to [CommonAppDataFolder].
  4. Create the folder structure shown in the screenshot above under the CommonAppDataFolder. (Microsoft, Team Foundation, Work Item Tracking, Custom Controls, 10.0)
  5. Add the Primary Output and Content Files from the user control class library we created earlier.
  6. Build and install the setup file on the local machine.

The client components are now all in place – the only remaining step is to add our custom control to one of the work item templates.

Modify the Work Item Template

I’m going to select the Task work item from the MSF for Agile Software Development 5.0 Beta 2 process templates as the testing work item template to apply our new custom control to.

Using the following command the existing work item template for the Task work item can be extracted from the Team Foundation Server.

C:\>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin” exportwitd /collection:localhost\defaultcollection /p:”{ExistingProject}” /n:Task /f:Task.xml

A couple of notes here:

  1. The WITAdmin tool is new to TFS 2010. When working with TFS 2008 the witimport / witexport tools would be used instead.
  2. In TFS 2008 adding custom controls to a work item template broke the process editor power tool – so all operations to import / export the work items must be done by command line. I am not sure whether this is going to be supported in the TFS 2010 power toys or not.

Now that we’ve got the work item template extracted we need to modify it to include our custom work item control. I’ve chosen to add the control to a new tab at on the bottom half of the screen.

The XML fragment below shows the addition of the time sheet control to the Task work item file in bold black font. Make sure that the ‘Type’ attribute for the Control node is set to the name of the .wicc file that has been deployed to the client machines.

        …

    <Tab
Label=Attachments>

    <Control
Type=AttachmentsControl
LabelPosition=Top />

        </Tab>

            <Tab Label=”TimeSheets”>

                <Control Type=”WorkItemTimeSheetControl” LabelPosition=”Top” />

            </Tab>

        </TabGroup>

</Layout>

</FORM>

</WORKITEMTYPE>

</witd:WITD>

The modified work item can then be imported back into TFS 2010 using the following command:

C:\TFS>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin” importwitd /collection:localhost\defaultcollection /p:”{ExistingProjectName}” /f:Task.xml

Testing the Changes …

Back on the Visual Studio client machine, load up an instance of Visual Studio 2010 Team Explorer Beta 2 and open a Task from within the team project that has had the modified work item template loaded. Assuming everything has gone to plan a new tab should exist on the Work Item form, and the custom control should have loaded and displayed correctly.

One gotcha to keep in mind here – Team Explorer will cache the work item templates and controls – so it may be necessary to restart the Team Explorer client in order to see the updated layout.

Next Steps

Hopefully this ‘getting started’ post is of some use to others as they work through this process … or at least will help me out next time I get some time free to continue with this side project J

Now that we’ve got a user control successfully loading from within the work item layout, my next (likely) steps include:

  • Adding interaction with the Work Item data model
  • Investigating how / if the TFS Web Interface can have a similar custom control applied
  • Investigating whether using WPF controls will simplify the implementation of think client / web client work item templates
  • Putting together some actual logic to solve the initial issue of time sheeting!