diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-04-23 19:56:48 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-04-23 19:56:48 +0300 |
| commit | 8046598cb1439b66a8d6e556a61b715fc859a6b0 (patch) | |
| tree | 5beaa8ca495f48ffbb40174b3569aab18debd6c1 /Software/Visual_Studio/Tango.TFS | |
| parent | 680563266381a80a453ff93214812796fe519fec (diff) | |
| download | Tango-8046598cb1439b66a8d6e556a61b715fc859a6b0.tar.gz Tango-8046598cb1439b66a8d6e556a61b715fc859a6b0.zip | |
Implemented TeamFoundationClient components !!!
Diffstat (limited to 'Software/Visual_Studio/Tango.TFS')
21 files changed, 1168 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.TFS/Area.cs b/Software/Visual_Studio/Tango.TFS/Area.cs new file mode 100644 index 000000000..a79f9c0f1 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Area.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class Area + { + public String Name { get; set; } + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Attachment.cs b/Software/Visual_Studio/Tango.TFS/Attachment.cs new file mode 100644 index 000000000..a32074d9d --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Attachment.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class Attachment + { + public String FilePath { get; set; } + public String Name { get; set; } + public String Description { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs b/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs new file mode 100644 index 000000000..0f8ae5e82 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public interface ITeamFoundationServiceClient + { + Task<Project> GetProject(String name); + + Task<WorkItem> UploadWorkItem(Project project, WorkItem workItem); + + Task<WorkItem> GetWorkItem(Project project, int id); + + Task DeleteWorkItem(Project project, int id); + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Iteration.cs b/Software/Visual_Studio/Tango.TFS/Iteration.cs new file mode 100644 index 000000000..f51f981bd --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Iteration.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class Iteration + { + public String Name { get; set; } + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Priority.cs b/Software/Visual_Studio/Tango.TFS/Priority.cs new file mode 100644 index 000000000..88e2a0ca5 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Priority.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public enum Priority + { + Priority1 = 1, + Priority2 = 2, + Priority3 = 3, + Priority4 = 4, + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Project.cs b/Software/Visual_Studio/Tango.TFS/Project.cs new file mode 100644 index 000000000..b3584ca23 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Project.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class Project + { + public Guid ID { get; set; } + public String Name { get; set; } + public String Description { get; set; } + public String URL { get; set; } + public List<Area> Areas { get; set; } + public List<Iteration> Iterations { get; set; } + public List<WorkItem> UserStories { get; set; } + public List<TeamMember> Members { get; set; } + public List<Tag> Tags { get; set; } + + public Project() + { + Areas = new List<Area>(); + Iterations = new List<Iteration>(); + UserStories = new List<WorkItem>(); + Members = new List<TeamMember>(); + Tags = new List<Tag>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.TFS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0b9dc84f7 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - VSTS API Library")] +[assembly: ComVisible(false)]
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.TFS/Properties/Resources.Designer.cs b/Software/Visual_Studio/Tango.TFS/Properties/Resources.Designer.cs new file mode 100644 index 000000000..5d8827cf6 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Tango.TFS.Properties { + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.TFS.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Properties/Resources.resx b/Software/Visual_Studio/Tango.TFS/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.TFS/Properties/Settings.Designer.cs b/Software/Visual_Studio/Tango.TFS/Properties/Settings.Designer.cs new file mode 100644 index 000000000..c3089365e --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Tango.TFS.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Properties/Settings.settings b/Software/Visual_Studio/Tango.TFS/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.TFS/Severity.cs b/Software/Visual_Studio/Tango.TFS/Severity.cs new file mode 100644 index 000000000..c57214d64 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Severity.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public enum Severity + { + [Description("1 - Critical")] + Critical, + [Description("2 - High")] + High, + [Description("3 - Medium")] + Medium, + [Description("4 - Low")] + Low, + } +} diff --git a/Software/Visual_Studio/Tango.TFS/State.cs b/Software/Visual_Studio/Tango.TFS/State.cs new file mode 100644 index 000000000..dfa905846 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/State.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public enum State + { + New, + Active, + Resolved, + Closed + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Tag.cs b/Software/Visual_Studio/Tango.TFS/Tag.cs new file mode 100644 index 000000000..008c8d8eb --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Tag.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class Tag + { + public Guid ID { get; set; } + public String Name { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj b/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj new file mode 100644 index 000000000..00c9171c3 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{998F8471-DC1B-41B6-9D96-354E1B4E7A32}</ProjectGuid> + <OutputType>library</OutputType> + <RootNamespace>Tango.TFS</RootNamespace> + <AssemblyName>Tango.TFS</AssemblyName> + <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <WarningLevel>4</WarningLevel> + <NuGetPackageImportStamp> + </NuGetPackageImportStamp> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\Build\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\Build\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.13.5.907, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.5\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath> + </Reference> + <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.13.5.907, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.5\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath> + </Reference> + <Reference Include="Microsoft.ServiceBus, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\WindowsAzure.ServiceBus.3.3.2\lib\net45-full\Microsoft.ServiceBus.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Build.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Build.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Build.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Build.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Build2.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Build2.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Chat.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Chat.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.VisualStudio.Services.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Core.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Core.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Dashboards.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Dashboards.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.DeleteTeamProject, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.DeleteTeamProject.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Diff, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Diff.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Discussion.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Discussion.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.DistributedTask.Common.Contracts, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundation.DistributedTask.Common.15.112.1\lib\net45\Microsoft.TeamFoundation.DistributedTask.Common.Contracts.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Git.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Git.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Lab.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Lab.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Lab.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Lab.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Lab.TestIntegration.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Lab.TestIntegration.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Lab.WorkflowIntegration.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.Lab.WorkflowIntegration.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Policy.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Policy.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.ProjectManagement, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.ProjectManagement.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.SharePointReporting.Integration, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.SharePointReporting.Integration.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.SourceControl.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.SourceControl.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Test.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Test.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.TestImpact.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.TestImpact.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.TestManagement.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.TestManagement.Client.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="Microsoft.TeamFoundation.TestManagement.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.TestManagement.Common.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="Microsoft.TeamFoundation.TestManagement.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.TestManagement.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.VersionControl.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.VersionControl.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.VersionControl.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.VersionControl.Common.Integration, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.Integration.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.Work.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.Work.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Client.QueryLanguage, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.QueryLanguage.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.Proxy, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll</HintPath> + </Reference> + <Reference Include="Microsoft.TeamFoundation.WorkItemTracking.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.TeamFoundationServer.Client.15.112.1\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.WebApi.dll</HintPath> + </Reference> + <Reference Include="Microsoft.VisualStudio.Services.Client.Interactive, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.VisualStudio.Services.InteractiveClient.15.112.1\lib\net45\Microsoft.VisualStudio.Services.Client.Interactive.dll</HintPath> + </Reference> + <Reference Include="Microsoft.VisualStudio.Services.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.VisualStudio.Services.Client.15.112.1\lib\net45\Microsoft.VisualStudio.Services.Common.dll</HintPath> + </Reference> + <Reference Include="Microsoft.VisualStudio.Services.WebApi, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.VisualStudio.Services.Client.15.112.1\lib\net45\Microsoft.VisualStudio.Services.WebApi.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.IdentityModel.Tokens.Jwt, Version=4.0.20622.1351, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\System.IdentityModel.Tokens.Jwt.4.0.2.206221351\lib\net45\System.IdentityModel.Tokens.Jwt.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http.Formatting, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.Serialization" /> + <Reference Include="System.ServiceModel" /> + <Reference Include="System.Threading.Tasks.Dataflow, Version=4.5.24.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.Tpl.Dataflow.4.5.24\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll</HintPath> + </Reference> + <Reference Include="System.Xml" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xaml"> + <RequiredTargetFramework>4.0</RequiredTargetFramework> + </Reference> + <Reference Include="WindowsBase" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="Area.cs" /> + <Compile Include="Attachment.cs" /> + <Compile Include="Iteration.cs" /> + <Compile Include="Priority.cs" /> + <Compile Include="Project.cs" /> + <Compile Include="Severity.cs" /> + <Compile Include="State.cs" /> + <Compile Include="Tag.cs" /> + <Compile Include="TeamFoundationServiceClient.cs" /> + <Compile Include="TeamMember.cs" /> + <Compile Include="WorkItem.cs" /> + <Compile Include="WorkItemType.cs" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ITeamFoundationServiceClient.cs" /> + <Compile Include="Properties\AssemblyInfo.cs"> + <SubType> + </SubType> + </Compile> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + <None Include="app.config" /> + <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\build\Microsoft.TeamFoundationServer.ExtendedClient.targets" Condition="Exists('..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\build\Microsoft.TeamFoundationServer.ExtendedClient.targets')" /> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\build\Microsoft.TeamFoundationServer.ExtendedClient.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.TeamFoundationServer.ExtendedClient.15.112.1\build\Microsoft.TeamFoundationServer.ExtendedClient.targets'))" /> + </Target> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs new file mode 100644 index 000000000..6bcea336e --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs @@ -0,0 +1,425 @@ +using Microsoft.TeamFoundation.Client; +using Microsoft.TeamFoundation.Core.WebApi; +using Microsoft.TeamFoundation.WorkItemTracking.Client; +using Microsoft.TeamFoundation.WorkItemTracking.WebApi; +using Microsoft.VisualStudio.Services.Common; +using Microsoft.VisualStudio.Services.WebApi; +using Microsoft.VisualStudio.Services.WebApi.Patch; +using Microsoft.VisualStudio.Services.WebApi.Patch.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class TeamFoundationServiceClient : ITeamFoundationServiceClient + { + private class ExtensionFields + { + public const String FOUND_IN_BUILD = "Microsoft.VSTS.Build.FoundIn"; + public const String SEVERITY = "Microsoft.VSTS.Common.Severity"; + public const String PRIORITY = "Microsoft.VSTS.Common.Priority"; + public const String STEPS_TO_REP = "Microsoft.VSTS.TCM.ReproSteps"; + public const String SYSTEM_INFO = "Microsoft.VSTS.TCM.SystemInfo"; + } + + public String CollectionURL { get; private set; } + + public String PersonalToken { get; private set; } + + public String UserName { get; private set; } + + public TeamFoundationServiceClient(String collectionURL, String userName, String personalToken) + { + CollectionURL = collectionURL; + UserName = userName; + PersonalToken = personalToken; + } + + public Task<Project> GetProject(string name) + { + return Task.Factory.StartNew<Project>(() => + { + Project p = new Project(); + + VssConnection connection = CreateConnection(); + + ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>(); + TeamProjectReference project = projectClient.GetProjects(null).Result.FirstOrDefault(x => x.Name == name); + + if (project == null) + { + throw new ArgumentException(String.Format("Project '{0}' could not be found.", name)); + } + + p.Name = project.Name; + p.ID = project.Id; + p.URL = project.Url; + p.Description = project.Description; + + TeamHttpClient teamClient = connection.GetClient<TeamHttpClient>(); + var team = teamClient.GetTeamsAsync(project.Id.ToString()).Result.FirstOrDefault(); + + IEnumerable<IdentityRef> teamMembers = teamClient.GetTeamMembersAsync(project.Id.ToString(), team.Id.ToString()).Result; + + foreach (var member in teamMembers) + { + TeamMember teamMember = new TeamMember(); + teamMember.ID = member.Id; + teamMember.DisplayName = member.DisplayName; + teamMember.ImageURL = member.ImageUrl; + teamMember.UniqueName = member.UniqueName; + teamMember.URL = member.Url; + + p.Members.Add(teamMember); + } + + TaggingHttpClient taggingClient = connection.GetClient<TaggingHttpClient>(); + WebApiTagDefinitionList tags = taggingClient.GetTagsAsync(project.Id).Result; + + foreach (var tag in tags) + { + p.Tags.Add(new Tag() + { + ID = tag.Id, + Name = tag.Name, + }); + } + + var projCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(CollectionURL)); + var store = projCollection.GetService<WorkItemStore>(); + + WorkItemCollection queryResults = store.Query("Select [State], [Title] " + "From WorkItems " + "Where [Work Item Type] = 'User Story'"); + + var userStories = queryResults.OfType<Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem>().Where(x => x.Project.Name == project.Name).ToList(); + + foreach (var userStory in userStories) + { + WorkItem story = new WorkItem(); + + story.Type = WorkItemType.UserStory; + story.Title = userStory.Title; + story.ID = userStory.Id; + story.URL = userStory.Uri.ToString(); + story.Description = userStory.Description; + + if (userStory.Fields[CoreField.AssignedTo].Value != null) + { + story.AssignedTo = p.Members.SingleOrDefault(x => x.AssignName == userStory.Fields[CoreField.AssignedTo].Value.ToString()); + } + + story.Area = new Area() { Name = userStory.AreaPath }; + story.Iteration = new Iteration() { Name = userStory.IterationPath }; + + p.UserStories.Add(story); + } + + p.Areas.Add(new Area() { Name = project.Name, Path = project.Name }); + + foreach (var area in store.Projects[project.Name].AreaRootNodes.OfType<Node>()) + { + p.Areas.Add(new Area() + { + Name = area.Name, + Path = area.Path, + }); + } + + foreach (var iteration in store.Projects[project.Name].IterationRootNodes.OfType<Node>()) + { + p.Iterations.Add(new Iteration() + { + Name = iteration.Name, + Path = iteration.Path, + }); + } + + return p; + }); + } + + public Task<WorkItem> UploadWorkItem(Project project, WorkItem workItem) + { + return Task.Factory.StartNew<WorkItem>(() => + { + var connection = CreateConnection(); + + //var projCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(CollectionURL)); + //WorkItemStore s = new WorkItemStore(projCollection, WorkItemStoreFlags.BypassRules); + + WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); + + var patchDocument = new JsonPatchDocument(); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.Title), + Value = workItem.Title, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.Description), + Value = workItem.Description, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.IterationPath), + Value = workItem.Iteration.Path, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.AreaPath), + Value = workItem.Area.Path, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.AssignedTo), + Value = workItem.AssignedTo.AssignName, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.CreatedBy), + Value = workItem.CreatedBy.AssignName, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.ChangedBy), + Value = workItem.ChangedBy.AssignName, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.AuthorizedAs), + Value = workItem.AuthorizedAs.AssignName, + }); + + if (workItem.UserStory != null) + { + patchDocument.Add( + new JsonPatchOperation() + { + Operation = Operation.Add, + Path = "/relations/-", + Value = new + { + rel = "System.LinkTypes.Hierarchy-Reverse", + url = workItem.UserStory.URL, + } + } + ); + } + + foreach (var attachment in workItem.Attachments) + { + Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.AttachmentReference attachmentReference = witClient.CreateAttachmentAsync(attachment.FilePath).Result; + + patchDocument.Add( + new JsonPatchOperation() + { + Operation = Operation.Add, + Path = "/relations/-", + Value = new + { + rel = "AttachedFile", + url = attachmentReference.Url, + attributes = new { comment = attachment.Description, name = attachment.Name } + } + } + ); + } + + if (workItem.Tags.Count > 0) + { + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.Tags), + Value = String.Join("; ", workItem.Tags.Select(x => x.Name)), + }); + } + + if (!String.IsNullOrWhiteSpace(workItem.StepsToReproduce)) + { + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetExtensionFieldNameForPut(ExtensionFields.STEPS_TO_REP), + Value = workItem.StepsToReproduce, + }); + } + + if (!String.IsNullOrWhiteSpace(workItem.FoundInBuild)) + { + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetExtensionFieldNameForPut(ExtensionFields.FOUND_IN_BUILD), + Value = workItem.FoundInBuild, + }); + } + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetFieldNameForPut(CoreField.State), + Value = workItem.State.ToString(), + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetExtensionFieldNameForPut(ExtensionFields.SEVERITY), + Value = workItem.Severity.ToDescription(), + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetExtensionFieldNameForPut(ExtensionFields.PRIORITY), + Value = (int)workItem.Priority, + }); + + patchDocument.Add(new JsonPatchOperation + { + Operation = Operation.Add, + Path = GetExtensionFieldNameForPut(ExtensionFields.SYSTEM_INFO), + Value = workItem.SystemInformation, + }); + + var resultWorkItem = witClient.CreateWorkItemAsync(patchDocument, project.Name, workItem.Type.ToString(), bypassRules: true).Result; + + workItem.ID = resultWorkItem.Id.Value; + workItem.URL = resultWorkItem.Url; + + return workItem; + }); + } + + private VssConnection CreateConnection() + { + VssConnection connection = new VssConnection(new Uri(CollectionURL), new VssBasicCredential(UserName, PersonalToken)); + return connection; + } + + private String GetFieldName(CoreField field) + { + return "System." + field.ToString(); + } + + private String GetFieldNameForPut(CoreField field) + { + return "/fields/System." + field.ToString(); + } + + private String GetExtensionFieldNameForPut(String extensionFieldName) + { + return "/fields/" + extensionFieldName; + } + + public Task<WorkItem> GetWorkItem(Project project, int id) + { + return Task.Factory.StartNew<WorkItem>(() => + { + WorkItem workItem = new WorkItem(); + + var connection = CreateConnection(); + + WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); + + var item = witClient.GetWorkItemAsync(id, expand: Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItemExpand.All).Result; + + workItem.ID = item.Id.Value; + workItem.Title = item.Fields[GetFieldName(CoreField.Title)].ToString(); + workItem.Description = TryGetField(item.Fields, GetFieldName(CoreField.Description)); + workItem.Area = new Area() + { + Path = item.Fields[GetFieldName(CoreField.AreaPath)].ToString(), + Name = Path.GetFileName(item.Fields[GetFieldName(CoreField.AreaPath)].ToString()), + }; + workItem.Iteration = new Iteration() + { + Path = item.Fields[GetFieldName(CoreField.IterationPath)].ToString(), + Name = Path.GetFileName(item.Fields[GetFieldName(CoreField.IterationPath)].ToString()), + }; + + workItem.AssignedTo = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldName(CoreField.AssignedTo))); + workItem.CreatedBy = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldName(CoreField.CreatedBy))); + workItem.ChangedBy = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldName(CoreField.ChangedBy))); + workItem.AuthorizedAs = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldName(CoreField.AuthorizedAs))); + + workItem.Type = (WorkItemType)Enum.Parse(typeof(WorkItemType), item.Fields[GetFieldName(CoreField.WorkItemType)].ToString()); + workItem.URL = item.Url; + + if (item.Fields.ContainsKey(GetFieldName(CoreField.Tags))) + { + List<String> tags = item.Fields[GetFieldName(CoreField.Tags)].ToString().Split(';').Select(x => x.Trim()).ToList(); + workItem.Tags = tags.Select(x => new Tag() { Name = x }).ToList(); + } + + workItem.FoundInBuild = item.Fields[ExtensionFields.FOUND_IN_BUILD].ToString(); + + workItem.State = (State)Enum.Parse(typeof(State), item.Fields[GetFieldName(CoreField.State)].ToString()); + + workItem.Severity = ParseEnumByDescription<Severity>(item.Fields[ExtensionFields.SEVERITY].ToString()); + + workItem.Priority = (Priority)int.Parse(item.Fields[ExtensionFields.PRIORITY].ToString()); + + workItem.StepsToReproduce = item.Fields[ExtensionFields.STEPS_TO_REP].ToString(); + + workItem.SystemInformation = item.Fields[ExtensionFields.SYSTEM_INFO].ToString(); + + return workItem; + }); + } + + public Task DeleteWorkItem(Project project, int id) + { + return Task.Factory.StartNew(() => + { + var connection = CreateConnection(); + + WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); + var result = witClient.DeleteWorkItemAsync(id, true).Result; + }); + } + + private String TryGetField(IDictionary<String, Object> fields, String key) + { + if (fields.ContainsKey(key)) + { + return fields[key].ToString(); + } + + return String.Empty; + } + + private T ParseEnumByDescription<T>(String description) + { + Dictionary<String, T> values = new Dictionary<string, T>(); + + foreach (var item in Enum.GetValues(typeof(T))) + { + values.Add(((Enum)item).ToDescription(), (T)item); + } + + return values[description]; + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/TeamMember.cs b/Software/Visual_Studio/Tango.TFS/TeamMember.cs new file mode 100644 index 000000000..0d8d402f8 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/TeamMember.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class TeamMember + { + public String ID { get; set; } + public String UniqueName { get; set; } + public String DisplayName { get; set; } + public String URL { get; set; } + public String ImageURL { get; set; } + + public String AssignName + { + get { return String.Format("{0} <{1}>", DisplayName, UniqueName); } + } + + } +} diff --git a/Software/Visual_Studio/Tango.TFS/WorkItem.cs b/Software/Visual_Studio/Tango.TFS/WorkItem.cs new file mode 100644 index 000000000..305f7d864 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/WorkItem.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public class WorkItem + { + public int ID { get; set; } + public String URL { get; set; } + public WorkItemType Type { get; set; } + public Area Area { get; set; } + public Iteration Iteration { get; set; } + public String Title { get; set; } + public String Description { get; set; } + public State State { get; set; } + public Severity Severity { get; set; } + public Priority Priority { get; set; } + public String StepsToReproduce { get; set; } + public String SystemInformation { get; set; } + public TeamMember AssignedTo { get; set; } + public TeamMember CreatedBy { get; set; } + public TeamMember ChangedBy { get; set; } + public TeamMember AuthorizedAs { get; set; } + public List<Attachment> Attachments { get; set; } + public List<Tag> Tags { get; set; } + public WorkItem UserStory { get; set; } + public String FoundInBuild { get; set; } + + public WorkItem() + { + Attachments = new List<Attachment>(); + Tags = new List<Tag>(); + Severity = Severity.Medium; + Priority = Priority.Priority3; + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/WorkItemType.cs b/Software/Visual_Studio/Tango.TFS/WorkItemType.cs new file mode 100644 index 000000000..31807ccb8 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/WorkItemType.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + public enum WorkItemType + { + Task, + Bug, + UserStory, + } +} diff --git a/Software/Visual_Studio/Tango.TFS/app.config b/Software/Visual_Studio/Tango.TFS/app.config new file mode 100644 index 000000000..de5386a47 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/app.config @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.TFS/packages.config b/Software/Visual_Studio/Tango.TFS/packages.config new file mode 100644 index 000000000..c39c44fe7 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/packages.config @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net46" /> + <package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net46" /> + <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.5" targetFramework="net46" /> + <package id="Microsoft.TeamFoundation.DistributedTask.Common" version="15.112.1" targetFramework="net46" /> + <package id="Microsoft.TeamFoundationServer.Client" version="15.112.1" targetFramework="net46" /> + <package id="Microsoft.TeamFoundationServer.ExtendedClient" version="15.112.1" targetFramework="net46" /> + <package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net46" /> + <package id="Microsoft.VisualStudio.Services.Client" version="15.112.1" targetFramework="net46" /> + <package id="Microsoft.VisualStudio.Services.InteractiveClient" version="15.112.1" targetFramework="net46" /> + <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net46" /> + <package id="System.IdentityModel.Tokens.Jwt" version="4.0.2.206221351" targetFramework="net46" /> + <package id="WindowsAzure.ServiceBus" version="3.3.2" targetFramework="net46" /> +</packages>
\ No newline at end of file |
