From d267d6cbfcc49ca0166db7a73ed4cdb43634ab5e Mon Sep 17 00:00:00 2001 From: "Martin Hinshelwood nkdAgility.com" Date: Thu, 25 Jul 2024 10:32:31 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20(WorkItemCloneCommand.cs):=20fix?= =?UTF-8?q?=20field=20access=20to=20use=20dictionary=20indexing=20?= =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(WorkItemCloneCommand.cs):=20rename=20vari?= =?UTF-8?q?ables=20for=20clarity=20and=20consistency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes fix the way fields are accessed in the `projectItem` object by using dictionary indexing (e.g., `projectItem.fields["System.Title"]`) instead of direct property access. This ensures compatibility with the data structure. Additionally, variable names are updated for better clarity and consistency, such as renaming `item` to `controlItem` in the `generateWorkItemsToBuildList` method. This improves code readability and maintainability. 📝 (Resources): add tst_jsonj_export_v20.json to Resources Introduce a new JSON file, `tst_jsonj_export_v20.json`, to the Resources directory. This file contains a list of work items with various fields such as `System.AreaPath`, `System.Tags`, `System.Title`, `Custom.Product`, `Microsoft.VSTS.Scheduling.Effort`, and `Custom.TRA_Milestone`. The addition of this file is intended to provide a sample dataset for testing and development purposes, ensuring that the application can handle and process work item data correctly. ✨ (data.json): add new tasks and milestones for engineering group New tasks and milestones are added to the data.json file to reflect the latest project requirements and scheduling efforts. This update ensures that all relevant tasks are tracked and managed effectively, improving project oversight and resource allocation. ♻️ (WorkItem.cs): change fields property type to Dictionary for flexibility The fields property is changed from a custom Fields type to a Dictionary. This change allows for more flexibility in handling various field types and structures that may be encountered in different work items. --- .../Commands/WorkItemCloneCommand.cs | 26 +- .../Resources/tst_jsonj_export_v20.json | 421 ++++++++++++++++++ .../DataContracts/WorkItem.cs | 2 +- 3 files changed, 433 insertions(+), 16 deletions(-) create mode 100644 AzureDevOps.WorkItemClone.ConsoleUI/Resources/tst_jsonj_export_v20.json diff --git a/AzureDevOps.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs b/AzureDevOps.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs index 5261299..9e465fe 100644 --- a/AzureDevOps.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs +++ b/AzureDevOps.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs @@ -230,8 +230,8 @@ await AnsiConsole.Progress() Dictionary queryParameters = new Dictionary() { { "@projectID", projectItem.id.ToString() }, - { "@projectTitle", projectItem.fields.SystemTitle }, - { "@projectTags", projectItem.fields.SystemTags }, + { "@projectTitle", projectItem.fields["System.Title"].ToString() }, + { "@projectTags", projectItem.fields["System.Tags"].ToString() }, { "@RunName", config.RunName } }; var query = await targetApi.CreateProjectQuery(config.targetQueryTitle, config.targetQueryFolder, config.targetQuery, queryParameters); @@ -250,13 +250,14 @@ await AnsiConsole.Progress() return 0; } + private async IAsyncEnumerable generateWorkItemsToBuildList(JArray jsonWorkItems, List templateWorkItems, WorkItemFull projectItem, string targetTeamProject) { - foreach (var item in jsonWorkItems) + foreach (var controlItem in jsonWorkItems) { WorkItemFull templateWorkItem = null; int jsonItemTemplateId = 0; - if (int.TryParse(item["id"].Value(), out jsonItemTemplateId)) + if (int.TryParse(controlItem["id"].Value(), out jsonItemTemplateId)) { templateWorkItem = templateWorkItems.Find(x => x.id == jsonItemTemplateId); } @@ -264,15 +265,9 @@ private async IAsyncEnumerable generateWorkItemsToBuildList(JAr newItem.guid = Guid.NewGuid(); newItem.hasComplexRelation = false; newItem.templateId = jsonItemTemplateId; - newItem.workItemType = templateWorkItem != null ? templateWorkItem.fields.SystemWorkItemType : "Deliverable"; + newItem.workItemType = templateWorkItem != null ? templateWorkItem.fields["System.WorkItemType"].ToString() : "Deliverable"; newItem.fields = new Dictionary(); - newItem.fields.Add("System.Description", templateWorkItem != null ? templateWorkItem.fields.SystemDescription : ""); - newItem.fields.Add("Microsoft.VSTS.Common.AcceptanceCriteria", templateWorkItem != null ? templateWorkItem.fields.MicrosoftVSTSCommonAcceptanceCriteria : ""); - //{ - // { "System.Tags", string.Join(";" , item.tags, item.area, item.fields.product, templateWorkItem != null? templateWorkItem.fields.SystemTags : "") }, - // { "System.AreaPath", string.Join("\\", targetTeamProject, item.area)}, - //}; - var fields = item["fields"].ToObject>(); + var fields = controlItem["fields"].ToObject>(); foreach (var field in fields) { switch (field.Key) @@ -281,14 +276,15 @@ private async IAsyncEnumerable generateWorkItemsToBuildList(JAr newItem.fields.Add(field.Key, string.Join("\\", targetTeamProject, field.Value)); break; default: - if (newItem.fields.ContainsKey(field.Key)) + if (templateWorkItem != null && templateWorkItem.fields.ContainsKey(field.Key) && (field.Value.Contains("${valuefromtemplate}") || field.Value.Contains("${fromtemplate}"))) { - newItem.fields[field.Key] = field.Value; + /// Add the value from the template + newItem.fields.Add(field.Key, templateWorkItem.fields[field.Key].ToString()); } else { + /// add value from control file newItem.fields.Add(field.Key, field.Value); - } break; } diff --git a/AzureDevOps.WorkItemClone.ConsoleUI/Resources/tst_jsonj_export_v20.json b/AzureDevOps.WorkItemClone.ConsoleUI/Resources/tst_jsonj_export_v20.json new file mode 100644 index 0000000..ab851b1 --- /dev/null +++ b/AzureDevOps.WorkItemClone.ConsoleUI/Resources/tst_jsonj_export_v20.json @@ -0,0 +1,421 @@ +[ + { + "id": 213928, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Technical specification", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 12, + "Custom.TRA_Milestone": "E0.1" + } + }, + { + "id": 251889, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Technical specification", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 12, + "Custom.TRA_Milestone": "E0.1" + } + }, + { + "id": 213380, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Handover protocol", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E1" + } + + }, + { + "id": 214467, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Kick off protocol", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E1" + } + }, + { + "id": 213849, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Engineering cost estimation", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E1.1" + } + }, + { + "id": 213363, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Time schedule", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 36.8, + "Custom.TRA_Milestone": "E1.1" + } + }, + { + "id": 213368, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Risk & Oppertunity Assement", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 8, + "Custom.TRA_Milestone": "E1.2" + } + }, + { + "id": 213366, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Project management plan", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E2" + } + }, + { + "id": 213367, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Document list", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 24, + "Custom.TRA_Milestone": "E2" + } + }, + { + "id": 213848, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Engineering Process Checklist", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 8, + "Custom.TRA_Milestone": "E2" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E2 Assessment", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E2" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E2 Mgmt Meeting", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E2" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Technical specification", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E3" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Technical specification", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E3" + } + }, + { + "id": 214486, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Rating plate", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E4.5" + } + }, + { + "id": 251898, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Rating plate", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E4.5" + } + }, + { + "id": 251899, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Rating plate", + "Custom.Product": "eBox", + "Microsoft.VSTS.Scheduling.Effort": 4, + "Custom.TRA_Milestone": "E4.5" + } + }, + { + "id": 213374, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Spare part list", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 2.4, + "Custom.TRA_Milestone": "E4.5" + } + }, + { + "id": 251900, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Spare part list", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 2.4, + "Custom.TRA_Milestone": "E4.5" + } + }, + { + "id": 214487, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Spare part portfolio", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 2.4, + "Custom.TRA_Milestone": "E4.6" + } + }, + { + "id": 251901, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Spare part portfolio", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 2.4, + "Custom.TRA_Milestone": "E4.6" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E4.8 Assessment", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E4.8" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E4.8 Mgmt Meeting", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E4.8" + } + }, + { + "id": 214489, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "REACh_Compliance_Declaration", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 12, + "Custom.TRA_Milestone": "E5" + } + }, + { + "id": 251905, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "REACh_Compliance_Declaration", + "Custom.Product": "eBox", + "Microsoft.VSTS.Scheduling.Effort": 12, + "Custom.TRA_Milestone": "E5" + } + }, + { + "id": 251904, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "REACh_Compliance_Declaration", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 12, + "Custom.TRA_Milestone": "E5" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E6.7 Assessment", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E6.7" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E6.7 Mgmt Meeting", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E6.7" + } + }, + { + "id": 213379, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Operatiom Manual ", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 40, + "Custom.TRA_Milestone": "E6.7" + } + }, + { + "id": 251902, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "Customer Document", + "System.Title": "Operatiom Manual ", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 40, + "Custom.TRA_Milestone": "E6.7" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E7.2 Assessment", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E7.2" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E7.2 Mgmt Meeting", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E7.2" + } + }, + { + "id": 214493, + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Handover SER/PLCM prot.", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2.4, + "Custom.TRA_Milestone": "E7.5" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Technical specification", + "Custom.Product": "CC", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E8" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Technical specification", + "Custom.Product": "ESS", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E8" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "Engineering Process Checklist", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E8" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E8 Assessment", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 2, + "Custom.TRA_Milestone": "E8" + } + }, + { + "id": "", + "fields": { + "System.AreaPath": "Engineering Group\\ECH Group\\ECH TPL 1", + "System.Tags": "", + "System.Title": "E8 Mgmt Meeting", + "Custom.Product": "", + "Microsoft.VSTS.Scheduling.Effort": 1, + "Custom.TRA_Milestone": "E8" + } + } +] \ No newline at end of file diff --git a/AzureDevOps.WorkItemClone/DataContracts/WorkItem.cs b/AzureDevOps.WorkItemClone/DataContracts/WorkItem.cs index 84509c3..431b893 100644 --- a/AzureDevOps.WorkItemClone/DataContracts/WorkItem.cs +++ b/AzureDevOps.WorkItemClone/DataContracts/WorkItem.cs @@ -17,7 +17,7 @@ public class WorkItemFull { public int id { get; set; } public int rev { get; set; } - public Fields fields { get; set; } + public Dictionary fields { get; set; } public Relation[] relations { get; set; } public _Links3 _links { get; set; } public string url { get; set; }