using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; namespace File_Folder_Helper.ADO2024.PI3; internal static partial class Helper20240822 { private record Record(string? Title, ReadOnlyCollection Tags, string? Completed); private record Root([property: JsonPropertyName("headings")] Heading[] Headings, [property: JsonPropertyName("lanes")] Lane[] Lanes); [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(Root))] private partial class Helper20240822RootSourceGenerationContext : JsonSerializerContext { } private record Welcome2([property: JsonPropertyName("headings")] Heading[] Headings, [property: JsonPropertyName("lanes")] Lane[] Lanes); private record Heading([property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("heading")] string HeadingHeading); private record Lane([property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("columns")] Column[][] Columns); private record Column([property: JsonPropertyName("id")] string Id, [property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("description")] string Description, [property: JsonPropertyName("metadata")] Metadata? Metadata, [property: JsonPropertyName("subTasks")] SubTask[]? SubTasks, [property: JsonPropertyName("relations")] object[] Relations, [property: JsonPropertyName("comments")] Comment[] Comments, [property: JsonPropertyName("column")] string ColumnColumn, [property: JsonPropertyName("workload")] long Workload, [property: JsonPropertyName("progress")] long Progress, [property: JsonPropertyName("remainingWorkload")] long RemainingWorkload, [property: JsonPropertyName("dueData")] DueData DueData); private record Comment([property: JsonPropertyName("text")] string Text, [property: JsonPropertyName("date")] DateTimeOffset Date); private record DueData([property: JsonPropertyName("completed")] bool Completed, [property: JsonPropertyName("completedDate")] object CompletedDate, [property: JsonPropertyName("dueDate")] DateTimeOffset DueDate, [property: JsonPropertyName("overdue")] bool Overdue, [property: JsonPropertyName("dueDelta")] long DueDelta, [property: JsonPropertyName("dueMessage")] string DueMessage); private record Metadata([property: JsonPropertyName("assigned")] string Assigned, [property: JsonPropertyName("created")] DateTimeOffset Created, [property: JsonPropertyName("progress")] long? Progress, [property: JsonPropertyName("started")] DateTimeOffset? Started, [property: JsonPropertyName("status")] string? Status, [property: JsonPropertyName("tags")] string[]? Tags, [property: JsonPropertyName("type")] string? Type, [property: JsonPropertyName("updated")] DateTimeOffset Updated, [property: JsonPropertyName("due")] DateTimeOffset? Due, [property: JsonPropertyName("completed")] DateTimeOffset? Completed); private record SubTask([property: JsonPropertyName("text")] string Text, [property: JsonPropertyName("completed")] bool Completed); private static ReadOnlyCollection> GetRecords(Column[][] columnCollection) { List> results = []; bool check; int subTasks; Column column; int completed; List row; string? subtasks; List tags; for (int i = 0; i < int.MaxValue; i++) { row = []; check = false; foreach (Column[] columns in columnCollection) { if (columns.Length <= i) row.Add(new(null, new([]), null)); else { tags = []; subTasks = 0; completed = 0; column = columns[i]; if (!check) check = true; if (column.Metadata?.Tags is not null && column.Metadata.Tags.Length != 0) { foreach (string tag in column.Metadata.Tags) tags.Add(tag); } if (column.SubTasks is not null && column.SubTasks.Length != 0) { foreach (SubTask subTask in column.SubTasks) { subTasks += 1; if (subTask.Completed) completed += 1; } } subtasks = subTasks == 0 ? subtasks = null : $"{completed} / {subTasks}"; row.Add(new(column.Name, new(tags), subtasks)); } } if (!check) break; if (results.Count > 0) { if (results[0].Count != row.Count) throw new Exception("Rows must match!"); } results.Add(new(row)); } return new(results); } private static void WriteFile(string destinationFile, Heading[] headings, ReadOnlyCollection> recordCollection) { string title; string completed; List lines = [ "", "", "", "", "", "" ]; foreach (Heading heading in headings) lines.Add($""); lines.Add(""); foreach (ReadOnlyCollection records in recordCollection) { lines.Add(""); foreach (Record record in records) { lines.Add(""); } lines.Add(""); } lines.Add("
{heading.Name}
"); title = record.Title is null ? " " : record.Title; completed = record.Completed is null ? " " : record.Completed; lines.Add($"
{title}
"); lines.Add("
"); foreach (string tag in record.Tags) lines.Add($"{tag}"); lines.Add("
"); lines.Add($"
{completed}
"); lines.Add("
"); lines.Add(""); File.WriteAllLines(destinationFile, lines); } private static void ParseKanbn(ILogger logger, string destinationFile, string json) { Root? root = JsonSerializer.Deserialize(json, Helper20240822RootSourceGenerationContext.Default.Root); if (root is null) logger.LogInformation("<{root}> is null!", root); else if (root.Lanes.Length != 1) logger.LogInformation("{root.Lanes} != 1", root.Lanes.Length); else if (root.Lanes[0].Columns.Length != root.Headings.Length) logger.LogInformation("{root[0].Columns.Lanes} != {root.Headings}", root.Lanes[0].Columns.Length, root.Headings.Length); else { ReadOnlyCollection> recordCollection = GetRecords(root.Lanes[0].Columns); WriteFile(destinationFile, root.Headings, recordCollection); } } internal static void ParseKanbn(ILogger logger, List args) { string sourceDirectory = Path.GetFullPath(args[0]); string sourceFile = Path.Combine(sourceDirectory, args[2]); string destinationFile = Path.Combine(sourceDirectory, $"{DateTime.Now.Ticks}-{args[3]}"); if (!File.Exists(sourceFile)) logger.LogInformation("<{sourceFile}> doesn't exist!", sourceFile); else { string json = File.ReadAllText(sourceFile); ParseKanbn(logger, destinationFile, json); } } }