diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-04-24 19:05:53 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-04-24 19:05:53 +0300 |
| commit | 97e45f70267d961168b77b149022b94022e0e199 (patch) | |
| tree | 89bf6c1c893ab099ef99690d155a0855ba8a9d92 /Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs | |
| parent | 8046598cb1439b66a8d6e556a61b715fc859a6b0 (diff) | |
| download | Tango-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.cs | 210 |
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 } } |
