Ready to start loading backlog
This commit is contained in:
parent
29bec0cb9a
commit
754cc1ee2b
22
.vscode/launch.json
vendored
22
.vscode/launch.json
vendored
@ -13,16 +13,18 @@
|
||||
"args": [
|
||||
"s",
|
||||
"X",
|
||||
"D:/5-Other-Small/Kanban-mestsa003/FI-Backlog-Mesa-Request-List/859-FI-Backlog-Mesa-Request-List/.vscode",
|
||||
"Day-Helper-2024-08-06",
|
||||
"1000",
|
||||
"D:/Logs",
|
||||
"*.txt",
|
||||
"25",
|
||||
"4",
|
||||
"D:/IFXApps/Logs",
|
||||
"8888",
|
||||
"9999"
|
||||
"T:/MESAFIBACKLOG/06_SourceCode/MESAFIBACKLOG/Adaptation/.vscode/helper",
|
||||
"Day-Helper-2024-08-09",
|
||||
"MES",
|
||||
"https://tfs.intra.infineon.com",
|
||||
"/tfs/FactoryIntegration",
|
||||
"ART SPS",
|
||||
"/_apis/wit",
|
||||
"/wiql/3373b300-8de3-4301-9795-e990c3b226f9",
|
||||
"4n7d2jcql6bkq32f66tohddonfxajkypq66lm5y3zqemtlohawsa",
|
||||
"FI Backlog Mesa - Request List.json",
|
||||
"Chase|infineon\\TuckerC,Dakota(SRP)|infineon\\Mitchem,Daniel|infineon\\StieberD,Jonathan|infineon\\Ouellette,Mike|infineon\\Phares",
|
||||
"Chad B|infineon\\cbecker1,Debra Q|infineon\\Quinones,Jeanne M|infineon\\jmcinty2,Jessica F|infineon\\jfuente1,Jonathon S|infineon\\jsperli1,Justin H|infineon\\jhollan2,Kelly C|infineon\\kclark1,Mark C|infineon\\mcouste1,Marti J|infineon\\mjarsey1,Nik C|infineon\\nclark1,Peyton M|infineon\\McChesne,Ron O|infineon\\Olmstead,Susan H|infineon\\HendersS,Tiffany M|infineon\\tmunoz1,Todd C|infineon\\tcarrie1"
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
|
@ -89,6 +89,8 @@ internal static class HelperDay
|
||||
Day.Q32024.Helper20240805.RenameFiles(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-08-06")
|
||||
Day.Q32024.Helper20240806.ArchiveFiles(logger, args);
|
||||
else if (args[1] == "Day-Helper-2024-08-09")
|
||||
Day.Q32024.Helper20240809.CreateWorkItems(logger, args);
|
||||
else
|
||||
throw new Exception(appSettings.Company);
|
||||
}
|
||||
|
144
Day/Q32024/ConvertExcelToJson/FIBacklogMesa.cs
Normal file
144
Day/Q32024/ConvertExcelToJson/FIBacklogMesa.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.ConvertExcelToJson;
|
||||
|
||||
public class FIBacklogMesa
|
||||
{
|
||||
[JsonConstructor]
|
||||
public FIBacklogMesa(string req,
|
||||
string submitted,
|
||||
string requestor,
|
||||
string assignedTo,
|
||||
string secondResource,
|
||||
string subject,
|
||||
string systemS,
|
||||
string priority,
|
||||
string training,
|
||||
string prioritySubset,
|
||||
string status,
|
||||
string definition,
|
||||
string updates,
|
||||
string estEffortDays,
|
||||
string commitDate,
|
||||
string reCommitDate,
|
||||
string uATAsOf,
|
||||
string cmpDate,
|
||||
string f20,
|
||||
string f21,
|
||||
string f22,
|
||||
string f23,
|
||||
string f24,
|
||||
string f25,
|
||||
string f26,
|
||||
string f27,
|
||||
string f28,
|
||||
string f29,
|
||||
string f30,
|
||||
string f31,
|
||||
string f32,
|
||||
string f33)
|
||||
{
|
||||
Req = req;
|
||||
Submitted = submitted;
|
||||
Requestor = requestor;
|
||||
AssignedTo = assignedTo;
|
||||
SecondResource = secondResource;
|
||||
Subject = subject;
|
||||
SystemS = systemS;
|
||||
Priority = priority;
|
||||
Training = training;
|
||||
PrioritySubset = prioritySubset;
|
||||
Status = status;
|
||||
Definition = definition;
|
||||
Updates = updates;
|
||||
EstEffortDays = estEffortDays;
|
||||
CommitDate = commitDate;
|
||||
ReCommitDate = reCommitDate;
|
||||
UATAsOf = uATAsOf;
|
||||
CMPDate = cmpDate;
|
||||
F20 = f20;
|
||||
F21 = f21;
|
||||
F22 = f22;
|
||||
F23 = f23;
|
||||
F24 = f24;
|
||||
F25 = f25;
|
||||
F26 = f26;
|
||||
F27 = f27;
|
||||
F28 = f28;
|
||||
F29 = f29;
|
||||
F30 = f30;
|
||||
F31 = f31;
|
||||
F32 = f32;
|
||||
F33 = f33;
|
||||
}
|
||||
|
||||
public string Req { get; set; } // { init; get; }
|
||||
public string Submitted { get; set; } // { init; get; }
|
||||
public string Requestor { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Assigned To")]
|
||||
public string AssignedTo { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Second Resource")]
|
||||
public string SecondResource { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Subject - from Requestor")]
|
||||
public string Subject { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System(s)")]
|
||||
public string SystemS { get; set; } // { init; get; }
|
||||
|
||||
public string Priority { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Spec/ECN/Training")]
|
||||
public string Training { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Qual/Eff")]
|
||||
public string PrioritySubset { get; set; } // { init; get; }
|
||||
public string Status { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Definition - from FI")]
|
||||
public string Definition { get; set; } // { init; get; }
|
||||
public string Updates { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Est Effort _(days)")]
|
||||
public string EstEffortDays { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Commit Date")]
|
||||
public string CommitDate { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Re-Commit Date")]
|
||||
public string ReCommitDate { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("UAT as of")]
|
||||
public string UATAsOf { get; set; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("CMP _Date")]
|
||||
public string CMPDate { get; set; } // { init; get; }
|
||||
public string F20 { get; set; } // { init; get; }
|
||||
public string F21 { get; set; } // { init; get; }
|
||||
public string F22 { get; set; } // { init; get; }
|
||||
public string F23 { get; set; } // { init; get; }
|
||||
public string F24 { get; set; } // { init; get; }
|
||||
public string F25 { get; set; } // { init; get; }
|
||||
public string F26 { get; set; } // { init; get; }
|
||||
public string F27 { get; set; } // { init; get; }
|
||||
public string F28 { get; set; } // { init; get; }
|
||||
public string F29 { get; set; } // { init; get; }
|
||||
public string F30 { get; set; } // { init; get; }
|
||||
public string F31 { get; set; } // { init; get; }
|
||||
public string F32 { get; set; } // { init; get; }
|
||||
public string F33 { get; set; } // { init; get; }
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true)]
|
||||
[JsonSerializable(typeof(FIBacklogMesa[]))]
|
||||
internal partial class FIBacklogMesaCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true)]
|
||||
[JsonSerializable(typeof(FIBacklogMesa))]
|
||||
internal partial class FIBacklogMesaSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
560
Day/Q32024/Helper-2024-08-09.cs
Normal file
560
Day/Q32024/Helper-2024-08-09.cs
Normal file
@ -0,0 +1,560 @@
|
||||
using File_Folder_Helper.Day.Q32024.ConvertExcelToJson;
|
||||
using File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
|
||||
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.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Web;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024;
|
||||
|
||||
internal static partial class Helper20240809
|
||||
{
|
||||
|
||||
private static void AddPatch(JsonPatchDocument document, string path, object value) =>
|
||||
document.Add(new JsonPatchOperation { From = null, Operation = Operation.Add, Path = path, Value = value });
|
||||
|
||||
private static Dictionary<string, FIBacklogMesa> GetFIBacklogMesaCollection(string json)
|
||||
{
|
||||
Dictionary<string, FIBacklogMesa> results = [];
|
||||
string key;
|
||||
FIBacklogMesa[]? fiBacklogMesaCollection;
|
||||
fiBacklogMesaCollection = JsonSerializer.Deserialize(json, FIBacklogMesaCollectionSourceGenerationContext.Default.FIBacklogMesaArray);
|
||||
if (fiBacklogMesaCollection is null || fiBacklogMesaCollection.Length == 0)
|
||||
throw new NullReferenceException();
|
||||
foreach (FIBacklogMesa fiBacklogMesa in fiBacklogMesaCollection)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Req))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Submitted))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Requestor))
|
||||
continue;
|
||||
key = $"{fiBacklogMesa.Req} - ";
|
||||
if (results.ContainsKey(key))
|
||||
continue;
|
||||
results.Add(key, fiBacklogMesa);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static string GetIds(HttpClient httpClient, string basePage, string api, string query)
|
||||
{
|
||||
StringBuilder result = new();
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, query));
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<Stream> streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync();
|
||||
streamTask.Wait();
|
||||
if (!streamTask.Result.CanRead)
|
||||
throw new NullReferenceException(nameof(streamTask));
|
||||
WIQL.Root? root = JsonSerializer.Deserialize(streamTask.Result, WIQL.WIQLRootSourceGenerationContext.Default.Root);
|
||||
streamTask.Result.Dispose();
|
||||
if (root is null || root.WorkItems is null)
|
||||
throw new NullReferenceException(nameof(root));
|
||||
foreach (WIQL.WorkItem workItem in root.WorkItems)
|
||||
_ = result.Append(workItem.Id).Append(',');
|
||||
if (result.Length > 0)
|
||||
_ = result.Remove(result.Length - 1, 1);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ValueWithReq> GetWorkItems(HttpClient httpClient, string sourceDirectory, string basePage, string api, string ids)
|
||||
{
|
||||
List<ValueWithReq> results = [];
|
||||
int req;
|
||||
string json;
|
||||
string file;
|
||||
Value? value;
|
||||
string[] segments;
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, $"/workitems?ids={ids}"));
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<Stream> streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync();
|
||||
streamTask.Wait();
|
||||
if (!streamTask.Result.CanRead)
|
||||
throw new NullReferenceException(nameof(streamTask));
|
||||
JsonElement? result = JsonSerializer.Deserialize<JsonElement>(streamTask.Result);
|
||||
if (result is null || result.Value.ValueKind != JsonValueKind.Object)
|
||||
throw new NullReferenceException(nameof(result));
|
||||
JsonElement[] jsonElements = result.Value.EnumerateObject().Last().Value.EnumerateArray().ToArray();
|
||||
foreach (JsonElement jsonElement in jsonElements)
|
||||
{
|
||||
json = jsonElement.GetRawText();
|
||||
value = JsonSerializer.Deserialize(json, ValueSourceGenerationContext.Default.Value);
|
||||
if (value is null)
|
||||
continue;
|
||||
segments = value.Fields.SystemTitle.Split('-');
|
||||
if (segments.Length < 2)
|
||||
continue;
|
||||
if (!int.TryParse(segments[0], out req) || req == 0)
|
||||
continue;
|
||||
file = Path.Combine(sourceDirectory, $"{req}.json");
|
||||
File.WriteAllText(file, json);
|
||||
results.Add(new(value, req, json));
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ValueWithReq> RemoveFrom(Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
List<ValueWithReq> results = [];
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
if (keyToFIBacklogMesa.Remove($"{valueWithReq.Req} - "))
|
||||
continue;
|
||||
results.Add(valueWithReq);
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static DateTime? GetCommitDate(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
DateTime? result;
|
||||
DateTime dateTime;
|
||||
DateTime minDateTime = DateTime.MinValue.AddYears(10);
|
||||
string commitDate = fiBacklogMesa.CommitDate.Split(' ')[0];
|
||||
if (string.IsNullOrEmpty(commitDate))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParseExact(commitDate, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParseExact(commitDate, "dd-MMM-yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParse(commitDate, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int GetPriority(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
int result;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Priority) || !int.TryParse(fiBacklogMesa.Priority[..1], out int priority) || priority == 0 || priority > 3)
|
||||
result = 4;
|
||||
else
|
||||
result = priority;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int? GetPrioritySubset(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
int? result;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.PrioritySubset) || !int.TryParse(fiBacklogMesa.PrioritySubset[..1], out int prioritySubset) || prioritySubset == 0 || prioritySubset > 3)
|
||||
result = null;
|
||||
else
|
||||
result = prioritySubset;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetIterationPath(string project, DateTime submittedDateTime) =>
|
||||
submittedDateTime.Year != 2024 ? project : string.Concat(project, "\\", submittedDateTime.Year);
|
||||
|
||||
private static string GetTitle(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
string result = $"{fiBacklogMesa.Req} - {fiBacklogMesa.Subject.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0]}";
|
||||
if (result.Length > 128)
|
||||
result = result[..127];
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetTitle(FIBacklogMesa fiBacklogMesa, ValueWithReq valueWithReq)
|
||||
{
|
||||
string result = $"{valueWithReq.Req} - {fiBacklogMesa.Subject.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0]}";
|
||||
if (result.Length > 128)
|
||||
result = result[..127];
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string? GetMappedState(FIBacklogMesa fiBacklogMesa) =>
|
||||
fiBacklogMesa.Status == "CMP" ? "Closed" : fiBacklogMesa.Status == "UAT" ? "Resolved" : fiBacklogMesa.Status == "In process" ? "Active" : null;
|
||||
|
||||
private static JsonPatchDocument GetBugDocument(string project, string site, ReadOnlyDictionary<string, string> assignedToNameToUser, ReadOnlyDictionary<string, string> requestorNameToUser, Task<WorkItem>? uatWorkItemTask, FIBacklogMesa fiBacklogMesa, DateTime submittedDateTime)
|
||||
{
|
||||
JsonPatchDocument result = [];
|
||||
string title = GetTitle(fiBacklogMesa);
|
||||
string iterationPath = GetIterationPath(project, submittedDateTime);
|
||||
if (uatWorkItemTask?.Result.Id is not null)
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = uatWorkItemTask.Result.Url });
|
||||
AddPatch(result, "/fields/System.AreaPath", string.Concat(project, "\\", site));
|
||||
AddPatch(result, "/fields/System.IterationPath", iterationPath);
|
||||
AddPatch(result, "/fields/System.Title", title);
|
||||
string? state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state))
|
||||
AddPatch(result, "/fields/System.State", state);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition))
|
||||
AddPatch(result, "/fields/System.Description", $"{fiBacklogMesa.Subject}<br> <br>{fiBacklogMesa.Definition}");
|
||||
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", assignedToUser);
|
||||
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/Custom.Requester", requestorUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetFeatureDocument(string project, string site, ReadOnlyDictionary<string, string> requestorNameToUser, ReadOnlyDictionary<string, string> assignedToNameToUser, List<string> tags, Task<WorkItem>? userStoryWorkItemTask, FIBacklogMesa fiBacklogMesa, DateTime submittedDateTime)
|
||||
{
|
||||
JsonPatchDocument result = [];
|
||||
string title = GetTitle(fiBacklogMesa);
|
||||
int priority = GetPriority(fiBacklogMesa);
|
||||
string? state = GetMappedState(fiBacklogMesa);
|
||||
int? prioritySubset = GetPrioritySubset(fiBacklogMesa);
|
||||
if (prioritySubset is not null)
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Common.TimeCriticality", prioritySubset);
|
||||
string iterationPath = GetIterationPath(project, submittedDateTime);
|
||||
if (userStoryWorkItemTask?.Result.Id is not null)
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = userStoryWorkItemTask.Result.Url });
|
||||
AddPatch(result, "/fields/System.AreaPath", string.Concat(project, "\\", site));
|
||||
if (tags.Count > 0)
|
||||
{
|
||||
AddPatch(result, "/fields/System.Tags", tags.Last());
|
||||
tags.RemoveAt(tags.Count - 1);
|
||||
}
|
||||
AddPatch(result, "/fields/System.IterationPath", iterationPath);
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Common.Priority", priority);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition))
|
||||
AddPatch(result, "/fields/System.Description", $"{fiBacklogMesa.Subject}<br> <br>{fiBacklogMesa.Definition}");
|
||||
if (!string.IsNullOrEmpty(state))
|
||||
AddPatch(result, "/fields/System.State", state);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.EstEffortDays) && int.TryParse(fiBacklogMesa.EstEffortDays, out int estEffortDays) && estEffortDays != 0)
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Scheduling.Effort", estEffortDays);
|
||||
DateTime? dateTime = GetCommitDate(fiBacklogMesa);
|
||||
if (dateTime is not null)
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Scheduling.TargetDate", dateTime);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Updates))
|
||||
AddPatch(result, "/fields/System.History", fiBacklogMesa.Updates);
|
||||
AddPatch(result, "/fields/System.Title", title);
|
||||
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", assignedToUser);
|
||||
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/Custom.Requester", requestorUser);
|
||||
// https://tfs.intra.infineon.com/tfs/ManufacturingIT/Mesa_FI/_apis/wit/workitemtypes/feature/fields?api-version=7.0
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<string> GetTags(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
List<string> results = [];
|
||||
foreach (string tag in fiBacklogMesa.SystemS.Split('/'))
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Trim()))
|
||||
continue;
|
||||
results.Add(tag.Trim());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<string> GetTags(Fields fields)
|
||||
{
|
||||
List<string> results = [];
|
||||
if (!string.IsNullOrEmpty(fields.SystemTags))
|
||||
{
|
||||
foreach (string tag in fields.SystemTags.Split(';'))
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Trim()))
|
||||
continue;
|
||||
results.Add(tag.Trim());
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void CreateWorkItem(WorkItemTrackingHttpClient workItemTrackingHttpClient, string project, string site, ReadOnlyDictionary<string, string> assignedToNameToUser, ReadOnlyDictionary<string, string> requestorNameToUser, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
DateTime submittedDateTime;
|
||||
JsonPatchDocument tagDocument;
|
||||
Task<WorkItem>? workItem = null;
|
||||
List<string> tags = GetTags(fiBacklogMesa);
|
||||
bool isBugFix = fiBacklogMesa.Priority == "0 - BugFix";
|
||||
if (assignedToNameToUser.Count > requestorNameToUser.Count)
|
||||
throw new Exception();
|
||||
if (!DateTime.TryParse(fiBacklogMesa.Submitted, out submittedDateTime))
|
||||
submittedDateTime = DateTime.MinValue;
|
||||
if (isBugFix)
|
||||
{
|
||||
Task<WorkItem>? uatWorkItemTask = null;
|
||||
JsonPatchDocument bugDocument = GetBugDocument(project, site, requestorNameToUser, assignedToNameToUser, uatWorkItemTask, fiBacklogMesa, submittedDateTime);
|
||||
workItem = workItemTrackingHttpClient.CreateWorkItemAsync(bugDocument, project, "Bug");
|
||||
workItem.Wait();
|
||||
}
|
||||
if (!isBugFix)
|
||||
{
|
||||
Task<WorkItem>? userStoryWorkItemTask = null;
|
||||
JsonPatchDocument featureDocument = GetFeatureDocument(project, site, requestorNameToUser, assignedToNameToUser, tags, userStoryWorkItemTask, fiBacklogMesa, submittedDateTime);
|
||||
workItem = workItemTrackingHttpClient.CreateWorkItemAsync(featureDocument, project, "Feature");
|
||||
workItem.Wait();
|
||||
}
|
||||
for (int i = tags.Count - 1; i > -1; i--)
|
||||
{
|
||||
if (workItem is null)
|
||||
continue;
|
||||
if (workItem.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
tagDocument = [];
|
||||
AddPatch(tagDocument, "/fields/System.Tags", tags[i]);
|
||||
tags.RemoveAt(i);
|
||||
workItem = workItemTrackingHttpClient.UpdateWorkItemAsync(tagDocument, workItem.Result.Id.Value);
|
||||
workItem.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
private static void KillTime(int loops)
|
||||
{
|
||||
for (int i = 1; i < loops; i++)
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
private static void Update(HttpClient httpClient, string basePage, string api, string query, HttpContent httpContent)
|
||||
{
|
||||
#if Windows
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.PatchAsync(string.Concat(basePage, api, query), httpContent);
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<string> stringTask = httpResponseMessageTask.Result.Content.ReadAsStringAsync();
|
||||
stringTask.Wait();
|
||||
#endif
|
||||
KillTime(30);
|
||||
}
|
||||
|
||||
private static void Update(HttpClient httpClient, string basePage, string api, WorkItemTrackingHttpClient workItemTrackingHttpClient, string sync, ValueWithReq valueWithReq)
|
||||
{
|
||||
JsonPatchDocument result = [];
|
||||
AddPatch(result, "/fields/System.Tags", sync);
|
||||
Task<WorkItem> workItem = workItemTrackingHttpClient.UpdateWorkItemAsync(result, valueWithReq.Value.Id);
|
||||
workItem.Wait();
|
||||
if (result is null)
|
||||
{
|
||||
var payload = new
|
||||
{
|
||||
op = "replace",
|
||||
path = "/fields/System.IterationPath",
|
||||
value = "Mesa_FI"
|
||||
};
|
||||
string stringPayload = JsonSerializer.Serialize(payload);
|
||||
HttpContent httpContent = new StringContent($"[{stringPayload}]", Encoding.UTF8, "application/json-patch+json");
|
||||
Update(httpClient, basePage, api, $"/workitems/{valueWithReq.Value.Id}?api-version=1.0", httpContent);
|
||||
}
|
||||
}
|
||||
|
||||
private static int SetSyncTag(HttpClient httpClient,
|
||||
string basePage,
|
||||
string api,
|
||||
WorkItemTrackingHttpClient workItemTrackingHttpClient,
|
||||
ReadOnlyDictionary<string, string> assignedToNameToUser,
|
||||
ReadOnlyDictionary<string, string> requestorNameToUser,
|
||||
Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa,
|
||||
ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
int result = 0;
|
||||
string key;
|
||||
string title;
|
||||
int priority;
|
||||
bool isBugFix;
|
||||
string? state;
|
||||
List<string> tags;
|
||||
TimeSpan timeSpan;
|
||||
DateTime? dateTime;
|
||||
List<string> compareTags;
|
||||
const string sync = "Sync";
|
||||
FIBacklogMesa? fiBacklogMesa;
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
key = $"{valueWithReq.Req} - ";
|
||||
compareTags = GetTags(valueWithReq.Value.Fields);
|
||||
if (compareTags.Contains(sync))
|
||||
continue;
|
||||
if (!keyToFIBacklogMesa.TryGetValue(key, out fiBacklogMesa))
|
||||
continue;
|
||||
tags = GetTags(fiBacklogMesa);
|
||||
title = GetTitle(fiBacklogMesa, valueWithReq);
|
||||
isBugFix = fiBacklogMesa.Priority == "0 - BugFix";
|
||||
_ = requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser);
|
||||
if (!string.IsNullOrEmpty(requestorUser) && (valueWithReq.Value.Fields.CustomRequester is null || !valueWithReq.Value.Fields.CustomRequester.UniqueName.Equals(requestorUser, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
_ = assignedToNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? assignedToUser);
|
||||
if (!string.IsNullOrEmpty(assignedToUser) && (valueWithReq.Value.Fields.SystemAssignedTo is null || !valueWithReq.Value.Fields.SystemAssignedTo.UniqueName.Equals(assignedToUser, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (valueWithReq.Value.Fields.SystemTitle != title)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
foreach (string tag in tags)
|
||||
{
|
||||
if (compareTags.Contains(tag))
|
||||
continue;
|
||||
_ = tags.Remove(tag);
|
||||
break;
|
||||
}
|
||||
if (tags.Count != compareTags.Count)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if ((isBugFix && valueWithReq.Value.Fields.SystemWorkItemType != "Bug") || (!isBugFix && valueWithReq.Value.Fields.SystemWorkItemType == "Bug"))
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (!isBugFix)
|
||||
{
|
||||
priority = GetPriority(fiBacklogMesa);
|
||||
if (valueWithReq.Value.Fields.MicrosoftVSTSCommonPriority != priority)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state) && valueWithReq.Value.Fields.SystemState != state)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (!isBugFix && int.TryParse(fiBacklogMesa.EstEffortDays, out int estEffortDays) && valueWithReq.Value.Fields.Effort != estEffortDays)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
dateTime = GetCommitDate(fiBacklogMesa);
|
||||
if (dateTime is not null)
|
||||
{
|
||||
timeSpan = new(valueWithReq.Value.Fields.TargetDate.Ticks - dateTime.Value.Ticks);
|
||||
if (timeSpan.Hours is > 32 or < -32)
|
||||
{
|
||||
result += 1;
|
||||
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void CreateWorkItems(HttpClient httpClient,
|
||||
string sourceDirectory,
|
||||
string basePage,
|
||||
string api,
|
||||
string query,
|
||||
WorkItemTrackingHttpClient workItemTrackingHttpClient,
|
||||
string project,
|
||||
string site,
|
||||
ReadOnlyDictionary<string, string> assignedToNameToUser,
|
||||
ReadOnlyDictionary<string, string> requestorNameToUser,
|
||||
string json)
|
||||
{
|
||||
int counter = 0;
|
||||
string ids = GetIds(httpClient, basePage, api, query);
|
||||
Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa = GetFIBacklogMesaCollection(json);
|
||||
ReadOnlyCollection<ValueWithReq> valueWithReqCollection = string.IsNullOrEmpty(ids) ? new([]) : GetWorkItems(httpClient, sourceDirectory, basePage, api, ids);
|
||||
int updated = SetSyncTag(httpClient, basePage, api, workItemTrackingHttpClient, assignedToNameToUser, requestorNameToUser, keyToFIBacklogMesa, valueWithReqCollection);
|
||||
if (updated == 0)
|
||||
{
|
||||
ReadOnlyCollection<ValueWithReq> extra = RemoveFrom(keyToFIBacklogMesa, valueWithReqCollection);
|
||||
foreach (KeyValuePair<string, FIBacklogMesa> keyValuePair in keyToFIBacklogMesa)
|
||||
{
|
||||
if (keyToFIBacklogMesa.Count == extra.Count)
|
||||
break;
|
||||
CreateWorkItem(workItemTrackingHttpClient, project, site, assignedToNameToUser, requestorNameToUser, keyValuePair.Value);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void CreateWorkItems(ILogger<Worker> logger, string sourceDirectory, string api, string site, string query, string project, string basePage, string baseAddress, byte[] bytes, string[] assignedToNames, string[] requestorNames, string reportFullPath, MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue, WorkItemTrackingHttpClient workItemTrackingHttpClient, HttpClient httpClient)
|
||||
{
|
||||
string base64 = Convert.ToBase64String(bytes);
|
||||
string json = File.ReadAllText(reportFullPath);
|
||||
httpClient.DefaultRequestHeaders.Authorization = new("Basic", base64);
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(mediaTypeWithQualityHeaderValue);
|
||||
ReadOnlyDictionary<string, string> requestorNameToUser = GetRequestorNameToUser(requestorNames);
|
||||
ReadOnlyDictionary<string, string> assignedToNameToUser = GetAssignedToNameToUser(assignedToNames);
|
||||
logger.LogInformation("{baseAddress}{basePage}/{project}{api}{query}", baseAddress, basePage, HttpUtility.HtmlEncode(project), api, query);
|
||||
CreateWorkItems(httpClient, sourceDirectory, basePage, api, query, workItemTrackingHttpClient, project, site, new(assignedToNameToUser), new(requestorNameToUser), json);
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, string> GetAssignedToNameToUser(string[] assignedToNames)
|
||||
{
|
||||
Dictionary<string, string> results = [];
|
||||
string[] segments;
|
||||
foreach (string assignedToName in assignedToNames)
|
||||
{
|
||||
segments = assignedToName.Split('|');
|
||||
if (segments.Length != 2)
|
||||
continue;
|
||||
results.Add(segments[0], segments[1]);
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, string> GetRequestorNameToUser(string[] requestorNames)
|
||||
{
|
||||
Dictionary<string, string> results = [];
|
||||
string[] segments;
|
||||
foreach (string requestorName in requestorNames)
|
||||
{
|
||||
segments = requestorName.Split('|');
|
||||
if (segments.Length != 2)
|
||||
continue;
|
||||
results.Add(segments[0], segments[1]);
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
internal static void CreateWorkItems(ILogger<Worker> logger, List<string> args)
|
||||
{
|
||||
string api = args[6];
|
||||
string pat = args[8];
|
||||
string site = args[2];
|
||||
string query = args[7];
|
||||
string project = args[5];
|
||||
string basePage = args[4];
|
||||
string baseAddress = args[3];
|
||||
string sourceDirectory = args[0];
|
||||
VssBasicCredential credential = new("", pat);
|
||||
string[] requestorNames = args[11].Split(',');
|
||||
string[] assignedToNames = args[10].Split(',');
|
||||
byte[] bytes = Encoding.ASCII.GetBytes($":{pat}");
|
||||
string reportFullPath = Path.GetFullPath(Path.Combine(sourceDirectory, args[9]));
|
||||
VssConnection connection = new(new(string.Concat(baseAddress, basePage)), credential);
|
||||
MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue = new("application/json");
|
||||
WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
|
||||
HttpClient httpClient = new(new HttpClientHandler() { UseDefaultCredentials = true }) { BaseAddress = new(baseAddress) };
|
||||
CreateWorkItems(logger, sourceDirectory, api, site, query, project, basePage, baseAddress, bytes, assignedToNames, requestorNames, reportFullPath, mediaTypeWithQualityHeaderValue, workItemTrackingHttpClient, httpClient);
|
||||
}
|
||||
|
||||
}
|
22
Day/Q32024/WIQL/Column.cs
Normal file
22
Day/Q32024/WIQL/Column.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WIQL;
|
||||
|
||||
public class Column
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Column(
|
||||
string referenceName,
|
||||
string name,
|
||||
string url
|
||||
)
|
||||
{
|
||||
ReferenceName = referenceName;
|
||||
Name = name;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public string ReferenceName { get; set; } // { init; get; }
|
||||
public string Name { get; set; } // { init; get; }
|
||||
public string Url { get; set; } // { init; get; }
|
||||
}
|
22
Day/Q32024/WIQL/Field.cs
Normal file
22
Day/Q32024/WIQL/Field.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WIQL;
|
||||
|
||||
public class Field
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Field(
|
||||
string referenceName,
|
||||
string name,
|
||||
string url
|
||||
)
|
||||
{
|
||||
ReferenceName = referenceName;
|
||||
Name = name;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public string ReferenceName { get; set; } // { init; get; }
|
||||
public string Name { get; set; } // { init; get; }
|
||||
public string Url { get; set; } // { init; get; }
|
||||
}
|
37
Day/Q32024/WIQL/Root.cs
Normal file
37
Day/Q32024/WIQL/Root.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WIQL;
|
||||
|
||||
public class Root
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Root(
|
||||
string queryType,
|
||||
string queryResultType,
|
||||
DateTime asOf,
|
||||
Column[] columns,
|
||||
SortColumn[] sortColumns,
|
||||
WorkItem[] workItems
|
||||
)
|
||||
{
|
||||
QueryType = queryType;
|
||||
QueryResultType = queryResultType;
|
||||
AsOf = asOf;
|
||||
Columns = columns;
|
||||
SortColumns = sortColumns;
|
||||
WorkItems = workItems;
|
||||
}
|
||||
|
||||
public string QueryType { get; set; } // { init; get; }
|
||||
public string QueryResultType { get; set; } // { init; get; }
|
||||
public DateTime AsOf { get; set; } // { init; get; }
|
||||
public Column[] Columns { get; set; } // { init; get; }
|
||||
public SortColumn[] SortColumns { get; set; } // { init; get; }
|
||||
public WorkItem[] WorkItems { get; set; } // { init; get; }
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true)]
|
||||
[JsonSerializable(typeof(Root))]
|
||||
internal partial class WIQLRootSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
19
Day/Q32024/WIQL/SortColumn.cs
Normal file
19
Day/Q32024/WIQL/SortColumn.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WIQL;
|
||||
|
||||
public class SortColumn
|
||||
{
|
||||
[JsonConstructor]
|
||||
public SortColumn(
|
||||
Field field,
|
||||
bool descending
|
||||
)
|
||||
{
|
||||
Field = field;
|
||||
Descending = descending;
|
||||
}
|
||||
|
||||
public Field Field { get; set; } // { init; get; }
|
||||
public bool Descending { get; set; } // { init; get; }
|
||||
}
|
19
Day/Q32024/WIQL/WorkItem.cs
Normal file
19
Day/Q32024/WIQL/WorkItem.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WIQL;
|
||||
|
||||
public class WorkItem
|
||||
{
|
||||
[JsonConstructor]
|
||||
public WorkItem(
|
||||
int id,
|
||||
string url
|
||||
)
|
||||
{
|
||||
Id = id;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public int Id { get; set; } // { init; get; }
|
||||
public string Url { get; set; } // { init; get; }
|
||||
}
|
13
Day/Q32024/WorkItems/Avatar.cs
Normal file
13
Day/Q32024/WorkItems/Avatar.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class Avatar
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Avatar(
|
||||
string href
|
||||
) => Href = href;
|
||||
|
||||
public string Href { get; } // { init; get; }
|
||||
}
|
27
Day/Q32024/WorkItems/CommentVersionRef.cs
Normal file
27
Day/Q32024/WorkItems/CommentVersionRef.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class CommentVersionRef
|
||||
{
|
||||
[JsonConstructor]
|
||||
public CommentVersionRef(
|
||||
int commentId,
|
||||
int version,
|
||||
string url
|
||||
)
|
||||
{
|
||||
CommentId = commentId;
|
||||
Version = version;
|
||||
URL = url;
|
||||
}
|
||||
|
||||
[JsonPropertyName("commentId")]
|
||||
public int CommentId { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public int Version { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string URL { get; } // { init; get; }
|
||||
}
|
47
Day/Q32024/WorkItems/CustomRequester.cs
Normal file
47
Day/Q32024/WorkItems/CustomRequester.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class CustomRequester
|
||||
{
|
||||
[JsonConstructor]
|
||||
public CustomRequester(
|
||||
string displayName,
|
||||
string url,
|
||||
Links links,
|
||||
string id,
|
||||
string uniqueName,
|
||||
string imageUrl,
|
||||
string descriptor
|
||||
)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Url = url;
|
||||
Links = links;
|
||||
Id = id;
|
||||
UniqueName = uniqueName;
|
||||
ImageUrl = imageUrl;
|
||||
Descriptor = descriptor;
|
||||
}
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
|
||||
[JsonPropertyName("_links")]
|
||||
public Links Links { get; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; }
|
||||
|
||||
[JsonPropertyName("uniqueName")]
|
||||
public string UniqueName { get; }
|
||||
|
||||
[JsonPropertyName("imageUrl")]
|
||||
public string ImageUrl { get; }
|
||||
|
||||
[JsonPropertyName("descriptor")]
|
||||
public string Descriptor { get; }
|
||||
}
|
117
Day/Q32024/WorkItems/Fields.cs
Normal file
117
Day/Q32024/WorkItems/Fields.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class Fields
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Fields(
|
||||
string systemAreaPath,
|
||||
string systemTeamProject,
|
||||
string systemIterationPath,
|
||||
string systemWorkItemType,
|
||||
string systemState,
|
||||
string systemReason,
|
||||
CustomRequester customRequester,
|
||||
SystemAssignedTo systemAssignedTo,
|
||||
DateTime systemCreatedDate,
|
||||
SystemCreatedBy systemCreatedBy,
|
||||
DateTime systemChangedDate,
|
||||
SystemChangedBy systemChangedBy,
|
||||
int systemCommentCount,
|
||||
string systemTitle,
|
||||
DateTime microsoftVSTSCommonStateChangeDate,
|
||||
int microsoftVSTSCommonPriority,
|
||||
string systemDescription,
|
||||
string systemTags,
|
||||
string systemHistory,
|
||||
float? effort,
|
||||
DateTime targetDate
|
||||
)
|
||||
{
|
||||
SystemAreaPath = systemAreaPath;
|
||||
SystemTeamProject = systemTeamProject;
|
||||
SystemIterationPath = systemIterationPath;
|
||||
SystemWorkItemType = systemWorkItemType;
|
||||
SystemState = systemState;
|
||||
SystemReason = systemReason;
|
||||
CustomRequester = customRequester;
|
||||
SystemAssignedTo = systemAssignedTo;
|
||||
SystemCreatedDate = systemCreatedDate;
|
||||
SystemCreatedBy = systemCreatedBy;
|
||||
SystemChangedDate = systemChangedDate;
|
||||
SystemChangedBy = systemChangedBy;
|
||||
SystemCommentCount = systemCommentCount;
|
||||
SystemTitle = systemTitle;
|
||||
MicrosoftVSTSCommonStateChangeDate = microsoftVSTSCommonStateChangeDate;
|
||||
MicrosoftVSTSCommonPriority = microsoftVSTSCommonPriority;
|
||||
SystemDescription = systemDescription;
|
||||
SystemTags = systemTags;
|
||||
SystemHistory = systemHistory;
|
||||
Effort = effort;
|
||||
TargetDate = targetDate;
|
||||
}
|
||||
|
||||
[JsonPropertyName("System.AreaPath")]
|
||||
public string SystemAreaPath { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.TeamProject")]
|
||||
public string SystemTeamProject { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.IterationPath")]
|
||||
public string SystemIterationPath { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.WorkItemType")]
|
||||
public string SystemWorkItemType { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.State")]
|
||||
public string SystemState { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.Reason")]
|
||||
public string SystemReason { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Custom.Requester")]
|
||||
public CustomRequester CustomRequester { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.AssignedTo")]
|
||||
public SystemAssignedTo SystemAssignedTo { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.CreatedDate")]
|
||||
public DateTime SystemCreatedDate { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.CreatedBy")]
|
||||
public SystemCreatedBy SystemCreatedBy { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.ChangedDate")]
|
||||
public DateTime SystemChangedDate { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.ChangedBy")]
|
||||
public SystemChangedBy SystemChangedBy { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.CommentCount")]
|
||||
public int SystemCommentCount { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.Title")]
|
||||
public string SystemTitle { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Microsoft.VSTS.Common.StateChangeDate")]
|
||||
public DateTime MicrosoftVSTSCommonStateChangeDate { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Microsoft.VSTS.Common.Priority")]
|
||||
public int MicrosoftVSTSCommonPriority { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.Description")]
|
||||
public string SystemDescription { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.Tags")]
|
||||
public string SystemTags { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("System.History")]
|
||||
public string SystemHistory { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Microsoft.VSTS.Scheduling.Effort")]
|
||||
public float? Effort { get; } // { init; get; }
|
||||
|
||||
[JsonPropertyName("Microsoft.VSTS.Scheduling.TargetDate")]
|
||||
public DateTime TargetDate { get; } // { init; get; }
|
||||
}
|
13
Day/Q32024/WorkItems/Html.cs
Normal file
13
Day/Q32024/WorkItems/Html.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class Html
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Html(
|
||||
string href
|
||||
) => Href = href;
|
||||
|
||||
public string Href { get; } // { init; get; }
|
||||
}
|
14
Day/Q32024/WorkItems/Links.cs
Normal file
14
Day/Q32024/WorkItems/Links.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class Links
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Links(
|
||||
Avatar avatar
|
||||
) => Avatar = avatar;
|
||||
|
||||
[JsonPropertyName("avatar")]
|
||||
public Avatar Avatar { get; }
|
||||
}
|
47
Day/Q32024/WorkItems/SystemAssignedTo.cs
Normal file
47
Day/Q32024/WorkItems/SystemAssignedTo.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class SystemAssignedTo
|
||||
{
|
||||
[JsonConstructor]
|
||||
public SystemAssignedTo(
|
||||
string displayName,
|
||||
string url,
|
||||
Links links,
|
||||
string id,
|
||||
string uniqueName,
|
||||
string imageUrl,
|
||||
string descriptor
|
||||
)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Url = url;
|
||||
Links = links;
|
||||
Id = id;
|
||||
UniqueName = uniqueName;
|
||||
ImageUrl = imageUrl;
|
||||
Descriptor = descriptor;
|
||||
}
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
|
||||
[JsonPropertyName("_links")]
|
||||
public Links Links { get; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; }
|
||||
|
||||
[JsonPropertyName("uniqueName")]
|
||||
public string UniqueName { get; }
|
||||
|
||||
[JsonPropertyName("imageUrl")]
|
||||
public string ImageUrl { get; }
|
||||
|
||||
[JsonPropertyName("descriptor")]
|
||||
public string Descriptor { get; }
|
||||
}
|
47
Day/Q32024/WorkItems/SystemChangedBy.cs
Normal file
47
Day/Q32024/WorkItems/SystemChangedBy.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class SystemChangedBy
|
||||
{
|
||||
[JsonConstructor]
|
||||
public SystemChangedBy(
|
||||
string displayName,
|
||||
string url,
|
||||
Links links,
|
||||
string id,
|
||||
string uniqueName,
|
||||
string imageUrl,
|
||||
string descriptor
|
||||
)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Url = url;
|
||||
Links = links;
|
||||
Id = id;
|
||||
UniqueName = uniqueName;
|
||||
ImageUrl = imageUrl;
|
||||
Descriptor = descriptor;
|
||||
}
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
|
||||
[JsonPropertyName("_links")]
|
||||
public Links Links { get; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; }
|
||||
|
||||
[JsonPropertyName("uniqueName")]
|
||||
public string UniqueName { get; }
|
||||
|
||||
[JsonPropertyName("imageUrl")]
|
||||
public string ImageUrl { get; }
|
||||
|
||||
[JsonPropertyName("descriptor")]
|
||||
public string Descriptor { get; }
|
||||
}
|
47
Day/Q32024/WorkItems/SystemCreatedBy.cs
Normal file
47
Day/Q32024/WorkItems/SystemCreatedBy.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class SystemCreatedBy
|
||||
{
|
||||
[JsonConstructor]
|
||||
public SystemCreatedBy(
|
||||
string displayName,
|
||||
string url,
|
||||
Links links,
|
||||
string id,
|
||||
string uniqueName,
|
||||
string imageUrl,
|
||||
string descriptor
|
||||
)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Url = url;
|
||||
Links = links;
|
||||
Id = id;
|
||||
UniqueName = uniqueName;
|
||||
ImageUrl = imageUrl;
|
||||
Descriptor = descriptor;
|
||||
}
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
|
||||
[JsonPropertyName("_links")]
|
||||
public Links Links { get; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; }
|
||||
|
||||
[JsonPropertyName("uniqueName")]
|
||||
public string UniqueName { get; }
|
||||
|
||||
[JsonPropertyName("imageUrl")]
|
||||
public string ImageUrl { get; }
|
||||
|
||||
[JsonPropertyName("descriptor")]
|
||||
public string Descriptor { get; }
|
||||
}
|
49
Day/Q32024/WorkItems/Value.cs
Normal file
49
Day/Q32024/WorkItems/Value.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class Value
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Value(
|
||||
int id,
|
||||
int rev,
|
||||
Fields fields,
|
||||
CommentVersionRef commentVersionRef,
|
||||
string url
|
||||
)
|
||||
{
|
||||
Id = id;
|
||||
Rev = rev;
|
||||
Fields = fields;
|
||||
CommentVersionRef = commentVersionRef;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; }
|
||||
|
||||
[JsonPropertyName("rev")]
|
||||
public int Rev { get; }
|
||||
|
||||
[JsonPropertyName("fields")]
|
||||
public Fields Fields { get; }
|
||||
|
||||
[JsonPropertyName("commentVersionRef")]
|
||||
public CommentVersionRef CommentVersionRef { get; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true)]
|
||||
[JsonSerializable(typeof(Value[]))]
|
||||
internal partial class ValueCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true)]
|
||||
[JsonSerializable(typeof(Value))]
|
||||
internal partial class ValueSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
19
Day/Q32024/WorkItems/ValueWithReq.cs
Normal file
19
Day/Q32024/WorkItems/ValueWithReq.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace File_Folder_Helper.Day.Q32024.WorkItems;
|
||||
|
||||
public class ValueWithReq
|
||||
{
|
||||
public ValueWithReq(
|
||||
Value value,
|
||||
int req,
|
||||
string json
|
||||
)
|
||||
{
|
||||
Value = value;
|
||||
Req = req;
|
||||
Json = json;
|
||||
}
|
||||
|
||||
public Value Value { get; set; } // { init; get; }
|
||||
public int Req { get; set; } // { init; get; }
|
||||
public string Json { get; set; } // { init; get; }
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Exe</OutputType>
|
||||
@ -16,6 +16,7 @@
|
||||
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.205.1" />
|
||||
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.7" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.4" />
|
||||
<PackageReference Include="TextCopy" Version="6.2.1" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user