Mike Phares 9c5e6fddf2 Tag property on Record
Fetch javascript function for testing

Absolute Delta
2025-04-17 16:19:14 -07:00

200 lines
8.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Adaptation.FileHandlers.json.WorkItems;
internal class Record
{
#nullable enable
[JsonConstructor]
public Record(WorkItem workItem, WorkItem? parent, Record[]? children, Record[]? related, Record[]? successors, Dictionary<string, string>? tag)
{
WorkItem = workItem;
Parent = parent;
Children = children;
Related = related;
Successors = successors;
Tag = tag;
}
[JsonPropertyName("WorkItem")] public WorkItem WorkItem { get; set; }
[JsonPropertyName("Parent")] public WorkItem? Parent { get; set; }
[JsonPropertyName("Children")] public Record[]? Children { get; set; }
[JsonPropertyName("Related")] public Record[]? Related { get; set; }
[JsonPropertyName("Successors")] public Record[]? Successors { get; set; }
[JsonPropertyName("Tag")] public Dictionary<string, string>? Tag { get; set; }
internal static Record GetWithoutNesting(Record record, string? violation)
{
Record result;
WorkItem workItem = new(activatedDate: record.WorkItem.ActivatedDate,
areaPath: record.WorkItem.AreaPath,
assignedTo: record.WorkItem.AssignedTo,
businessValue: record.WorkItem.BusinessValue,
changedDate: record.WorkItem.ChangedDate,
closedDate: record.WorkItem.ClosedDate,
commentCount: record.WorkItem.CommentCount,
createdDate: record.WorkItem.CreatedDate,
description: record.WorkItem.Description,
effort: record.WorkItem.Effort,
id: record.WorkItem.Id,
iterationPath: record.WorkItem.IterationPath,
parent: record.WorkItem.Parent,
priority: record.WorkItem.Priority,
relations: record.WorkItem.Relations,
remainingWork: record.WorkItem.RemainingWork,
requester: record.WorkItem.Requester,
resolvedDate: record.WorkItem.ResolvedDate,
revision: record.WorkItem.Revision,
riskReductionMinusOpportunityEnablement: record.WorkItem.RiskReductionMinusOpportunityEnablement,
startDate: record.WorkItem.StartDate,
state: record.WorkItem.State,
storyPoints: record.WorkItem.StoryPoints,
tags: record.WorkItem.Tags,
targetDate: record.WorkItem.TargetDate,
timeCriticality: record.WorkItem.TimeCriticality,
title: record.WorkItem.Title,
violation: record.WorkItem.Violation is null ? violation : record.WorkItem.Violation,
weightedShortestJobFirst: record.WorkItem.WeightedShortestJobFirst,
workItemType: record.WorkItem.WorkItemType);
result = new(workItem, record.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>(), record.Tag);
return result;
}
private static Record Get(Record record, bool keepRelations)
{
Record result;
Record[]? childRecords;
Record[]? relatedRecords;
Record[]? successorRecords;
List<Record> relationRecords;
WorkItem? parentWorkItem = keepRelations ? record.Parent : WorkItem.GetWithOutRelations(record.Parent);
WorkItem? workItem = keepRelations ? record.WorkItem : WorkItem.GetWithOutRelations(record.WorkItem) ?? throw new Exception();
if (record.Children is null)
childRecords = null;
else
{
relationRecords = new();
foreach (Record r in record.Children)
relationRecords.Add(Get(r, keepRelations));
childRecords = relationRecords.ToArray();
}
if (record.Related is null)
relatedRecords = null;
else
{
relationRecords = new();
foreach (Record r in record.Related)
relationRecords.Add(Get(r, keepRelations));
relatedRecords = relationRecords.ToArray();
}
if (record.Successors is null)
successorRecords = null;
else
{
relationRecords = new();
foreach (Record r in record.Successors)
relationRecords.Add(Get(r, keepRelations));
successorRecords = relationRecords.ToArray();
}
result = new(workItem, parentWorkItem, childRecords, relatedRecords, successorRecords, record.Tag);
return result;
}
internal static Dictionary<string, string>? GetTag(ReadOnlyCollection<Record>? records)
{
Dictionary<string, string>? result;
if (records is null)
result = null;
else
{
List<long> collection = new();
foreach (Record record in records)
{
if (record.WorkItem.State is "Closed" or "Resolved" || record.WorkItem.StoryPoints is null)
continue;
collection.Add(record.WorkItem.StoryPoints.Value);
}
if (collection.Count == 0)
result = null;
else
{
string json = JsonSerializer.Serialize(collection);
result = new Dictionary<string, string> { { "StoryPoints", json } };
}
}
return result;
}
internal static Record Get(WorkItem workItem, WorkItem? parent, ReadOnlyCollection<Record>? children, ReadOnlyCollection<Record>? related, ReadOnlyCollection<Record>? successors, bool keepRelations)
{
Record result;
Dictionary<string, string>? tag = GetTag(children);
Record record = new(workItem, parent, children?.ToArray(), related?.ToArray(), successors?.ToArray(), tag);
result = Get(record, keepRelations);
return result;
}
internal static ReadOnlyCollection<Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, WorkItem workItem, string relationName, List<bool> nests, bool keepRelations)
{
List<Record> results = new();
Record record;
nests.Add(true);
WorkItem? parentWorkItem;
WorkItem? relationWorkItem;
List<WorkItem> collection = new();
ReadOnlyCollection<Record>? childRecords;
ReadOnlyCollection<Record>? relatedRecords;
ReadOnlyCollection<Record>? successorRecords;
if (workItem.Relations is not null && workItem.Relations.Length > 0)
{
collection.Clear();
foreach (Relation relation in workItem.Relations)
{
if (relation.Attributes.Name != relationName)
continue;
if (workItem.Parent is not null && relation.Id == workItem.Parent.Value)
continue;
if (!keyValuePairs.TryGetValue(relation.Id, out relationWorkItem))
continue;
collection.Add(relationWorkItem);
}
collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList();
foreach (WorkItem w in collection)
{
if (nests.Count > 500)
break;
if (w.Parent is null)
parentWorkItem = null;
else
_ = keyValuePairs.TryGetValue(w.Parent.Value, out parentWorkItem);
childRecords = GetKeyValuePairs(keyValuePairs, w, "Child", nests, keepRelations); // Forward
relatedRecords = null; // GetKeyValuePairs(keyValuePairs, w, "Related", nests, keepRelations); // Related
successorRecords = null; // GetKeyValuePairs(keyValuePairs, w, "Successor", nests, keepRelations); // Forward
// predecessorRecords = GetKeyValuePairs(keyValuePairs, w, "Predecessor", nests, keepRelations); // Reverse
record = Get(w, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
results.Add(record);
}
}
return new(results);
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Record))]
internal partial class RecordSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Record[]))]
internal partial class RecordCollectionSourceGenerationContext : JsonSerializerContext
{
}