aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-04-24 19:05:53 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-04-24 19:05:53 +0300
commit97e45f70267d961168b77b149022b94022e0e199 (patch)
tree89bf6c1c893ab099ef99690d155a0855ba8a9d92 /Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs
parent8046598cb1439b66a8d6e556a61b715fc859a6b0 (diff)
downloadTango-97e45f70267d961168b77b149022b94022e0e199.tar.gz
Tango-97e45f70267d961168b77b149022b94022e0e199.zip
Working on reporting...
Diffstat (limited to 'Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs')
-rw-r--r--Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs210
1 files changed, 152 insertions, 58 deletions
diff --git a/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs
index 6bcea336e..e6390260e 100644
--- a/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs
+++ b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs
@@ -12,11 +12,18 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core;
namespace Tango.TFS
{
- public class TeamFoundationServiceClient : ITeamFoundationServiceClient
+ /// <summary>
+ /// Represents a VSTS (Visual Studio On-line) client implementation.
+ /// </summary>
+ /// <seealso cref="Tango.TFS.ITeamFoundationServiceClient" />
+ public class TeamFoundationServiceClient : ExtendedObject, ITeamFoundationServiceClient
{
+ #region Extension Fields Constants
+
private class ExtensionFields
{
public const String FOUND_IN_BUILD = "Microsoft.VSTS.Build.FoundIn";
@@ -26,12 +33,35 @@ namespace Tango.TFS
public const String SYSTEM_INFO = "Microsoft.VSTS.TCM.SystemInfo";
}
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets the default team collection URL.
+ /// </summary>
public String CollectionURL { get; private set; }
+ /// <summary>
+ /// Gets the personal token used to authenticate against the service. https://docs.microsoft.com/en-us/vsts/accounts/use-personal-access-tokens-to-authenticate?view=vsts
+ /// </summary>
public String PersonalToken { get; private set; }
+ /// <summary>
+ /// Gets the VSTS user name (optional).
+ /// </summary>
public String UserName { get; private set; }
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TeamFoundationServiceClient"/> class.
+ /// </summary>
+ /// <param name="collectionURL">The collection URL.</param>
+ /// <param name="userName">Name of the user.</param>
+ /// <param name="personalToken">The personal token.</param>
public TeamFoundationServiceClient(String collectionURL, String userName, String personalToken)
{
CollectionURL = collectionURL;
@@ -39,6 +69,15 @@ namespace Tango.TFS
PersonalToken = personalToken;
}
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Gets a team project by the specified name.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <returns></returns>
public Task<Project> GetProject(string name)
{
return Task.Factory.StartNew<Project>(() =>
@@ -141,15 +180,18 @@ namespace Tango.TFS
});
}
+ /// <summary>
+ /// Uploads a work item to the specified team project.
+ /// </summary>
+ /// <param name="project">The project.</param>
+ /// <param name="workItem">The work item.</param>
+ /// <returns></returns>
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();
@@ -157,56 +199,59 @@ namespace Tango.TFS
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.Title),
+ Path = GetFieldNameForWrite(CoreField.Title),
Value = workItem.Title,
});
- patchDocument.Add(new JsonPatchOperation
+ if (!String.IsNullOrWhiteSpace(workItem.Description))
{
- Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.Description),
- Value = workItem.Description,
- });
+ patchDocument.Add(new JsonPatchOperation
+ {
+ Operation = Operation.Add,
+ Path = GetFieldNameForWrite(CoreField.Description),
+ Value = workItem.Description,
+ });
+ }
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.IterationPath),
+ Path = GetFieldNameForWrite(CoreField.IterationPath),
Value = workItem.Iteration.Path,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.AreaPath),
+ Path = GetFieldNameForWrite(CoreField.AreaPath),
Value = workItem.Area.Path,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.AssignedTo),
+ Path = GetFieldNameForWrite(CoreField.AssignedTo),
Value = workItem.AssignedTo.AssignName,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.CreatedBy),
+ Path = GetFieldNameForWrite(CoreField.CreatedBy),
Value = workItem.CreatedBy.AssignName,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.ChangedBy),
+ Path = GetFieldNameForWrite(CoreField.ChangedBy),
Value = workItem.ChangedBy.AssignName,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.AuthorizedAs),
+ Path = GetFieldNameForWrite(CoreField.AuthorizedAs),
Value = workItem.AuthorizedAs.AssignName,
});
@@ -250,7 +295,7 @@ namespace Tango.TFS
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.Tags),
+ Path = GetFieldNameForWrite(CoreField.Tags),
Value = String.Join("; ", workItem.Tags.Select(x => x.Name)),
});
}
@@ -260,7 +305,7 @@ namespace Tango.TFS
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetExtensionFieldNameForPut(ExtensionFields.STEPS_TO_REP),
+ Path = GetExtensionFieldNameForWrite(ExtensionFields.STEPS_TO_REP),
Value = workItem.StepsToReproduce,
});
}
@@ -270,7 +315,7 @@ namespace Tango.TFS
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetExtensionFieldNameForPut(ExtensionFields.FOUND_IN_BUILD),
+ Path = GetExtensionFieldNameForWrite(ExtensionFields.FOUND_IN_BUILD),
Value = workItem.FoundInBuild,
});
}
@@ -278,28 +323,28 @@ namespace Tango.TFS
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetFieldNameForPut(CoreField.State),
+ Path = GetFieldNameForWrite(CoreField.State),
Value = workItem.State.ToString(),
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetExtensionFieldNameForPut(ExtensionFields.SEVERITY),
+ Path = GetExtensionFieldNameForWrite(ExtensionFields.SEVERITY),
Value = workItem.Severity.ToDescription(),
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetExtensionFieldNameForPut(ExtensionFields.PRIORITY),
+ Path = GetExtensionFieldNameForWrite(ExtensionFields.PRIORITY),
Value = (int)workItem.Priority,
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Operation.Add,
- Path = GetExtensionFieldNameForPut(ExtensionFields.SYSTEM_INFO),
+ Path = GetExtensionFieldNameForWrite(ExtensionFields.SYSTEM_INFO),
Value = workItem.SystemInformation,
});
@@ -312,27 +357,12 @@ namespace Tango.TFS
});
}
- 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;
- }
-
+ /// <summary>
+ /// Gets a work item by the specified team project and work item id.
+ /// </summary>
+ /// <param name="project">The project.</param>
+ /// <param name="id">The identifier.</param>
+ /// <returns></returns>
public Task<WorkItem> GetWorkItem(Project project, int id)
{
return Task.Factory.StartNew<WorkItem>(() =>
@@ -346,36 +376,36 @@ namespace Tango.TFS
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.Title = item.Fields[GetFieldNameForRead(CoreField.Title)].ToString();
+ workItem.Description = TryGetField(item.Fields, GetFieldNameForRead(CoreField.Description));
workItem.Area = new Area()
{
- Path = item.Fields[GetFieldName(CoreField.AreaPath)].ToString(),
- Name = Path.GetFileName(item.Fields[GetFieldName(CoreField.AreaPath)].ToString()),
+ Path = item.Fields[GetFieldNameForRead(CoreField.AreaPath)].ToString(),
+ Name = Path.GetFileName(item.Fields[GetFieldNameForRead(CoreField.AreaPath)].ToString()),
};
workItem.Iteration = new Iteration()
{
- Path = item.Fields[GetFieldName(CoreField.IterationPath)].ToString(),
- Name = Path.GetFileName(item.Fields[GetFieldName(CoreField.IterationPath)].ToString()),
+ Path = item.Fields[GetFieldNameForRead(CoreField.IterationPath)].ToString(),
+ Name = Path.GetFileName(item.Fields[GetFieldNameForRead(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.AssignedTo = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldNameForRead(CoreField.AssignedTo)));
+ workItem.CreatedBy = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldNameForRead(CoreField.CreatedBy)));
+ workItem.ChangedBy = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldNameForRead(CoreField.ChangedBy)));
+ workItem.AuthorizedAs = project.Members.SingleOrDefault(x => x.AssignName == TryGetField(item.Fields, GetFieldNameForRead(CoreField.AuthorizedAs)));
- workItem.Type = (WorkItemType)Enum.Parse(typeof(WorkItemType), item.Fields[GetFieldName(CoreField.WorkItemType)].ToString());
+ workItem.Type = (WorkItemType)Enum.Parse(typeof(WorkItemType), item.Fields[GetFieldNameForRead(CoreField.WorkItemType)].ToString());
workItem.URL = item.Url;
- if (item.Fields.ContainsKey(GetFieldName(CoreField.Tags)))
+ if (item.Fields.ContainsKey(GetFieldNameForRead(CoreField.Tags)))
{
- List<String> tags = item.Fields[GetFieldName(CoreField.Tags)].ToString().Split(';').Select(x => x.Trim()).ToList();
+ List<String> tags = item.Fields[GetFieldNameForRead(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.State = (State)Enum.Parse(typeof(State), item.Fields[GetFieldNameForRead(CoreField.State)].ToString());
workItem.Severity = ParseEnumByDescription<Severity>(item.Fields[ExtensionFields.SEVERITY].ToString());
@@ -389,6 +419,12 @@ namespace Tango.TFS
});
}
+ /// <summary>
+ /// Deletes the specified work item.
+ /// </summary>
+ /// <param name="project">The project.</param>
+ /// <param name="id">The identifier.</param>
+ /// <returns></returns>
public Task DeleteWorkItem(Project project, int id)
{
return Task.Factory.StartNew(() =>
@@ -400,6 +436,56 @@ namespace Tango.TFS
});
}
+ #endregion
+
+ #region Private Methods
+
+ /// <summary>
+ /// Creates connection to VSTS.
+ /// </summary>
+ /// <returns></returns>
+ private VssConnection CreateConnection()
+ {
+ VssConnection connection = new VssConnection(new Uri(CollectionURL), new VssBasicCredential(UserName, PersonalToken));
+ return connection;
+ }
+
+ /// <summary>
+ /// Creates a string representation of a VSTS field when reading.
+ /// </summary>
+ /// <param name="field">The field.</param>
+ /// <returns></returns>
+ private String GetFieldNameForRead(CoreField field)
+ {
+ return "System." + field.ToString();
+ }
+
+ /// <summary>
+ /// Creates a string representation of a VSTS field when writing.
+ /// </summary>
+ /// <param name="field">The field.</param>
+ /// <returns></returns>
+ private String GetFieldNameForWrite(CoreField field)
+ {
+ return "/fields/System." + field.ToString();
+ }
+
+ /// <summary>
+ /// Creates a string representation of a VSTS extension field when writing.
+ /// </summary>
+ /// <param name="field">The field.</param>
+ /// <returns></returns>
+ private String GetExtensionFieldNameForWrite(String extensionFieldName)
+ {
+ return "/fields/" + extensionFieldName;
+ }
+
+ /// <summary>
+ /// Returns a value of the specified field key if found. Otherwise return an empty string.
+ /// </summary>
+ /// <param name="fields">The fields.</param>
+ /// <param name="key">The key.</param>
+ /// <returns></returns>
private String TryGetField(IDictionary<String, Object> fields, String key)
{
if (fields.ContainsKey(key))
@@ -410,6 +496,12 @@ namespace Tango.TFS
return String.Empty;
}
+ /// <summary>
+ /// Returns the specified enum type value by it's [Description] attribute.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="description">The description.</param>
+ /// <returns></returns>
private T ParseEnumByDescription<T>(String description)
{
Dictionary<String, T> values = new Dictionary<string, T>();
@@ -421,5 +513,7 @@ namespace Tango.TFS
return values[description];
}
+
+ #endregion
}
}