diff --git a/Adaptation/FileHandlers/Kanban/FileRead.cs b/Adaptation/FileHandlers/Kanban/FileRead.cs index 9ab59ba..6504ba5 100644 --- a/Adaptation/FileHandlers/Kanban/FileRead.cs +++ b/Adaptation/FileHandlers/Kanban/FileRead.cs @@ -1,5 +1,4 @@ using Adaptation.Eaf.Management.ConfigurationData.CellAutomation; -using Adaptation.FileHandlers.json.WorkItems; using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration; using Adaptation.Shared; using Adaptation.Shared.Duplicator; @@ -15,6 +14,8 @@ namespace Adaptation.FileHandlers.Kanban; public class FileRead : Shared.FileRead, IFileRead { + private long? _TickOffset; + private readonly string _URL; private readonly ReadOnlyCollection _CSSLines; private readonly ReadOnlyCollection _FrontMatterLines; @@ -31,6 +32,8 @@ public class FileRead : Shared.FileRead, IFileRead if (!_IsDuplicator) throw new Exception(cellInstanceConnectionName); List cssLines = new(); + string cellInstanceNamed = string.Concat("CellInstance.", _EquipmentType); + _URL = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.URL"); string cssLinesName = string.Concat("CellInstance.", cellInstanceName, '.', cellInstanceConnectionName, ".CSS.Lines"); ModelObjectParameterDefinition[] cssLinesDefinitions = GetProperties(cellInstanceConnectionName, modelObjectParameters, cssLinesName); foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in cssLinesDefinitions) @@ -111,87 +114,21 @@ public class FileRead : Shared.FileRead, IFileRead return results; } -#nullable enable - - private void Save(string fileNameWithoutExtension, WorkItem[] workItems) - { - string old; - string json; - string checkFile; - string tasksDirectory; - string kanbanDirectory; - string vscodeDirectory; - string singletonDirectory; - List indexLines = new(); - JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; - string rootDirectory = Path.Combine(_FileConnectorConfiguration.TargetFileLocation, fileNameWithoutExtension); - if (string.IsNullOrEmpty(rootDirectory)) - throw new NullReferenceException(nameof(rootDirectory)); - foreach (WorkItem workItem in workItems) - { - json = JsonSerializer.Serialize(workItem, jsonSerializerOptions); - singletonDirectory = Path.Combine(rootDirectory, workItem.WorkItemType.Replace(" ", "-"), $"{workItem.Id}-{workItem.WorkItemType.Replace(" ", "-")}"); - kanbanDirectory = Path.Combine(singletonDirectory, ".kanbn"); - if (!Directory.Exists(kanbanDirectory)) - _ = Directory.CreateDirectory(kanbanDirectory); - tasksDirectory = Path.Combine(kanbanDirectory, "tasks"); - if (!Directory.Exists(tasksDirectory)) - _ = Directory.CreateDirectory(tasksDirectory); - vscodeDirectory = Path.Combine(singletonDirectory, ".vscode"); - if (!Directory.Exists(vscodeDirectory)) - _ = Directory.CreateDirectory(vscodeDirectory); - checkFile = Path.Combine(vscodeDirectory, "settings.json"); - if (!File.Exists(checkFile)) - File.WriteAllText(checkFile, "{ \"[markdown]\": { \"editor.wordWrap\": \"off\" }, \"cSpell.words\": [ \"kanbn\" ] }"); - indexLines.Clear(); - indexLines.AddRange(_FrontMatterLines); - indexLines.Add(string.Empty); - indexLines.Add($"# {workItem.Id}"); - indexLines.Add(string.Empty); - indexLines.Add("## Backlog"); - indexLines.Add(string.Empty); - indexLines.Add("## Todo"); - indexLines.Add(string.Empty); - indexLines.Add("## In Progress"); - indexLines.Add(string.Empty); - indexLines.Add("## Done"); - checkFile = Path.Combine(kanbanDirectory, "board.css"); - if (!File.Exists(checkFile)) - File.WriteAllLines(checkFile, _CSSLines); - checkFile = Path.Combine(kanbanDirectory, "index.md"); - if (!File.Exists(checkFile)) - File.WriteAllLines(checkFile, indexLines); - checkFile = Path.Combine(kanbanDirectory, ".json"); - if (File.Exists(checkFile)) - { - old = File.ReadAllText(checkFile); - if (old == json) - continue; - } - File.WriteAllText(checkFile, json); - } - } - -#pragma warning disable IDE0060 - private void Save(string reportFullPath, DateTime dateTime) -#pragma warning restore IDE0060 - { - string json = File.ReadAllText(reportFullPath); - WorkItem[]? workItems = JsonSerializer.Deserialize(json); - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(reportFullPath); - if (workItems is null) - throw new Exception(nameof(workItems)); - if (workItems.Length > 0) - Save(fileNameWithoutExtension, workItems); - } - private Tuple> GetExtractResult(string reportFullPath, DateTime dateTime) { - Tuple> results; + Tuple> results = new(string.Empty, null, null, new List()); + _TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks; _Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};"); - if (_IsEAFHosted) - Save(reportFullPath, dateTime); - results = new(_Logistics.Logistics1[0], Array.Empty(), Array.Empty(), new List()); + SetFileParameterLotIDToLogisticsMID(); + if (_Logistics.FileInfo.Length < _MinFileLength) + results.Item4.Add(_Logistics.FileInfo); + else + { + IProcessData iProcessData = new ProcessData(this, _Logistics, _FileConnectorConfiguration.TargetFileLocation, _URL, _CSSLines, _FrontMatterLines, results.Item4); + if (iProcessData.Details.Count == 0) + throw new Exception(string.Concat("B) No Data - ", dateTime.Ticks)); + results = iProcessData.GetResults(this, _Logistics, results.Item4); + } return results; } diff --git a/Adaptation/FileHandlers/Kanban/ProcessData.cs b/Adaptation/FileHandlers/Kanban/ProcessData.cs new file mode 100644 index 0000000..9ff85b0 --- /dev/null +++ b/Adaptation/FileHandlers/Kanban/ProcessData.cs @@ -0,0 +1,334 @@ +using Adaptation.FileHandlers.json.WorkItems; +using Adaptation.Shared; +using Adaptation.Shared.Duplicator; +using Adaptation.Shared.Methods; +using log4net; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Adaptation.FileHandlers.Kanban; + +public class ProcessData : IProcessData +{ + + private readonly List _Details; + + List Shared.Properties.IProcessData.Details => _Details; + + private readonly ILog _Log; + + public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection cssLines, ReadOnlyCollection frontMatterLines, List fileInfoCollection) + { + if (fileRead.IsEAFHosted) + { } + fileInfoCollection.Clear(); + _Details = new List(); + _Log = LogManager.GetLogger(typeof(ProcessData)); + WriteFiles(fileRead, logistics, url, cssLines, frontMatterLines, targetFileLocation, fileInfoCollection); + } + + string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary reactors) => + throw new Exception(string.Concat("See ", nameof(WriteFiles))); + + Tuple> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List fileInfoCollection) => + new(logistics.Logistics1[0], Array.Empty(), Array.Empty(), fileInfoCollection); + +#nullable enable + + internal static List GetDescriptions(JsonElement[] jsonElements) + { + List results = new(); + Description? description; + JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; + foreach (JsonElement jsonElement in jsonElements) + { + if (jsonElement.ValueKind != JsonValueKind.Object) + throw new Exception(); + description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); + if (description is null) + continue; + results.Add(description); + } + return results; + } + + private void WriteFiles(IFileRead fileRead, Logistics logistics, string url, ReadOnlyCollection cssLines, ReadOnlyCollection frontMatterLines, string destinationDirectory, List fileInfoCollection) + { + if (!Directory.Exists(destinationDirectory)) + _ = Directory.CreateDirectory(destinationDirectory); + string json = File.ReadAllText(logistics.ReportFullPath); + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(logistics.ReportFullPath); + WorkItem[]? workItems = JsonSerializer.Deserialize(json); + if (workItems is null) + throw new Exception(nameof(workItems)); + _Details.Add(workItems); + ReadOnlyDictionary keyValuePairs = GetWorkItems(workItems); + WriteFileStructure(destinationDirectory, keyValuePairs); + WriteFiles(fileRead, destinationDirectory, fileInfoCollection, fileNameWithoutExtension, keyValuePairs); + WriteKanbanFiles(fileRead, destinationDirectory, cssLines, frontMatterLines, fileInfoCollection, keyValuePairs); + } + + private static ReadOnlyDictionary GetWorkItems(WorkItem[] workItems) + { + ReadOnlyDictionary results; + Dictionary keyValuePairs = new(); + foreach (WorkItem workItem in workItems) + keyValuePairs.Add(workItem.Id, workItem); + results = GetKeyValuePairs(new(keyValuePairs)); + return results; + } + + private static void WriteFileStructure(string destinationDirectory, ReadOnlyDictionary keyValuePairs) + { + ReadOnlyCollection collection = GetDirectories(destinationDirectory, keyValuePairs); + foreach (string directory in collection) + { + if (directory.Length > 222) + continue; + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + } + } + + private void WriteFiles(IFileRead fileRead, string destinationDirectory, List fileInfoCollection, string fileNameWithoutExtension, ReadOnlyDictionary keyValuePairs) + { + string old; + string json; + string checkFile; + WorkItem workItem; + string singletonDirectory; + JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; + string rootDirectory = Path.Combine(destinationDirectory, fileNameWithoutExtension); + if (string.IsNullOrEmpty(rootDirectory)) + throw new NullReferenceException(nameof(rootDirectory)); + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + workItem = keyValuePair.Value.WorkItem; + json = JsonSerializer.Serialize(workItem, jsonSerializerOptions); + singletonDirectory = Path.Combine(rootDirectory, workItem.WorkItemType.Replace(" ", "-"), $"{workItem.Id}-{workItem.WorkItemType.Replace(" ", "-")}"); + if (!Directory.Exists(singletonDirectory)) + _ = Directory.CreateDirectory(singletonDirectory); + checkFile = Path.Combine(singletonDirectory, ".json"); + if (File.Exists(checkFile)) + { + old = File.ReadAllText(checkFile); + if (old == json) + continue; + } + File.WriteAllText(checkFile, json); + if (!fileRead.IsEAFHosted) + fileInfoCollection.Add(new(checkFile)); + } + + } + + private void WriteKanbanFiles(IFileRead fileRead, string destinationDirectory, ReadOnlyCollection cssLines, ReadOnlyCollection frontMatterLines, List fileInfoCollection, ReadOnlyDictionary keyValuePairs) + { + string old; + string json; + Record record; + string checkFile; + string tasksDirectory; + string kanbanDirectory; + string vscodeDirectory; + string[] iterationPaths; + string singletonDirectory; + List indexLines = new(); + JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + record = keyValuePair.Value; + singletonDirectory = destinationDirectory; + iterationPaths = record.WorkItem.IterationPath.Split('\\'); + json = JsonSerializer.Serialize(record, jsonSerializerOptions); + foreach (string iterationPath in iterationPaths) + { + if (iterationPath.Contains("Sprint")) + continue; + singletonDirectory = Path.Combine(singletonDirectory, iterationPath); + } + singletonDirectory = Path.Combine(singletonDirectory, record.WorkItem.WorkItemType.Replace(" ", "-"), $"{record.WorkItem.Id}-{record.WorkItem.WorkItemType.Replace(" ", "-")}"); + kanbanDirectory = Path.Combine(singletonDirectory, ".kanbn"); + if (!Directory.Exists(kanbanDirectory)) + _ = Directory.CreateDirectory(kanbanDirectory); + tasksDirectory = Path.Combine(kanbanDirectory, "tasks"); + if (!Directory.Exists(tasksDirectory)) + _ = Directory.CreateDirectory(tasksDirectory); + vscodeDirectory = Path.Combine(singletonDirectory, ".vscode"); + if (!Directory.Exists(vscodeDirectory)) + _ = Directory.CreateDirectory(vscodeDirectory); + checkFile = Path.Combine(vscodeDirectory, "settings.json"); + if (!File.Exists(checkFile)) + File.WriteAllText(checkFile, "{ \"[markdown]\": { \"editor.wordWrap\": \"off\" }, \"cSpell.words\": [ \"kanbn\" ] }"); + indexLines.Clear(); + indexLines.AddRange(frontMatterLines); + indexLines.Add(string.Empty); + indexLines.Add($"# {record.WorkItem.Id}"); + indexLines.Add(string.Empty); + indexLines.Add("## Backlog"); + indexLines.Add(string.Empty); + indexLines.Add("## Todo"); + indexLines.Add(string.Empty); + indexLines.Add("## In Progress"); + indexLines.Add(string.Empty); + indexLines.Add("## Done"); + checkFile = Path.Combine(kanbanDirectory, "board.css"); + if (!File.Exists(checkFile)) + File.WriteAllLines(checkFile, cssLines); + checkFile = Path.Combine(kanbanDirectory, "index.md"); + if (!File.Exists(checkFile)) + File.WriteAllLines(checkFile, indexLines); + checkFile = Path.Combine(kanbanDirectory, ".json"); + if (File.Exists(checkFile)) + { + old = File.ReadAllText(checkFile); + if (old == json) + continue; + } + File.WriteAllText(checkFile, json); + if (!fileRead.IsEAFHosted) + fileInfoCollection.Add(new(checkFile)); + } + } + + private static ReadOnlyDictionary GetKeyValuePairs(ReadOnlyDictionary keyValuePairs) + { + Dictionary results = new(); + Record record; + List nests = new(); + WorkItem? parentWorkItem; + ReadOnlyCollection records; + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + nests.Clear(); + if (keyValuePair.Value.Parent is null) + parentWorkItem = null; + else + _ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem); + try + { + records = GetKeyValuePairs(keyValuePairs, keyValuePair.Value, nests); + record = new(keyValuePair.Value, parentWorkItem, records, null); + } + catch (Exception) + { + record = new(keyValuePair.Value, parentWorkItem, new(Array.Empty()), null); + } + results.Add(keyValuePair.Key, record); + } + return new(results); + } + + private static ReadOnlyCollection GetDirectories(string destinationDirectory, ReadOnlyDictionary keyValuePairs) + { + List results = new(); + Record record; + string directory; + List nests = new(); + ReadOnlyCollection childrenDirectories; + string dateDirectory = Path.Combine(destinationDirectory, "_", DateTime.Now.ToString("yyyy-MM-dd")); + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + record = keyValuePair.Value; + if (record.Parent is not null && (record.WorkItem.Parent is null || record.Parent.Id != record.WorkItem.Parent.Value)) + continue; + if (record.Parent is not null) + continue; + // if (record.WorkItem.Id == 110730) + // continue; + // if (record.WorkItem.Id == 110732) + // continue; + nests.Clear(); + directory = Path.Combine(dateDirectory, $"{record.WorkItem.WorkItemType.Substring(0, 1)}-{record.WorkItem.Id}-{record.WorkItem.Title.Trim().Substring(0, 1)}"); + childrenDirectories = GetChildrenDirectories(keyValuePairs, nests, directory, record); + results.AddRange(childrenDirectories); + } + return new(results.Distinct().ToArray()); + } + + private static ReadOnlyCollection GetKeyValuePairs(ReadOnlyDictionary keyValuePairs, WorkItem workItem, List nests) + { + List results = new(); + int? childId; + Record record; + nests.Add(true); + WorkItem? childWorkItem; + WorkItem? parentWorkItem; + List collection = new(); + ReadOnlyCollection records; + if (workItem.Relations is not null && workItem.Relations.Length > 0) + { + collection.Clear(); + foreach (Relation relation in workItem.Relations) + { + childId = GetIdFromUrlIfChild(relation); + if (childId is not null && workItem.Parent is not null && relation?.URL is not null && relation.URL.Contains(workItem.Parent.Value.ToString())) + continue; + if (childId is null || !keyValuePairs.TryGetValue(childId.Value, out childWorkItem)) + continue; + collection.Add(childWorkItem); + } + collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList(); + foreach (WorkItem w in collection) + { + if (nests.Count > 99) + break; + if (w.Parent is null) + parentWorkItem = null; + else + _ = keyValuePairs.TryGetValue(w.Parent.Value, out parentWorkItem); + records = GetKeyValuePairs(keyValuePairs, w, nests); + record = new(w, parentWorkItem, records, null); + results.Add(record); + } + } + return new(results); + } + + private static ReadOnlyCollection GetChildrenDirectories(ReadOnlyDictionary keyValuePairs, List nests, string parentDirectory, Record record) + { + List results = new(); + nests.Add(true); + string directory; + Record? childRecord; + ReadOnlyCollection childrenDirectories; + foreach (Record r in record.Children) + { + // if (record.WorkItem.Id == 110730) + // continue; + // if (record.WorkItem.Id == 110732) + // continue; + directory = Path.Combine(parentDirectory, $"{r.WorkItem.WorkItemType.Substring(0, 1)}-{r.WorkItem.Id}-{r.WorkItem.Title.Trim().Substring(0, 1)}"); + results.Add(directory); + if (!keyValuePairs.TryGetValue(r.WorkItem.Id, out childRecord)) + continue; + if (nests.Count > 99) + break; + childrenDirectories = GetChildrenDirectories(keyValuePairs, nests, directory, childRecord); + results.AddRange(childrenDirectories); + } + return new(results); + } + + private static int? GetIdFromUrlIfChild(Relation relation) + { + int? result; + string[] segments = relation?.Attributes is null || relation.Attributes.Name != "Child" ? Array.Empty() : relation.URL.Split('/'); + if (segments.Length < 2) + result = null; + else + { + if (!int.TryParse(segments[segments.Length - 1], out int id)) + result = null; + else + result = id; + } + return result; + } + +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/Markdown/ProcessData.cs b/Adaptation/FileHandlers/Markdown/ProcessData.cs index 1125392..c4aeacc 100644 --- a/Adaptation/FileHandlers/Markdown/ProcessData.cs +++ b/Adaptation/FileHandlers/Markdown/ProcessData.cs @@ -59,6 +59,8 @@ public class ProcessData : IProcessData private void WriteFiles(IFileRead fileRead, Logistics logistics, string url, ReadOnlyCollection workItemTypes, string destinationDirectory, List fileInfoCollection) { + if (!Directory.Exists(destinationDirectory)) + _ = Directory.CreateDirectory(destinationDirectory); string json = File.ReadAllText(logistics.ReportFullPath); WorkItem[]? workItems = JsonSerializer.Deserialize(json); if (workItems is null) @@ -67,12 +69,9 @@ public class ProcessData : IProcessData List lines = new(); ReadOnlyCollection results; ReadOnlyDictionary keyValuePairs = GetWorkItems(workItems); - WriteFileStructure(destinationDirectory, keyValuePairs); ReadOnlyCollection records = new(keyValuePairs.Values.ToArray()); ReadOnlyCollection bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" }); ReadOnlyCollection bugUserStoryTaskWorkItemTypes = new(new string[] { "Bug", "User Story", "Task" }); - if (!Directory.Exists(destinationDirectory)) - _ = Directory.CreateDirectory(destinationDirectory); WriteFiles(fileRead, destinationDirectory, fileInfoCollection, records, "with-parents"); foreach (string workItemType in workItemTypes) { @@ -166,18 +165,6 @@ public class ProcessData : IProcessData return results; } - private static void WriteFileStructure(string destinationDirectory, ReadOnlyDictionary keyValuePairs) - { - ReadOnlyCollection collection = GetDirectories(destinationDirectory, keyValuePairs); - foreach (string directory in collection) - { - if (directory.Length > 222) - continue; - if (!Directory.Exists(directory)) - _ = Directory.CreateDirectory(directory); - } - } - private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List fileInfoCollection, ReadOnlyCollection records, string fileName) { string json = JsonSerializer.Serialize(records, new JsonSerializerOptions() { WriteIndented = true }); @@ -255,6 +242,7 @@ public class ProcessData : IProcessData private static ReadOnlyDictionary GetKeyValuePairs(ReadOnlyDictionary keyValuePairs) { Dictionary results = new(); + Record record; List nests = new(); WorkItem? parentWorkItem; ReadOnlyCollection records; @@ -268,43 +256,17 @@ public class ProcessData : IProcessData try { records = GetKeyValuePairs(keyValuePairs, keyValuePair.Value, nests); - results.Add(keyValuePair.Key, new(keyValuePair.Value, parentWorkItem, records)); + record = new(keyValuePair.Value, parentWorkItem, records, null); } catch (Exception) { - results.Add(keyValuePair.Key, new(keyValuePair.Value, parentWorkItem, new(Array.Empty()))); + record = new(keyValuePair.Value, parentWorkItem, new(Array.Empty()), null); } + results.Add(keyValuePair.Key, record); } return new(results); } - private static ReadOnlyCollection GetDirectories(string destinationDirectory, ReadOnlyDictionary keyValuePairs) - { - List results = new(); - Record record; - string directory; - List nests = new(); - ReadOnlyCollection childrenDirectories; - string dateDirectory = Path.Combine(destinationDirectory, "_", DateTime.Now.ToString("yyyy-MM-dd")); - foreach (KeyValuePair keyValuePair in keyValuePairs) - { - record = keyValuePair.Value; - if (record.Parent is not null && (record.WorkItem.Parent is null || record.Parent.Id != record.WorkItem.Parent.Value)) - continue; - if (record.Parent is not null) - continue; - // if (record.WorkItem.Id == 110730) - // continue; - // if (record.WorkItem.Id == 110732) - // continue; - nests.Clear(); - directory = Path.Combine(dateDirectory, $"{record.WorkItem.WorkItemType.Substring(0, 1)}-{record.WorkItem.Id}-{record.WorkItem.Title.Trim().Substring(0, 1)}"); - childrenDirectories = GetChildrenDirectories(keyValuePairs, nests, directory, record); - results.AddRange(childrenDirectories); - } - return new(results.Distinct().ToArray()); - } - private static string GetLine(List spaces, WorkItem workItem, Record record, bool condensed, bool sprintOnly) { string result; @@ -319,6 +281,7 @@ public class ProcessData : IProcessData { List results = new(); int? childId; + Record record; nests.Add(true); WorkItem? childWorkItem; WorkItem? parentWorkItem; @@ -346,12 +309,32 @@ public class ProcessData : IProcessData else _ = keyValuePairs.TryGetValue(w.Parent.Value, out parentWorkItem); records = GetKeyValuePairs(keyValuePairs, w, nests); - results.Add(new(w, parentWorkItem, records)); + record = new(w, parentWorkItem, records, null); + results.Add(record); } } return new(results); } + private static string GetClosed(WorkItem workItem) => + workItem.State != "Closed" ? "[ ]" : "[x]"; + + private static int? GetIdFromUrlIfChild(Relation relation) + { + int? result; + string[] segments = relation?.Attributes is null || relation.Attributes.Name != "Child" ? Array.Empty() : relation.URL.Split('/'); + if (segments.Length < 2) + result = null; + else + { + if (!int.TryParse(segments[segments.Length - 1], out int id)) + result = null; + else + result = id; + } + return result; + } + private static ReadOnlyCollection GetChildrenDirectories(ReadOnlyDictionary keyValuePairs, List nests, string parentDirectory, Record record) { List results = new(); @@ -377,25 +360,6 @@ public class ProcessData : IProcessData return new(results); } - private static string GetClosed(WorkItem workItem) => - workItem.State != "Closed" ? "[ ]" : "[x]"; - - private static int? GetIdFromUrlIfChild(Relation relation) - { - int? result; - string[] segments = relation?.Attributes is null || relation.Attributes.Name != "Child" ? Array.Empty() : relation.URL.Split('/'); - if (segments.Length < 2) - result = null; - else - { - if (!int.TryParse(segments[segments.Length - 1], out int id)) - result = null; - else - result = id; - } - return result; - } - private static void FilterChildren(ReadOnlyCollection workItemTypes, Record record, List results) { foreach (Record r in record.Children) diff --git a/Adaptation/FileHandlers/json/FileRead.cs b/Adaptation/FileHandlers/json/FileRead.cs index 3ff6be9..6621a0e 100644 --- a/Adaptation/FileHandlers/json/FileRead.cs +++ b/Adaptation/FileHandlers/json/FileRead.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Text.Json; @@ -197,22 +198,31 @@ public class FileRead : Shared.FileRead, IFileRead } } - private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders) + private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar, string[] alternateTargetFolders) { if (!Directory.Exists(fileConnectorConfiguration.TargetFileLocation)) _ = Directory.CreateDirectory(fileConnectorConfiguration.TargetFileLocation); + DateTime dateTime = DateTime.Now; + string weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); + string weekDirectory = Path.Combine(fileConnectorConfiguration.TargetFileLocation, $"{dateTime:yyyy}_Week_{weekOfYear}"); string[] files = Directory.GetFiles(fileConnectorConfiguration.TargetFileLocation, fileConnectorConfiguration.SourceFileFilter, SearchOption.TopDirectoryOnly); + if (!Directory.Exists(weekDirectory)) + { + _ = Directory.CreateDirectory(weekDirectory); + foreach (string file in files) + File.Copy(file, Path.Combine(weekDirectory, Path.GetFileName(file))); + } ReadOnlyCollection collection = GetWorkItems(files); ReadOnlyCollection workItems = GetWorkItems(collection); if (workItems.Count > 0) WriteCollectionJson(fileConnectorConfiguration, alternateTargetFolders, workItems); } - private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration) + private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, Calendar calendar) { string[] alternateTargetFolders = fileConnectorConfiguration.AlternateTargetFolder.Split('|'); if (alternateTargetFolders.Length > 0) - ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders); + ParseWorkItemsAsync(fileConnectorConfiguration, calendar, alternateTargetFolders); } private void Callback(object state) @@ -220,7 +230,7 @@ public class FileRead : Shared.FileRead, IFileRead try { if (_IsEAFHosted) - ParseWorkItemsAsync(_FileConnectorConfiguration); + ParseWorkItemsAsync(_FileConnectorConfiguration, _Calendar); } catch (Exception exception) { diff --git a/Adaptation/FileHandlers/json/WorkItems/PollValues.cs b/Adaptation/FileHandlers/json/WorkItems/PollValues.cs new file mode 100644 index 0000000..6a1168e --- /dev/null +++ b/Adaptation/FileHandlers/json/WorkItems/PollValues.cs @@ -0,0 +1,36 @@ +namespace Adaptation.FileHandlers.json.WorkItems; + +public class PollValues +{ + +#nullable enable + + public PollValues(float? business, + int businessCount, + float? effort, + int effortCount, + float? risk, + int riskCount, + float? time, + int timeCount) + { + Business = business; + BusinessCount = businessCount; + Effort = effort; + EffortCount = effortCount; + Risk = risk; + RiskCount = riskCount; + Time = time; + TimeCount = timeCount; + } + + public float? Business { get; set; } + public int? BusinessCount { get; set; } + public float? Effort { get; set; } + public int? EffortCount { get; set; } + public float? Risk { get; set; } + public int? RiskCount { get; set; } + public float? Time { get; set; } + public int? TimeCount { get; set; } + +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/json/WorkItems/Record.cs b/Adaptation/FileHandlers/json/WorkItems/Record.cs index 21196ef..1a5ad2c 100644 --- a/Adaptation/FileHandlers/json/WorkItems/Record.cs +++ b/Adaptation/FileHandlers/json/WorkItems/Record.cs @@ -7,15 +7,17 @@ public class Record #nullable enable - public Record(WorkItem workItem, WorkItem? parent, ReadOnlyCollection children) + public Record(WorkItem workItem, WorkItem? parent, ReadOnlyCollection children, PollValues? pollValues) { WorkItem = workItem; Parent = parent; Children = children; + PollValues = pollValues; } public WorkItem WorkItem { get; set; } public WorkItem? Parent { get; set; } public ReadOnlyCollection Children { get; set; } + public PollValues? PollValues { get; set; } } \ No newline at end of file diff --git a/MESAFIBACKLOG.csproj b/MESAFIBACKLOG.csproj index f3eb66a..424ef67 100644 --- a/MESAFIBACKLOG.csproj +++ b/MESAFIBACKLOG.csproj @@ -129,6 +129,7 @@ + @@ -137,6 +138,7 @@ +