fix: restore 26eac54 behavior for 26.1 port

This commit is contained in:
Meik
2026-06-30 14:17:55 +02:00
parent 12ebd1fce9
commit 942473501e
2 changed files with 79 additions and 786 deletions

View File

@@ -1,6 +1,13 @@
using System;
using C4IT.F4SDM;
using C4IT.FASD.Base;
using C4IT.Logging;
using Matrix42.Common;
using Newtonsoft.Json;
using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Dynamic;
using System.Globalization;
using System.IO;
@@ -13,18 +20,9 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Matrix42.Common;
using Matrix42.WebApi.Contracts;
using update4u.SPS.DataLayer;
using update4u.SPS.DataLayer.Transaction;
using Newtonsoft.Json;
using C4IT.F4SDM;
using C4IT.FASD.Base;
using C4IT.Logging;
using static C4IT.FASD.Base.cF4SDTicket;
using static C4IT.Logging.cLogManager;
namespace C4IT.F4SD
@@ -52,11 +50,11 @@ namespace C4IT.F4SD
private const string placeHolderSubject = "PARAM_SUBJECT";
private const string placeHolderDescription = "PARAM_DESCRIPTION";
private static bool? ticketAndServiceRequestEnabledCache;
private const string c4itf4sdmonLinkBase = "f4sdsend://localhost";
private const string F4SDTicketTableName = "M42WPM-TICKETS-INFOS";
private const string F4SDTicketStatusColumnName = "STATUS";
private static bool? ticketAndServiceRequestEnabledCache;
public static IEnumerable<string> ReadLines(Func<Stream> streamProvider,
@@ -73,6 +71,39 @@ namespace C4IT.F4SD
}
}
private static NameValueCollection ParseQueryString(string query)
{
var values = new NameValueCollection();
query = (query ?? string.Empty).TrimStart('?');
if (string.IsNullOrWhiteSpace(query))
return values;
foreach (var pair in query.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
{
var parts = pair.Split(new[] { '=' }, 2);
var key = WebUtility.UrlDecode(parts[0]);
var value = parts.Length > 1 ? WebUtility.UrlDecode(parts[1]) : string.Empty;
if (!string.IsNullOrEmpty(key))
values.Add(key, value);
}
return values;
}
private static string ToQueryString(NameValueCollection queryString)
{
if (queryString == null || queryString.Count == 0)
return string.Empty;
return string.Join("&",
queryString.AllKeys
.Where(key => !string.IsNullOrEmpty(key))
.SelectMany(key => (queryString.GetValues(key) ?? new[] { string.Empty })
.Select(value => $"{WebUtility.UrlEncode(key)}={WebUtility.UrlEncode(value)}")));
}
internal async Task<string> getDirectLinkF4SD(Guid EOID, string type)
{
var CM = MethodBase.GetCurrentMethod();
@@ -81,7 +112,7 @@ namespace C4IT.F4SD
{
LogEntry($"Generating F4SD URI for type: '{type}', GUID: '{EOID}'", LogLevels.Debug);
var builder = new UriBuilder(c4itf4sdmonLinkBase);
var queryString = UrlQueryBuilder.Parse(builder.Query);
var queryString = ParseQueryString(builder.Query);
switch (type.ToLowerInvariant().Split('.').Last())
{
@@ -140,7 +171,7 @@ namespace C4IT.F4SD
break;
}
builder.Query = queryString.ToString();
builder.Query = ToQueryString(queryString);
return string.IsNullOrEmpty(builder.Query) ? null : builder.ToString();
}
catch (Exception E)
@@ -155,7 +186,6 @@ namespace C4IT.F4SD
}
[Obsolete]
internal async Task<List<cF4SDTicketSummary>> getTicketListByUser(string userSid, int hours, int queueoption, List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
@@ -269,116 +299,6 @@ namespace C4IT.F4SD
}
}
internal async Task<List<cF4SDTicketSummary>> getTicketListByUser(Guid userId, int hours, int queueoption, List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
LogEntry($"Generating ticket list for userId: '{userId}', {hours} hours", LogLevels.Debug);
await Task.Delay(0);
var tickets = new List<cF4SDTicketSummary>();
var activityFilter = GetActivityFilter(userId, hours, ticketAndServiceRequestEnabled(), queueoption, queues);
LogEntry($"ASql Filter: {activityFilter}");
var activityTable = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
"[Expression-ObjectID] as EOID, TicketNumber, Subject, Service.ID as ServiceId, Service.Name as ServiceName, SUBQUERY(BasicSchemaObjectType as bso, bso.Name, bso.id = base.T(SPSCommonClassBase).TypeID) as ActivityType" +
", COALESCE(T(SPSActivityClassIncident).Asset.T(SPSComputerClassBase).Name, T(SPSActivityClassIncident).Asset.T(SPSAssetClassSIMCard).PhoneNumber, T(SPSActivityClassIncident).Asset.Name, T(SPSActivityClassIncident).Asset.objectid) as AssetName" +
", SUBQUERY(BasicSchemaObjectType AS t, t.Name, t.ID=base.T(SPSActivityClassIncident).Asset.T(SPSCommonClassBase).TypeID) as AssetCIName",
activityFilter);
if (activityTable?.Rows == null || activityTable.Rows.Count == 0)
{
LogEntry($"No activity entries found for userId: '{userId}'", LogLevels.Warning);
return null;
}
for (int i = 0; i < activityTable.Rows.Count; i++)
{
DataRow entry = activityTable.Rows[i];
var activityEOId = getGuidFromObject(entry["EOID"]);
var ticketNumber = getStringFromObject(entry["TicketNumber"]);
var activityType = getStringFromObject(entry["ActivityType"]);
var assetName = getStringFromObject(entry["AssetName"]);
var ServiceName = getStringFromObject(entry["ServiceName"]);
var assetCIName = getStringFromObject(entry["AssetCIName"]);
var subject = getStringFromObject(entry["Subject"]);
var stateData = GetActivityState(activityEOId);
var state = stateData.Item1;
var stateDisp = stateData.Item2;
LogEntry($"Activity found {i + 1}/{activityTable.Rows.Count}: ObjectID={activityEOId}, TicketNumber={ticketNumber}, Subject={subject}, State={state}", LogLevels.Debug);
if (string.IsNullOrEmpty(ticketNumber))
{
LogEntry($"No TicketNumber found for activity entry", LogLevels.Warning);
continue;
}
if (string.IsNullOrEmpty(assetName))
{
LogEntry($"No AssetName found for activity entry", LogLevels.Debug);
}
if (string.IsNullOrEmpty(assetCIName))
{
LogEntry($"No AssetCIName found for activity entry", LogLevels.Debug);
}
var ServiceId = getGuidFromObject(entry["ServiceId"]);
if (ServiceId == Guid.Empty)
{
LogEntry($"no ServiceId found for activity entry", LogLevels.Debug);
}
var AssetCIName = getStringFromObject(entry["AssetCIName"]);
if (AssetCIName == string.Empty)
{
LogEntry($"no AssetCIName found for activity entry", LogLevels.Debug);
}
var Subject = getStringFromObject(entry["Subject"]);
if (Subject == string.Empty)
{
LogEntry($"no Subject found for activity entry", LogLevels.Warning);
continue;
}
if (string.IsNullOrEmpty(subject))
{
LogEntry($"No Subject found for activity entry", LogLevels.Warning);
continue;
}
tickets.Add(new cF4SDTicketSummary()
{
TicketObjectId = activityEOId,
Name = ticketNumber,
ActivityType = activityType,
AssetCIName = assetCIName,
AssetName = assetName,
ServiceId = ServiceId,
ServiceName = ServiceName,
StatusId = state,
Status = stateDisp,
Summary = subject,
IsPrimaryAccount = true
});
}
tickets = tickets.OrderByDescending(x => x.Name).ToList();
return tickets;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
private static readonly string[] TicketOverviewKeys = new[]
{
"TicketsNew",
@@ -393,62 +313,6 @@ namespace C4IT.F4SD
"UnassignedTicketsCritical"
};
public class cF4SDTicket : cF4SDTicketSummary
{
public enum enumTicketCreationSource
{
Unknown = 0,
Mail = 1,
Phone = 2,
F4SD = 3
}
public class cTicketJournalItem
{
public DateTime CreationDate { get; set; }
public string Header { get; set; }
public string CreatedBy { get; set; }
public string DescriptionHtml { get; set; }
public string Description { get; set; }
public bool IsVisibleForUser { get; set; }
public Guid ActivityObjectId { get; set; }
public Guid JournalId { get; set; }
}
public Guid AffectedUserId { get; set; }
public Guid AssetId { get; set; }
public DateTime CreationDate { get; set; }
public DateTime? ClosingDate { get; set; }
public int CreationSourceId { get; set; }
public string CreationSource { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public int PriorityId { get; set; }
public string Priority { get; set; }
public Guid CategoryId { get; set; }
public string Category { get; set; }
public string CategoryHierarchical { get; set; }
public string CIName { get; set; }
public string DirectLinkEdit { get; set; }
public Guid AssetCIId { get; set; }
public int AssetSKUAssetGroupId { get; set; }
public string AssetSKUAssetGroup { get; set; }
public int AssetSKUTypeId { get; set; }
public string AssetSKUType { get; set; }
public string DirectLinkPreview { get; set; }
public string DirectLinkClose { get; set; }
public string AffectedUser { get; set; }
public string SolutionHtml { get; set; }
public string Solution { get; set; }
public string AssetDomain { get; set; }
public string Urgency { get; set; }
public int UrgencyId { get; set; }
public string Impact { get; set; }
public int ImpactId { get; set; }
}
public class TicketOverviewCountsResult
{
[JsonProperty("counts")]
@@ -497,7 +361,6 @@ namespace C4IT.F4SD
public string ActivityType { get; set; }
}
[Obsolete]
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(
string sid,
string scope,
@@ -555,64 +418,6 @@ namespace C4IT.F4SD
}
}
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(
Guid userId,
string scope,
IEnumerable<string> keys,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
var normalizedKeys = (keys ?? Array.Empty<string>())
.Where(k => !string.IsNullOrWhiteSpace(k))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (normalizedKeys.Count == 0)
{
normalizedKeys.AddRange(TicketOverviewKeys);
}
var entries = await LoadTicketOverviewEntries(userId, useRoleScope, queueoption, queues);
List<TicketOverviewEntry> unassignedEntries = null;
if (!useRoleScope && normalizedKeys.Any(IsUnassignedOverviewKey))
{
unassignedEntries = await LoadTicketOverviewUnassignedEntriesForPersonalScope(userId, queueoption, queues);
}
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
foreach (var key in normalizedKeys)
{
if (!useRoleScope && IsUnassignedOverviewKey(key))
{
counts[key] = (unassignedEntries ?? new List<TicketOverviewEntry>())
.Count(entry => MatchesTicketOverviewKey(entry, key));
}
else
{
counts[key] = entries.Count(entry => MatchesTicketOverviewKey(entry, key));
}
}
return new TicketOverviewCountsResult { Counts = counts };
}
catch (Exception E)
{
LogException(E);
return new TicketOverviewCountsResult();
}
finally
{
LogMethodEnd(CM);
}
}
[Obsolete]
internal async Task<TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles(
string sid,
IEnumerable<Guid> roleGuids,
@@ -676,70 +481,6 @@ namespace C4IT.F4SD
}
}
internal async Task<TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles(
Guid userId,
IEnumerable<Guid> roleGuids,
IEnumerable<string> keys,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var normalizedKeys = (keys ?? Array.Empty<string>())
.Where(k => !string.IsNullOrWhiteSpace(k))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (normalizedKeys.Count == 0)
{
normalizedKeys.AddRange(TicketOverviewKeys);
}
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, roleGuids);
if (roleIds.Count == 0)
return new TicketOverviewCountsByRoleResult();
var entries = await LoadTicketOverviewEntriesByRoleIds(roleIds, queueoption, queues);
var entriesByRole = entries
.GroupBy(entry => entry.RecipientRoleId)
.ToDictionary(group => group.Key, group => group.ToList());
var countsByRole = new Dictionary<string, Dictionary<string, int>>(StringComparer.OrdinalIgnoreCase);
foreach (var roleId in roleIds)
{
var roleEntries = entriesByRole.TryGetValue(roleId, out var list)
? list
: new List<TicketOverviewEntry>();
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
foreach (var key in normalizedKeys)
{
counts[key] = roleEntries.Count(entry => MatchesTicketOverviewKey(entry, key));
}
countsByRole[roleId.ToString()] = counts;
}
return new TicketOverviewCountsByRoleResult
{
GeneratedAtUtc = DateTime.UtcNow,
CountsByRole = countsByRole
};
}
catch (Exception E)
{
LogException(E);
return new TicketOverviewCountsByRoleResult();
}
finally
{
LogMethodEnd(CM);
}
}
[Obsolete]
internal async Task<List<TicketOverviewRelationDto>> getTicketOverviewRelations(
string sid,
string scope,
@@ -819,86 +560,6 @@ namespace C4IT.F4SD
}
}
internal async Task<List<TicketOverviewRelationDto>> getTicketOverviewRelations(
Guid userId,
string scope,
string key,
int count,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (string.IsNullOrWhiteSpace(key))
return new List<TicketOverviewRelationDto>();
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
List<TicketOverviewEntry> entries;
if (!useRoleScope && IsUnassignedOverviewKey(key))
{
entries = await LoadTicketOverviewUnassignedEntriesForPersonalScope(userId, queueoption, queues);
}
else
{
entries = await LoadTicketOverviewEntries(userId, useRoleScope, queueoption, queues);
}
var filtered = entries
.Where(entry => MatchesTicketOverviewKey(entry, key))
.OrderByDescending(entry => entry.CreatedDate)
.ToList();
if (count > 0)
filtered = filtered.Take(count).ToList();
var relations = new List<TicketOverviewRelationDto>(filtered.Count);
foreach (var entry in filtered)
{
var relation = new TicketOverviewRelationDto
{
Type = enumF4sdSearchResultClass.Ticket,
DisplayName = entry.TicketNumber ?? string.Empty,
Name = entry.TicketNumber ?? string.Empty,
id = entry.TicketId,
Status = enumF4sdSearchResultStatus.Active,
Infos = new Dictionary<string, string>
{
["Summary"] = entry.Summary ?? string.Empty,
["StatusId"] = ConvertM42State(entry.State),
["ActivityType"] = entry.ActivityType ?? string.Empty,
["UserDisplayName"] = entry.InitiatorDisplayName ?? string.Empty,
["UserAccount"] = entry.InitiatorAccount ?? string.Empty,
["UserDomain"] = entry.InitiatorDomain ?? string.Empty,
["UserSid"] = entry.InitiatorSid ?? string.Empty,
["Sids"] = entry.InitiatorSid ?? string.Empty,
["UserId"] = entry.InitiatorId != Guid.Empty ? entry.InitiatorId.ToString() : string.Empty,
["UserGuid"] = entry.InitiatorId != Guid.Empty ? entry.InitiatorId.ToString() : string.Empty
},
Identities = new List<cF4sdIdentityEntry>
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = entry.TicketId },
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = entry.InitiatorId }
}
};
relations.Add(relation);
}
return relations;
}
catch (Exception E)
{
LogException(E);
return new List<TicketOverviewRelationDto>();
}
finally
{
LogMethodEnd(CM);
}
}
[Obsolete]
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntries(
string sid,
bool useRoleScope,
@@ -928,34 +589,6 @@ namespace C4IT.F4SD
}
}
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntries(
Guid userId,
bool useRoleScope,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (userId == Guid.Empty)
return new List<TicketOverviewEntry>();
var filter = await BuildTicketOverviewFilterAsync(userId, useRoleScope, queueoption, queues);
return await LoadTicketOverviewEntriesByFilter(filter);
}
catch (Exception E)
{
LogException(E);
return new List<TicketOverviewEntry>();
}
finally
{
LogMethodEnd(CM);
}
}
[Obsolete]
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewUnassignedEntriesForPersonalScope(
string sid,
int queueoption,
@@ -989,39 +622,6 @@ namespace C4IT.F4SD
}
}
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewUnassignedEntriesForPersonalScope(
Guid userId,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
if (userId == Guid.Empty)
return new List<TicketOverviewEntry>();
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues);
if (string.IsNullOrWhiteSpace(filter))
return new List<TicketOverviewEntry>();
filter += " AND Recipient IS NULL";
return await LoadTicketOverviewEntriesByFilter(filter);
}
catch (Exception E)
{
LogException(E);
return new List<TicketOverviewEntry>();
}
finally
{
LogMethodEnd(CM);
}
}
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntriesByRoleIds(
IEnumerable<Guid> roleIds,
int queueoption,
@@ -1172,7 +772,6 @@ namespace C4IT.F4SD
return null;
}
[Obsolete]
private async Task<string> BuildTicketOverviewFilterAsync(
string sid,
bool useRoleScope,
@@ -1192,25 +791,6 @@ namespace C4IT.F4SD
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
}
private async Task<string> BuildTicketOverviewFilterAsync(
Guid userId,
bool useRoleScope,
int queueoption,
List<cApiM42TicketQueueInfo> queues)
{
var filter = BuildTicketOverviewBaseFilter(queueoption, queues);
if (!useRoleScope)
{
var recipientFilter = $"Recipient = '{Escape(userId.ToString("D"))}'";
filter += $" AND ({recipientFilter})";
return filter;
}
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
}
private string BuildTicketOverviewBaseFilter(int queueoption, List<cApiM42TicketQueueInfo> queues)
{
var filter = "T(SPSCommonClassBase).State <> 204";
@@ -1309,7 +889,6 @@ namespace C4IT.F4SD
return filter;
}
[Obsolete]
private async Task<List<Guid>> ResolveTicketOverviewRoleIdsAsync(string sid, IEnumerable<Guid> roleGuids)
{
var roleIds = (roleGuids ?? Enumerable.Empty<Guid>())
@@ -1335,26 +914,6 @@ namespace C4IT.F4SD
.ToList();
}
private async Task<List<Guid>> ResolveTicketOverviewRoleIdsAsync(Guid userId, IEnumerable<Guid> roleGuids)
{
var roleIds = (roleGuids ?? Enumerable.Empty<Guid>())
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
if (roleIds.Count > 0)
return roleIds;
if (userId == Guid.Empty)
return new List<Guid>();
var roles = await getRoleMembershipById(userId) ?? new List<M42Role>();
return roles
.Where(role => role != null && role.Id != Guid.Empty)
.Select(role => role.Id)
.Distinct()
.ToList();
}
private static bool IsUnassignedOverviewKey(string key)
{
if (string.IsNullOrWhiteSpace(key))
@@ -1462,8 +1021,6 @@ namespace C4IT.F4SD
{
return input?.Replace("'", "''");
}
[Obsolete]
private string GetActivityFilter(
string userSid,
int hours,
@@ -1551,92 +1108,6 @@ namespace C4IT.F4SD
return filter;
}
private string GetActivityFilter(
Guid userId,
int hours,
bool ticketAndServiceRequestEnabled,
int queueoption,
List<cApiM42TicketQueueInfo> queues
)
{
// Baseline-Filter auf User und Datum
var filter = $"Initiator = '{Escape(userId.ToString("D"))}'";
string fStartDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow.AddHours(-hours), true);
string fEndDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow, true);
// Incident vs. Ticket/ServiceRequest
if (ticketAndServiceRequestEnabled)
{
filter +=
" AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL" +
" OR UsedInTypeSPSActivityTypeTicket IS NOT NULL" +
" OR UsedInTypeSPSActivityTypeServiceRequest IS NOT NULL)";
}
else
{
filter += " AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL)";
}
// Offene bzw. kürzlich geschlossene Objekte
filter +=
" AND (T(SPSCommonClassBase).State <> 204" +
$" OR (ClosedDate > {fStartDate} AND ClosedDate < {fEndDate}))";
// Queue-Filter nur, wenn tatsächlich Queues übergeben wurden
if (queues != null && queues.Count > 0)
{
// URL-escaping für Name und ID
var escapedNames = queues
.Select(q => $"'{Escape(q.QueueName)}'")
.ToList();
var escapedIds = queues
.Select(q => $"'{Escape(q.QueueID.ToString())}'")
.ToList();
string nameList = string.Join(", ", escapedNames);
string idList = string.Join(", ", escapedIds);
switch (queueoption)
{
// 1 = entweder keine Queue oder eine der übergebenen Queues (Name oder ID)
case 1:
filter +=
$" AND (" +
"Queue IS NULL" +
$" OR Queue.Name IN ({nameList})" +
$" OR Queue.ID IN ({idList})" +
")";
break;
// 2 = nur die übergebenen Queues (Name oder ID)
case 2:
filter +=
$" AND (" +
"Queue IS NOT NULL" +
$" AND (Queue.Name IN ({nameList})" +
$" OR Queue.ID IN ({idList}))" +
")";
break;
// 3 = nur Objekte ohne Queue
case 3:
filter += " AND Queue IS NULL";
break;
// 0 oder andere = keine zusätzliche Einschränkung
default:
break;
}
}
else if (queueoption == 3)
{
// Ausnahme: wenn keine Queues übergeben, aber Option 3 = nur ohne Queue
filter += " AND Queue IS NULL";
}
return filter;
}
internal async Task<DirectLink> getDirectLinkCreateTicket(string sid, string assetname)
{
@@ -1929,21 +1400,21 @@ namespace C4IT.F4SD
}
}
internal async Task<List<cF4SDTicket.cTicketJournalItem>> GetJournalEntries(Guid activityEOID)
internal async Task<List<cTicketJournalItem>> GetJournalEntries(Guid activityEOID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
List<cF4SDTicket.cTicketJournalItem> journalEntries = new List<cF4SDTicket.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);
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
for (int i = 0; i < entries.Length; i++)
{
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={item.CreatedDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
journalEntries.Add(new cF4SDTicket.cTicketJournalItem()
journalEntries.Add(new cTicketJournalItem()
{
JournalId = item.Id,
ActivityObjectId = activityEOID,
@@ -2311,7 +1782,7 @@ namespace C4IT.F4SD
}
zipArchive.Dispose();
memoryStream.Position = 0L;
HttpResponseMessage httpResponseMessage = HttpResponseExtensions.CreateResponse(request, HttpStatusCode.OK);
HttpResponseMessage httpResponseMessage = request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(memoryStream);
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
@@ -2500,7 +1971,7 @@ namespace C4IT.F4SD
try
{
await Task.Delay(0);
var asqlFilter = string.Format("Members.Id = '{0}'", UserId.ToString("D"));
var asqlFilter = string.Format("Members.Id = '{0}'", UserId.ToString());
LogEntry($"ASql Filter: {asqlFilter}");
FragmentRequestBase fragmentRequestBase = new FragmentRequestBase(SPSSecurityClassRole, ColumnSelectOption.List, "Id as Id" +
@@ -2721,41 +2192,4 @@ namespace C4IT.F4SD
Roles = new List<M42Role>();
}
}
internal sealed class UrlQueryBuilder
{
private readonly List<KeyValuePair<string, string>> _values = new List<KeyValuePair<string, string>>();
private UrlQueryBuilder()
{
}
public static UrlQueryBuilder Parse(string query)
{
var builder = new UrlQueryBuilder();
var normalizedQuery = (query ?? string.Empty).TrimStart('?');
foreach (var pair in normalizedQuery.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
{
var separatorIndex = pair.IndexOf('=');
var key = separatorIndex >= 0 ? pair.Substring(0, separatorIndex) : pair;
var value = separatorIndex >= 0 ? pair.Substring(separatorIndex + 1) : string.Empty;
builder.Add(WebUtility.UrlDecode(key), WebUtility.UrlDecode(value));
}
return builder;
}
public void Add(string key, string value)
{
if (!string.IsNullOrEmpty(key))
_values.Add(new KeyValuePair<string, string>(key, value ?? string.Empty));
}
public override string ToString()
{
return string.Join("&", _values.Select(pair => $"{WebUtility.UrlEncode(pair.Key)}={WebUtility.UrlEncode(pair.Value)}"));
}
}
}