fix: restore 26eac54 behavior for 26.1 port
This commit is contained in:
@@ -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.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -13,18 +20,9 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Matrix42.Common;
|
|
||||||
using Matrix42.WebApi.Contracts;
|
|
||||||
using update4u.SPS.DataLayer;
|
using update4u.SPS.DataLayer;
|
||||||
using update4u.SPS.DataLayer.Transaction;
|
using update4u.SPS.DataLayer.Transaction;
|
||||||
|
using static C4IT.FASD.Base.cF4SDTicket;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
using C4IT.F4SDM;
|
|
||||||
using C4IT.FASD.Base;
|
|
||||||
using C4IT.Logging;
|
|
||||||
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
namespace C4IT.F4SD
|
namespace C4IT.F4SD
|
||||||
@@ -52,11 +50,11 @@ namespace C4IT.F4SD
|
|||||||
|
|
||||||
private const string placeHolderSubject = "PARAM_SUBJECT";
|
private const string placeHolderSubject = "PARAM_SUBJECT";
|
||||||
private const string placeHolderDescription = "PARAM_DESCRIPTION";
|
private const string placeHolderDescription = "PARAM_DESCRIPTION";
|
||||||
private static bool? ticketAndServiceRequestEnabledCache;
|
|
||||||
private const string c4itf4sdmonLinkBase = "f4sdsend://localhost";
|
private const string c4itf4sdmonLinkBase = "f4sdsend://localhost";
|
||||||
|
|
||||||
private const string F4SDTicketTableName = "M42WPM-TICKETS-INFOS";
|
private const string F4SDTicketTableName = "M42WPM-TICKETS-INFOS";
|
||||||
private const string F4SDTicketStatusColumnName = "STATUS";
|
private const string F4SDTicketStatusColumnName = "STATUS";
|
||||||
|
private static bool? ticketAndServiceRequestEnabledCache;
|
||||||
|
|
||||||
|
|
||||||
public static IEnumerable<string> ReadLines(Func<Stream> streamProvider,
|
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)
|
internal async Task<string> getDirectLinkF4SD(Guid EOID, string type)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -81,7 +112,7 @@ namespace C4IT.F4SD
|
|||||||
{
|
{
|
||||||
LogEntry($"Generating F4SD URI for type: '{type}', GUID: '{EOID}'", LogLevels.Debug);
|
LogEntry($"Generating F4SD URI for type: '{type}', GUID: '{EOID}'", LogLevels.Debug);
|
||||||
var builder = new UriBuilder(c4itf4sdmonLinkBase);
|
var builder = new UriBuilder(c4itf4sdmonLinkBase);
|
||||||
var queryString = UrlQueryBuilder.Parse(builder.Query);
|
var queryString = ParseQueryString(builder.Query);
|
||||||
|
|
||||||
switch (type.ToLowerInvariant().Split('.').Last())
|
switch (type.ToLowerInvariant().Split('.').Last())
|
||||||
{
|
{
|
||||||
@@ -140,7 +171,7 @@ namespace C4IT.F4SD
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Query = queryString.ToString();
|
builder.Query = ToQueryString(queryString);
|
||||||
return string.IsNullOrEmpty(builder.Query) ? null : builder.ToString();
|
return string.IsNullOrEmpty(builder.Query) ? null : builder.ToString();
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
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)
|
internal async Task<List<cF4SDTicketSummary>> getTicketListByUser(string userSid, int hours, int queueoption, List<cApiM42TicketQueueInfo> queues)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
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[]
|
private static readonly string[] TicketOverviewKeys = new[]
|
||||||
{
|
{
|
||||||
"TicketsNew",
|
"TicketsNew",
|
||||||
@@ -393,62 +313,6 @@ namespace C4IT.F4SD
|
|||||||
"UnassignedTicketsCritical"
|
"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
|
public class TicketOverviewCountsResult
|
||||||
{
|
{
|
||||||
[JsonProperty("counts")]
|
[JsonProperty("counts")]
|
||||||
@@ -497,7 +361,6 @@ namespace C4IT.F4SD
|
|||||||
public string ActivityType { get; set; }
|
public string ActivityType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(
|
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(
|
||||||
string sid,
|
string sid,
|
||||||
string scope,
|
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(
|
internal async Task<TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles(
|
||||||
string sid,
|
string sid,
|
||||||
IEnumerable<Guid> roleGuids,
|
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(
|
internal async Task<List<TicketOverviewRelationDto>> getTicketOverviewRelations(
|
||||||
string sid,
|
string sid,
|
||||||
string scope,
|
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(
|
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntries(
|
||||||
string sid,
|
string sid,
|
||||||
bool useRoleScope,
|
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(
|
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewUnassignedEntriesForPersonalScope(
|
||||||
string sid,
|
string sid,
|
||||||
int queueoption,
|
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(
|
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntriesByRoleIds(
|
||||||
IEnumerable<Guid> roleIds,
|
IEnumerable<Guid> roleIds,
|
||||||
int queueoption,
|
int queueoption,
|
||||||
@@ -1172,7 +772,6 @@ namespace C4IT.F4SD
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
private async Task<string> BuildTicketOverviewFilterAsync(
|
private async Task<string> BuildTicketOverviewFilterAsync(
|
||||||
string sid,
|
string sid,
|
||||||
bool useRoleScope,
|
bool useRoleScope,
|
||||||
@@ -1192,25 +791,6 @@ namespace C4IT.F4SD
|
|||||||
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
|
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)
|
private string BuildTicketOverviewBaseFilter(int queueoption, List<cApiM42TicketQueueInfo> queues)
|
||||||
{
|
{
|
||||||
var filter = "T(SPSCommonClassBase).State <> 204";
|
var filter = "T(SPSCommonClassBase).State <> 204";
|
||||||
@@ -1309,7 +889,6 @@ namespace C4IT.F4SD
|
|||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
private async Task<List<Guid>> ResolveTicketOverviewRoleIdsAsync(string sid, IEnumerable<Guid> roleGuids)
|
private async Task<List<Guid>> ResolveTicketOverviewRoleIdsAsync(string sid, IEnumerable<Guid> roleGuids)
|
||||||
{
|
{
|
||||||
var roleIds = (roleGuids ?? Enumerable.Empty<Guid>())
|
var roleIds = (roleGuids ?? Enumerable.Empty<Guid>())
|
||||||
@@ -1335,26 +914,6 @@ namespace C4IT.F4SD
|
|||||||
.ToList();
|
.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)
|
private static bool IsUnassignedOverviewKey(string key)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
if (string.IsNullOrWhiteSpace(key))
|
||||||
@@ -1462,8 +1021,6 @@ namespace C4IT.F4SD
|
|||||||
{
|
{
|
||||||
return input?.Replace("'", "''");
|
return input?.Replace("'", "''");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
private string GetActivityFilter(
|
private string GetActivityFilter(
|
||||||
string userSid,
|
string userSid,
|
||||||
int hours,
|
int hours,
|
||||||
@@ -1551,92 +1108,6 @@ namespace C4IT.F4SD
|
|||||||
return filter;
|
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)
|
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();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Delay(0);
|
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);
|
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);
|
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
|
||||||
for (int i = 0; i < entries.Length; i++)
|
for (int i = 0; i < entries.Length; i++)
|
||||||
{
|
{
|
||||||
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[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);
|
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,
|
JournalId = item.Id,
|
||||||
ActivityObjectId = activityEOID,
|
ActivityObjectId = activityEOID,
|
||||||
@@ -2311,7 +1782,7 @@ namespace C4IT.F4SD
|
|||||||
}
|
}
|
||||||
zipArchive.Dispose();
|
zipArchive.Dispose();
|
||||||
memoryStream.Position = 0L;
|
memoryStream.Position = 0L;
|
||||||
HttpResponseMessage httpResponseMessage = HttpResponseExtensions.CreateResponse(request, HttpStatusCode.OK);
|
HttpResponseMessage httpResponseMessage = request.CreateResponse(HttpStatusCode.OK);
|
||||||
httpResponseMessage.Content = new StreamContent(memoryStream);
|
httpResponseMessage.Content = new StreamContent(memoryStream);
|
||||||
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
|
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
|
||||||
{
|
{
|
||||||
@@ -2500,7 +1971,7 @@ namespace C4IT.F4SD
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Delay(0);
|
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}");
|
LogEntry($"ASql Filter: {asqlFilter}");
|
||||||
|
|
||||||
FragmentRequestBase fragmentRequestBase = new FragmentRequestBase(SPSSecurityClassRole, ColumnSelectOption.List, "Id as Id" +
|
FragmentRequestBase fragmentRequestBase = new FragmentRequestBase(SPSSecurityClassRole, ColumnSelectOption.List, "Id as Id" +
|
||||||
@@ -2721,41 +2192,4 @@ namespace C4IT.F4SD
|
|||||||
Roles = new List<M42Role>();
|
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)}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -23,6 +23,7 @@ using C4IT.F4SDM;
|
|||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
using C4IT.Logging;
|
using C4IT.Logging;
|
||||||
|
|
||||||
|
using static C4IT.FASD.Base.cF4SDTicket;
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
namespace C4IT.F4SD
|
namespace C4IT.F4SD
|
||||||
@@ -31,7 +32,6 @@ namespace C4IT.F4SD
|
|||||||
public partial class F4SDM42WebApiController : ApiController
|
public partial class F4SDM42WebApiController : ApiController
|
||||||
{
|
{
|
||||||
public static bool IsInitialized { get; private set; } = false;
|
public static bool IsInitialized { get; private set; } = false;
|
||||||
|
|
||||||
public static F4SDM42WebApiController defaultInstance;
|
public static F4SDM42WebApiController defaultInstance;
|
||||||
//private readonly IIncidentService _incidentService;
|
//private readonly IIncidentService _incidentService;
|
||||||
internal readonly GlobalConfigurationProvider _globalConfigurationProvider;
|
internal readonly GlobalConfigurationProvider _globalConfigurationProvider;
|
||||||
@@ -48,6 +48,10 @@ namespace C4IT.F4SD
|
|||||||
{
|
{
|
||||||
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
|
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
|
||||||
defaultInstance = this;
|
defaultInstance = this;
|
||||||
|
//_objectService = objectService;
|
||||||
|
//_fragmentService = fragmentService;
|
||||||
|
//_incidentService = Guard.NullArgument(incidentService, "incidentService");
|
||||||
|
|
||||||
_globalConfigurationProvider = GlobalConfigurationProvider.Instance;
|
_globalConfigurationProvider = GlobalConfigurationProvider.Instance;
|
||||||
_f4stHelperService = new F4SDHelperService();
|
_f4stHelperService = new F4SDHelperService();
|
||||||
EnsureInitialized();
|
EnsureInitialized();
|
||||||
@@ -58,6 +62,7 @@ namespace C4IT.F4SD
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//System.Diagnostics.Debugger.Launch();
|
||||||
lock (initLock)
|
lock (initLock)
|
||||||
{
|
{
|
||||||
if (IsInitialized || F4SDM42LogsWebApiController.IsInitialized)
|
if (IsInitialized || F4SDM42LogsWebApiController.IsInitialized)
|
||||||
@@ -99,14 +104,12 @@ namespace C4IT.F4SD
|
|||||||
await Task.Delay(0);
|
await Task.Delay(0);
|
||||||
return await _f4stHelperService.getDirectLinkCreateTicket(sid, assetname);
|
return await _f4stHelperService.getDirectLinkCreateTicket(sid, assetname);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getDirectLinkF4SD"), HttpGet]
|
[Route("getDirectLinkF4SD"), HttpGet]
|
||||||
public async Task<string> getDirectLinkF4SD(Guid EOID, string Type)
|
public async Task<string> getDirectLinkF4SD(Guid EOID, string Type)
|
||||||
{
|
{
|
||||||
return await _f4stHelperService.getDirectLinkF4SD(EOID, Type);
|
return await _f4stHelperService.getDirectLinkF4SD(EOID, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
[Route("getTicketList"), HttpGet]
|
[Route("getTicketList"), HttpGet]
|
||||||
public async Task<List<cF4SDTicketSummary>> getTicketList(
|
public async Task<List<cF4SDTicketSummary>> getTicketList(
|
||||||
string sid,
|
string sid,
|
||||||
@@ -126,28 +129,9 @@ namespace C4IT.F4SD
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getTicketListForUser"), HttpGet]
|
|
||||||
public async Task<List<cF4SDTicketSummary>> getTicketListForUser(
|
|
||||||
Guid userId,
|
|
||||||
int hours,
|
|
||||||
int queueoption = 0,
|
|
||||||
string queues = ""
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var decodedPairs = ParseQueues(queues);
|
|
||||||
|
|
||||||
// Nun weiterreichen an Service
|
|
||||||
return await _f4stHelperService.getTicketListByUser(
|
|
||||||
userId,
|
|
||||||
hours,
|
|
||||||
queueoption,
|
|
||||||
decodedPairs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Route("getTicketDetails"), HttpGet]
|
[Route("getTicketDetails"), HttpGet]
|
||||||
public async Task<F4SDHelperService.cF4SDTicket> getTicketDetails(Guid objectId)
|
public async Task<cF4SDTicket> getTicketDetails(Guid objectId)
|
||||||
{
|
{
|
||||||
var tickets = await _f4stHelperService.getTicketDetails(new List<Guid>() { objectId });
|
var tickets = await _f4stHelperService.getTicketDetails(new List<Guid>() { objectId });
|
||||||
if (tickets.Count > 0)
|
if (tickets.Count > 0)
|
||||||
@@ -157,12 +141,11 @@ namespace C4IT.F4SD
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("getTicketHistory"), HttpGet]
|
[Route("getTicketHistory"), HttpGet]
|
||||||
public async Task<List<F4SDHelperService.cF4SDTicket.cTicketJournalItem>> getTicketHistory(Guid objectId)
|
public async Task<List<cTicketJournalItem>> getTicketHistory(Guid objectId)
|
||||||
{
|
{
|
||||||
return await _f4stHelperService.GetJournalEntries(objectId);
|
return await _f4stHelperService.GetJournalEntries(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
[Route("getTicketOverviewCounts"), HttpGet]
|
[Route("getTicketOverviewCounts"), HttpGet]
|
||||||
public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCounts(
|
public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCounts(
|
||||||
string sid,
|
string sid,
|
||||||
@@ -182,27 +165,6 @@ namespace C4IT.F4SD
|
|||||||
return await _f4stHelperService.getTicketOverviewCounts(sid, scope, parsedKeys, queueoption, decodedQueues);
|
return await _f4stHelperService.getTicketOverviewCounts(sid, scope, parsedKeys, queueoption, decodedQueues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Route("getTicketOverviewCountsForUser"), HttpGet]
|
|
||||||
public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCountsForUser(
|
|
||||||
Guid userId,
|
|
||||||
string scope = "personal",
|
|
||||||
string keys = "",
|
|
||||||
int queueoption = 0,
|
|
||||||
string queues = ""
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var parsedKeys = (keys ?? string.Empty)
|
|
||||||
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
|
||||||
.Select(key => key.Trim())
|
|
||||||
.Where(key => !string.IsNullOrWhiteSpace(key))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var decodedQueues = ParseQueues(queues);
|
|
||||||
return await _f4stHelperService.getTicketOverviewCounts(userId, scope, parsedKeys, queueoption, decodedQueues);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
[Route("getTicketOverviewCountsByRoles"), HttpPost]
|
[Route("getTicketOverviewCountsByRoles"), HttpPost]
|
||||||
public async Task<F4SDHelperService.TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles([FromBody] TicketOverviewCountsByRolesRequest request)
|
public async Task<F4SDHelperService.TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles([FromBody] TicketOverviewCountsByRolesRequest request)
|
||||||
{
|
{
|
||||||
@@ -227,31 +189,6 @@ namespace C4IT.F4SD
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getTicketOverviewCountsByRolesForUser"), HttpPost]
|
|
||||||
public async Task<F4SDHelperService.TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRolesForUser([FromBody] TicketOverviewCountsByRolesForUserRequest request)
|
|
||||||
{
|
|
||||||
var parsedKeys = (request?.Keys ?? new List<string>())
|
|
||||||
.Where(key => !string.IsNullOrWhiteSpace(key))
|
|
||||||
.Select(key => key.Trim())
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var roleGuids = (request?.RoleGuids ?? new List<Guid>())
|
|
||||||
.Where(roleId => roleId != Guid.Empty)
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var decodedQueues = ParseQueues(request?.Queues ?? string.Empty);
|
|
||||||
return await _f4stHelperService.getTicketOverviewCountsByRoles(
|
|
||||||
request.userId,
|
|
||||||
roleGuids,
|
|
||||||
parsedKeys,
|
|
||||||
request?.QueueOption ?? 0,
|
|
||||||
decodedQueues
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
[Route("getTicketOverviewRelations"), HttpGet]
|
[Route("getTicketOverviewRelations"), HttpGet]
|
||||||
public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelations(
|
public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelations(
|
||||||
string sid,
|
string sid,
|
||||||
@@ -265,22 +202,6 @@ namespace C4IT.F4SD
|
|||||||
var decodedQueues = ParseQueues(queues);
|
var decodedQueues = ParseQueues(queues);
|
||||||
return await _f4stHelperService.getTicketOverviewRelations(sid, scope, key, count, queueoption, decodedQueues);
|
return await _f4stHelperService.getTicketOverviewRelations(sid, scope, key, count, queueoption, decodedQueues);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getTicketOverviewRelationsForUser"), HttpGet]
|
|
||||||
public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelations(
|
|
||||||
Guid userId,
|
|
||||||
string scope = "personal",
|
|
||||||
string key = "",
|
|
||||||
int count = 0,
|
|
||||||
int queueoption = 0,
|
|
||||||
string queues = ""
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var decodedQueues = ParseQueues(queues);
|
|
||||||
return await _f4stHelperService.getTicketOverviewRelations(userId, scope, key, count, queueoption, decodedQueues);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[Route("updateActivitySolution/{objectId}"), HttpPost]
|
[Route("updateActivitySolution/{objectId}"), HttpPost]
|
||||||
public async Task<HttpResponseMessage> updateActivitySolution(Guid objectId, [FromBody] string SolutionHtml)
|
public async Task<HttpResponseMessage> updateActivitySolution(Guid objectId, [FromBody] string SolutionHtml)
|
||||||
@@ -293,14 +214,10 @@ namespace C4IT.F4SD
|
|||||||
*/
|
*/
|
||||||
[Route("getPickup/{name}"), HttpGet]
|
[Route("getPickup/{name}"), HttpGet]
|
||||||
//[CacheOutput(UseETAG = true)]
|
//[CacheOutput(UseETAG = true)]
|
||||||
public async Task<EntityEnumeration> getPickup(string name, [FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, [FromUri] Int32 group = -1)
|
public async Task<HttpResponseMessage> getPickup(string name, [FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, [FromUri] Int32 group = -1)
|
||||||
{
|
{
|
||||||
await Task.Delay(0);
|
await Task.Delay(0);
|
||||||
var pickupName = ResolvePickupName(name);
|
EntityEnumeration enumerationTemp = GetEnumeration(name, mode);
|
||||||
if (string.IsNullOrWhiteSpace(pickupName))
|
|
||||||
throw new ArgumentException("Pickup name is required.", nameof(name));
|
|
||||||
|
|
||||||
EntityEnumeration enumerationTemp = GetEnumeration(pickupName, mode);
|
|
||||||
var vals = enumerationTemp.Values;
|
var vals = enumerationTemp.Values;
|
||||||
|
|
||||||
if (group > -1)
|
if (group > -1)
|
||||||
@@ -320,22 +237,22 @@ namespace C4IT.F4SD
|
|||||||
Values = vals.ToArray()
|
Values = vals.ToArray()
|
||||||
};
|
};
|
||||||
//CacheOutputAttribute.RegisterResponseEtag($"enum_{enumeration.Name}_{(int)mode}", $"{enumeration.Name}_{(int)mode}", cultureInvariant: false, userInvariant: true, val);
|
//CacheOutputAttribute.RegisterResponseEtag($"enum_{enumeration.Name}_{(int)mode}", $"{enumeration.Name}_{(int)mode}", cultureInvariant: false, userInvariant: true, val);
|
||||||
return enumeration;
|
return Request.CreateResponse(HttpStatusCode.OK, enumeration);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getMyRoleMemberships"), HttpGet]
|
[Route("getMyRoleMemberships"), HttpGet]
|
||||||
public async Task<object> getMyRoleMemberships()
|
public async Task<HttpResponseMessage> getMyRoleMemberships()
|
||||||
{
|
{
|
||||||
var userId = GetCurrentUserId();
|
var userId = GetCurrentUserId();
|
||||||
if (userId == Guid.Empty)
|
if (userId == Guid.Empty)
|
||||||
throw new UnauthorizedAccessException("Cannot determine the interactive Matrix42 user.");
|
throw new UnauthorizedAccessException("Cannot determine the interactive Matrix42 user.");
|
||||||
|
|
||||||
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
|
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
|
||||||
return await _f4stHelperService.UserPermissionsInfo(filter);
|
return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
|
||||||
}
|
}
|
||||||
|
[HttpGet]
|
||||||
[Route("getRoleMemberships"), HttpGet]
|
[Route("getRoleMemberships")]
|
||||||
public async Task<object> getRoleMemberships([FromUri] GetRoleMembershipsRequest req)
|
public async Task<HttpResponseMessage> getRoleMemberships([FromUri] GetRoleMembershipsRequest req)
|
||||||
{
|
{
|
||||||
var filter = "";
|
var filter = "";
|
||||||
|
|
||||||
@@ -354,7 +271,7 @@ namespace C4IT.F4SD
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(filter))
|
if (!string.IsNullOrEmpty(filter))
|
||||||
{
|
{
|
||||||
return await _f4stHelperService.UserPermissionsInfo(filter);
|
return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -362,14 +279,6 @@ namespace C4IT.F4SD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("getRoleMemberships/{userId}"), HttpGet]
|
|
||||||
public async Task<object> getRoleMembershipForUser(Guid userId)
|
|
||||||
{
|
|
||||||
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
|
|
||||||
return await _f4stHelperService.UserPermissionsInfo(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
public class GetRoleMembershipsRequest
|
public class GetRoleMembershipsRequest
|
||||||
{
|
{
|
||||||
public Guid? Id { get; set; }
|
public Guid? Id { get; set; }
|
||||||
@@ -378,7 +287,6 @@ namespace C4IT.F4SD
|
|||||||
public GetRoleMembershipsRequest() { }
|
public GetRoleMembershipsRequest() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete]
|
|
||||||
public class TicketOverviewCountsByRolesRequest
|
public class TicketOverviewCountsByRolesRequest
|
||||||
{
|
{
|
||||||
public string Sid { get; set; }
|
public string Sid { get; set; }
|
||||||
@@ -388,15 +296,6 @@ namespace C4IT.F4SD
|
|||||||
public string Queues { get; set; }
|
public string Queues { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TicketOverviewCountsByRolesForUserRequest
|
|
||||||
{
|
|
||||||
public Guid userId { get; set; }
|
|
||||||
public List<Guid> RoleGuids { get; set; } = new List<Guid>();
|
|
||||||
public List<string> Keys { get; set; } = new List<string>();
|
|
||||||
public int? QueueOption { get; set; }
|
|
||||||
public string Queues { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private EntityEnumeration GetEnumeration(string name, EntityEnumerationVisibilityMode mode)
|
private EntityEnumeration GetEnumeration(string name, EntityEnumerationVisibilityMode mode)
|
||||||
{
|
{
|
||||||
name = name?.Trim();
|
name = name?.Trim();
|
||||||
@@ -432,20 +331,6 @@ namespace C4IT.F4SD
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResolvePickupName(string routeName)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(routeName))
|
|
||||||
return routeName.Trim();
|
|
||||||
|
|
||||||
var pathSegment = Request?.RequestUri?.Segments?
|
|
||||||
.LastOrDefault(segment => !string.IsNullOrWhiteSpace(segment) && segment != "/");
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(pathSegment))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return Uri.UnescapeDataString(pathSegment.Trim('/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool? GetVisibilityFilter(EntityEnumerationVisibilityMode mode)
|
private static bool? GetVisibilityFilter(EntityEnumerationVisibilityMode mode)
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
@@ -506,46 +391,25 @@ namespace C4IT.F4SD
|
|||||||
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
|
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(part =>
|
.Select(part =>
|
||||||
{
|
{
|
||||||
var decodedPart = WebUtility.UrlDecode(part)?.Trim();
|
var segments = part.Split(':');
|
||||||
if (string.IsNullOrWhiteSpace(decodedPart))
|
if (segments.Length != 2)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var name = decodedPart;
|
var name = WebUtility.UrlDecode(segments[0]);
|
||||||
string idStr = null;
|
var idStr = WebUtility.UrlDecode(segments[1]);
|
||||||
|
|
||||||
var separatorIndex = decodedPart.IndexOf(':');
|
return Guid.TryParse(idStr, out var guid)
|
||||||
if (separatorIndex >= 0)
|
? new cApiM42TicketQueueInfo { QueueName = name, QueueID = guid }
|
||||||
{
|
: null;
|
||||||
name = decodedPart.Substring(0, separatorIndex).Trim();
|
|
||||||
idStr = decodedPart.Substring(separatorIndex + 1).Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
var queue = new cApiM42TicketQueueInfo();
|
|
||||||
if (!string.IsNullOrWhiteSpace(name))
|
|
||||||
queue.QueueName = name;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(idStr))
|
|
||||||
{
|
|
||||||
if (!Guid.TryParse(idStr, out var guid))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
queue.QueueID = guid;
|
|
||||||
queue.QueueName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queue.QueueID == Guid.Empty && string.IsNullOrWhiteSpace(queue.QueueName))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return queue;
|
|
||||||
})
|
})
|
||||||
.Where(q => q != null)
|
.Where(q => q != null)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("isAlive"), HttpGet]
|
[Route("isAlive"), HttpGet]
|
||||||
public IHttpActionResult isAlive()
|
public HttpResponseMessage isAlive()
|
||||||
{
|
{
|
||||||
return new StatusCodeResult(HttpStatusCode.NoContent);
|
return new HttpResponseMessage(HttpStatusCode.NoContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("loglevel"), HttpGet]
|
[Route("loglevel"), HttpGet]
|
||||||
@@ -584,7 +448,6 @@ namespace C4IT.F4SD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RoutePrefix("api/C4ITF4SDWebApi/Logs")]
|
[RoutePrefix("api/C4ITF4SDWebApi/Logs")]
|
||||||
public partial class F4SDM42LogsWebApiController : ApiController
|
public partial class F4SDM42LogsWebApiController : ApiController
|
||||||
{
|
{
|
||||||
@@ -613,6 +476,8 @@ namespace C4IT.F4SD
|
|||||||
catch { };
|
catch { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public F4SDM42LogsWebApiController()
|
public F4SDM42LogsWebApiController()
|
||||||
{
|
{
|
||||||
_f4stHelperService = new F4SDHelperService();
|
_f4stHelperService = new F4SDHelperService();
|
||||||
@@ -660,12 +525,6 @@ namespace C4IT.F4SD
|
|||||||
(entry.Theme?.IndexOf(filter, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0);
|
(entry.Theme?.IndexOf(filter, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryOptions?.Skip != null)
|
|
||||||
result = result.Skip(queryOptions.Skip.Value);
|
|
||||||
|
|
||||||
if (queryOptions?.Top != null)
|
|
||||||
result = result.Take(queryOptions.Top.Value);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user