fix: invoke journal service compatibly across 26.1 patches
This commit is contained in:
@@ -13,7 +13,7 @@
|
|||||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||||
<M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId>
|
<M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId>
|
||||||
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
|
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
|
||||||
<M42PackageVersion>1.4.0.23</M42PackageVersion>
|
<M42PackageVersion>1.4.0.24</M42PackageVersion>
|
||||||
<M42BuildPackage>true</M42BuildPackage>
|
<M42BuildPackage>true</M42BuildPackage>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1408,15 +1408,15 @@ namespace C4IT.F4SD
|
|||||||
{
|
{
|
||||||
await Task.Delay(0);
|
await Task.Delay(0);
|
||||||
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
|
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
|
||||||
var entries = F4SDM42WebApiController.defaultInstance.GetJournalService().GetJournalList(activityEOID, false, 0, 50, "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>", 120);
|
var entries = LoadJournalEntries(activityEOID);
|
||||||
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
|
LogEntry($"{entries.Count} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
|
||||||
for (int i = 0; i < entries.Length; i++)
|
for (int i = 0; i < entries.Count; i++)
|
||||||
{
|
{
|
||||||
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
|
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
|
||||||
var text = item.Text ?? string.Empty;
|
var text = item.Text ?? string.Empty;
|
||||||
var createdDate = item.CreatedDate ?? DateTime.MinValue;
|
var createdDate = item.CreatedDate ?? DateTime.MinValue;
|
||||||
|
|
||||||
LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
|
LogEntry($"Journal entry {i + 1}/{entries.Count}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
|
||||||
journalEntries.Add(new cTicketJournalItem()
|
journalEntries.Add(new cTicketJournalItem()
|
||||||
{
|
{
|
||||||
JournalId = item.Id,
|
JournalId = item.Id,
|
||||||
@@ -1446,6 +1446,125 @@ namespace C4IT.F4SD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> LoadJournalEntries(Guid activityEOID)
|
||||||
|
{
|
||||||
|
var journalService = F4SDM42WebApiController.defaultInstance.GetJournalService();
|
||||||
|
var serviceType = journalService.GetType();
|
||||||
|
var objectLinkTemplate = "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>";
|
||||||
|
var methods = serviceType
|
||||||
|
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||||
|
.Where(IsJournalReaderMethod)
|
||||||
|
.OrderByDescending(method => method.GetParameters().Length)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var method in methods)
|
||||||
|
{
|
||||||
|
if (!TryBuildJournalListArguments(method, activityEOID, objectLinkTemplate, out var arguments))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = method.Invoke(journalService, arguments);
|
||||||
|
if (result is Matrix42.Contracts.Platform.Data.JournalEntryInfo[] arrayResult)
|
||||||
|
return arrayResult;
|
||||||
|
|
||||||
|
if (result is IEnumerable<Matrix42.Contracts.Platform.Data.JournalEntryInfo> enumerableResult)
|
||||||
|
return enumerableResult.ToList();
|
||||||
|
|
||||||
|
throw new MissingMethodException($"IJournalService.GetJournalList returned unsupported type '{result?.GetType().FullName ?? "<null>"}'.");
|
||||||
|
}
|
||||||
|
catch (TargetInvocationException ex) when (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
throw ex.InnerException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MissingMethodException($"No compatible IJournalService.GetJournalList overload was found on '{serviceType.FullName}'. Available overloads: {string.Join("; ", methods.Select(FormatMethodSignature))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsJournalReaderMethod(MethodInfo method)
|
||||||
|
{
|
||||||
|
var methodName = method.Name;
|
||||||
|
if (methodName.Contains("."))
|
||||||
|
methodName = methodName.Substring(methodName.LastIndexOf(".", StringComparison.Ordinal) + 1);
|
||||||
|
|
||||||
|
if (!(methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase) || methodName.StartsWith("Load", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!methodName.Contains("Journal", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!method.GetParameters().Any(parameter => parameter.ParameterType == typeof(Guid)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var returnType = method.ReturnType;
|
||||||
|
if (returnType.IsArray)
|
||||||
|
return returnType.GetElementType()?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName;
|
||||||
|
|
||||||
|
if (returnType.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return returnType.GetInterfaces()
|
||||||
|
.Where(type => type.IsGenericType)
|
||||||
|
.Select(type => type.GetGenericArguments().FirstOrDefault())
|
||||||
|
.Any(type => type?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryBuildJournalListArguments(MethodInfo method, Guid activityEOID, string objectLinkTemplate, out object[] arguments)
|
||||||
|
{
|
||||||
|
var parameters = method.GetParameters();
|
||||||
|
arguments = new object[parameters.Length];
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
|
{
|
||||||
|
var parameter = parameters[i];
|
||||||
|
var parameterType = parameter.ParameterType;
|
||||||
|
var parameterName = parameter.Name ?? string.Empty;
|
||||||
|
var lowerName = parameterName.ToLowerInvariant();
|
||||||
|
|
||||||
|
if (parameterType == typeof(Guid))
|
||||||
|
{
|
||||||
|
arguments[i] = activityEOID;
|
||||||
|
}
|
||||||
|
else if (parameterType == typeof(bool))
|
||||||
|
{
|
||||||
|
arguments[i] = false;
|
||||||
|
}
|
||||||
|
else if (parameterType == typeof(int))
|
||||||
|
{
|
||||||
|
if (lowerName.Contains("time"))
|
||||||
|
arguments[i] = 120;
|
||||||
|
else if (lowerName.Contains("count") || lowerName.Contains("take") || lowerName.Contains("limit") || lowerName.Contains("size"))
|
||||||
|
arguments[i] = 50;
|
||||||
|
else
|
||||||
|
arguments[i] = 0;
|
||||||
|
}
|
||||||
|
else if (parameterType == typeof(string))
|
||||||
|
{
|
||||||
|
arguments[i] = lowerName.Contains("template") || lowerName.Contains("link") ? objectLinkTemplate : null;
|
||||||
|
}
|
||||||
|
else if (parameterType == typeof(string[]))
|
||||||
|
{
|
||||||
|
arguments[i] = null;
|
||||||
|
}
|
||||||
|
else if (parameter.HasDefaultValue)
|
||||||
|
{
|
||||||
|
arguments[i] = parameter.DefaultValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatMethodSignature(MethodInfo method)
|
||||||
|
{
|
||||||
|
return $"{method.ReturnType.FullName} {method.Name}({string.Join(", ", method.GetParameters().Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}"))})";
|
||||||
|
}
|
||||||
|
|
||||||
internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml)
|
internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user