Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions Osiris.AssociateRecentWorkItems/NewWorkItemsSection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.Controls;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace Osiris.AssociateRecentWorkItems
{
[TeamExplorerSection(SectionId, TeamExplorerPageIds.PendingChanges, 34)]
public class NewWorkItemsSection : WorkItemsSectionBase
{
public const string SectionId = "433130C1-5E7B-48A3-A142-B1F1567B2AB3";
private const string SectionTitle = "My Newest Work Items";

public NewWorkItemsSection()
: base(SectionTitle, false) { }

protected override IEnumerable<WorkItemInfo> GetWorkItems(WorkItemCheckinInfo[] currentlyAssociatedWorkItems)
{
var context = CurrentContext;
if (context == null || !context.HasCollection || !context.HasTeamProject)
return Enumerable.Empty<WorkItemInfo>();

var store = context.TeamProjectCollection.GetService<WorkItemStore>();
if (store == null)
return Enumerable.Empty<WorkItemInfo>();

var workItems = new List<WorkItemInfo>();

var results = store.Query(@"
Select [ID], [Title]
From WorkItems
Where [System.TeamProject] = '" + context.TeamProjectName + @"' AND [Assigned to] = @Me
Order By [Created Date] desc");

foreach (WorkItem workItem in results)
{
if (currentlyAssociatedWorkItems.All(w => w.WorkItem.Id != workItem.Id))
{
workItems.Add(new WorkItemInfo(workItem.Id, workItem.Title, workItem.Type.Name, workItem.State, "@Me"));

if (workItems.Count == 5)
break;
}
}

return workItems;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,25 @@
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Linq" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Guids.cs" />
<Compile Include="NewWorkItemsSection.cs" />
<Compile Include="WorkItemInfo.cs" />
<Compile Include="WorkItemsSectionBase.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="RecentWorkItemsSection.cs" />
<Compile Include="RecentWorkItemsView.xaml.cs">
<DependentUpon>RecentWorkItemsView.xaml</DependentUpon>
<Compile Include="WorkItemsView.xaml.cs">
<DependentUpon>WorkItemsView.xaml</DependentUpon>
</Compile>
<Compile Include="AssociateRecentWorkItemsPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down Expand Up @@ -184,7 +188,7 @@
<Content Include="Resources\Package.ico" />
</ItemGroup>
<ItemGroup>
<Page Include="RecentWorkItemsView.xaml">
<Page Include="WorkItemsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<Generator>MSBuild:Compile</Generator>
Expand Down
156 changes: 18 additions & 138 deletions Osiris.AssociateRecentWorkItems/RecentWorkItemsSection.cs
Original file line number Diff line number Diff line change
@@ -1,170 +1,50 @@
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Controls;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.VersionControl.Controls.Extensibility;
using Microsoft.VisualStudio.TeamFoundation.WorkItemTracking;
using Osiris.TeamExplorer.Extensions.Common;

namespace Osiris.AssociateRecentWorkItems
{
/// <summary>
/// Selected file info section.
/// </summary>
[TeamExplorerSection(SectionId, TeamExplorerPageIds.PendingChanges, 35)]
public class RecentWorkItemsSection : TeamExplorerBaseSection
public class RecentWorkItemsSection : WorkItemsSectionBase
{
public const string SectionId = "A7D7E0F2-6847-439F-834A-7CDB508FEBFA";
private const string SectionTitle = "Recently Associated Work Items";

private ObservableCollection<AssociatedWorkItemInfo> recentWorkItems = new ObservableCollection<AssociatedWorkItemInfo>();

/// <summary>
/// Constructor.
/// </summary>
public RecentWorkItemsSection()
: base()
{
this.Title = SectionTitle;
this.IsExpanded = true;
this.IsBusy = false;
this.SectionContent = new RecentWorkItemsView();
this.View.ParentSection = this;
}

/// <summary>
/// Get the view.
/// </summary>
protected RecentWorkItemsView View
{
get { return this.SectionContent as RecentWorkItemsView; }
}

/// <summary>
/// Initialize override.
/// </summary>
public override void Initialize(object sender, SectionInitializeEventArgs e)
{
base.Initialize(sender, e);

// Find the Pending Changes extensibility service and sign up for
// property change notifications
var pcExt = this.GetService<IPendingChangesExt>();
if (pcExt != null)
{
pcExt.PropertyChanged += pcExt_PropertyChanged;
}

var ds = this.GetService<DocumentService>();
this.View.Context = this.CurrentContext;
this.View.DocumentService = ds;
this.RefreshAsync();
}
: base(SectionTitle, true) { }

/// <summary>
/// Dispose override.
/// </summary>
public override void Dispose()
protected override IEnumerable<WorkItemInfo> GetWorkItems(WorkItemCheckinInfo[] currentlyAssociatedWorkItems)
{
base.Dispose();
var context = CurrentContext;
if (context == null || !context.HasCollection || !context.HasTeamProject)
return Enumerable.Empty<WorkItemInfo>();

var pcExt = this.GetService<IPendingChangesExt>();
if (pcExt != null)
{
pcExt.PropertyChanged -= pcExt_PropertyChanged;
}
}

/// <summary>
/// Pending Changes Extensibility PropertyChanged event handler.
/// </summary>
private void pcExt_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "WorkItems":
Refresh();
break;
}
}
var vcs = context.TeamProjectCollection.GetService<VersionControlServer>();
if (vcs == null)
return Enumerable.Empty<WorkItemInfo>();

/// <summary>
/// Refresh override.
/// </summary>
public async override void Refresh()
{
base.Refresh();
await RefreshAsync();
}
var workItems = new List<WorkItemInfo>();

/// <summary>
/// Refresh the changeset data asynchronously.
/// </summary>
private async Task RefreshAsync()
{
try
string path = "$/" + context.TeamProjectName;
foreach (Changeset changeset in vcs.QueryHistory(path, VersionSpec.Latest, 0, RecursionType.Full, vcs.AuthorizedUser, null, null, 10, false, true))
{
var pc = GetService<IPendingChangesExt>();
var currentlyAssociatedWorkItems = pc.WorkItems;

// Set our busy flag and clear the previous data
this.IsBusy = true;
this.RecentWorkItems.Clear();

var workItems = new ObservableCollection<AssociatedWorkItemInfo>();

// Make the server call asynchronously to avoid blocking the UI
await Task.Run(() =>
foreach (var wi in changeset.AssociatedWorkItems)
{
ITeamFoundationContext context = this.CurrentContext;
if (context != null && context.HasCollection && context.HasTeamProject)
if (workItems.All(w => w.Id != wi.Id) && currentlyAssociatedWorkItems.All(w => w.WorkItem.Id != wi.Id))
{
var vcs = context.TeamProjectCollection.GetService<VersionControlServer>();
if (vcs != null)
{
string path = "$/" + context.TeamProjectName;
foreach (Changeset changeset in vcs.QueryHistory(path, VersionSpec.Latest, 0, RecursionType.Full,
vcs.AuthorizedUser, null, null, 10, false, true))
{
foreach (var wi in changeset.AssociatedWorkItems)
{
if (workItems.All(w => w.Id != wi.Id) && currentlyAssociatedWorkItems.All(w => w.WorkItem.Id != wi.Id))
{
workItems.Add(wi);
}
}
}
}
workItems.Add(new WorkItemInfo(wi.Id, wi.Title, wi.WorkItemType, wi.State, wi.AssignedTo));
}
});

// Now back on the UI thread, update the bound collection and section title
this.RecentWorkItems = new ObservableCollection<AssociatedWorkItemInfo>(workItems.Take(5));
this.Title = this.RecentWorkItems.Count > 0 ? String.Format(" {0} ({1})", SectionTitle, this.RecentWorkItems.Count)
: SectionTitle;
}
catch (Exception ex)
{
ShowNotification(ex.Message, NotificationType.Error);
}
finally
{
// Always clear our busy flag when done
this.IsBusy = false;
}
}
}

public ObservableCollection<AssociatedWorkItemInfo> RecentWorkItems
{
get { return recentWorkItems; }
protected set { recentWorkItems = value; RaisePropertyChanged("RecentWorkItems"); }
return workItems;
}

}


}
24 changes: 24 additions & 0 deletions Osiris.AssociateRecentWorkItems/WorkItemInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Osiris.AssociateRecentWorkItems
{
public class WorkItemInfo
{
public int Id { get; private set; }

public string Title { get; private set; }

public string WorkItemType { get; private set; }

public string State { get; private set; }

public string AssignedTo { get; private set; }

public WorkItemInfo(int id, string title, string workItemType, string state, string assignedTo)
{
Id = id;
Title = title;
WorkItemType = workItemType;
State = state;
AssignedTo = assignedTo;
}
}
}
Loading