Compare commits

...

20 Commits

Author SHA1 Message Date
Meik
7392454a63 aktueller stand 2026-02-10 16:53:06 +01:00
Meik
f89e2de60d fixed fallabschluss höhe 2026-02-10 11:29:57 +01:00
Meik
764a8cffb8 generic hierarchical control 2026-02-09 21:07:39 +01:00
Meik
e8584c1453 kategorie fix highlight current value 2026-02-09 20:43:47 +01:00
Meik
deb8d43911 maximized close case dialog 2026-02-09 20:28:24 +01:00
Meik
bf9d37d7af maximized close case dialog 2026-02-09 20:18:31 +01:00
Meik
9e5a7f7946 added transparent click through region 2026-02-09 20:00:30 +01:00
Meik
ca584d3929 fix dropdown scroll fokus 2026-02-09 19:55:29 +01:00
Meik
820a6ad3f3 fix aktions scroll fokus 2026-02-09 19:48:11 +01:00
Meik
fe49708c2e aktueller Stand 2026-02-09 19:44:23 +01:00
Meik
d6cbbe1ef1 aktueller Stand 2026-02-09 19:36:39 +01:00
Meik
825ddf05d4 aktueller Stand 2026-02-05 13:49:54 +01:00
Meik
7ba20b3aa6 aktueller Stand 2026-02-05 11:21:36 +01:00
Meik
aafd1f12de aktueller Stand 2026-02-05 10:04:19 +01:00
Meik
3d055ac2ba aktueller Stand 2026-02-04 21:39:44 +01:00
Meik
101572d35f aktueller Stand 2026-02-04 21:05:52 +01:00
Meik
a1506f36c9 aktueller Stand 2026-02-04 19:01:24 +01:00
Meik
5a9e58dcfb aktueller Stand 2026-02-04 17:52:39 +01:00
Meik
c1f600bc0d aktueller Stand 2026-02-04 13:27:03 +01:00
Meik
195d5c9188 aktueller Stand 2026-02-04 11:22:55 +01:00
49 changed files with 78798 additions and 76286 deletions

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<F4SD-Global-Configuration>
<ShouldSkipSlimView Policy="Default" Value="true" />
<SmallViewAlignment Policy="Default" Value="Right" />
<FavouriteBarAlignment Policy="Default" Value="Right" />
<InformationClassSearchPriority Policy="Hidden">
<InformationClass Type="User" />
<InformationClass Type="Computer" />
<InformationClass Type="VirtualSession" />
<InformationClass Type="Ticket" />
</InformationClassSearchPriority>
<TicketConfiguration>
<DisableAutomaticTimeTracking Policy="Mandatory" Value="true" />
<CompletitionPolicy Policy="Mandatory" Value="IfRequired" />
<NotesMandatory Policy="Mandatory" Value="true" />
<ShowOverview Policy="Mandatory" Value="true" />
<OpenActivitiesExternally Policy="Mandatory" Value="false">
<OpenActivityOverride ActivityType="SPSActivityTypeTicket" Value="false" />
<OpenActivityOverride ActivityType="SPSActivityTypeServiceRequest" Value="true" />
</OpenActivitiesExternally>
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
<OverviewPollingRole Policy="Mandatory" Value="5" />
</TicketConfiguration>
</F4SD-Global-Configuration>

View File

@@ -116,12 +116,15 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Config\F4SD-MenuSection-Configuration.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\F4SD-QuickAction-Configuration.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\F4SD-MenuSection-Configuration.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\F4SD-Global-Configuration.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\F4SD-QuickAction-Configuration.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="app.config" />
<None Include="Config\F4SD-CopyTemplate-Configuration.xsd">
<SubType>Designer</SubType>
@@ -249,9 +252,12 @@
<None Include="MockupPickup\M42Wpm-Ticket-CloseCase-Services.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="MockupPickup\M42Wpm-Ticket-QuickCalls.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="MockupPickup\M42Wpm-Ticket-QuickCalls.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="MockupPickup\M42Wpm-Ticket-Categories.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
@@ -270,4 +276,4 @@
<PropertyGroup>
<PreBuildEvent>copy "$(ProjectDir)..\..\C4IT FASD\_Common\XmlSchemas\*" "$(ProjectDir)Config"</PreBuildEvent>
</PropertyGroup>
</Project>
</Project>

View File

@@ -3,18 +3,20 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using Newtonsoft.Json;
using FasdCockpitBase.Models;
using FasdCockpitCommunicationDemo;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using FasdCockpitBase;
using C4IT.Logging;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Xml;
using Newtonsoft.Json;
using FasdCockpitBase.Models;
using FasdCockpitCommunicationDemo;
using C4IT.Configuration;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using FasdCockpitBase;
using C4IT.Logging;
namespace C4IT.FASD.Cockpit.Communication
@@ -27,13 +29,14 @@ namespace C4IT.FASD.Cockpit.Communication
private readonly Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable> MockupPickup = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable>();
private readonly Dictionary<string, string> CategoryNameLookup = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
#region Ticketübersicht
private readonly Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>> TicketOverviewRelations =
new Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<Guid> _generatedTicketIds = new HashSet<Guid>();
private readonly object _demoTicketSync = new object();
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
#endregion
public cFasdCockpitCommunicationDemo()
@@ -41,16 +44,18 @@ namespace C4IT.FASD.Cockpit.Communication
if (LoadMockupData(out var loadedData))
MockupData = loadedData;
MockupPickup = LoadMockupPickup();
LoadTicketOverviewRelations();
LoadGeneratedTickets();
}
MockupPickup = LoadMockupPickup();
BuildCategoryLookup();
LoadTicketOverviewRelations();
LoadGeneratedTickets();
EnsureOverviewTicketJournalEntries();
}
public override bool IsDemo() => true;
private Dictionary<Guid, cFasdApiSearchResultCollection> SearchCache = new Dictionary<Guid, cFasdApiSearchResultCollection>();
private Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable> LoadMockupPickup()
private Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable> LoadMockupPickup()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
@@ -99,6 +104,50 @@ namespace C4IT.FASD.Cockpit.Communication
return null;
}
private void BuildCategoryLookup()
{
CategoryNameLookup.Clear();
if (MockupPickup == null || !MockupPickup.TryGetValue("M42Wpm-Ticket-Categories", out var table))
return;
if (table?.Columns == null)
return;
if (!table.Columns.TryGetValue("id", out var idColumn))
return;
if (!table.Columns.TryGetValue("Name", out var nameColumn))
return;
for (int i = 0; i < idColumn.Values.Count; i++)
{
var id = idColumn.Values[i]?.ToString();
if (string.IsNullOrWhiteSpace(id))
continue;
var name = i < nameColumn.Values.Count ? nameColumn.Values[i]?.ToString() : null;
if (string.IsNullOrWhiteSpace(name))
continue;
CategoryNameLookup[id] = name;
}
}
private string ResolveCategoryDisplayName(string categoryIdOrName)
{
if (string.IsNullOrWhiteSpace(categoryIdOrName))
return categoryIdOrName;
if (!Guid.TryParse(categoryIdOrName, out _))
return categoryIdOrName;
if (CategoryNameLookup.TryGetValue(categoryIdOrName, out var name))
return name;
return categoryIdOrName;
}
#region Ticketübersicht
private void LoadTicketOverviewRelations()
@@ -146,11 +195,11 @@ namespace C4IT.FASD.Cockpit.Communication
}
}
private void LoadGeneratedTickets()
{
try
{
var records = TicketOverviewDataStore.LoadTickets();
private void LoadGeneratedTickets()
{
try
{
var records = TicketOverviewDataStore.LoadTickets();
foreach (var record in records)
{
AppendDemoTicket(record);
@@ -198,18 +247,19 @@ namespace C4IT.FASD.Cockpit.Communication
scopeDictionary[scopeKey] = definitions;
}
if (!definitions.Any(d => d.TicketId == record.TicketId))
{
definitions.Add(new TicketOverviewRelationDefinition
{
TicketId = record.TicketId,
UserId = record.UserId,
DisplayName = record.DisplayName,
Summary = record.Summary,
StatusId = record.StatusId,
UserDisplayName = record.UserDisplayName,
UserAccount = record.UserAccount,
UserDomain = record.UserDomain
if (!definitions.Any(d => d.TicketId == record.TicketId))
{
definitions.Add(new TicketOverviewRelationDefinition
{
TicketId = record.TicketId,
UserId = record.UserId,
DisplayName = record.DisplayName,
ActivityType = record.ActivityType,
Summary = record.Summary,
StatusId = record.StatusId,
UserDisplayName = record.UserDisplayName,
UserAccount = record.UserAccount,
UserDomain = record.UserDomain
});
}
@@ -221,9 +271,112 @@ namespace C4IT.FASD.Cockpit.Communication
return;
var generatedTicket = ConvertToTicket(record);
targetSample.Tickets.Add(generatedTicket);
}
}
targetSample.Tickets.Add(generatedTicket);
EnsureTicketHasMinimumDemoJournalEntries(generatedTicket);
}
}
private void EnsureOverviewTicketJournalEntries()
{
try
{
var overviewTicketIds = TicketOverviewRelations.Values
.Where(scopeMap => scopeMap != null)
.SelectMany(scopeMap => scopeMap.Values)
.Where(definitions => definitions != null)
.SelectMany(definitions => definitions)
.Where(definition => definition != null && definition.TicketId != Guid.Empty)
.Select(definition => definition.TicketId)
.Distinct()
.ToList();
foreach (var ticketId in overviewTicketIds)
{
var ticket = MockupData
.FirstOrDefault(data => data != null && data.Tickets != null && data.Tickets.Any(t => t.Id == ticketId))
?.Tickets
.FirstOrDefault(t => t.Id == ticketId);
if (ticket == null)
continue;
EnsureTicketHasMinimumDemoJournalEntries(ticket);
}
}
catch (Exception E)
{
LogException(E);
}
}
private void EnsureTicketHasMinimumDemoJournalEntries(cF4SDTicket ticket)
{
if (ticket == null)
return;
if (ticket.JournalItems == null)
ticket.JournalItems = new List<cF4SDTicket.cTicketJournalItem>();
if (ticket.JournalItems.Count >= 2)
return;
bool isIncident = (ticket.Name ?? string.Empty).StartsWith("INC", StringComparison.OrdinalIgnoreCase);
var baseTime = ticket.CreationDate == default ? DateTime.Now.AddHours(-2) : ticket.CreationDate;
if (ticket.JournalItems.Count == 0)
{
ticket.JournalItems.Add(CreateDemoJournalItem(
baseTime,
isIncident ? "Incident erfasst" : "Ticket erfasst",
"Der Vorgang wurde in der Ticketuebersicht erfasst und priorisiert."));
}
if (ticket.JournalItems.Count < 2)
{
string header;
string text;
switch (ticket.Status)
{
case enumTicketStatus.InProgress:
header = "Bearbeitung aufgenommen";
text = "Der Vorgang wurde einem Bearbeiter zugeordnet und die Analyse gestartet.";
break;
case enumTicketStatus.OnHold:
header = "Warte auf Rueckmeldung";
text = "Fuer die weitere Bearbeitung werden zusaetzliche Informationen vom Anwender erwartet.";
break;
case enumTicketStatus.New:
header = "Sichtung durch Service Desk";
text = "Der Vorgang wurde gesichtet und zur Bearbeitung vorbereitet.";
break;
case enumTicketStatus.Closed:
header = "Abschluss dokumentiert";
text = "Loesung und Abschluss wurden fuer den Vorgang dokumentiert.";
break;
default:
header = "Status aktualisiert";
text = "Der aktuelle Bearbeitungsstand wurde im Vorgang aktualisiert.";
break;
}
ticket.JournalItems.Add(CreateDemoJournalItem(baseTime.AddMinutes(15), header, text));
}
}
private static cF4SDTicket.cTicketJournalItem CreateDemoJournalItem(DateTime timestamp, string header, string text)
{
var creationTime = timestamp == default ? DateTime.Now : timestamp;
return new cF4SDTicket.cTicketJournalItem
{
Header = header ?? string.Empty,
Description = text ?? string.Empty,
DescriptionHtml = $"<p>{text ?? string.Empty}</p>",
IsVisibleForUser = true,
CreationDate = creationTime,
CreationDaysSinceNow = Math.Max(0, (int)(DateTime.Now - creationTime).TotalDays)
};
}
private static cF4SDTicket ConvertToTicket(DemoTicketRecord record)
{
@@ -240,13 +393,12 @@ namespace C4IT.FASD.Cockpit.Communication
Name = record.DisplayName,
Summary = record.Summary,
Status = status,
AffectedUser = detail.AffectedUser ?? record.UserDisplayName,
Asset = detail.Asset,
Category = detail.Category,
Classification = detail.Classification,
Description = detail.Description,
DescriptionHtml = detail.DescriptionHtml,
Solution = detail.Solution,
AffectedUser = detail.AffectedUser ?? record.UserDisplayName,
Asset = detail.Asset,
Category = detail.Category,
Description = detail.Description,
DescriptionHtml = detail.DescriptionHtml,
Solution = detail.Solution,
SolutionHtml = detail.SolutionHtml,
CreationDate = createdAt.ToLocalTime(),
CreationDaysSinceNow = Math.Max(0, (int)(DateTime.UtcNow - createdAt).TotalDays),
@@ -332,31 +484,39 @@ namespace C4IT.FASD.Cockpit.Communication
await SimulateTicketOverviewLatencyAsync(count);
return new List<cF4sdApiSearchResultRelation>();
}
int requestedCount = count <= 0 ? definitions.Count : Math.Min(count, definitions.Count);
await SimulateTicketOverviewLatencyAsync(requestedCount);
var relations = new List<cF4sdApiSearchResultRelation>(requestedCount);
foreach (var definition in definitions.Take(requestedCount))
{
var relation = new cF4sdApiSearchResultRelation
{
Type = enumF4sdSearchResultClass.Ticket,
DisplayName = definition.DisplayName ?? string.Empty,
Name = definition.DisplayName ?? string.Empty,
int requestedCount = count <= 0 ? definitions.Count : Math.Min(count, definitions.Count);
await SimulateTicketOverviewLatencyAsync(requestedCount);
var relations = new List<cF4sdApiSearchResultRelation>(requestedCount);
foreach (var definition in definitions.Take(requestedCount))
{
var detailTicket = FindTicketForOverviewRelation(definition);
var summary = definition.Summary ?? string.Empty;
if (detailTicket != null && !string.IsNullOrWhiteSpace(detailTicket.Summary))
summary = detailTicket.Summary;
var activityType = string.IsNullOrWhiteSpace(definition.ActivityType)
? null
: definition.ActivityType.Trim();
var relation = new cF4sdApiSearchResultRelation
{
Type = enumF4sdSearchResultClass.Ticket,
DisplayName = definition.DisplayName ?? string.Empty,
Name = definition.DisplayName ?? string.Empty,
id = definition.TicketId,
Status = enumF4sdSearchResultStatus.Active,
Infos = new Dictionary<string, string>
{
["Summary"] = definition.Summary ?? string.Empty,
["StatusId"] = definition.StatusId ?? string.Empty,
["UserDisplayName"] = definition.UserDisplayName ?? string.Empty,
["UserAccount"] = definition.UserAccount ?? string.Empty,
["UserDomain"] = definition.UserDomain ?? string.Empty,
[DemoTicketHasDetailsInfoKey] = HasTicketDetails(definition.TicketId).ToString()
},
Identities = new cF4sdIdentityList
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = definition.TicketId },
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = definition.UserId }
Status = enumF4sdSearchResultStatus.Active,
Infos = new Dictionary<string, string>
{
["Summary"] = summary,
["StatusId"] = definition.StatusId ?? string.Empty,
["UserDisplayName"] = definition.UserDisplayName ?? string.Empty,
["UserAccount"] = definition.UserAccount ?? string.Empty,
["UserDomain"] = definition.UserDomain ?? string.Empty,
["ActivityType"] = activityType
},
Identities = new cF4sdIdentityList
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = definition.TicketId },
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = definition.UserId }
}
};
relations.Add(relation);
@@ -370,34 +530,165 @@ namespace C4IT.FASD.Cockpit.Communication
}
finally
{
LogMethodEnd(CM);
}
}
private bool HasTicketDetails(Guid ticketId)
{
if (ticketId == Guid.Empty)
return false;
foreach (var sample in MockupData)
{
var tickets = sample?.Tickets;
if (tickets == null)
continue;
foreach (var ticket in tickets)
{
if (ticket?.Id == ticketId)
return true;
}
}
return false;
}
private static Task SimulateTicketOverviewLatencyAsync(int count)
{
int baseMs = 420;
int perItem = 100;
LogMethodEnd(CM);
}
}
private cF4SDTicket FindTicketForOverviewRelation(TicketOverviewRelationDefinition definition)
{
if (definition == null || definition.TicketId == Guid.Empty)
return null;
cF4SDTicket selectedTicket = null;
if (definition.UserId != Guid.Empty)
{
var selectedData = MockupData.FirstOrDefault(data => data.SampleDataId == definition.UserId);
if (selectedData != null && selectedData.Tickets != null)
selectedTicket = selectedData.Tickets.FirstOrDefault(ticket => ticket.Id == definition.TicketId);
}
if (selectedTicket != null)
return selectedTicket;
var fallbackData = MockupData.FirstOrDefault(data =>
data != null &&
data.Tickets != null &&
data.Tickets.Any(ticket => ticket.Id == definition.TicketId));
if (fallbackData == null || fallbackData.Tickets == null)
return null;
return fallbackData.Tickets.FirstOrDefault(ticket => ticket.Id == definition.TicketId);
}
private static string ResolveTicketActivityType(string displayName, cF4SDTicket detailTicket = null)
{
var linkType = TryGetActivityTypeFromTicketLinks(detailTicket);
if (!string.IsNullOrWhiteSpace(linkType))
return linkType;
var ticketName = displayName ?? detailTicket?.Name;
if (string.IsNullOrWhiteSpace(ticketName))
return "SPSActivityTypeTicket";
if (ticketName.StartsWith("INC", StringComparison.OrdinalIgnoreCase))
return "SPSActivityTypeIncident";
if (ticketName.StartsWith("SRQ", StringComparison.OrdinalIgnoreCase))
return "SPSActivityTypeServiceRequest";
if (ticketName.StartsWith("PRB", StringComparison.OrdinalIgnoreCase))
return "SPSActivityTypeGroupTicket";
if (ticketName.StartsWith("ALT", StringComparison.OrdinalIgnoreCase))
return "SPSActivityTypeAlert";
if (ticketName.StartsWith("CHG", StringComparison.OrdinalIgnoreCase))
return "SVMChangeRequestType";
if (ticketName.StartsWith("TSK", StringComparison.OrdinalIgnoreCase))
return "SPSActivityTypeBase";
return "SPSActivityTypeTicket";
}
private static string TryGetActivityTypeFromTicketLinks(cF4SDTicket ticket)
{
if (ticket?.DirectLinks == null || ticket.DirectLinks.Count == 0)
return null;
foreach (var link in ticket.DirectLinks.Values)
{
var type = TryGetActivityTypeFromUrl(link);
if (!string.IsNullOrWhiteSpace(type))
return type;
}
return null;
}
private static string TryGetActivityTypeFromUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
return null;
var markerList = new[] { "preview-object/", "edit-object/", "create-object/" };
foreach (var marker in markerList)
{
var markerIndex = url.IndexOf(marker, StringComparison.OrdinalIgnoreCase);
if (markerIndex < 0)
continue;
var start = markerIndex + marker.Length;
var end = url.IndexOf('/', start);
if (end < 0)
end = url.IndexOf('?', start);
if (end < 0)
end = url.Length;
if (end <= start)
continue;
var activityType = url.Substring(start, end - start).Trim();
if (!string.IsNullOrWhiteSpace(activityType))
return activityType;
}
// Fallback for view-options based deeplinks.
var decodedUrl = Uri.UnescapeDataString(url);
const string queryTypeToken = "\"type\":\"";
var typeStart = decodedUrl.IndexOf(queryTypeToken, StringComparison.OrdinalIgnoreCase);
if (typeStart < 0)
return null;
typeStart += queryTypeToken.Length;
var typeEnd = decodedUrl.IndexOf('"', typeStart);
if (typeEnd <= typeStart)
return null;
var parsedType = decodedUrl.Substring(typeStart, typeEnd - typeStart).Trim();
return string.IsNullOrWhiteSpace(parsedType) ? null : parsedType;
}
private string ResolveDemoM42Server()
{
foreach (var sampleData in MockupData)
{
if (sampleData?.Tickets == null)
continue;
foreach (var ticket in sampleData.Tickets)
{
if (ticket?.DirectLinks == null)
continue;
foreach (var link in ticket.DirectLinks.Values)
{
if (TryExtractServerBase(link, out var serverBase))
return serverBase;
}
}
}
return "https://srvwsm001.imagoverum.com";
}
private static bool TryExtractServerBase(string url, out string serverBase)
{
serverBase = null;
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
return false;
serverBase = uri.GetLeftPart(UriPartial.Authority);
return !string.IsNullOrWhiteSpace(serverBase);
}
private static Task SimulateTicketOverviewLatencyAsync(int count)
{
int baseMs = 420;
int perItem = 100;
int capped = Math.Max(0, Math.Min(count, 5));
int delay = Math.Max(240, Math.Min(baseMs + capped * perItem, 2000));
return Task.Delay(delay);
@@ -668,21 +959,115 @@ namespace C4IT.FASD.Cockpit.Communication
return output;
}
public override async Task<cFasdApiSearchResultCollection> GetUserSearchResults(string Name, List<string> SIDs)
{
var output = new cFasdApiSearchResultCollection();
try
{
foreach (var data in MockupData)
{
if (data.SampleDataName.Equals(Name, StringComparison.InvariantCultureIgnoreCase))
{
//todo: add a field in demo data
var searchResultClass = enumF4sdSearchResultClass.User;
output[data.SampleDataName] = new List<cFasdApiSearchResultEntry>() { new cFasdApiSearchResultEntry() { id = data.SampleDataId, Name = data.SampleDataName, DisplayName = data.SampleDataName, Type = searchResultClass } };
}
}
public override async Task<cFasdApiSearchResultCollection> GetUserSearchResults(string Name, List<string> SIDs)
{
var output = new cFasdApiSearchResultCollection();
try
{
bool IsNameMatch(string sourceName, string requestName)
{
if (string.IsNullOrWhiteSpace(sourceName) || string.IsNullOrWhiteSpace(requestName))
return false;
if (sourceName.Equals(requestName, StringComparison.InvariantCultureIgnoreCase))
return true;
string Normalize(string value)
{
return string.Join(" ", (value ?? string.Empty)
.ToLowerInvariant()
.Replace(",", " ")
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
}
int LevenshteinDistance(string left, string right)
{
if (string.IsNullOrEmpty(left))
return right?.Length ?? 0;
if (string.IsNullOrEmpty(right))
return left.Length;
int[] previous = new int[right.Length + 1];
int[] current = new int[right.Length + 1];
for (int j = 0; j <= right.Length; j++)
previous[j] = j;
for (int i = 1; i <= left.Length; i++)
{
current[0] = i;
for (int j = 1; j <= right.Length; j++)
{
int cost = left[i - 1] == right[j - 1] ? 0 : 1;
current[j] = Math.Min(
Math.Min(current[j - 1] + 1, previous[j] + 1),
previous[j - 1] + cost);
}
var temp = previous;
previous = current;
current = temp;
}
return previous[right.Length];
}
bool IsTokenMatch(string leftToken, string rightToken)
{
if (leftToken == rightToken)
return true;
int sharedLength = Math.Min(Math.Min(leftToken.Length, rightToken.Length), 5);
if (sharedLength >= 4 && leftToken.Substring(0, sharedLength) == rightToken.Substring(0, sharedLength))
return true;
return LevenshteinDistance(leftToken, rightToken) <= 2;
}
var normalizedSource = Normalize(sourceName);
var normalizedRequest = Normalize(requestName);
if (normalizedSource == normalizedRequest)
return true;
var sourceTokens = normalizedSource.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
var requestTokens = normalizedRequest.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
if (sourceTokens.Count == 0 || requestTokens.Count == 0 || sourceTokens.Count != requestTokens.Count)
return false;
var remaining = new List<string>(sourceTokens);
foreach (var token in requestTokens)
{
int index = remaining.FindIndex(candidate => IsTokenMatch(candidate, token));
if (index < 0)
return false;
remaining.RemoveAt(index);
}
return remaining.Count == 0;
}
foreach (var data in MockupData)
{
if (!IsNameMatch(data.SampleDataName, Name))
continue;
//todo: add a field in demo data
var searchResultClass = enumF4sdSearchResultClass.User;
if (!output.ContainsKey(data.SampleDataName))
{
output[data.SampleDataName] = new List<cFasdApiSearchResultEntry>()
{
new cFasdApiSearchResultEntry()
{
id = data.SampleDataId,
Name = data.SampleDataName,
DisplayName = data.SampleDataName,
Type = searchResultClass
}
};
}
}
await Task.CompletedTask;
}
catch (Exception E)
@@ -712,8 +1097,8 @@ namespace C4IT.FASD.Cockpit.Communication
var output = new List<cF4sdApiSearchResultRelation>();
switch (resultIds.First().ToString())
{
switch (resultIds.First().ToString())
{
case constGuidOlliOffline: // Olli Offline
output.Add(new cF4sdApiSearchResultRelation() { id = Guid.NewGuid(), Name = "C4-NB005", DisplayName = "C4-NB005", Infos = new Dictionary<string, string>() { ["UserAccountType"] = "AD", ["UserAccount"] = "C4-NB005", ["UserDomain"] = "C4IT" }, LastUsed = DateTime.UtcNow.AddDays(-10), Type = enumF4sdSearchResultClass.Computer, UsingLevel = 1, Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = Guid.Parse(constGuidOlliOffline) }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = Guid.NewGuid() } } });
@@ -871,10 +1256,10 @@ namespace C4IT.FASD.Cockpit.Communication
var demoTickets = await GetDemoTicketData(new cF4sdHealthCardRawDataRequest() { Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = Guid.Parse(constGuidTimoTicket) }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = Guid.NewGuid() } } });
foreach (var demoTicket in demoTickets)
{
output.Add(new cF4sdApiSearchResultRelation() { id = demoTicket.Id, Name = demoTicket.Name, DisplayName = demoTicket.Name, Infos = new Dictionary<string, string>() { ["Summary"] = demoTicket.Summary, ["Status"] = demoTicket.Status.ToString(), ["StatusId"] = ((int)demoTicket.Status).ToString(), ["Asset"] = demoTicket.Asset }, Type = enumF4sdSearchResultClass.Ticket, Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = Guid.Parse(constGuidTimoTicket) }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Ticket, Id = demoTicket.Id } } });
}
foreach (var demoTicket in demoTickets)
{
output.Add(new cF4sdApiSearchResultRelation() { id = demoTicket.Id, Name = demoTicket.Name, DisplayName = demoTicket.Name, Infos = new Dictionary<string, string>() { ["Summary"] = demoTicket.Summary, ["Status"] = demoTicket.Status.ToString(), ["StatusId"] = ((int)demoTicket.Status).ToString(), ["Asset"] = demoTicket.Asset, ["ActivityType"] = ResolveTicketActivityType(demoTicket.Name, demoTicket) }, Type = enumF4sdSearchResultClass.Ticket, Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = Guid.Parse(constGuidTimoTicket) }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Ticket, Id = demoTicket.Id } } });
}
break;
case constGuidTimoTicketComputer:
@@ -884,18 +1269,68 @@ namespace C4IT.FASD.Cockpit.Communication
case constGuidComputer: // Computer
break;
default:
output.Add(new cF4sdApiSearchResultRelation() { id = Guid.NewGuid(), Name = "C4IT-007", DisplayName = "C4IT-007", LastUsed = DateTime.UtcNow, Type = enumF4sdSearchResultClass.Computer, UsingLevel = 1, Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = resultIds.First() }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = Guid.NewGuid() } } });
break;
}
await Task.CompletedTask;
output = output.OrderByDescending(relation => relation.LastUsed).ToList();
return output;
}
public override async Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData)
{
output.Add(new cF4sdApiSearchResultRelation() { id = Guid.NewGuid(), Name = "C4IT-007", DisplayName = "C4IT-007", LastUsed = DateTime.UtcNow, Type = enumF4sdSearchResultClass.Computer, UsingLevel = 1, Identities = new cF4sdIdentityList() { new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = resultIds.First() }, new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = Guid.NewGuid() } } });
break;
}
if (resultType == enumF4sdSearchResultClass.User)
{
foreach (var userId in resultIds)
{
AppendDemoTicketRelationsForUser(userId, output);
}
}
await Task.CompletedTask;
output = output.OrderByDescending(relation => relation.LastUsed).ToList();
return output;
}
private void AppendDemoTicketRelationsForUser(Guid userId, List<cF4sdApiSearchResultRelation> output)
{
if (userId == Guid.Empty || output == null)
return;
var selectedData = MockupData.FirstOrDefault(data => data?.SampleDataId == userId);
if (selectedData?.Tickets == null)
return;
foreach (var demoTicket in selectedData.Tickets)
{
if (demoTicket == null || demoTicket.Id == Guid.Empty)
continue;
if (output.Any(relation => relation.Type == enumF4sdSearchResultClass.Ticket && relation.id == demoTicket.Id))
continue;
output.Add(new cF4sdApiSearchResultRelation()
{
id = demoTicket.Id,
Name = demoTicket.Name,
DisplayName = demoTicket.Name,
LastUsed = demoTicket.CreationDate == default ? DateTime.UtcNow : demoTicket.CreationDate.ToUniversalTime(),
Type = enumF4sdSearchResultClass.Ticket,
UsingLevel = 1,
Infos = new Dictionary<string, string>()
{
["Summary"] = demoTicket.Summary ?? string.Empty,
["Status"] = demoTicket.Status.ToString(),
["StatusId"] = ((int)demoTicket.Status).ToString(),
["Asset"] = demoTicket.Asset ?? string.Empty,
["ActivityType"] = ResolveTicketActivityType(demoTicket.Name, demoTicket)
},
Identities = new cF4sdIdentityList()
{
new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = userId },
new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Ticket, Id = demoTicket.Id }
}
});
}
}
public override async Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
@@ -906,19 +1341,45 @@ namespace C4IT.FASD.Cockpit.Communication
{
await Task.Delay(250);
var selectedData = MockupData.FirstOrDefault(data => requestData.Identities.Any(identity => identity.Id == data.SampleDataId));
var selectedData = MockupData.FirstOrDefault(data => requestData.Identities.Any(identity => identity.Id == data.SampleDataId));
if (selectedData is null)
{
var ticketIdentity = requestData.Identities?
.FirstOrDefault(identity => identity.Class is enumFasdInformationClass.Ticket);
if (ticketIdentity != null)
{
selectedData = MockupData.FirstOrDefault(data =>
data?.Tickets != null && data.Tickets.Any(ticket => ticket?.Id == ticketIdentity.Id));
}
}
if (selectedData is null)
return output;
if (selectedData is null)
return output;
output = selectedData.GetHealthCardData();
var ticketRequest = requestData.Identities.FirstOrDefault(data => data.Class is enumFasdInformationClass.Ticket);
if (ticketRequest != null)
{
var selectedTicket = selectedData.Tickets.FirstOrDefault(ticket => ticket.Id == ticketRequest.Id);
if (selectedTicket != null)
{
string ticketStatusString = string.Empty;
output = selectedData.GetHealthCardData();
var ticketRequest = requestData.Identities.FirstOrDefault(data => data.Class is enumFasdInformationClass.Ticket);
if (ticketRequest != null)
{
var selectedTicket = selectedData.Tickets.FirstOrDefault(ticket => ticket.Id == ticketRequest.Id);
// Some demo users share the same SampleDataId; resolve by TicketId if the first user match has no ticket details.
if (selectedTicket == null)
{
var fallbackData = MockupData.FirstOrDefault(data =>
data?.Tickets != null && data.Tickets.Any(ticket => ticket?.Id == ticketRequest.Id));
if (fallbackData != null)
{
selectedData = fallbackData;
output = selectedData.GetHealthCardData();
selectedTicket = selectedData.Tickets.FirstOrDefault(ticket => ticket.Id == ticketRequest.Id);
}
}
if (selectedTicket != null)
{
string ticketStatusString = string.Empty;
switch (selectedTicket.Status)
{
case enumTicketStatus.Unknown:
@@ -951,14 +1412,15 @@ namespace C4IT.FASD.Cockpit.Communication
["AffectedUser"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.AffectedUser } },
["AssetName"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Asset } },
["CreationDaysSinceNow"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.CreationDaysSinceNow } },
["CreationDate"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.CreationDate.ToUniversalTime() } },
["ClosingDaysSinceNow"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.ClosingDaysSinceNow } },
["ClosingDate"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.ClosingDate } },
["Category"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Category } },
["CreationSource"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.CreationSource.ToString() } },
["Description"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Description?.ToString() } },
["DescriptionHtml"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.DescriptionHtml?.ToString() } },
["Summary"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Summary.ToString() } },
["CreationDate"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.CreationDate.ToUniversalTime() } },
["ClosingDaysSinceNow"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.ClosingDaysSinceNow } },
["ClosingDate"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.ClosingDate } },
["Category"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { ResolveCategoryDisplayName(selectedTicket.Category) } },
["CategoryId"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Category } },
["CreationSource"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.CreationSource.ToString() } },
["Description"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Description?.ToString() } },
["DescriptionHtml"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.DescriptionHtml?.ToString() } },
["Summary"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Summary.ToString() } },
["Solution"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.Solution?.ToString() } },
["SolutionHtml"] = new cF4SDHealthCardRawData.cHealthCardTableColumn(outputTable) { Values = new List<object>() { selectedTicket.SolutionHtml?.ToString() } },
};
@@ -1442,9 +1904,6 @@ namespace C4IT.FASD.Cockpit.Communication
if (writeParams.Values.TryGetValue("Category", out var category))
output.Category = category.ToString();
if (writeParams.Values.TryGetValue("Classification", out var classification))
output.Classification = classification.ToString();
if (writeParams.Values.TryGetValue("CreationSource", out var creationSourceObj))
if (Enum.TryParse(creationSourceObj.ToString(), out cF4SDTicket.enumTicketCreationSource creationSource))
output.CreationSource = creationSource;
@@ -1679,16 +2138,43 @@ namespace C4IT.FASD.Cockpit.Communication
return true;
}
public override async Task<bool> GetCockpitConfiguration()
{
cCockpitConfiguration.Instance = new cCockpitConfiguration();
cCockpitConfiguration.Instance.agentApiConfiguration = new cAgentApiConfiguration() { ApiUrl = "", ClientId = "", ClientSecret = "", LogonUrl = "", OrganizationCode = 0 };
cCockpitConfiguration.Instance.m42ServerConfiguration = new cM42ServerConfiguration() { Server = "" };
await Task.CompletedTask;
return true;
}
public override Task<bool> GetAgentOnlineStatus(int AgentDeviceId, int? AgentUserId = null) => Task.FromResult(true);
public override async Task<bool> GetCockpitConfiguration()
{
cCockpitConfiguration.Instance = new cCockpitConfiguration();
cCockpitConfiguration.Instance.agentApiConfiguration = new cAgentApiConfiguration() { ApiUrl = "", ClientId = "", ClientSecret = "", LogonUrl = "", OrganizationCode = 0 };
cCockpitConfiguration.Instance.m42ServerConfiguration = new cM42ServerConfiguration() { Server = ResolveDemoM42Server() };
cCockpitConfiguration.Instance.GlobalConfig = LoadDemoGlobalConfig();
await Task.CompletedTask;
return true;
}
private static cConfigHelperParameterList LoadDemoGlobalConfig()
{
try
{
var executingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var filePath = Path.Combine(executingDirectory, "Config", "F4SD-Global-Configuration.xml");
if (!File.Exists(filePath))
return null;
var xmlDocument = new XmlDocument();
xmlDocument.Load(filePath);
var root = xmlDocument.DocumentElement;
if (root == null || !string.Equals(root.Name, "F4SD-Global-Configuration", StringComparison.OrdinalIgnoreCase))
return null;
return cF4sdGlobalConfigParameterParser.Parse(root);
}
catch (Exception E)
{
LogException(E);
}
return null;
}
public override Task<bool> GetAgentOnlineStatus(int AgentDeviceId, int? AgentUserId = null) => Task.FromResult(true);
public override Task<cF4sdAgentScript> GetQuickActionOfAgent(int ScriptId) => Task.FromResult(new cF4sdAgentScript() { Id = ScriptId, Name = "AgentScript", Type = enumAgentScriptType.user, UserPermissionRequired = false });

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,714 @@
{
"AlternateStaticTable": null,
"Name": "M42Wpm-Ticket-Categories",
"StartingIndex": 0,
"IsIncomplete": false,
"IsStatic": false,
"TableType": 5,
"TimeFrames": null,
"InformationClass": 3,
"Columns": {
"id": {
"ColumnName": "id",
"Values": [
"9282a500-caea-49bb-944f-9d0274fcc80a",
"8ba5e53d-3b6b-425a-baba-34438845f00d",
"cbbec585-0184-4ae3-ab68-7caeb3d0e5b2",
"fd4ca144-2aca-48c4-b8b9-ce75b07ca3cb",
"70d3cb04-11ab-43cb-a769-368517ba4879",
"9d468c5c-c543-4ee5-9a23-4f9975e5c145",
"b05a28a4-a1ae-4cb8-a30d-08fe6873b467",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"4e7bafad-c49b-432a-b88e-f4bced36e5ed",
"2c6fca4b-a1a0-ed11-5a81-000c299eb325",
"d457c1f4-e4bd-4753-9e02-c8e645d5e342",
"facc2d0f-3216-4ccd-9c81-57cb29150e9e",
"5f385abf-a574-468b-a4ba-feed4fc0c76d",
"ced65ab8-d526-4518-be11-caf68b31d959",
"f5f3e9d2-2e63-4fc4-a00c-0e8d12750a70",
"2ed6c1ac-70ee-4f3d-911a-f4508cdf085c",
"a84abed8-7384-4fd1-8ed1-6f2bd7398e7c",
"c92984c5-6c88-452f-b5eb-17c73cf2f406",
"5ccae795-9ba5-ea11-2ca6-2c6fc9364e44",
"4d51cfdd-ccaa-49a0-89cf-b16666f38de5",
"2533dacc-5a9f-ea11-b083-000d3a24f586",
"3f00c4b0-9ba5-ea11-2ca6-2c6fc9364e44",
"bfbfaff9-30b9-4bab-9472-8203d9c638e7",
"da6a307f-f4ed-ea11-e683-000d3a24f586",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
"54779070-3b79-4bef-abfa-901e35fe6d64",
"8d757427-f2ed-ea11-e683-000d3a24f586",
"9b129a5b-18b2-4489-a889-8496eb975b38",
"dd47d5d9-9fa5-ea11-2ca6-2c6fc9364e44",
"3ee839fa-05cc-ea11-fba7-0c9d921bfedc",
"3838d26f-bc49-4065-a29f-b8965b199946",
"14a23183-337e-e811-b382-000d3a24f586",
"b0c38014-e147-e511-0681-0050562f9516",
"d08ff475-e7c4-4dd5-8399-a751f27cc62f",
"5bd861fd-1dcf-4e48-ac1b-f439295fae88",
"fe30d3d8-32c0-40f2-8205-3519c4b52ddd",
"50e4a6d3-37f9-ec11-3185-000d3abff293",
"3d75c99d-b3e3-eb11-5684-000d3aad24a5",
"d0fe2578-d7e2-4bbf-ad59-58e297fac109",
"b457c1f4-e4bd-4753-9e02-c8e645d5e342",
"5310b2a1-92b9-4627-8478-2a687232e5f3",
"44e88873-4960-41e0-b7eb-3334ec76102c",
"30f73af3-abb7-4d68-876d-9202b24ca3f1",
"bb1fd7f2-0d95-469d-ac83-a2d391eb111b",
"2964fa66-368e-4d92-b322-df51ff25182c",
"3d1f7ff5-f9c5-4f84-8783-e649382666d7",
"ab49d197-b3e3-eb11-5684-000d3aad24a5",
"a198b490-337e-e811-b382-000d3a24f586",
"809dceed-3d2d-ee11-e685-000d3abff293",
"a76f2ae1-4830-ee11-e785-000d3abff293",
"02c7a5f8-6133-4be3-9d63-2687b96a1e72",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"85623dea-dad3-4102-a45a-00f9379fde26",
"0f9f345f-ef08-44a5-bcbf-d7d1087295a3",
"c1e4f87f-a8ab-4acc-a7e8-3e9a78c8f3f9",
"ece302ae-c844-4336-8718-859a10de6b54",
"6870c5ce-464d-41b3-8799-b97b0768f884",
"139d9c55-b636-4feb-a798-39f4cf9e1726",
"4e708c19-5355-41d9-8fd7-45cba87ccf27",
"c08cc910-304b-44c9-8ea8-a12bada124f5",
"e7600b86-4c38-4e66-b1b1-fb2fd7ebf73c",
"5861e772-9c19-e111-4789-005056c00008",
"17ee0029-939b-e211-0084-8c89a56499ca",
"a7e3ba44-f047-ee11-f785-000d3abff293",
"5b76bcda-9566-4131-9fa0-0f579de9c812",
"26661087-5ca8-4721-9cae-3d2ce5f06e4c",
"ee89d782-94c0-46fa-b712-b65503759cfb",
"5c092a0d-e55a-4674-8dab-785f0f2af6a3",
"85f4d1ff-6933-4121-b196-a9e463dedf32",
"4e9cce05-cafb-4724-9bd9-5b5c903d3fb8",
"f0ea9b3d-3f5e-eb11-2081-00505690226c",
"d8d05c5c-63fa-4718-9e06-9228a1afafe9",
"1d33330f-e4e1-4737-8716-c47ab5161266",
"394b1e74-5d60-e511-2681-0050562f9516",
"c3d6a2b1-021a-409a-bd74-9ddf79f84363",
"46240b02-93a5-ea11-2ca6-2c6fc9364e44",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"52811274-7b0e-4cdb-a18a-0843fd663f0c",
"7c67d904-139b-476e-9844-40aea66bf09a",
"653792bf-ee60-4c57-9d72-4f1fb51c27d0",
"958195f1-8717-458f-95e2-ab6656f68069",
"05327149-f029-40be-80cd-b99a1094e6b8",
"b025b1b3-b3b8-44ca-9404-0ab586578451",
"7a74937d-5e48-4430-8936-1b5f501cf305",
"82c0a3f1-1f37-47e6-9d95-2d807750cbbc",
"b2996b4d-86e8-4df2-9e8e-8d3c6fc92ab2",
"303636d7-cfad-4911-be1e-cd9ff2c98542",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"ae9447c6-0901-4cdf-9c39-52576a027406",
"fe57e004-243a-4a9f-bc5b-64794d57cd2b",
"3556a4a5-1419-4edd-8412-86630a5530e7",
"9b6f7c35-076b-475b-abd2-a990ebe7345f",
"f122e1bd-a5d7-4f18-8f65-dbfe65a4360c",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"54f6d721-d0a4-e611-e881-0050562f9516",
"0e0e5d31-ae18-477f-9514-23d23e3009b8",
"7ef2fce4-96a5-ea11-2ca6-2c6fc9364e44",
"82b5d230-9c71-4276-b712-80c33149f5c6",
"f4a559ba-e3a3-4489-8434-a5ebe38d8f7e",
"f40a9704-eba2-4d4a-b93b-29eab11fb1b0",
"6de22308-4704-4c94-89f2-484a5cec8aa0",
"8021fb31-1a36-47cd-b869-62effa8b71ae",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"3fcab71f-db57-4d2f-aec1-e76b850b2372",
"74f41b6f-e21b-4df4-8663-11366be2f3e9",
"27988b9a-56b7-4135-b6cd-32b685cd248d",
"2a749ac4-a143-4ed6-9553-ad185525dbef",
"33b82336-21fb-47bd-b219-9903ed15efc2"
],
"IsIncomplete": false,
"IsWritable": false
},
"SysObjectId": {
"ColumnName": "SysObjectId",
"Values": [
"95f1fe4d-e86e-4f9f-85cc-89747d44273f",
"4fc190b5-8d9b-455e-ad61-8183f1c18a86",
"bcdc65fa-1466-4dd4-9ee4-00dff432f503",
"9ec89038-51ef-4e85-a43b-28c54cb803de",
"ac0d2834-e731-44c1-b8fd-7e88e8689427",
"9e86523e-8107-430e-a225-e4334d0db3b9",
"f471ecfd-e89f-4de6-b706-207aeb951ccf",
"99fe9328-4b5c-4520-935d-5004f31ac396",
"68151e08-959e-4215-a9cd-02cf0738451c",
"4029889e-64ce-cd35-c695-08db02c51bfe",
"a825e856-b789-4030-bd1a-a11cecd7bbbe",
"f1e57c0f-d7da-4fd6-b1ea-781baa12f0b5",
"460d1320-7bdc-4283-8631-bf0a0e51633f",
"d0c53f6d-54b0-413d-8c7a-dae6d4735c83",
"77fd9d09-b8fe-4fcb-a420-61edcc6dee7b",
"54827c82-da2f-45c1-86af-0f8b3c3f3588",
"c63cb394-090b-4708-8faa-91a0562164b9",
"474bae50-e464-450d-a933-5e361f19a1c4",
"24615680-3dc1-cecf-e622-08d807bf677d",
"994aad52-24a2-4cbe-82af-a228c5a7d108",
"8a02482e-6ee4-c1dd-9d42-08d8017e9781",
"84e19468-8d24-ce62-b2c7-08d807bf8e4c",
"3322155e-5992-4f87-a6ff-2d2fa598c7fc",
"6fa18a91-73f0-c88b-6460-08d85017907e",
"2d0209de-1aa7-4d9c-be9d-0260e61f47ed",
"71001502-5eb3-4f17-a82e-87c6486ffe13",
"282c788d-3678-c24a-90d2-08d850160393",
"83e78848-2e09-49f7-8620-541ec2d7f81c",
"7f7d71cc-c6f4-c4ef-665f-08d807bfa037",
"f1f99037-b978-c502-8871-08d82e284a96",
"bff0be05-411d-4f34-a763-5a085842bfba",
"f593ac72-becf-c147-8512-08d5e0576230",
"aac38014-e147-e511-0681-0050562f9516",
"aa1e2465-4b33-4c08-90f3-4ad0398ee6d5",
"9da03209-520c-4645-80fb-d92e7667b629",
"ac794830-0a29-4440-9929-3be9de13857f",
"57a76791-fa99-c94e-5cab-08da5b5bb033",
"f827d84c-364d-c603-91aa-08d945d7822a",
"2b92c49c-fba2-4935-9e56-7464f165f538",
"b825e856-b789-4030-bd1a-a11cecd7bbbe",
"4fa1b861-fbbe-4ba0-aa07-79f8231e137b",
"8c5213ed-cc2c-44db-8e94-261ac6889d16",
"9b8b8713-b67e-46ee-8824-3ae9bb7b5661",
"85004e7d-cc1b-4466-9efa-94c47dda3e2b",
"93612578-4e1f-4b9c-862a-11faf216b2a3",
"80fef6bf-8af7-4312-9ccf-0bac3b6f22bd",
"3d4082b9-1655-c951-cfd4-08d945d77629",
"db86fc24-5529-ce77-4178-08d5e0576ac3",
"5a8abb2f-5520-cccf-598a-08db8f61b225",
"770d895f-cf26-c0bc-35c0-08db926cb92d",
"31606439-93e2-41a2-b348-e2107950801e",
"b4ed335d-9c1d-4cf7-afe8-69a99f8b5804",
"0258ca0c-7749-4746-9877-c979c817fcfd",
"3719b13a-f578-4b74-addf-ecbc219cadb8",
"b8dde1d8-37f6-4950-b3fa-f5c73d89890a",
"3cb2fd90-1f64-47b1-9736-fe5ee44f89c1",
"c808a2ac-b3bf-47a9-8795-25a3d1bb1a3d",
"3cc9d00f-9780-4757-b797-4f64f1ae98c0",
"2e7077c0-3d21-4f08-a562-d49e2efc08cc",
"8e977585-cf06-4b1f-aae3-502a4ea75726",
"27cc9771-dc56-48ad-bc39-02df5939b3f4",
"5261e772-9c19-e111-4789-005056c00008",
"11ee0029-939b-e211-0084-8c89a56499ca",
"3c0f33fa-ac65-c402-d8f4-08dbaa1400f7",
"4be9b8d7-4dc2-4957-b777-6471c1a0c750",
"d45c883f-513b-4373-bb84-719e96d61578",
"33837d5f-7a85-411e-8a01-9ff47d301b00",
"83a43358-2879-4925-b674-04d697c488d0",
"472d4ddc-c761-413e-bebf-491ebdbe9641",
"7077baa4-dfae-4d3a-aaa4-253c7a5f4bff",
"e20c43e9-8da2-c67f-4744-08d8c0631f96",
"9af6450f-3741-4697-bd46-3038db8cb21a",
"46a96916-1e80-4850-8407-b1c872b0ca30",
"334b1e74-5d60-e511-2681-0050562f9516",
"fd9f0cee-b410-4ff1-8b2b-873341f4fe1c",
"c3a3c4b6-c98b-cfb6-b5cb-08d807b4a882",
"24c76522-8edb-4300-8cf4-7cf082ded2bf",
"605449d5-7302-40d5-9607-60032bad49f2",
"b87c4094-6aff-4a42-94bc-a6221d09d942",
"f4419dc7-bd11-4e86-bd3e-4ff6ccdedb09",
"4f005c1b-19de-4373-aad2-aef650c7ea97",
"cb6b8159-c971-47f6-8bdf-7e1a09835dce",
"64dc84b3-ebe4-4bee-85d3-8f9eea5a217a",
"d2c5ed0e-154e-445e-a573-d754c03c5212",
"cb28c887-46e6-40b9-a471-83b0acfe96f6",
"c2335069-0b6f-4823-bfb2-9401bdafa581",
"d4360c64-04ed-4354-a58d-fce0c0dcaaaa",
"f8f00236-c8b1-4121-847a-7dd233438274",
"a7b21eb7-57b9-4931-95b9-32de27d8c42f",
"0e567893-8d4f-422d-92d1-99fa5aeb6008",
"4bf3458d-1dc0-4e67-84e7-3d06330216d6",
"46d853b2-6cb3-45a4-b439-8c031822198d",
"ec635c81-5ba9-426b-9c33-0b6f4736e3b4",
"964419fa-3840-43d9-afa4-151d0d8972e8",
"d6102937-a051-4e2c-8c29-ea91b38caeb7",
"9ff59754-32be-4b12-9aff-d1771d1b66dc",
"4ef6d721-d0a4-e611-e881-0050562f9516",
"69a3f348-f159-440a-980e-0675d035f2c0",
"ef91cb83-867f-c95b-3795-08d807b8d450",
"91544dfb-5afe-4435-97e6-8c1f24e6bdab",
"91a6b9d9-7f51-49b9-a309-e9d4f047e7dd",
"05d1e707-80fc-4f5c-a3cb-d35a7d69ec27",
"0b8c25ee-d951-4be4-a4a1-6c95754e26d0",
"e5d7e59f-fd42-49c9-bee2-a92bdb4fadf9",
"f7d51b56-c3f5-4259-a7ad-2c0fac6cc653",
"dbbad401-7602-4732-ba2b-05a328a4e059",
"6b903456-94b2-48d3-8795-8f6620b48d82",
"e905c92e-e42a-4de8-ae1e-624bc2103d65",
"8a058953-ed70-41cc-aa85-dd6e37a67caa",
"56b2c18c-e2c3-4900-a4c3-312235a97ad2"
],
"IsIncomplete": false,
"IsWritable": false
},
"SysName": {
"ColumnName": "SysName",
"Values": [
"ACT00063",
"ACT00053",
"ACT00055",
"ACT00007",
"ACT00085",
"ACT00083",
"ACT00097",
"ACT00012",
"ACT00058",
"ACT00112",
"ACT00028",
"ACT00047",
"ACT00030",
"ACT00045",
"ACT00080",
"ACT00086",
"ACT00092",
"ACT00049",
"ACT00080",
"ACT00041",
"ACT00095",
"ACT00081",
"ACT00091",
"ACT00102",
"ACT00038",
"ACT00022",
"ACT00101",
"ACT00097",
"ACT00082",
"ACT00078",
"ACT00040",
"ACT00093",
"ACT00078",
"ACT00088",
"ACT00034",
"ACT00044",
"ACT00107",
"ACT00105",
"ACT00019",
"ACT00092",
"ACT00065",
"ACT00069",
"ACT00090",
"ACT00085",
"ACT00073",
"ACT00002",
"ACT00104",
"ACT00094",
"ACT00109",
"ACT00110",
"ACT00078",
"ACT00077",
"ACT00094",
"ACT00093",
"ACT00039",
"ACT00056",
"ACT00059",
"ACT00062",
"ACT00052",
"ACT00013",
"ACT00064",
"ACT00099",
"ACT00077",
"ACT00111",
"ACT00042",
"ACT00018",
"ACT00054",
"ACT00089",
"ACT00050",
"ACT00048",
"ACT00078",
"ACT00060",
"ACT00046",
"ACT00079",
"ACT00096",
"ACT00078",
"ACT00020",
"ACT00015",
"ACT00087",
"ACT00067",
"ACT00083",
"ACT00088",
"ACT00075",
"ACT00071",
"ACT00068",
"ACT00091",
"ACT00072",
"ACT00076",
"ACT00086",
"ACT00079",
"ACT00070",
"ACT00066",
"ACT00074",
"ACT00084",
"ACT00089",
"ACT00033",
"ACT00081",
"ACT00082",
"ACT00079",
"ACT00090",
"ACT00081",
"ACT00087",
"ACT00061",
"ACT00057",
"ACT00008",
"ACT00043",
"ACT00082",
"ACT00095",
"ACT00084",
"ACT00051"
],
"IsIncomplete": false,
"IsWritable": false
},
"Name": {
"ColumnName": "Name",
"Values": [
"Ablage",
"Abschluss",
"Abschluss",
"Active Directory",
"Aktualisierte Software Vorlage",
"Aktualisiertes Lizenzmodell",
"Altiris Client-Installation",
"\u00c4nderungen",
"Angebot",
"Assetleihe",
"Asset-Verwaltung",
"Audit",
"Aufgaben",
"Ausschreibung",
"Bedarfe",
"Bereitstellung",
"Best\u00e4tigung",
"Bestellung",
"Client Lifecycle Management",
"Controlling",
"CRM",
"Data Protection",
"Duplikate",
"EDR",
"Einkauf",
"Empirum Client Installationen",
"Endger\u00e4te",
"Enteo [Centennial] Client Installation",
"Enterprise Mobility Management",
"Enterprise Queue",
"Erf\u00fcllung",
"Facility Management",
"Facility Management",
"Fehlbestand",
"Fehlbestand",
"Finanzbuchhaltung",
"Fleet Management",
"FM",
"Genehmigungen",
"Gesch\u00e4ftsbeziehungen",
"Hardware",
"Hardware",
"Hardware",
"Hardware",
"Hardware",
"Hardwareauslieferung",
"HR",
"Human Resources",
"Human Resources",
"Human Resources",
"Installationen",
"Inventarisierung",
"Katalog Artikelabweichung",
"Katalog Mehrfacheintrag",
"Konformit\u00e4t",
"Korrespondenz",
"Kostenplanung",
"K\u00fcndigung",
"Lieferung",
"Lizenzmanagement",
"Mahnwesen",
"MDM Ger\u00e4teanmeldung",
"Mobile Applikationen",
"Office",
"Organisation",
"Probleme",
"Prognose",
"Pr\u00fcfung",
"Rechnungsstellung",
"Rechtspr\u00fcfung",
"Release Management",
"Revision",
"ROI Pr\u00fcfung",
"SAP",
"SCCM Client Installationen",
"Secure Unified Endpoint Management",
"Service Catalog",
"Service Desk",
"Serviceanfragen",
"Sicherheit",
"Sicherheit",
"Sicherheit",
"Sicherheit",
"Sicherheit",
"Software",
"Software",
"Software",
"Software",
"Software",
"Softwareprodukte",
"Sonstige",
"Sonstige",
"Sonstige",
"Sonstige",
"Sonstige",
"St\u00f6rungen",
"Telefonie",
"Tickets",
"Unified Endpoint Management",
"Validierung",
"Validierung",
"Verf\u00fcgbare Software Vorlage",
"Verhandlung",
"Verl\u00e4ngerung",
"Vertragsverwaltung",
"Vertrieb",
"Wartung",
"Wegfall Lizenzmodell",
"Wegfall Software Vorlage",
"Zahlung"
],
"IsIncomplete": false,
"IsWritable": false
},
"parentValue": {
"ColumnName": "parentValue",
"Values": [
"5b76bcda-9566-4131-9fa0-0f579de9c812",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
"3fcab71f-db57-4d2f-aec1-e76b850b2372",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"3fcab71f-db57-4d2f-aec1-e76b850b2372",
"d457c1f4-e4bd-4753-9e02-c8e645d5e342",
null,
"c1e4f87f-a8ab-4acc-a7e8-3e9a78c8f3f9",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
"c08cc910-304b-44c9-8ea8-a12bada124f5",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"f5f3e9d2-2e63-4fc4-a00c-0e8d12750a70",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
"7ef2fce4-96a5-ea11-2ca6-2c6fc9364e44",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"82c0a3f1-1f37-47e6-9d95-2d807750cbbc",
"46240b02-93a5-ea11-2ca6-2c6fc9364e44",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"05327149-f029-40be-80cd-b99a1094e6b8",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"05327149-f029-40be-80cd-b99a1094e6b8",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"7ef2fce4-96a5-ea11-2ca6-2c6fc9364e44",
null,
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"d457c1f4-e4bd-4753-9e02-c8e645d5e342",
"4d51cfdd-ccaa-49a0-89cf-b16666f38de5",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"3ee839fa-05cc-ea11-fba7-0c9d921bfedc",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"0e0e5d31-ae18-477f-9514-23d23e3009b8",
"26661087-5ca8-4721-9cae-3d2ce5f06e4c",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"3ee839fa-05cc-ea11-fba7-0c9d921bfedc",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"c08cc910-304b-44c9-8ea8-a12bada124f5",
"c08cc910-304b-44c9-8ea8-a12bada124f5",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"5b76bcda-9566-4131-9fa0-0f579de9c812",
"4d51cfdd-ccaa-49a0-89cf-b16666f38de5",
"3838d26f-bc49-4065-a29f-b8965b199946",
"3838d26f-bc49-4065-a29f-b8965b199946",
null,
"3fcab71f-db57-4d2f-aec1-e76b850b2372",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
null,
"82c0a3f1-1f37-47e6-9d95-2d807750cbbc",
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"4d51cfdd-ccaa-49a0-89cf-b16666f38de5",
"f5f3e9d2-2e63-4fc4-a00c-0e8d12750a70",
"3fcab71f-db57-4d2f-aec1-e76b850b2372",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
null,
"c1e4f87f-a8ab-4acc-a7e8-3e9a78c8f3f9",
"4d51cfdd-ccaa-49a0-89cf-b16666f38de5",
"82c0a3f1-1f37-47e6-9d95-2d807750cbbc",
"8fe597cd-9fbf-4552-a061-ca15defb1291",
null,
null,
null,
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"0e0e5d31-ae18-477f-9514-23d23e3009b8",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"26661087-5ca8-4721-9cae-3d2ce5f06e4c",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"26661087-5ca8-4721-9cae-3d2ce5f06e4c",
"0e0e5d31-ae18-477f-9514-23d23e3009b8",
"c08cc910-304b-44c9-8ea8-a12bada124f5",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"26661087-5ca8-4721-9cae-3d2ce5f06e4c",
"0e0e5d31-ae18-477f-9514-23d23e3009b8",
"1d1608c0-c32e-44ec-85af-6d4846752877",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"d0f04f85-458f-40bd-aeb0-e97b08b933b5",
"46240b02-93a5-ea11-2ca6-2c6fc9364e44",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"d457c1f4-e4bd-4753-9e02-c8e645d5e342",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"d4eceb45-34ef-4ffc-905c-7ef91a8ab1a6",
"3838d26f-bc49-4065-a29f-b8965b199946",
null,
"ded1c666-cb2a-45a7-8554-96f1244e3b32",
"d1656ef7-dda6-4227-b8bb-1da5f35eed32",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"f671cdfd-80ad-4d71-afbb-a70fbda242ff",
"3838d26f-bc49-4065-a29f-b8965b199946"
],
"IsIncomplete": false,
"IsWritable": false
},
"parent": {
"ColumnName": "parent",
"Values": [
"Organisation",
"Einkauf",
"Vertrieb",
"Service Catalog",
"Softwareprodukte",
"Softwareprodukte",
"Service Catalog",
"Service Desk",
"Vertrieb",
"Asset-Verwaltung",
null,
"Konformit\u00e4t",
"Service Desk",
"Einkauf",
"Lizenzmanagement",
"Inventarisierung",
"Bedarfe",
"Einkauf",
"Unified Endpoint Management",
"Vertragsverwaltung",
"Software",
"Secure Unified Endpoint Management",
"Softwareprodukte",
"Sicherheit",
"Vertragsverwaltung",
"Service Catalog",
"Sicherheit",
"Service Catalog",
"Unified Endpoint Management",
null,
"Vertragsverwaltung",
"Service Catalog",
"St\u00f6rungen",
"Inventarisierung",
"Asset-Verwaltung",
"Controlling",
"St\u00f6rungen",
"Enterprise Queue",
"Service Catalog",
"Vertragsverwaltung",
"\u00c4nderungen",
"St\u00f6rungen",
"Serviceanfragen",
"Tickets",
"Probleme",
"Service Catalog",
"Enterprise Queue",
"Service Catalog",
"St\u00f6rungen",
"Serviceanfragen",
"Lizenzmanagement",
"Lizenzmanagement",
"Inventarisierung",
"Inventarisierung",
"Vertragsverwaltung",
"Organisation",
"Controlling",
"Erf\u00fcllung",
"Erf\u00fcllung",
null,
"Vertrieb",
"Service Catalog",
null,
"Software",
"Vertragsverwaltung",
"Service Desk",
"Controlling",
"Bedarfe",
"Vertrieb",
"Einkauf",
null,
"Konformit\u00e4t",
"Controlling",
"Software",
"Service Catalog",
null,
null,
null,
"Service Desk",
"\u00c4nderungen",
"Tickets",
"Serviceanfragen",
"Probleme",
"St\u00f6rungen",
"\u00c4nderungen",
"Serviceanfragen",
"St\u00f6rungen",
"Probleme",
"Tickets",
"Lizenzmanagement",
"St\u00f6rungen",
"\u00c4nderungen",
"Probleme",
"Tickets",
"Serviceanfragen",
"Service Desk",
"St\u00f6rungen",
"Service Desk",
"Secure Unified Endpoint Management",
"Inventarisierung",
"Asset-Verwaltung",
"Softwareprodukte",
"Einkauf",
"Erf\u00fcllung",
null,
"Vertragsverwaltung",
"Inventarisierung",
"Softwareprodukte",
"Softwareprodukte",
"Erf\u00fcllung"
],
"IsIncomplete": false,
"IsWritable": false
}
}
}

View File

@@ -77,21 +77,21 @@
"Name": {
"ColumnName": "Name",
"Values": [
"Anmeldung nicht möglich",
"Anmeldung nicht m\u00f6glich",
"Bildschirm bleibt schwarz",
"CRM Störung",
"CRM St\u00f6rung",
"Dateityp kann nicht gelesen werden",
"Druckerstörung",
"E-Mail-Versand nicht mehr möglich",
"F4SD Störung",
"Internetverbindung gestört",
"Druckerst\u00f6rung",
"E-Mail-Versand nicht mehr m\u00f6glich",
"F4SD St\u00f6rung",
"Internetverbindung gest\u00f6rt",
"Jalousiensteuerung defekt",
"Klimatisierungsstörung - Raumtemperatur zu hoch",
"Klimatisierungsst\u00f6rung - Raumtemperatur zu hoch",
"Lampe ist defekt",
"Netzwerklaufwerk nicht erreichbar",
"Passcode vergessen, Mobilgerät ist gesperrt",
"Passcode vergessen, Mobilger\u00e4t ist gesperrt",
"Software-Service arbeitet nicht mehr korrekt",
"Telefonstörung"
"Telefonst\u00f6rung"
],
"IsIncomplete": false,
"IsWritable": false
@@ -101,19 +101,19 @@
"Values": [
"Der Anwender kann sich nicht mehr anmelden",
"Der Bildschirm bleibt schwarz, Computer startet nicht mehr",
"CRM Störung",
"CRM St\u00f6rung",
"Ein bestimmter Dateityp kann nicht verarbeitet werden",
"Ein Drucker arbeitet nicht mehr zufriedenstellend oder ist kaputt",
"Der Versand von E-Mails ist nicht mehr möglich",
"F4SD Störung",
"Der Versand von E-Mails ist nicht mehr m\u00f6glich",
"F4SD St\u00f6rung",
"Der Anwender kommt nicht mehr ins Internet",
"Die automatischen Sonnenschutzvorrichtungen funktionieren nicht mehr",
"Die Raumklimatisierung funktioniert nicht mehr korrekt",
"Lampe ausgefallen oder schwach",
"Ein Netzwerklaufwerk kann vom Anwender nicht mehr erreicht werden",
"Das mobile Endgerät des Anwenders ist gesperrt, der Passcode vergessen",
"Das mobile Endger\u00e4t des Anwenders ist gesperrt, der Passcode vergessen",
"Ein Software-Service funktioniert nicht mehr richtig",
"Das Telefon des Anwenders ist gestört"
"Das Telefon des Anwenders ist gest\u00f6rt"
],
"IsIncomplete": false,
"IsWritable": false
@@ -184,27 +184,27 @@
"IsIncomplete": false,
"IsWritable": false
},
"Classification": {
"ColumnName": "Classification",
"Category": {
"ColumnName": "Category",
"Values": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
"9282a500-caea-49bb-944f-9d0274fcc80a",
"8ba5e53d-3b6b-425a-baba-34438845f00d",
"cbbec585-0184-4ae3-ab68-7caeb3d0e5b2",
"fd4ca144-2aca-48c4-b8b9-ce75b07ca3cb",
"70d3cb04-11ab-43cb-a769-368517ba4879",
"9d468c5c-c543-4ee5-9a23-4f9975e5c145",
"42b49002-fed3-4c9b-9532-cf351df038cf",
"f42521f8-748f-4a24-8084-27867c8ac5d0",
"4e7bafad-c49b-432a-b88e-f4bced36e5ed",
"2c6fca4b-a1a0-ed11-5a81-000c299eb325",
"d457c1f4-e4bd-4753-9e02-c8e645d5e342",
"facc2d0f-3216-4ccd-9c81-57cb29150e9e",
"5f385abf-a574-468b-a4ba-feed4fc0c76d",
"ced65ab8-d526-4518-be11-caf68b31d959",
"f5f3e9d2-2e63-4fc4-a00c-0e8d12750a70"
],
"IsIncomplete": false,
"IsWritable": false
}
}
}
}

View File

@@ -3,6 +3,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Neue Störung: VPN trennt nach wenigen Minuten",
@@ -13,8 +14,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Ticketsystem",
"Classification": "Incident",
"Category": "9282a500-caea-49bb-944f-9d0274fcc80a",
"Description": "Der Benutzer meldet, dass die VPN-Verbindung spätestens nach zwei Minuten getrennt wird. Eine stabile Remote-Arbeit ist aktuell nicht möglich.",
"DescriptionHtml": "<p>Der Benutzer meldet, dass die VPN-Verbindung spätestens nach zwei Minuten getrennt wird. Eine stabile Remote-Arbeit ist aktuell nicht möglich.</p>",
"Priority": 2,
@@ -31,6 +31,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Teams-Meldungen kommen verzögert an",
@@ -41,8 +42,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Kommunikation",
"Classification": "Incident",
"Category": "8ba5e53d-3b6b-425a-baba-34438845f00d",
"Description": "Teams-Nachrichten und Meetings starten mit deutlicher Verzögerung. Laut Rückmeldung wirkt der Client zeitweise eingefroren.",
"DescriptionHtml": "<p>Teams-Nachrichten und Meetings starten mit deutlicher Verzögerung. Laut Rückmeldung wirkt der Client zeitweise eingefroren.</p>",
"Priority": 2,
@@ -59,6 +59,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Anfrage: Gerät startet nicht zuverlässig",
@@ -69,8 +70,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Hardware",
"Classification": "Request",
"Category": "cbbec585-0184-4ae3-ab68-7caeb3d0e5b2",
"Description": "Das bereitgestellte Notebook startet nur unregelmäßig. An manchen Tagen benötigt es mehrere Versuche bis zur Anmeldung.",
"DescriptionHtml": "<p>Das bereitgestellte Notebook startet nur unregelmäßig. An manchen Tagen benötigt es mehrere Versuche bis zur Anmeldung.</p>",
"Priority": 3,
@@ -87,6 +87,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Bitte um Rückmeldung: Ticketsystem reagiert langsam",
@@ -97,8 +98,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Service",
"Classification": "Incident",
"Category": "fd4ca144-2aca-48c4-b8b9-ce75b07ca3cb",
"Description": "Das Ticketsystem reagiert auffallend träge. Ansichten benötigen bis zu 30 Sekunden zum Laden.",
"DescriptionHtml": "<p>Das Ticketsystem reagiert auffallend träge. Ansichten benötigen bis zu 30 Sekunden zum Laden.</p>",
"Priority": 1,
@@ -112,12 +112,10 @@
]
}
},
/* --- Ab hier: 5 neue Klassiker --- */
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Passwort-Reset für AD-Benutzer erforderlich",
@@ -128,8 +126,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Account",
"Classification": "Request",
"Category": "70d3cb04-11ab-43cb-a769-368517ba4879",
"Description": "Der Benutzer hat sein Passwort vergessen und benötigt einen Reset sowie die Aktualisierung am Diensthandy (Outlook/Teams).",
"DescriptionHtml": "<p>Der Benutzer hat sein Passwort vergessen und benötigt einen Reset sowie die Aktualisierung am Diensthandy (Outlook/Teams).</p>",
"Priority": 3,
@@ -146,6 +143,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Netzwerkdrucker druckt nur leere Seiten",
@@ -156,8 +154,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "PRN-3OG-HP-LJ",
"Category": "Demo / Drucker",
"Classification": "Incident",
"Category": "9d468c5c-c543-4ee5-9a23-4f9975e5c145",
"Description": "Beim Druck auf den HP-LaserJet im 3. OG kommen nur leere Seiten heraus. Testseite aus Windows zeigt dasselbe Verhalten.",
"DescriptionHtml": "<p>Beim Druck auf den HP-LaserJet im 3. OG kommen nur leere Seiten heraus. Testseite aus Windows zeigt dasselbe Verhalten.</p>",
"Priority": 2,
@@ -174,6 +171,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Outlook: Speicherlimit erreicht Postfach voll",
@@ -184,8 +182,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00015",
"Category": "Demo / Mail",
"Classification": "Incident",
"Category": "b05a28a4-a1ae-4cb8-a30d-08fe6873b467",
"Description": "Der Benutzer kann keine E-Mails mehr senden oder empfangen. Outlook meldet, dass das Postfachkontingent überschritten ist.",
"DescriptionHtml": "<p>Der Benutzer kann keine E-Mails mehr senden oder empfangen. Outlook meldet, dass das Postfachkontingent überschritten ist.</p>",
"Priority": 2,
@@ -202,6 +199,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Softwareanfrage: Microsoft Visio Standard",
@@ -212,8 +210,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00016",
"Category": "Demo / Software",
"Classification": "Request",
"Category": "f42521f8-748f-4a24-8084-27867c8ac5d0",
"Description": "Benötigt Visio Standard für Prozessdiagramme. Bitte Installation via Softwareverteilung und Lizenzzuweisung im M365 Admin Center.",
"DescriptionHtml": "<p>Benötigt Visio Standard für Prozessdiagramme. Bitte Installation via Softwareverteilung und Lizenzzuweisung im M365 Admin Center.</p>",
"Priority": 3,
@@ -230,6 +227,7 @@
{
"TileKey": "TicketsNew",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayNamePrefix": "TCK",
"Summary": "Konto gesperrt nach mehrfachen Fehlversuchen",
@@ -240,8 +238,7 @@
"Detail": {
"AffectedUser": "Ticket, Timo",
"Asset": "C4-NB00016",
"Category": "Demo / Account",
"Classification": "Incident",
"Category": "4e7bafad-c49b-432a-b88e-f4bced36e5ed",
"Description": "Nach mehreren falschen Passworteingaben ist das AD-Konto gesperrt. Benutzer kann sich weder am Notebook noch an M365 anmelden.",
"DescriptionHtml": "<p>Nach mehreren falschen Passworteingaben ist das AD-Konto gesperrt. Benutzer kann sich weder am Notebook noch an M365 anmelden.</p>",
"Priority": 1,
@@ -256,5 +253,122 @@
}
}
],
"Tickets": []
"Tickets": [
{
"TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6",
"UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2",
"TileKey": "UnassignedTickets",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"DisplayName": "TCK00414",
"Summary": "Pool Notebook fuer Schulungsteilnehmer fehlt",
"StatusId": "New",
"UserDisplayName": "Virtual, Vera",
"UserAccount": "VV004",
"UserDomain": "CONTOSO",
"Detail": {
"AffectedUser": "Virtual, Vera",
"Asset": "C4-NB02014",
"Category": "42b49002-fed3-4c9b-9532-cf351df038cf",
"Description": "Ein Pool-Notebook fuer die morgige Schulung ist nicht auffindbar. Das Ticket wurde noch keinem Bearbeiter zugewiesen.",
"DescriptionHtml": "<p>Ein Pool-Notebook fuer die morgige Schulung ist nicht auffindbar. Das Ticket wurde noch keinem Bearbeiter zugewiesen.</p>",
"Priority": 2,
"Journal": [
{
"Header": "Ticket erstellt",
"Description": "Demodatensatz fuer Ticketuebersicht (Eingang).",
"DescriptionHtml": "<p>Demodatensatz fuer Ticketuebersicht (Eingang).</p>",
"IsVisibleForUser": true
}
]
}
},
{
"TicketId": "ebe8818e-b197-411e-b56e-40b77b623ae2",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"TileKey": "UnassignedTickets",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"DisplayName": "TCK00415",
"Summary": "Etikettendrucker im Lager meldet Papierstau",
"StatusId": "New",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
"UserDomain": "CONTOSO",
"Detail": {
"AffectedUser": "Anwender, Peter",
"Asset": "PRN-LAGER-03",
"Category": "42b49002-fed3-4c9b-9532-cf351df038cf",
"Description": "Der Etikettendrucker im Lager zeigt permanent Papierstau, obwohl kein Papier klemmt. Ticket ist neu und noch unzugewiesen.",
"DescriptionHtml": "<p>Der Etikettendrucker im Lager zeigt permanent Papierstau, obwohl kein Papier klemmt. Ticket ist neu und noch unzugewiesen.</p>",
"Priority": 2,
"Journal": [
{
"Header": "Ticket erstellt",
"Description": "Demodatensatz fuer Ticketuebersicht (Eingang).",
"DescriptionHtml": "<p>Demodatensatz fuer Ticketuebersicht (Eingang).</p>",
"IsVisibleForUser": true
}
]
}
},
{
"TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"TileKey": "UnassignedTicketsCritical",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"DisplayName": "TCK00416",
"Summary": "WLAN Controller im Werk startet zyklisch neu",
"StatusId": "InProgress",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
"UserDomain": "CONTOSO",
"Detail": {
"AffectedUser": "Seifert, Dominik",
"Asset": "NET-WLC-01",
"Category": "42b49002-fed3-4c9b-9532-cf351df038cf",
"Description": "Der WLAN-Controller im Werk rebootet im 5-Minuten-Takt. Das Ticket ist kritisch markiert und noch nicht personell zugewiesen.",
"DescriptionHtml": "<p>Der WLAN-Controller im Werk rebootet im 5-Minuten-Takt. Das Ticket ist kritisch markiert und noch nicht personell zugewiesen.</p>",
"Priority": 1,
"Journal": [
{
"Header": "Stoerung eingegangen",
"Description": "Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).",
"DescriptionHtml": "<p>Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).</p>",
"IsVisibleForUser": true
}
]
}
},
{
"TicketId": "d427dc61-9842-4464-b37a-612878d3de0f",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"TileKey": "UnassignedTicketsCritical",
"UseRoleScope": false,
"ActivityType": "SPSActivityTypeTicket",
"DisplayName": "TCK00417",
"Summary": "SAP Buchungsjob bricht nachts wiederholt ab",
"StatusId": "InProgress",
"UserDisplayName": "Boss, Bernd",
"UserAccount": "BB003",
"UserDomain": "CONTOSO",
"Detail": {
"AffectedUser": "Boss, Bernd",
"Asset": "SAP-PRD-APP02",
"Category": "42b49002-fed3-4c9b-9532-cf351df038cf",
"Description": "Naechtlicher Buchungsjob endet mit Fehlercode. Ticket ist kritisch und liegt im Eingang zur Erstzuweisung.",
"DescriptionHtml": "<p>Naechtlicher Buchungsjob endet mit Fehlercode. Ticket ist kritisch und liegt im Eingang zur Erstzuweisung.</p>",
"Priority": 1,
"Journal": [
{
"Header": "Stoerung eingegangen",
"Description": "Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).",
"DescriptionHtml": "<p>Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).</p>",
"IsVisibleForUser": true
}
]
}
}
]
}

View File

@@ -5,6 +5,7 @@
"TicketId": "2e9cb83d-ecb7-c93b-e8e4-08daaa97265f",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00186",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Mein OneDrive synchronisiert nicht mehr",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
@@ -17,6 +18,7 @@
"TicketId": "bb2e4a9d-2c1e-4b32-8f75-6e7c9f99f2d4",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00761",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "VPN-Verbindung bricht nach wenigen Minuten ab",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
@@ -27,6 +29,7 @@
"TicketId": "d63e5ea1-0785-4998-82ad-9a9e5a0f8c37",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00765",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Teams-Benachrichtigungen kommen verzögert an",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
@@ -37,6 +40,7 @@
"TicketId": "f7771fde-33ba-421a-8d9b-cdf468e7541c",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "TCK00403",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Neuer Monitor fuer Hotline Arbeitsplatz",
"UserDisplayName": "Busch, Andrea",
"UserAccount": "AB014",
@@ -47,6 +51,7 @@
"TicketId": "6294eec7-fb80-42f3-8ce8-7f7982ae200c",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "TCK00404",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Monitor flackert seit Firmware Update",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -61,6 +66,7 @@
"TicketId": "75e08a29-4103-41d6-962c-009c3342bc46",
"UserId": "6180aa17-ba2d-455a-bf2f-ec4a075c2d64",
"DisplayName": "TCK00406",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "CAD Software startet nach Update nicht mehr",
"UserDisplayName": "Kohl, Carlos",
"UserAccount": "CK102",
@@ -73,7 +79,8 @@
"TicketId": "2e9cb83d-ecb7-c93b-e8e4-08daaa97265f",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00405",
"Summary": "OneDrive Synchronisation bleibt haengen",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Mein OneDrive synchronisiert nicht mehr",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
"UserDomain": "CONTOSO",
@@ -83,6 +90,7 @@
"TicketId": "ff62a3e2-5004-4a8c-b71c-7ebb1877d1a4",
"UserId": "0fad5e21-5a29-44c6-b532-46f862ea8694",
"DisplayName": "TCK00407",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Netzlaufwerk Projekt X nicht erreichbar",
"UserDisplayName": "Hanova, Hans",
"UserAccount": "HH101",
@@ -97,6 +105,7 @@
"TicketId": "1507691c-6d47-4ae3-83b3-ef483d84a246",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00408",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "VPN Konzentrator in Aussenstelle offline",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -107,6 +116,7 @@
"TicketId": "5c6d981e-9e67-4fde-b249-8c6288d325a7",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "TCK00409",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "SAP Produktionsauftrag bricht ab",
"UserDisplayName": "Boss, Bernd",
"UserAccount": "BB003",
@@ -119,6 +129,7 @@
"TicketId": "1507691c-6d47-4ae3-83b3-ef483d84a246",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00408",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "VPN Konzentrator in Aussenstelle offline",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -129,6 +140,7 @@
"TicketId": "9b7710d4-72da-4b2a-9d0c-be02575d2c52",
"UserId": "a2c35ad1-7cc7-4b2b-9aa5-d03fdaecd155",
"DisplayName": "TCK00410",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "WLAN im Lager faellt minutenweise aus",
"UserDisplayName": "Kiefer, Maximilian",
"UserAccount": "MK009",
@@ -139,6 +151,7 @@
"TicketId": "5c6d981e-9e67-4fde-b249-8c6288d325a7",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "TCK00409",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "SAP Produktionsauftrag bricht ab",
"UserDisplayName": "Boss, Bernd",
"UserAccount": "BB003",
@@ -153,7 +166,8 @@
"TicketId": "de403992-98cb-4476-9e04-d645ab22e6de",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00411",
"Summary": "Rueckfrage zur Passwort Ruecksetzung beantworten",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Passwort muss zur\u00fcckgesetzt werden",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
"UserDomain": "CONTOSO",
@@ -163,6 +177,7 @@
"TicketId": "7c29dd33-1247-453c-9db6-f7a59107d276",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "TCK00412",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Techniker bittet um Rueckmeldung zum Notebook",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -175,7 +190,8 @@
"TicketId": "de403992-98cb-4476-9e04-d645ab22e6de",
"UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a",
"DisplayName": "TCK00411",
"Summary": "Rueckfrage zur Passwort Ruecksetzung beantworten",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Passwort muss zur\u00fcckgesetzt werden",
"UserDisplayName": "Ticket, Timo",
"UserAccount": "TT007",
"UserDomain": "CONTOSO",
@@ -185,6 +201,7 @@
"TicketId": "b207822d-7e1c-42a7-b8c9-4246f711dd18",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00413",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Wartungsfenster fuer Firewall verschieben",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -199,6 +216,7 @@
"TicketId": "e0ba7c81-f9b1-4e99-a4d6-efecc5e4312e",
"UserId": "f69dd1a9-591f-4004-b950-264238663bf0",
"DisplayName": "INC00401",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Teams Telefonie ist fuer Standort Sued offline",
"UserDisplayName": "Ottmann, Thomas",
"UserAccount": "TO011",
@@ -207,8 +225,9 @@
},
{
"TicketId": "a8deb50d-9f15-4371-9ebc-a28791f27d5c",
"UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92",
"UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2",
"DisplayName": "INC00402",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "SharePoint Bereich Vertrieb laedt extrem langsam",
"UserDisplayName": "Virtual, Vera",
"UserAccount": "VV004",
@@ -221,6 +240,7 @@
"TicketId": "fe15284f-f553-4434-8b59-7d8b9f481bf7",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "INC00403",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Firewall Cluster meldet Sync Fehler",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -231,6 +251,7 @@
"TicketId": "9cdddacf-9395-476b-811a-09c5f1491d4b",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "INC00404",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "CRM Anmeldung liefert Timeout fuer Kundencenter",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -245,6 +266,7 @@
"TicketId": "7e852bb9-420b-4caa-b79a-9178d793fc06",
"UserId": "a2c35ad1-7cc7-4b2b-9aa5-d03fdaecd155",
"DisplayName": "INC00405",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Windows Rollout haengt auf mehreren Clients",
"UserDisplayName": "Kiefer, Maximilian",
"UserAccount": "MK009",
@@ -255,6 +277,7 @@
"TicketId": "3c3c70cf-5c60-4ecc-9313-b5f9c1968fc7",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "INC00406",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Remotedesktop Sitzung trennt nach wenigen Minuten",
"UserDisplayName": "Busch, Andrea",
"UserAccount": "AB014",
@@ -267,6 +290,7 @@
"TicketId": "486df93d-15b6-41d4-b902-2c1e1838c74b",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "INC00407",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Firewall Cluster meldet weiterhin Sync Fehler",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -277,6 +301,7 @@
"TicketId": "86da28b0-013b-4542-bcff-175044d5bb02",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "INC00408",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Produktionslinie meldet keine Sensordaten",
"UserDisplayName": "Zufall, Rainer",
"UserAccount": "RZ011",
@@ -287,6 +312,7 @@
"TicketId": "a1cf6635-a5c4-4401-b4f0-60b9c65b4d75",
"UserId": "0fad5e21-5a29-44c6-b532-46f862ea8694",
"DisplayName": "INC00409",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Exchange Transportdienst setzt Mails in Warteschlange",
"UserDisplayName": "Hanova, Hans",
"UserAccount": "HH101",
@@ -301,6 +327,7 @@
"TicketId": "9aae7eca-39d7-441e-8b33-5fc6f34765c8",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "INC00410",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Kuehlung im Rechenzentrum U3 ausgefallen",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -313,6 +340,7 @@
"TicketId": "9aae7eca-39d7-441e-8b33-5fc6f34765c8",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "INC00410",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Kuehlung im Rechenzentrum U3 ausgefallen",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
@@ -323,6 +351,7 @@
"TicketId": "130ec52f-dac3-427d-803e-e7cf67e4a744",
"UserId": "f69dd1a9-591f-4004-b950-264238663bf0",
"DisplayName": "INC00411",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Kartenzahlung in den Filialen nicht moeglich",
"UserDisplayName": "Ottmann, Thomas",
"UserAccount": "TO011",
@@ -333,6 +362,7 @@
"TicketId": "b7d22b65-c11e-459c-ac31-5b1c08e4118d",
"UserId": "8c3ca0fb-f18c-4893-ad83-290e6e02f352",
"DisplayName": "INC00412",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Datenbank Cluster benoetigt manuellen Failover",
"UserDisplayName": "Perschmann, Paul",
"UserAccount": "PP201",
@@ -347,6 +377,7 @@
"TicketId": "d1a2c544-4f59-4f2b-875f-3621a23d4228",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "INC00413",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Backup Team hat Rueckfrage zur Sicherung",
"UserDisplayName": "Busch, Andrea",
"UserAccount": "AB014",
@@ -359,6 +390,7 @@
"TicketId": "74846c1b-9a97-420f-8bf2-91e88aa0516a",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "INC00415",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Lieferant bittet um Rueckmeldung zu Offsite Backup",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -369,6 +401,7 @@
"TicketId": "1372b3cf-5d87-4099-ab83-ec0cccf7194e",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "INC00416",
"ActivityType": "SPSActivityTypeIncident",
"Summary": "Fernwartung benoetigt Zugangsdaten zur SPS",
"UserDisplayName": "Zufall, Rainer",
"UserAccount": "RZ011",
@@ -381,8 +414,9 @@
"Personal": [
{
"TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6",
"UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92",
"UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2",
"DisplayName": "TCK00414",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Pool Notebook fuer Schulungsteilnehmer fehlt",
"UserDisplayName": "Virtual, Vera",
"UserAccount": "VV004",
@@ -393,6 +427,7 @@
"TicketId": "ebe8818e-b197-411e-b56e-40b77b623ae2",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "TCK00415",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Etikettendrucker im Lager meldet Papierstau",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -403,8 +438,9 @@
"Role": [
{
"TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6",
"UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92",
"UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2",
"DisplayName": "TCK00414",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Pool Notebook fuer Schulungsteilnehmer fehlt",
"UserDisplayName": "Virtual, Vera",
"UserAccount": "VV004",
@@ -415,6 +451,7 @@
"TicketId": "ebe8818e-b197-411e-b56e-40b77b623ae2",
"UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b",
"DisplayName": "TCK00415",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "Etikettendrucker im Lager meldet Papierstau",
"UserDisplayName": "Anwender, Peter",
"UserAccount": "PA010",
@@ -425,7 +462,8 @@
"TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00416",
"Summary": "Ueberwachung meldet sporadische Alarme",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "WLAN Controller im Werk startet zyklisch neu",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
"UserDomain": "CONTOSO",
@@ -439,7 +477,8 @@
"TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00416",
"Summary": "Ueberwachung meldet sporadische Alarme",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "WLAN Controller im Werk startet zyklisch neu",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
"UserDomain": "CONTOSO",
@@ -451,7 +490,8 @@
"TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab",
"UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec",
"DisplayName": "TCK00416",
"Summary": "Ueberwachung meldet sporadische Alarme",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "WLAN Controller im Werk startet zyklisch neu",
"UserDisplayName": "Seifert, Dominik",
"UserAccount": "DS014",
"UserDomain": "CONTOSO",
@@ -461,7 +501,8 @@
"TicketId": "d427dc61-9842-4464-b37a-612878d3de0f",
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
"DisplayName": "TCK00417",
"Summary": "Produktionsroboter steht nach Not Aus",
"ActivityType": "SPSActivityTypeTicket",
"Summary": "SAP Buchungsjob bricht nachts wiederholt ab",
"UserDisplayName": "Boss, Bernd",
"UserAccount": "BB003",
"UserDomain": "CONTOSO",
@@ -469,4 +510,4 @@
}
]
}
}
}

View File

@@ -45,12 +45,11 @@ namespace FasdCockpitCommunicationDemo
public DateTime? ClosingDate { get; set; }
public enumTicketCreationSource CreationSource { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public int Priority { get; set; }
public string Classification { get; set; } //todo: replace with enum
public string Category { get; set; } //todo: replace with tree structure
public string Solution { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public int Priority { get; set; }
public string Category { get; set; } //todo: replace with tree structure
public string Solution { get; set; }
public string SolutionHtml { get; set; }
public Dictionary<string, string> DirectLinks { get; set; }

View File

@@ -21,7 +21,6 @@ namespace FasdCockpitCommunicationDemo
public string AffectedUser { get; set; }
public string Asset { get; set; }
public string Category { get; set; }
public string Classification { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public int? Priority { get; set; }
@@ -35,6 +34,7 @@ namespace FasdCockpitCommunicationDemo
public string TileKey { get; set; } = "TicketsNew";
public bool UseRoleScope { get; set; }
public Guid? UserId { get; set; }
public string ActivityType { get; set; }
public string DisplayNamePrefix { get; set; } = "TCK";
public string Summary { get; set; }
public string StatusId { get; set; } = "New";
@@ -50,6 +50,7 @@ namespace FasdCockpitCommunicationDemo
public Guid UserId { get; set; }
public string TileKey { get; set; }
public bool UseRoleScope { get; set; }
public string ActivityType { get; set; }
public string DisplayName { get; set; }
public string Summary { get; set; }
public string StatusId { get; set; }
@@ -149,7 +150,6 @@ namespace FasdCockpitCommunicationDemo
AffectedUser = source.AffectedUser,
Asset = source.Asset,
Category = source.Category,
Classification = source.Classification,
Description = source.Description,
DescriptionHtml = source.DescriptionHtml,
Priority = source.Priority,
@@ -169,6 +169,7 @@ namespace FasdCockpitCommunicationDemo
TileKey = source.TileKey,
UseRoleScope = source.UseRoleScope,
UserId = source.UserId,
ActivityType = source.ActivityType,
DisplayNamePrefix = source.DisplayNamePrefix,
Summary = source.Summary,
StatusId = source.StatusId,
@@ -190,6 +191,7 @@ namespace FasdCockpitCommunicationDemo
UserId = source.UserId,
TileKey = source.TileKey,
UseRoleScope = source.UseRoleScope,
ActivityType = source.ActivityType,
DisplayName = source.DisplayName,
Summary = source.Summary,
StatusId = source.StatusId,

View File

@@ -2,15 +2,16 @@ using System;
namespace FasdCockpitCommunicationDemo
{
public class TicketOverviewRelationDefinition
{
public Guid TicketId { get; set; }
public Guid UserId { get; set; }
public string DisplayName { get; set; }
public string Summary { get; set; }
public string StatusId { get; set; }
public string UserDisplayName { get; set; }
public string UserAccount { get; set; }
public string UserDomain { get; set; }
public class TicketOverviewRelationDefinition
{
public Guid TicketId { get; set; }
public Guid UserId { get; set; }
public string DisplayName { get; set; }
public string ActivityType { get; set; }
public string Summary { get; set; }
public string StatusId { get; set; }
public string UserDisplayName { get; set; }
public string UserAccount { get; set; }
public string UserDomain { get; set; }
}
}

View File

@@ -506,7 +506,7 @@ namespace FasdDesktopUi
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
}
await cFasdCockpitCommunicationBase.Instance.TerminateAsync();
await cFasdCockpitCommunicationBase.Instance?.TerminateAsync();
if (notifyIcon != null)
{

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using C4IT.FASD.Base;
using C4IT.Logging;
using FasdDesktopUi.Basics;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Helper
{
internal static class TicketDeepLinkHelper
{
internal static bool TryOpenTicketRelationExternally(cF4sdApiSearchResultRelation relation)
{
try
{
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
return false;
var ticketConfig = cFasdCockpitConfig.Instance?.Global?.TicketConfiguration;
if (ticketConfig == null)
return false;
var activityType = GetActivityType(relation);
var openExternally = ShouldOpenExternally(ticketConfig, activityType);
if (!openExternally)
return false;
var url = BuildTicketDeepLink(relation.id, activityType);
if (string.IsNullOrWhiteSpace(url))
return false;
new cBrowsers().Start("default", url);
return true;
}
catch (Exception ex)
{
LogException(ex);
}
return false;
}
private static string GetActivityType(cF4sdApiSearchResultRelation relation)
{
if (relation?.Infos != null && relation.Infos.TryGetValue("ActivityType", out var activityTypeValue))
return activityTypeValue;
return null;
}
private static bool ShouldOpenExternally(cF4sdTicketConfig ticketConfig, string activityType)
{
if (ticketConfig == null)
return false;
if (TryGetOverride(ticketConfig.OpenActivitiesExternallyOverrides, activityType, out var overrideValue))
return overrideValue;
return ticketConfig.OpenActivitiesExternally;
}
private static bool TryGetOverride(IEnumerable<string> overrides, string activityType, out bool value)
{
value = false;
if (string.IsNullOrWhiteSpace(activityType) || overrides == null)
return false;
foreach (var entry in overrides)
{
if (string.IsNullOrWhiteSpace(entry))
continue;
var parts = entry.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
continue;
var typeName = parts[0].Trim();
if (!string.Equals(typeName, activityType, StringComparison.OrdinalIgnoreCase))
continue;
if (!TryParseBool(parts[1], out value))
return false;
return true;
}
return false;
}
private static bool TryParseBool(string value, out bool result)
{
result = false;
if (string.IsNullOrWhiteSpace(value))
return false;
switch (value.Trim().ToLowerInvariant())
{
case "true":
case "1":
case "yes":
result = true;
return true;
case "false":
case "0":
case "no":
result = false;
return true;
default:
return bool.TryParse(value, out result);
}
}
internal static string BuildTicketDeepLink(Guid ticketId, string activityType)
{
if (ticketId == Guid.Empty)
return null;
var server = cCockpitConfiguration.Instance?.m42ServerConfiguration?.Server;
if (string.IsNullOrWhiteSpace(server))
return null;
var baseUrl = server.TrimEnd('/');
if (!baseUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
!baseUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
baseUrl = "https://" + baseUrl;
}
if (!baseUrl.EndsWith("/wm", StringComparison.OrdinalIgnoreCase))
baseUrl += "/wm";
if (string.IsNullOrWhiteSpace(activityType))
return null;
var viewOptionsJson = $"{{\"embedded\":false,\"objectId\":\"{ticketId}\",\"type\":\"{activityType}\",\"viewType\":\"preview\",\"archived\":0}}";
var viewOptionsEncoded = Uri.EscapeDataString(viewOptionsJson);
return $"{baseUrl}/app-ServiceDesk/?view-options={viewOptionsEncoded}";
}
}
}

View File

@@ -55,27 +55,28 @@ namespace FasdDesktopUi.Basics.Models
set { if (_incidentCriticalSelected != value) { _incidentCriticalSelected = value; OnPropertyChanged(nameof(IncidentCriticalSelected)); } }
}
private bool _incidentNewInfoSelected;
public bool IncidentNewInfoSelected
{
get => _incidentNewInfoSelected;
set { if (_incidentNewInfoSelected != value) { _incidentNewInfoSelected = value; OnPropertyChanged(nameof(IncidentNewInfoSelected)); } }
}
private bool _unassignedTicketsSelected;
public bool UnassignedTicketsSelected
{
get => _unassignedTicketsSelected;
set { if (_unassignedTicketsSelected != value) { _unassignedTicketsSelected = value; OnPropertyChanged(nameof(UnassignedTicketsSelected)); } }
}
private bool _unassignedTicketsCriticalSelected;
public bool UnassignedTicketsCriticalSelected
{
get => _unassignedTicketsCriticalSelected;
set { if (_unassignedTicketsCriticalSelected != value) { _unassignedTicketsCriticalSelected = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalSelected)); } }
}
#endregion
private bool _incidentNewInfoSelected;
public bool IncidentNewInfoSelected
{
get => _incidentNewInfoSelected;
set { if (_incidentNewInfoSelected != value) { _incidentNewInfoSelected = value; OnPropertyChanged(nameof(IncidentNewInfoSelected)); } }
}
private bool _unassignedTicketsSelected;
public bool UnassignedTicketsSelected
{
get => _unassignedTicketsSelected;
set { if (_unassignedTicketsSelected != value) { _unassignedTicketsSelected = value; OnPropertyChanged(nameof(UnassignedTicketsSelected)); } }
}
private bool _unassignedTicketsCriticalSelected;
public bool UnassignedTicketsCriticalSelected
{
get => _unassignedTicketsCriticalSelected;
set { if (_unassignedTicketsCriticalSelected != value) { _unassignedTicketsCriticalSelected = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalSelected)); } }
}
#endregion
#region Highlight-Properties
private bool _ticketsNewHighlighted;
@@ -99,15 +100,16 @@ namespace FasdDesktopUi.Basics.Models
private bool _incidentCriticalHighlighted;
public bool IncidentCriticalHighlighted { get => _incidentCriticalHighlighted; set { if (_incidentCriticalHighlighted != value) { _incidentCriticalHighlighted = value; OnPropertyChanged(nameof(IncidentCriticalHighlighted)); } } }
private bool _incidentNewInfoHighlighted;
public bool IncidentNewInfoHighlighted { get => _incidentNewInfoHighlighted; set { if (_incidentNewInfoHighlighted != value) { _incidentNewInfoHighlighted = value; OnPropertyChanged(nameof(IncidentNewInfoHighlighted)); } } }
private bool _unassignedTicketsHighlighted;
public bool UnassignedTicketsHighlighted { get => _unassignedTicketsHighlighted; set { if (_unassignedTicketsHighlighted != value) { _unassignedTicketsHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsHighlighted)); } } }
private bool _unassignedTicketsCriticalHighlighted;
public bool UnassignedTicketsCriticalHighlighted { get => _unassignedTicketsCriticalHighlighted; set { if (_unassignedTicketsCriticalHighlighted != value) { _unassignedTicketsCriticalHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalHighlighted)); } } }
#endregion
private bool _incidentNewInfoHighlighted;
public bool IncidentNewInfoHighlighted { get => _incidentNewInfoHighlighted; set { if (_incidentNewInfoHighlighted != value) { _incidentNewInfoHighlighted = value; OnPropertyChanged(nameof(IncidentNewInfoHighlighted)); } } }
private bool _unassignedTicketsHighlighted;
public bool UnassignedTicketsHighlighted { get => _unassignedTicketsHighlighted; set { if (_unassignedTicketsHighlighted != value) { _unassignedTicketsHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsHighlighted)); } } }
private bool _unassignedTicketsCriticalHighlighted;
public bool UnassignedTicketsCriticalHighlighted { get => _unassignedTicketsCriticalHighlighted; set { if (_unassignedTicketsCriticalHighlighted != value) { _unassignedTicketsCriticalHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalHighlighted)); } } }
#endregion
#region Change Hint Properties
private string _ticketsNewChangeHint;
@@ -131,15 +133,16 @@ namespace FasdDesktopUi.Basics.Models
private string _incidentCriticalChangeHint;
public string IncidentCriticalChangeHint { get => _incidentCriticalChangeHint; set { if (_incidentCriticalChangeHint != value) { _incidentCriticalChangeHint = value; OnPropertyChanged(nameof(IncidentCriticalChangeHint)); } } }
private string _incidentNewInfoChangeHint;
public string IncidentNewInfoChangeHint { get => _incidentNewInfoChangeHint; set { if (_incidentNewInfoChangeHint != value) { _incidentNewInfoChangeHint = value; OnPropertyChanged(nameof(IncidentNewInfoChangeHint)); } } }
private string _unassignedTicketsChangeHint;
public string UnassignedTicketsChangeHint { get => _unassignedTicketsChangeHint; set { if (_unassignedTicketsChangeHint != value) { _unassignedTicketsChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsChangeHint)); } } }
private string _unassignedTicketsCriticalChangeHint;
public string UnassignedTicketsCriticalChangeHint { get => _unassignedTicketsCriticalChangeHint; set { if (_unassignedTicketsCriticalChangeHint != value) { _unassignedTicketsCriticalChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalChangeHint)); } } }
#endregion
private string _incidentNewInfoChangeHint;
public string IncidentNewInfoChangeHint { get => _incidentNewInfoChangeHint; set { if (_incidentNewInfoChangeHint != value) { _incidentNewInfoChangeHint = value; OnPropertyChanged(nameof(IncidentNewInfoChangeHint)); } } }
private string _unassignedTicketsChangeHint;
public string UnassignedTicketsChangeHint { get => _unassignedTicketsChangeHint; set { if (_unassignedTicketsChangeHint != value) { _unassignedTicketsChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsChangeHint)); } } }
private string _unassignedTicketsCriticalChangeHint;
public string UnassignedTicketsCriticalChangeHint { get => _unassignedTicketsCriticalChangeHint; set { if (_unassignedTicketsCriticalChangeHint != value) { _unassignedTicketsCriticalChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalChangeHint)); } } }
#endregion
#region Ticket & Incident-Properties
@@ -166,20 +169,19 @@ namespace FasdDesktopUi.Basics.Models
private int _incidentCritical;
public int IncidentCritical { get => _incidentCritical; set { _incidentCritical = value; OnPropertyChanged(nameof(IncidentCritical)); } }
private int _incidentNewInfo;
public int IncidentNewInfo { get => _incidentNewInfo; set { _incidentNewInfo = value; OnPropertyChanged(nameof(IncidentNewInfo)); } }
// Unassigned Ticket Properties
private int _unassignedTickets;
public int UnassignedTickets { get => _unassignedTickets; set { _unassignedTickets = value; OnPropertyChanged(nameof(UnassignedTickets)); } }
private int _unassignedTicketsCritical;
public int UnassignedTicketsCritical { get => _unassignedTicketsCritical; set { _unassignedTicketsCritical = value; OnPropertyChanged(nameof(UnassignedTicketsCritical)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private int _incidentNewInfo;
public int IncidentNewInfo { get => _incidentNewInfo; set { _incidentNewInfo = value; OnPropertyChanged(nameof(IncidentNewInfo)); } }
// Unassigned Ticket Properties
private int _unassignedTickets;
public int UnassignedTickets { get => _unassignedTickets; set { _unassignedTickets = value; OnPropertyChanged(nameof(UnassignedTickets)); } }
private int _unassignedTicketsCritical;
public int UnassignedTicketsCritical { get => _unassignedTicketsCritical; set { _unassignedTicketsCritical = value; OnPropertyChanged(nameof(UnassignedTicketsCritical)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
#region Helper-Methods
@@ -193,12 +195,13 @@ namespace FasdDesktopUi.Basics.Models
IncidentNewSelected = false;
IncidentActiveSelected = false;
IncidentCriticalSelected = false;
IncidentNewInfoSelected = false;
UnassignedTicketsSelected = false;
UnassignedTicketsCriticalSelected = false;
}
IncidentCriticalSelected = false;
IncidentNewInfoSelected = false;
UnassignedTicketsSelected = false;
UnassignedTicketsCriticalSelected = false;
}
public void ResetHighlights()
{
@@ -208,26 +211,27 @@ namespace FasdDesktopUi.Basics.Models
TicketsNewInfoHighlighted = false;
IncidentNewHighlighted = false;
IncidentActiveHighlighted = false;
IncidentCriticalHighlighted = false;
IncidentNewInfoHighlighted = false;
UnassignedTicketsHighlighted = false;
UnassignedTicketsCriticalHighlighted = false;
TicketsNewChangeHint = null;
TicketsActiveChangeHint = null;
TicketsCriticalChangeHint = null;
IncidentActiveHighlighted = false;
IncidentCriticalHighlighted = false;
IncidentNewInfoHighlighted = false;
UnassignedTicketsHighlighted = false;
UnassignedTicketsCriticalHighlighted = false;
TicketsNewChangeHint = null;
TicketsActiveChangeHint = null;
TicketsCriticalChangeHint = null;
TicketsNewInfoChangeHint = null;
IncidentNewChangeHint = null;
IncidentActiveChangeHint = null;
IncidentCriticalChangeHint = null;
IncidentNewInfoChangeHint = null;
UnassignedTicketsChangeHint = null;
UnassignedTicketsCriticalChangeHint = null;
}
IncidentNewChangeHint = null;
IncidentActiveChangeHint = null;
IncidentCriticalChangeHint = null;
IncidentNewInfoChangeHint = null;
UnassignedTicketsChangeHint = null;
UnassignedTicketsCriticalChangeHint = null;
}
#endregion
public TicketOverviewModel()

View File

@@ -140,8 +140,8 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
{
return tablesToLoad.All(t =>
_rawDataCache.TryGetValue(relation, out var cachedRawData)
&& cachedRawData.Tables.TryGetValue(t, out var cachedTable)
&& !cachedTable.IsIncomplete && !cachedTable.Columns.Values.Any(c => c.IsIncomplete)
&& (cachedRawData?.Tables?.TryGetValue(t, out var cachedTable) ?? false)
&& cachedTable != null && !cachedTable.IsIncomplete && !cachedTable.Columns.Values.Any(c => c.IsIncomplete)
);
}
@@ -235,11 +235,12 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
table.IsIncomplete = true;
foreach (var column in table.Columns.Values)
{
column.Values[0] = null;
column.IsIncomplete = true;
}
foreach (var column in table.Columns.Values)
{
if (column.Values != null && column.Values.Count > 0)
column.Values[0] = null;
column.IsIncomplete = true;
}
invalidatedTables.Add(table);
}
@@ -251,11 +252,12 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
{
table.IsIncomplete = true;
foreach (var column in table.Columns.Values)
{
column.Values[0] = null;
column.IsIncomplete = true;
}
foreach (var column in table.Columns.Values)
{
if (column.Values != null && column.Values.Count > 0)
column.Values[0] = null;
column.IsIncomplete = true;
}
}
}
catch (Exception ex)

View File

@@ -24,16 +24,15 @@ namespace FasdDesktopUi.Basics.Services
{
"TicketsNew",
"TicketsActive",
"TicketsCritical",
"TicketsNewInfo",
"IncidentNew",
"IncidentActive",
"IncidentCritical",
"IncidentNewInfo",
"UnassignedTickets",
"UnassignedTicketsCritical"
};
private const string DemoTicketDetailsKey = "Demo.HasTicketDetails";
"TicketsCritical",
"TicketsNewInfo",
"IncidentNew",
"IncidentActive",
"IncidentCritical",
"IncidentNewInfo",
"UnassignedTickets",
"UnassignedTicketsCritical"
};
private readonly Dispatcher _dispatcher;
private readonly Dictionary<string, TileCounts> _currentCounts = new Dictionary<string, TileCounts>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<(string Key, bool UseRoleScope), List<cF4sdApiSearchResultRelation>> _demoRelations = new Dictionary<(string, bool), List<cF4sdApiSearchResultRelation>>();
@@ -317,18 +316,6 @@ namespace FasdDesktopUi.Basics.Services
}
}
if (_isDemo)
{
foreach (var key in OverviewKeys)
{
var extras = GetDemoRelationCount(key, scope == TileScope.Role);
if (counts.ContainsKey(key))
counts[key] += extras;
else
counts[key] = extras;
}
}
if (!_isEnabled)
return;
@@ -551,48 +538,55 @@ namespace FasdDesktopUi.Basics.Services
}
}
private cF4sdApiSearchResultRelation CreateRelationFromRecord(DemoTicketRecord record)
{
var relation = new cF4sdApiSearchResultRelation
{
Type = enumF4sdSearchResultClass.Ticket,
DisplayName = record.DisplayName,
Name = record.DisplayName,
private cF4sdApiSearchResultRelation CreateRelationFromRecord(DemoTicketRecord record)
{
var activityType = ResolveDemoActivityType(record?.ActivityType);
var relation = new cF4sdApiSearchResultRelation
{
Type = enumF4sdSearchResultClass.Ticket,
DisplayName = record.DisplayName,
Name = record.DisplayName,
id = record.TicketId,
Status = enumF4sdSearchResultStatus.Active,
Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["Summary"] = record.Summary ?? string.Empty,
["StatusId"] = record.StatusId ?? string.Empty,
["UserDisplayName"] = record.UserDisplayName ?? string.Empty,
["UserAccount"] = record.UserAccount ?? string.Empty,
["UserDomain"] = record.UserDomain ?? string.Empty,
[DemoTicketDetailsKey] = bool.TrueString
},
Identities = new cF4sdIdentityList
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = record.TicketId },
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = record.UserId }
Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["Summary"] = record.Summary ?? string.Empty,
["StatusId"] = record.StatusId ?? string.Empty,
["UserDisplayName"] = record.UserDisplayName ?? string.Empty,
["UserAccount"] = record.UserAccount ?? string.Empty,
["UserDomain"] = record.UserDomain ?? string.Empty,
["ActivityType"] = activityType
},
Identities = new cF4sdIdentityList
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = record.TicketId },
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = record.UserId }
}
};
return relation;
}
return relation;
}
private static string ResolveDemoActivityType(string configuredActivityType)
{
return string.IsNullOrWhiteSpace(configuredActivityType)
? null
: configuredActivityType.Trim();
}
private DemoTicketDetail CloneDetail(DemoTicketDetail source)
{
if (source == null)
return new DemoTicketDetail();
return new DemoTicketDetail
{
AffectedUser = source.AffectedUser,
Asset = source.Asset,
Category = source.Category,
Classification = source.Classification,
Description = source.Description,
DescriptionHtml = source.DescriptionHtml,
Priority = source.Priority,
return new DemoTicketDetail
{
AffectedUser = source.AffectedUser,
Asset = source.Asset,
Category = source.Category,
Description = source.Description,
DescriptionHtml = source.DescriptionHtml,
Priority = source.Priority,
Solution = source.Solution,
SolutionHtml = source.SolutionHtml,
Journal = source.Journal?.Select(entry => new DemoTicketJournalEntry
@@ -749,15 +743,16 @@ namespace FasdDesktopUi.Basics.Services
entry.CreationDate = createdAt;
}
return new DemoTicketRecord
{
TicketId = relationId,
TileKey = string.IsNullOrWhiteSpace(template.TileKey) ? "TicketsNew" : template.TileKey,
UseRoleScope = template.UseRoleScope,
DisplayName = displayName,
Summary = summary,
StatusId = string.IsNullOrWhiteSpace(template.StatusId) ? "New" : template.StatusId,
UserDisplayName = template.UserDisplayName ?? detail.AffectedUser ?? "Ticket, Timo",
return new DemoTicketRecord
{
TicketId = relationId,
TileKey = string.IsNullOrWhiteSpace(template.TileKey) ? "TicketsNew" : template.TileKey,
UseRoleScope = template.UseRoleScope,
ActivityType = ResolveDemoActivityType(template.ActivityType),
DisplayName = displayName,
Summary = summary,
StatusId = string.IsNullOrWhiteSpace(template.StatusId) ? "New" : template.StatusId,
UserDisplayName = template.UserDisplayName ?? detail.AffectedUser ?? "Ticket, Timo",
UserAccount = template.UserAccount ?? "TT007",
UserDomain = template.UserDomain ?? "CONTOSO",
UserId = template.UserId ?? Guid.Parse("42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a"),

View File

@@ -237,7 +237,7 @@ namespace FasdDesktopUi.Basics
if (relationToFocus is null)
return selectedRelation;
relationToFocus.Identities = selectedRelation.Identities;
relationToFocus.Identities = selectedRelation.Identities.Clone();
return relationToFocus;
}
catch (Exception ex)
@@ -672,7 +672,6 @@ namespace FasdDesktopUi.Basics
ComputerRemoved |= relationIdentity.Class == enumFasdInformationClass.Computer;
ComputerAdded |= relationIdentity.Class == enumFasdInformationClass.Computer;
}
relationIdentity.CopyTo(existingIdentity);
}
}

View File

@@ -1,6 +1,7 @@
using C4IT.FASD.Base;
using C4IT.Logging;
using C4IT.MultiLanguage;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Services.RelationService;
using System;
using System.Collections.Generic;
@@ -60,15 +61,18 @@ namespace FasdDesktopUi.Basics.UiActions
return false;
}
if (_selectedRelation == null)
{
Debug.Assert(true, "A new support case can't be opend, if we have no selected relation or seach result");
LogEntry("A new support case can't be opend, if we have no sselected relation or seach result", LogLevels.Error);
return false;
}
// check, if have an active support case
var supportCaseActive = dataProvider?.IsActive ?? false;
if (_selectedRelation == null)
{
Debug.Assert(true, "A new support case can't be opend, if we have no selected relation or seach result");
LogEntry("A new support case can't be opend, if we have no sselected relation or seach result", LogLevels.Error);
return false;
}
if (TicketDeepLinkHelper.TryOpenTicketRelationExternally(_selectedRelation))
return false;
// check, if have an active support case
var supportCaseActive = dataProvider?.IsActive ?? false;
// create the search histroy entry
var _seachHistoryEntry = new cSearchHistoryRelationEntry(Name, _selectedSearchResult, _relations, _selectedRelation, _searchUiProvider);

View File

@@ -1,6 +1,7 @@
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Models;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -124,12 +125,25 @@ namespace FasdDesktopUi.Basics.UserControls
}
public static readonly DependencyProperty SearchDataChangedProperty =
DependencyProperty.Register("SearchDataChanged", typeof(EventHandler<cF4sdHealthSelectionDataRequest>), typeof(ComboBoxPageable), new PropertyMetadata(null));
#endregion
#region ItemData
public static readonly DependencyProperty SearchDataChangedProperty =
DependencyProperty.Register("SearchDataChanged", typeof(EventHandler<cF4sdHealthSelectionDataRequest>), typeof(ComboBoxPageable), new PropertyMetadata(null));
#endregion
#region RestoreParentScrollFocusOnDropDownClose
public bool RestoreParentScrollFocusOnDropDownClose
{
get { return (bool)GetValue(RestoreParentScrollFocusOnDropDownCloseProperty); }
set { SetValue(RestoreParentScrollFocusOnDropDownCloseProperty, value); }
}
public static readonly DependencyProperty RestoreParentScrollFocusOnDropDownCloseProperty =
DependencyProperty.Register("RestoreParentScrollFocusOnDropDownClose", typeof(bool), typeof(ComboBoxPageable), new PropertyMetadata(false));
#endregion
#region ItemData
public ObservableCollection<KeyValuePair<string, object>> ItemData
{
@@ -302,11 +316,33 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void ComboBoxControl_DropDownClosed(object sender, EventArgs e)
{
timer.Stop();
cFocusInvoker.InvokeLostFocus(this, e);
}
private void ComboBoxControl_DropDownClosed(object sender, EventArgs e)
{
timer.Stop();
cFocusInvoker.InvokeLostFocus(this, e);
if (RestoreParentScrollFocusOnDropDownClose)
{
_ = Dispatcher.BeginInvoke((Action)(() =>
{
try
{
var parentScrollViewer = cUiElementHelper.GetFirstParentOfType<ScrollViewer>(this);
Keyboard.ClearFocus();
if (parentScrollViewer != null)
{
parentScrollViewer.Focus();
Keyboard.Focus(parentScrollViewer);
}
}
catch (Exception exception)
{
LogException(exception);
}
}), System.Windows.Threading.DispatcherPriority.Input);
}
}
private void ComboBoxControl_DropDownOpened(object sender, EventArgs e)
{

View File

@@ -105,10 +105,12 @@
Padding="4"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
BorderThickness="1">
<ScrollViewer MaxHeight="320"
<ScrollViewer x:Name="PART_ItemsScrollViewer"
MaxHeight="320"
VerticalScrollBarVisibility="Auto"
Background="Transparent"
BorderThickness="0">
BorderThickness="0"
PreviewMouseWheel="ItemsScrollViewer_PreviewMouseWheel">
<TreeView x:Name="PART_TreeView"
Background="Transparent"
BorderThickness="0"

View File

@@ -8,7 +8,6 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
@@ -22,6 +21,7 @@ namespace FasdDesktopUi.Basics.UserControls
private TextBox searchTextBox;
private TreeView treeViewControl;
private ScrollViewer itemsScrollViewer;
public ObservableCollection<HierarchicalSelectionItem> VisibleItems => visibleItems;
@@ -40,7 +40,6 @@ namespace FasdDesktopUi.Basics.UserControls
EnsureTemplateParts();
if (treeViewControl != null)
treeViewControl.ItemsSource = VisibleItems;
UpdateDisplaySelection();
}
#region DependencyProperties
@@ -63,7 +62,6 @@ namespace FasdDesktopUi.Basics.UserControls
{
control.RebuildLookup();
control.ApplyFilter(control.lastSearchText);
control.TryExpandToSelectedItem();
}
}
@@ -83,8 +81,8 @@ namespace FasdDesktopUi.Basics.UserControls
{
if (d is HierarchicalSelectionControl control)
{
control.LogSelectedItemChange(e.NewValue as HierarchicalSelectionItem);
control.TryExpandToSelectedItem();
control.SyncTreeSelectionWithSelectedItem(bringIntoView: false);
}
}
@@ -108,13 +106,15 @@ namespace FasdDesktopUi.Basics.UserControls
#endregion
#region UI Event Handling
private void ComboBoxControl_DropDownOpened(object sender, EventArgs e)
{
EnsureTemplateParts();
searchTextBox?.Focus();
searchTextBox?.SelectAll();
suppressTreeSelectionChanged = false;
LogEntry($"[CategoryPicker] DropDownOpened. Selected={SelectedItem?.FullPath ?? "<null>"}");
SyncTreeSelectionWithSelectedItem(bringIntoView: true);
DropDownOpened?.Invoke(this, e);
}
@@ -122,7 +122,6 @@ namespace FasdDesktopUi.Basics.UserControls
{
searchDelayTimer.Stop();
suppressTreeSelectionChanged = false;
LogEntry("[CategoryPicker] DropDownClosed");
DropDownClosed?.Invoke(this, e);
}
@@ -136,7 +135,6 @@ namespace FasdDesktopUi.Basics.UserControls
{
searchDelayTimer.Stop();
lastSearchText = searchTextBox?.Text ?? string.Empty;
LogEntry($"[CategoryPicker] Search text changed: '{lastSearchText}'");
ApplyFilter(lastSearchText);
}
@@ -151,7 +149,6 @@ namespace FasdDesktopUi.Basics.UserControls
if (original != null && !Equals(SelectedItem, original))
{
SelectedItem = original;
LogEntry($"[CategoryPicker] Tree selection changed: {original.FullPath}");
}
suppressTreeSelectionChanged = true;
@@ -159,6 +156,10 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
#endregion
#region Data Preparation and Filtering
private HierarchicalSelectionItem ResolveOriginalItem(HierarchicalSelectionItem item)
{
if (item == null)
@@ -202,6 +203,7 @@ namespace FasdDesktopUi.Basics.UserControls
}
TryExpandToSelectedItem();
SyncTreeSelectionWithSelectedItem(bringIntoView: false);
return;
}
@@ -219,6 +221,9 @@ namespace FasdDesktopUi.Basics.UserControls
clone.SetExpandedRecursive(true);
visibleItems.Add(clone);
}
// If the selected item is part of current results, keep it visually selected.
SyncTreeSelectionWithSelectedItem(bringIntoView: false);
}
private void TryExpandToSelectedItem()
@@ -237,6 +242,101 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
#endregion
#region Tree Selection Sync
private void SyncTreeSelectionWithSelectedItem(bool bringIntoView)
{
if (SelectedItem == null || string.IsNullOrWhiteSpace(SelectedItem.Id))
return;
EnsureTemplateParts();
if (treeViewControl == null)
return;
// Wait for popup/template layout to finish so item containers are generated.
Dispatcher.BeginInvoke(new Action(() =>
{
var target = FindVisibleItemById(VisibleItems, SelectedItem.Id);
if (target == null)
return;
var ancestor = target.Parent;
while (ancestor != null)
{
ancestor.IsExpanded = true;
ancestor = ancestor.Parent;
}
treeViewControl.UpdateLayout();
var targetContainer = GetTreeViewItemContainer(treeViewControl, target);
if (targetContainer == null)
return;
suppressTreeSelectionChanged = true;
try
{
targetContainer.IsSelected = true;
if (bringIntoView)
targetContainer.BringIntoView();
}
finally
{
suppressTreeSelectionChanged = false;
}
}), DispatcherPriority.Loaded);
}
private static HierarchicalSelectionItem FindVisibleItemById(IEnumerable<HierarchicalSelectionItem> items, string id)
{
if (items == null || string.IsNullOrWhiteSpace(id))
return null;
foreach (var item in items)
{
if (item == null)
continue;
if (string.Equals(item.Id, id, StringComparison.OrdinalIgnoreCase))
return item;
var childMatch = FindVisibleItemById(item.Children, id);
if (childMatch != null)
return childMatch;
}
return null;
}
private static TreeViewItem GetTreeViewItemContainer(ItemsControl root, object targetItem)
{
if (root == null || targetItem == null)
return null;
var directContainer = root.ItemContainerGenerator.ContainerFromItem(targetItem) as TreeViewItem;
if (directContainer != null)
return directContainer;
foreach (var child in root.Items)
{
var childContainer = root.ItemContainerGenerator.ContainerFromItem(child) as TreeViewItem;
if (childContainer == null)
continue;
childContainer.UpdateLayout();
var result = GetTreeViewItemContainer(childContainer, targetItem);
if (result != null)
return result;
}
return null;
}
#endregion
#region Template and Scroll Handling
private void EnsureTemplateParts()
{
if (treeViewControl == null)
@@ -255,26 +355,54 @@ namespace FasdDesktopUi.Basics.UserControls
if (searchTextBox != null)
searchTextBox.TextChanged += SearchTextBox_TextChanged;
}
}
private void UpdateDisplaySelection()
{
// Display handled by template TextBlock bound to SelectedItem.FullPath.
}
private void LogSelectedItemChange(HierarchicalSelectionItem newValue)
{
var description = "<null>";
if (newValue != null)
if (itemsScrollViewer == null)
{
var fullPath = string.IsNullOrWhiteSpace(newValue.FullPath) ? newValue.DisplayName : newValue.FullPath;
var id = string.IsNullOrWhiteSpace(newValue.Id) ? "<null>" : newValue.Id;
description = $"{fullPath} (Id={id})";
itemsScrollViewer = ComboBoxControl.Template.FindName("PART_ItemsScrollViewer", ComboBoxControl) as ScrollViewer;
}
}
private void ItemsScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var scroller = itemsScrollViewer ?? sender as ScrollViewer;
if (scroller == null || scroller.ScrollableHeight <= 0)
return;
var lines = SystemParameters.WheelScrollLines;
if (lines < 0)
{
if (e.Delta < 0)
scroller.PageDown();
else
scroller.PageUp();
e.Handled = true;
return;
}
LogEntry($"[CategoryPicker] DependencyProperty SelectedItem updated -> {description}");
if (lines == 0)
{
scroller.ScrollToVerticalOffset(scroller.VerticalOffset - e.Delta);
e.Handled = true;
return;
}
var direction = e.Delta < 0 ? 1 : -1;
var stepCount = Math.Max(1, Math.Abs(e.Delta) / 120) * lines;
for (var i = 0; i < stepCount; i++)
{
if (direction > 0)
scroller.LineDown();
else
scroller.LineUp();
}
e.Handled = true;
}
#endregion
#region Keyboard
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
@@ -295,5 +423,7 @@ namespace FasdDesktopUi.Basics.UserControls
e.Handled = true;
}
}
#endregion
}
}

View File

@@ -1209,8 +1209,7 @@ namespace FasdDesktopUi.Basics.UserControls
if (quickCallsTable == null) return;
if (!quickCallsTable.Columns.TryGetValue("Name", out var namesColumn) ||
!quickCallsTable.Columns.TryGetValue("id", out var idsColumn) ||
!quickCallsTable.Columns.TryGetValue("Classification", out var classificationColumn))
!quickCallsTable.Columns.TryGetValue("id", out var idsColumn))
{
return;
}
@@ -1222,17 +1221,10 @@ namespace FasdDesktopUi.Basics.UserControls
var id = idsColumn.Values[i].ToString();
var name = namesColumn.Values[i].ToString();
Guid? classification = null;
var classificationValue = classificationColumn.Values[i]?.ToString();
if (Guid.TryParse(classificationValue, out var parsedClassification))
classification = parsedClassification;
quickCallListe.Add(new QuickCallEntry
{
ID = id,
DisplayName = name,
Classification = classification
DisplayName = name
});
}
@@ -1252,7 +1244,6 @@ namespace FasdDesktopUi.Basics.UserControls
{
public string ID { get; set; }
public string DisplayName { get; set; }
public Guid? Classification { get; set; }
public override string ToString()
{
return DisplayName.ToString();
@@ -1622,17 +1613,11 @@ namespace FasdDesktopUi.Basics.UserControls
["Priority"] = 2,
};
Guid quickcallId = Guid.Empty;
Guid? quickCallClassificationId = null;
if (QuickTicketSelection.SelectedItem is QuickCallEntry selectedQuickTicketItem)
{
//ticketValues.Add("Category", selectedQuickTicketItem.DisplayName);
ticketValues.Add("QuickCallId", selectedQuickTicketItem.ID);
Guid.TryParse(selectedQuickTicketItem.ID?.ToString(), out quickcallId);
if (selectedQuickTicketItem.Classification.HasValue)
{
quickCallClassificationId = selectedQuickTicketItem.Classification;
ticketValues["Classification"] = quickCallClassificationId.Value;
}
}
var selectedCategoryId = GetSelectedCategoryGuid();
if (selectedCategoryId.HasValue)
@@ -1901,7 +1886,6 @@ namespace FasdDesktopUi.Basics.UserControls
Summary = TicketSummaryTextBox.Text,
DescriptionHtml = htmlCaseNotes.ToString(),
Quickcall = quickcallId,
Classification = quickCallClassificationId,
CopyTemplates = string.IsNullOrWhiteSpace(copyStringHtml) ? copyString : copyStringHtml,
SolutionHtml = solutionHtmlString,
ErrorType = errorType,

View File

@@ -87,9 +87,10 @@
</Style>
</UserControl.Resources>
<ScrollViewer Height="570"
Padding="0 0 5 0"
VerticalScrollBarVisibility="Auto">
<ScrollViewer x:Name="DialogContentScrollViewer"
Padding="0 0 5 0"
VerticalScrollBarVisibility="Auto"
Focusable="True">
<StackPanel>
<Border x:Name="NewOrExistingOrNoneTicketSelectionBorder">
<WrapPanel x:Name="NewOrExistingOrNoneTicketWrap"
@@ -169,8 +170,28 @@
<StackPanel x:Name="TicketSelectionContainer" />
</Border>
</Popup>
</StackPanel>
<StackPanel x:Name="MainStack">
</StackPanel>
<StackPanel x:Name="MainStack">
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Template}"
Style="{StaticResource MandatoryFieldLabelStyle}" />
<Border x:Name="QuickTicketValidationBorder"
Style="{StaticResource MandatoryFieldBorderStyle}">
<ComboBox x:Name="QuickTicketSelection"
Background="{Binding Background, RelativeSource={RelativeSource AncestorType=Border}}"
BorderBrush="Transparent"
BorderThickness="0"
SelectedIndex="0"
SelectionChanged="QuickTicketSelection_SelectionChanged"
PreviewKeyDown="Combobox_PreviewKeyDown"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
AutomationProperties.IsRequiredForForm="True"
AutomationProperties.HelpText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ValidationErrorQuickCallEmpty}">
</ComboBox>
</Border>
</StackPanel>
<StackPanel x:Name="CategoryLabelPanel">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Category}"
Style="{StaticResource MandatoryFieldLabelStyle}" />
@@ -189,26 +210,6 @@
AutomationProperties.IsRequiredForForm="True"
AutomationProperties.HelpText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ValidationErrorCategoryEmpty}" />
</Border>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Template}"
Style="{StaticResource MandatoryFieldLabelStyle}" />
<Border x:Name="QuickTicketValidationBorder"
Style="{StaticResource MandatoryFieldBorderStyle}">
<ComboBox x:Name="QuickTicketSelection"
Background="{Binding Background, RelativeSource={RelativeSource AncestorType=Border}}"
BorderBrush="Transparent"
BorderThickness="0"
SelectedIndex="0"
SelectionChanged="QuickTicketSelection_SelectionChanged"
PreviewKeyDown="Combobox_PreviewKeyDown"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
AutomationProperties.IsRequiredForForm="True"
AutomationProperties.HelpText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ValidationErrorQuickCallEmpty}">
</ComboBox>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="SetOrUpdateComputerInTicketLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.SetAffectedAssetLabel}"
@@ -269,14 +270,15 @@
SelectedInternIcon="status_bad"
VerticalAlignment="Bottom" />
</StackPanel>
<local:ComboBoxPageable x:Name="ServiceSelectionControl"
Margin="0 5 0 0"
ResetFilterLabel="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ResetFilter.Services}"
SelectedItem="{Binding SelectedService, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
IsEnabled="{Binding SetOrUpdateServiceInTicket, ElementName=CloseCaseDialogUc}"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
PreviewKeyDown="Combobox_PreviewKeyDown" />
<local:ComboBoxPageable x:Name="ServiceSelectionControl"
Margin="0 5 0 0"
ResetFilterLabel="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ResetFilter.Services}"
SelectedItem="{Binding SelectedService, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
IsEnabled="{Binding SetOrUpdateServiceInTicket, ElementName=CloseCaseDialogUc}"
RestoreParentScrollFocusOnDropDownClose="True"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
PreviewKeyDown="Combobox_PreviewKeyDown" />
</StackPanel>
<StackPanel>

View File

@@ -26,6 +26,8 @@ namespace FasdDesktopUi.Basics.UserControls
{
public partial class CloseCaseDialogWithTicket : UserControl
{
private const double MinDialogContentHeightDip = 220d;
#region Fields & Properties
private readonly Dictionary<string, string> _errors = new Dictionary<string, string>();
@@ -69,6 +71,8 @@ namespace FasdDesktopUi.Basics.UserControls
private const string CategoryTableNamePrimary = "M42Wpm-Ticket-Categories";
private const string CategoryTableNameLegacy = "M42Wpm-Ticket-CloseCase-Categories";
private const string TicketDetailsTableName = "M42Wpm-Tickets";
private const string TicketDetailsCategoryIdColumnName = "CategoryId";
private string activeCategoryTableName = CategoryTableNamePrimary;
private static readonly Brush SharedValidationBorderBrush = CreateValidationBrush();
@@ -240,6 +244,7 @@ namespace FasdDesktopUi.Basics.UserControls
EnableHoldTicketAction = statusId != enumTicketStatus.OnHold;
}
TrySelectTicketCategoryFromTicketInfos();
_ = EnsureSelectedTicketCategoryFromDetailsAsync(_selectedTicket);
}
}
@@ -1182,6 +1187,76 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private bool ShouldLoadCategoryFromDetails(cF4sdApiSearchResultRelation ticket)
{
if (ticket == null || ticket == _newTicketRelation || ticket == _selectTicketRelation || ticket == _noTicketRelation)
return false;
if (ticket.Infos == null)
return true;
if (!ticket.Infos.TryGetValue(TicketInfoKeys.Category, out var categoryValue) || string.IsNullOrWhiteSpace(categoryValue))
return true;
return !Guid.TryParse(categoryValue, out _);
}
private async Task EnsureSelectedTicketCategoryFromDetailsAsync(cF4sdApiSearchResultRelation ticket)
{
try
{
if (!ShouldLoadCategoryFromDetails(ticket))
return;
var communication = cFasdCockpitCommunicationBase.Instance;
if (communication == null)
return;
var request = new cF4sdHealthCardRawDataRequest
{
Tables = new List<string> { TicketDetailsTableName },
Identities = new cF4sdIdentityList
{
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = ticket.id }
},
MaxAge = 1
};
var rawData = await communication.GetHealthCardData(request).ConfigureAwait(false);
if (rawData?.Tables == null)
return;
if (!rawData.Tables.TryGetValue(TicketDetailsTableName, out var ticketTable))
return;
if (!ticketTable.Columns.TryGetValue(TicketDetailsCategoryIdColumnName, out var categoryColumn))
return;
var categoryId = categoryColumn.Values?.FirstOrDefault()?.ToString();
if (string.IsNullOrWhiteSpace(categoryId))
return;
await Dispatcher.InvokeAsync(() =>
{
if (SelectedTicket == null)
return;
if (!ReferenceEquals(SelectedTicket, ticket) && SelectedTicket.id != ticket.id)
return;
if (SelectedTicket.Infos == null)
SelectedTicket.Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
SelectedTicket.Infos[TicketInfoKeys.Category] = categoryId;
TrySelectTicketCategoryFromTicketInfos();
});
}
catch (Exception E)
{
LogException(E);
}
}
private Guid? GetSelectedCategoryGuid()
{
if (SelectedCategory == null || string.IsNullOrWhiteSpace(SelectedCategory.Id))
@@ -1209,12 +1284,13 @@ namespace FasdDesktopUi.Basics.UserControls
if (quickCallsTable == null) return;
if (!quickCallsTable.Columns.TryGetValue("Name", out var namesColumn) ||
!quickCallsTable.Columns.TryGetValue("id", out var idsColumn) ||
!quickCallsTable.Columns.TryGetValue("Classification", out var classificationColumn))
!quickCallsTable.Columns.TryGetValue("id", out var idsColumn))
{
return;
}
quickCallsTable.Columns.TryGetValue("Category", out var categoryColumn);
var quickCallListe = new List<QuickCallEntry>();
for (int i = 0; i < idsColumn.Values.Count; i++)
@@ -1222,17 +1298,19 @@ namespace FasdDesktopUi.Basics.UserControls
var id = idsColumn.Values[i].ToString();
var name = namesColumn.Values[i].ToString();
Guid? classification = null;
var classificationValue = classificationColumn.Values[i]?.ToString();
if (Guid.TryParse(classificationValue, out var parsedClassification))
classification = parsedClassification;
Guid? categoryId = null;
if (categoryColumn?.Values != null && i < categoryColumn.Values.Count)
{
var categoryValue = categoryColumn.Values[i]?.ToString();
if (Guid.TryParse(categoryValue, out var parsedCategory))
categoryId = parsedCategory;
}
quickCallListe.Add(new QuickCallEntry
{
ID = id,
DisplayName = name,
Classification = classification
CategoryId = categoryId
});
}
@@ -1241,6 +1319,7 @@ namespace FasdDesktopUi.Basics.UserControls
QuickTicketSelection.SelectedItem = quickCallListe
.FirstOrDefault(x => x.ID == "7bbe64e2-94d0-ee11-4285-00155d010a04");
ValidateProperty(ValidationPropertyNames.QuickTicketSelection);
ApplyQuickCallCategorySelection();
}
catch (Exception e)
{
@@ -1252,13 +1331,47 @@ namespace FasdDesktopUi.Basics.UserControls
{
public string ID { get; set; }
public string DisplayName { get; set; }
public Guid? Classification { get; set; }
public Guid? CategoryId { get; set; }
public override string ToString()
{
return DisplayName.ToString();
}
}
private void ApplyQuickCallCategorySelection()
{
try
{
if (!NewTicketPillSelected)
return;
if (!(QuickTicketSelection?.SelectedItem is QuickCallEntry quickCall))
return;
if (!quickCall.CategoryId.HasValue || quickCall.CategoryId.Value == Guid.Empty)
return;
var targetTicket = SelectedTicket ?? _selectTicketRelation;
if (targetTicket.Infos == null)
targetTicket.Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
targetTicket.Infos[TicketInfoKeys.Category] = quickCall.CategoryId.Value.ToString();
if (ReferenceEquals(targetTicket, SelectedTicket))
{
TrySelectTicketCategoryFromTicketInfos();
}
else if (SelectedTicket == null && ReferenceEquals(targetTicket, _selectTicketRelation))
{
SelectedTicket = targetTicket;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
private void UpdateTicketSelection()
{
@@ -1394,6 +1507,7 @@ namespace FasdDesktopUi.Basics.UserControls
if (selectionPill.IsSelected)
{
SelectedTicket = _selectTicketRelation;
ApplyQuickCallCategorySelection();
}
ValidateProperty(ValidationPropertyNames.SelectedTicket);
ValidateProperty(ValidationPropertyNames.TicketSummaryTextBox);
@@ -1622,17 +1736,11 @@ namespace FasdDesktopUi.Basics.UserControls
["Priority"] = 2,
};
Guid quickcallId = Guid.Empty;
Guid? quickCallClassificationId = null;
if (QuickTicketSelection.SelectedItem is QuickCallEntry selectedQuickTicketItem)
{
//ticketValues.Add("Category", selectedQuickTicketItem.DisplayName);
ticketValues.Add("QuickCallId", selectedQuickTicketItem.ID);
Guid.TryParse(selectedQuickTicketItem.ID?.ToString(), out quickcallId);
if (selectedQuickTicketItem.Classification.HasValue)
{
quickCallClassificationId = selectedQuickTicketItem.Classification;
ticketValues["Classification"] = quickCallClassificationId.Value;
}
}
var selectedCategoryId = GetSelectedCategoryGuid();
if (selectedCategoryId.HasValue)
@@ -1901,7 +2009,6 @@ namespace FasdDesktopUi.Basics.UserControls
Summary = TicketSummaryTextBox.Text,
DescriptionHtml = htmlCaseNotes.ToString(),
Quickcall = quickcallId,
Classification = quickCallClassificationId,
CopyTemplates = string.IsNullOrWhiteSpace(copyStringHtml) ? copyString : copyStringHtml,
SolutionHtml = solutionHtmlString,
ErrorType = errorType,
@@ -2614,6 +2721,39 @@ namespace FasdDesktopUi.Basics.UserControls
cFocusInvoker.InvokeGotFocus(parentBorder, e);
}
private void RestoreDialogFocusAfterTicketActionSelection()
{
try
{
if (DialogContentScrollViewer == null)
return;
Keyboard.ClearFocus();
DialogContentScrollViewer.Focus();
Keyboard.Focus(DialogContentScrollViewer);
}
catch (Exception E)
{
LogException(E);
}
}
public void SetDialogContentMaxHeight(double maxHeight)
{
try
{
if (DialogContentScrollViewer == null)
return;
// Keep dialog usable on very small screens; parent window already constrains max size.
DialogContentScrollViewer.MaxHeight = Math.Max(MinDialogContentHeightDip, maxHeight);
}
catch (Exception E)
{
LogException(E);
}
}
private void DropDownClosed(object sender, EventArgs e)
{
if (!(sender is FrameworkElement fe)) return;
@@ -2623,7 +2763,7 @@ namespace FasdDesktopUi.Basics.UserControls
if (parentBorder != null)
cFocusInvoker.InvokeLostFocus(parentBorder, e);
DynamicStatusAdditionBorder?.Focus();
_ = Dispatcher.BeginInvoke(new Action(RestoreDialogFocusAfterTicketActionSelection), System.Windows.Threading.DispatcherPriority.Input);
}
#endregion
@@ -2654,6 +2794,7 @@ namespace FasdDesktopUi.Basics.UserControls
private void QuickTicketSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ValidateProperty(ValidationPropertyNames.QuickTicketSelection);
ApplyQuickCallCategorySelection();
}
private void TransferCaseNotesCheck_Unchecked(object sender, RoutedEventArgs e)

View File

@@ -176,20 +176,39 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
ErrorTypeValueChanged?.Invoke(this, EventArgs.Empty);
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
ErrorTypeValueChanged?.Invoke(this, EventArgs.Empty);
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
_ = Dispatcher.BeginInvoke((Action)(() =>
{
try
{
var parentScrollViewer = cUiElementHelper.GetFirstParentOfType<ScrollViewer>(this);
Keyboard.ClearFocus();
if (parentScrollViewer != null)
{
parentScrollViewer.Focus();
Keyboard.Focus(parentScrollViewer);
}
}
catch (Exception exception)
{
LogException(exception);
}
}), System.Windows.Threading.DispatcherPriority.Input);
}
catch (Exception E)
{
LogException(E);
}
}

View File

@@ -24,6 +24,7 @@
Style="{StaticResource MandatoryFieldBorderStyle}">
<local:ComboBoxPageable x:Name="RoleSelectionControl"
SelectedItem="{Binding ElementName=ForwardTicketDialogUc, Path=SelectedRole, Mode=TwoWay}"
RestoreParentScrollFocusOnDropDownClose="True"
ComboBoxBackground="{Binding Background, RelativeSource={RelativeSource AncestorType=Border}}"
BorderBrush="Transparent"
BorderThickness="0" />
@@ -38,6 +39,7 @@
Style="{StaticResource MandatoryFieldBorderStyle}">
<local:ComboBoxPageable x:Name="PersonSelectionControl"
SelectedItem="{Binding ElementName=ForwardTicketDialogUc, Path=SelectedPerson, Mode=TwoWay}"
RestoreParentScrollFocusOnDropDownClose="True"
ComboBoxBackground="{Binding Background, RelativeSource={RelativeSource AncestorType=Border}}"
BorderBrush="Transparent"
BorderThickness="0" />

View File

@@ -252,20 +252,39 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
_ = Dispatcher.BeginInvoke((Action)(() =>
{
try
{
var parentScrollViewer = cUiElementHelper.GetFirstParentOfType<ScrollViewer>(this);
Keyboard.ClearFocus();
if (parentScrollViewer != null)
{
parentScrollViewer.Focus();
Keyboard.Focus(parentScrollViewer);
}
}
catch (Exception exception)
{
LogException(exception);
}
}), System.Windows.Threading.DispatcherPriority.Input);
}
catch (Exception E)
{
LogException(E);
}
}
public event PropertyChangedEventHandler PropertyChanged;

View File

@@ -153,7 +153,7 @@
<UIItem Name="StartUp.SplashScreen.NoAuthorization">
<Language Lang="EN">User is not authorized for Cockpit usage</Language>
<Language Lang="DE">Nutzer ist nicht für die Cockpit-Nutzung authorisiert</Language>
<Language Lang="DE">Nutzer ist nicht für die Cockpit-Nutzung autorisiert</Language>
</UIItem>
<UIItem Name="StartUp.SplashScreen.InitAppComponents">
@@ -280,7 +280,7 @@
<UIItem Name="Searchbar.Status.Unauthorized">
<Language Lang="EN">Not authorized</Language>
<Language Lang="DE">Nicht authorisiert</Language>
<Language Lang="DE">Nicht autorisiert</Language>
</UIItem>
<UIItem Name="Searchbar.Placeholder">
@@ -473,12 +473,7 @@
<Language Lang="DE">Geschlossen</Language>
</UIItem>
<UIItem Name="Searchbar.Demo.NoTicketDetails">
<Language Lang="EN">No demo ticket details available</Language>
<Language Lang="DE">Keine Demo-Ticketdetails verfügbar</Language>
</UIItem>
<UIItem Name="TicketOverview.Notification.Title">
<UIItem Name="TicketOverview.Notification.Title">
<Language Lang="EN">Ticket overview updated</Language>
<Language Lang="DE">Ticketübersicht aktualisiert</Language>
</UIItem>
@@ -508,30 +503,30 @@
<Language Lang="DE">Eigene Tickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.Incidents">
<Language Lang="EN">My incidents</Language>
<Language Lang="DE">Eigene Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.Incidents">
<Language Lang="EN">My incidents</Language>
<Language Lang="DE">Eigene Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.UnassignedTickets">
<Language Lang="EN">My unassigned</Language>
<Language Lang="DE">Eigener Eingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Tickets">
<Language Lang="EN">Role tickets</Language>
<Language Lang="DE">Rollentickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.UnassignedTickets">
<Language Lang="EN">My unassigned</Language>
<Language Lang="DE">Eigener Eingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Tickets">
<Language Lang="EN">Role tickets</Language>
<Language Lang="DE">Rollentickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Incidents">
<Language Lang="EN">Role incidents</Language>
<Language Lang="DE">Rollenstörungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.UnassignedTickets">
<Language Lang="EN">Role unassigned</Language>
<Language Lang="DE">Rolleneingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Incidents">
<Language Lang="EN">Role incidents</Language>
<Language Lang="DE">Rollenstörungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.UnassignedTickets">
<Language Lang="EN">Role unassigned</Language>
<Language Lang="DE">Rolleneingang</Language>
</UIItem>
<!--Menu-->
<UIItem Name="Menu.About">
@@ -1720,13 +1715,13 @@
<Language Lang="DE">Tickets</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.Incidents">
<Language Lang="EN">Incidents</Language>
<Language Lang="DE">Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.UnassignedTickets">
<Language Lang="EN">Unassigned</Language>
<Language Lang="DE">Eingang</Language>
</UIItem>
</UILanguage>
<UIItem Name="TicketOverview.Row.Heading.Incidents">
<Language Lang="EN">Incidents</Language>
<Language Lang="DE">Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.UnassignedTickets">
<Language Lang="EN">Unassigned</Language>
<Language Lang="DE">Eingang</Language>
</UIItem>
</UILanguage>

View File

@@ -218,8 +218,9 @@
<Compile Include="Basics\SupportCaseDataProvider.cs" />
<Compile Include="Basics\Enums\enumActionDisplayType.cs" />
<Compile Include="Basics\Helper\DirectConnectionHelper.cs" />
<Compile Include="Basics\Helper\HealthCardDataHelper.cs" />
<Compile Include="Basics\Helper\QuickActionProtocollHelper.cs" />
<Compile Include="Basics\Helper\HealthCardDataHelper.cs" />
<Compile Include="Basics\Helper\TicketDeepLinkHelper.cs" />
<Compile Include="Basics\Helper\QuickActionProtocollHelper.cs" />
<Compile Include="Basics\Helper\RichTextBoxHelper.cs" />
<Compile Include="Basics\Helper\UiElementHelper.cs" />
<Compile Include="Basics\HotKeyManager.cs" />

View File

@@ -422,44 +422,52 @@ namespace FasdDesktopUi.Pages.DetailsPage
#region BlurBorder Click
private void BlurBorder_Click()
{
try
{
Dispatcher.Invoke(() =>
{
Panel.SetZIndex(NavigationHeadingUc, 1);
NavigationHeadingUc.ResetSelectors();
if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online)
{
SearchBarUserControl.Visibility = Visibility.Collapsed;
SearchBarUserControl.Clear();
MenuBarUserControl.Visibility = Visibility.Visible;
}
SearchResultBorder.Visibility = Visibility.Collapsed;
OverlayBorder.Child = null;
OverlayBorder.Visibility = Visibility.Collapsed;
if (BlurInvokers?.Count > 0)
{
foreach (var blurInvoker in BlurInvokers.ToArray())
{
if (blurInvoker is Window blurInvokerWindow)
blurInvokerWindow.Hide();
}
}
IsBlurred = BlurInvokers?.Count > 0;
});
}
catch (Exception E)
{
LogException(E);
}
}
private void BlurBorder_Click()
{
BlurBorder_Click(keepTicketCompletion: false);
}
private void BlurBorder_Click(bool keepTicketCompletion)
{
try
{
Dispatcher.Invoke(() =>
{
Panel.SetZIndex(NavigationHeadingUc, 1);
NavigationHeadingUc.ResetSelectors();
if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online)
{
SearchBarUserControl.Visibility = Visibility.Collapsed;
SearchBarUserControl.Clear();
MenuBarUserControl.Visibility = Visibility.Visible;
}
SearchResultBorder.Visibility = Visibility.Collapsed;
OverlayBorder.Child = null;
OverlayBorder.Visibility = Visibility.Collapsed;
if (BlurInvokers?.Count > 0)
{
foreach (var blurInvoker in BlurInvokers.ToArray())
{
if (keepTicketCompletion && blurInvoker is TicketCompletion.TicketCompletion)
continue;
if (blurInvoker is Window blurInvokerWindow)
blurInvokerWindow.Hide();
}
}
IsBlurred = BlurInvokers?.Count > 0;
});
}
catch (Exception E)
{
LogException(E);
}
}
private void BlurBorder_MouseUp(object sender, MouseButtonEventArgs e)
{
@@ -1039,8 +1047,8 @@ namespace FasdDesktopUi.Pages.DetailsPage
Dispatcher.Invoke(UpdateHistoryWidth);
if (e is BooleanEventArgs booleanArgs && booleanArgs.BooleanArg is true)
BlurBorder_Click();
if (e is BooleanEventArgs booleanArgs && booleanArgs.BooleanArg is true)
BlurBorder_Click(keepTicketCompletion: true);
isDataChangedEventRunning = false;

View File

@@ -34,8 +34,6 @@ namespace FasdDesktopUi.Pages.SearchPage
public partial class SearchPageView : Window, ISearchUiProvider
{
private static SearchPageView _instance = null;
private const int WM_NCHITTEST = 0x0084;
private const int HTTRANSPARENT = -1;
#region Ticketübersicht
@@ -47,7 +45,6 @@ namespace FasdDesktopUi.Pages.SearchPage
private EventHandler _ticketOverviewAutoContinueCaseChangedHandler;
private bool _renderTicketOverviewUserNames = false;
private readonly HashSet<cSearchHistorySearchResultEntry> _ticketOverviewHistoryEntries = new HashSet<cSearchHistorySearchResultEntry>();
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
// Event zum auslösen wenn Toggle geändert wird
public event EventHandler<bool> FilterToggleCheckedChanged;
@@ -216,15 +213,10 @@ namespace FasdDesktopUi.Pages.SearchPage
bool isEnabled = cHealthCardDataHelper.HasAvailableHealthCard(requiredInformationClasses);
string disabledReason = null;
if (!isEnabled)
{
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
else if (ShouldDisableTicketRelationForDemo(relation))
{
isEnabled = false;
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.Demo.NoTicketDetails") ?? string.Empty;
}
if (!isEnabled)
{
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
string trailingText = null;
if (_renderTicketOverviewUserNames && relation.Infos != null && relation.Infos.TryGetValue("UserDisplayName", out var relationUserDisplayName))
{
@@ -268,15 +260,10 @@ namespace FasdDesktopUi.Pages.SearchPage
{
var required = new List<enumFasdInformationClass> { cF4sdIdentityEntry.GetFromSearchResult(relation.Type) };
fallbackIsEnabled = cHealthCardDataHelper.HasAvailableHealthCard(required);
if (!fallbackIsEnabled)
{
fallbackDisabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
else if (ShouldDisableTicketRelationForDemo(relation))
{
fallbackIsEnabled = false;
fallbackDisabledReason = cMultiLanguageSupport.GetItem("Searchbar.Demo.NoTicketDetails") ?? string.Empty;
}
if (!fallbackIsEnabled)
{
fallbackDisabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
}
catch
{
@@ -915,9 +902,6 @@ namespace FasdDesktopUi.Pages.SearchPage
{
Dispatcher.Invoke(() =>
{
if (TicketOverviewBorder.Visibility == Visibility.Visible)
return;
var useRoleScope = scope.Value == TileScope.Role;
if (FilterCheckbox != null && FilterCheckbox.IsChecked != useRoleScope)
FilterCheckbox.IsChecked = useRoleScope;
@@ -1010,6 +994,9 @@ namespace FasdDesktopUi.Pages.SearchPage
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
return Task.CompletedTask;
if (TryOpenTicketOverviewRelationExternally(relation))
return Task.CompletedTask;
var ticketName = string.IsNullOrWhiteSpace(relation.DisplayName) ? relation.Name : relation.DisplayName;
var ticketId = relation.id;
if (ticketId == Guid.Empty)
@@ -1030,6 +1017,11 @@ namespace FasdDesktopUi.Pages.SearchPage
return RunTicketSearchAsync(ticketName, ticketId, userName, sids, suppressUi: true);
}
private bool TryOpenTicketOverviewRelationExternally(cF4sdApiSearchResultRelation relation)
{
return TicketDeepLinkHelper.TryOpenTicketRelationExternally(relation);
}
private Task RunTicketSearchAsync(string ticketName, Guid ticketId, string userName, string sids, bool suppressUi = false)
{
if (ticketId == Guid.Empty)
@@ -1064,6 +1056,7 @@ namespace FasdDesktopUi.Pages.SearchPage
var _ticketRelation = new cF4sdApiSearchResultRelation()
{
Type = enumF4sdSearchResultClass.Ticket,
Name = ticketName,
DisplayName = ticketName,
id = ticketId,
Status = enumF4sdSearchResultStatus.Active,
@@ -1351,14 +1344,14 @@ namespace FasdDesktopUi.Pages.SearchPage
var normalized = key.ToLowerInvariant();
if (normalized.StartsWith("tickets"))
rowKey = "TicketOverview.Row.Heading.Tickets";
else if (normalized.StartsWith("incident"))
rowKey = "TicketOverview.Row.Heading.Incidents";
else if (normalized.StartsWith("unassigned"))
rowKey = "TicketOverview.Row.Heading.UnassignedTickets";
else
return false;
if (normalized.StartsWith("tickets"))
rowKey = "TicketOverview.Row.Heading.Tickets";
else if (normalized.StartsWith("incident"))
rowKey = "TicketOverview.Row.Heading.Incidents";
else if (normalized.StartsWith("unassigned"))
rowKey = "TicketOverview.Row.Heading.UnassignedTickets";
else
return false;
columnKey = ResolveColumnTranslationKey(normalized);
return columnKey != null;
@@ -1380,10 +1373,10 @@ namespace FasdDesktopUi.Pages.SearchPage
string suffix = null;
if (string.Equals(rowKey, "TicketOverview.Row.Heading.Tickets", StringComparison.OrdinalIgnoreCase))
suffix = "Tickets";
else if (string.Equals(rowKey, "TicketOverview.Row.Heading.Incidents", StringComparison.OrdinalIgnoreCase))
suffix = "Incidents";
else if (string.Equals(rowKey, "TicketOverview.Row.Heading.UnassignedTickets", StringComparison.OrdinalIgnoreCase))
suffix = "UnassignedTickets";
else if (string.Equals(rowKey, "TicketOverview.Row.Heading.Incidents", StringComparison.OrdinalIgnoreCase))
suffix = "Incidents";
else if (string.Equals(rowKey, "TicketOverview.Row.Heading.UnassignedTickets", StringComparison.OrdinalIgnoreCase))
suffix = "UnassignedTickets";
var translationKey = scope == TileScope.Role
? $"TicketOverview.ScopeRow.Role.{suffix}"
@@ -1461,15 +1454,10 @@ namespace FasdDesktopUi.Pages.SearchPage
var required = new List<enumFasdInformationClass> { cF4sdIdentityEntry.GetFromSearchResult(r.Type) };
bool isEnabled = cHealthCardDataHelper.HasAvailableHealthCard(required);
string disabledReason = null;
if (!isEnabled)
{
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
else if (ShouldDisableTicketRelationForDemo(r))
{
isEnabled = false;
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.Demo.NoTicketDetails") ?? string.Empty;
}
if (!isEnabled)
{
disabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty;
}
string trailingUser = null;
if (_renderTicketOverviewUserNames && r.Infos != null && r.Infos.TryGetValue("UserDisplayName", out var userDisplayName))
{
@@ -1565,30 +1553,6 @@ namespace FasdDesktopUi.Pages.SearchPage
return "Searchbar.Header.Filter.Overview";
}
private bool ShouldDisableTicketRelationForDemo(cF4sdApiSearchResultRelation relation)
{
if (relation == null)
return false;
var communication = cFasdCockpitCommunicationBase.Instance;
if (communication?.IsDemo() != true)
return false;
if (relation.Type != enumF4sdSearchResultClass.Ticket)
return false;
if (relation.Infos == null)
return false;
if (!relation.Infos.TryGetValue(DemoTicketHasDetailsInfoKey, out var hasDetailsValue))
return false;
if (bool.TryParse(hasDetailsValue, out var hasDetails))
return !hasDetails;
return true;
}
private async Task<List<cF4sdApiSearchResultRelation>> LoadRelationsForTileAsync(string key, bool useRoleScope, int count)
{
var communication = cFasdCockpitCommunicationBase.Instance;
@@ -1717,6 +1681,11 @@ namespace FasdDesktopUi.Pages.SearchPage
#endregion
#region Click-Through fuer transparente SearchView-Bereiche
private const int WM_NCHITTEST = 0x0084;
private const int HTTRANSPARENT = -1;
private IntPtr SearchViewWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_NCHITTEST)
@@ -1783,6 +1752,8 @@ namespace FasdDesktopUi.Pages.SearchPage
return LogicalTreeHelper.GetParent(current);
}
#endregion
private void UpdateSearchResults(cFilteredResults filteredResults)
{
this.Dispatcher.Invoke(new Action(() =>

View File

@@ -1,29 +1,30 @@
<settingspagebase:SettingsPageBase
xmlns:settingspagebase="clr-namespace:FasdDesktopUi.Pages.SettingsPage"
x:Class="FasdDesktopUi.Pages.SettingsPage.SettingsPageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FasdDesktopUi.Pages.SettingsPage"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="SettingsPageView"
ResizeMode="NoResize"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
MinHeight="100"
MinWidth="400"
ShowInTaskbar="False"
Topmost="True"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Initialized="Window_Initialized"
x:Name="SettingsWindow"
KeyDown="SettingsWindow_KeyDown" Closed="SettingsWindow_Closed" IsVisibleChanged="SettingsWindow_IsVisibleChanged">
<settingspagebase:SettingsPageBase xmlns:settingspagebase="clr-namespace:FasdDesktopUi.Pages.SettingsPage"
x:Class="FasdDesktopUi.Pages.SettingsPage.SettingsPageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FasdDesktopUi.Pages.SettingsPage"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="SettingsPageView"
ResizeMode="NoResize"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
MinHeight="100"
MinWidth="400"
ShowInTaskbar="False"
Topmost="True"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Initialized="Window_Initialized"
x:Name="SettingsWindow"
KeyDown="SettingsWindow_KeyDown"
Closed="SettingsWindow_Closed"
IsVisibleChanged="SettingsWindow_IsVisibleChanged">
<settingspagebase:SettingsPageBase.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
@@ -203,25 +204,39 @@
SelectedCountryCode="GB" />
</StackPanel>
<StackPanel x:Name="ShouldSkipSlimViewLabel" Orientation="Horizontal">
<StackPanel x:Name="ShouldSkipSlimViewLabel"
Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Menu.ShouldSkipSlimView}" />
<ico:AdaptableIcon x:Name="ShouldSkipSlimViewPolicy" SelectedInternIcon="lock_closed" Margin="-25,-5,0,0" IconWidth="23" IconHeight="23" Visibility="Collapsed"/>
<ico:AdaptableIcon x:Name="ShouldSkipSlimViewPolicy"
SelectedInternIcon="lock_closed"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
Margin="-25,-5,0,0"
IconWidth="23"
IconHeight="23"
Visibility="Collapsed" />
</StackPanel>
<CheckBox x:Name="ShouldSkipSlimViewCheckBox"
Style="{DynamicResource ToggleSwitch}"
IsChecked="{Binding ElementName=SettingsWindow, Path=ShouldSkipSlimView}"
HorizontalAlignment="Left"
Margin="0,3,0,10"
>
Margin="0,3,0,10">
</CheckBox>
<StackPanel x:Name="PositionOfSmallViewsLabel" Orientation="Horizontal">
<StackPanel x:Name="PositionOfSmallViewsLabel"
Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Menu.PositionOfSmallViews}" />
<ico:AdaptableIcon x:Name="PositionOfSmallViewsPolicy" SelectedInternIcon="lock_closed" Margin="-25,-5,0,0" IconWidth="23" IconHeight="23" Visibility="Collapsed"/>
<ico:AdaptableIcon x:Name="PositionOfSmallViewsPolicy"
SelectedInternIcon="lock_closed"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
Margin="-25,-5,0,0"
IconWidth="23"
IconHeight="23"
Visibility="Collapsed" />
</StackPanel>
<Grid x:Name="PositionOfSmallViewsInput" Grid.IsSharedSizeScope="True"
<Grid x:Name="PositionOfSmallViewsInput"
Grid.IsSharedSizeScope="True"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
@@ -269,12 +284,20 @@
</Grid>
<StackPanel x:Name="PositionOfFavouriteBarLabel" Orientation="Horizontal">
<StackPanel x:Name="PositionOfFavouriteBarLabel"
Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Menu.PositionOfFavouriteBar}" />
<ico:AdaptableIcon x:Name="PositionOfFavouriteBarPolicy" SelectedInternIcon="lock_closed" Margin="-25,-5,0,0" IconWidth="23" IconHeight="23" Visibility="Collapsed"/>
<ico:AdaptableIcon x:Name="PositionOfFavouriteBarPolicy"
SelectedInternIcon="lock_closed"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
Margin="-25,-5,0,0"
IconWidth="23"
IconHeight="23"
Visibility="Collapsed" />
</StackPanel>
<Grid x:Name="PositionOfFavouriteBarInput" Grid.IsSharedSizeScope="True"
<Grid x:Name="PositionOfFavouriteBarInput"
Grid.IsSharedSizeScope="True"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"

View File

@@ -3,19 +3,26 @@ using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Models;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static C4IT.Logging.cLogManager;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using WinForms = System.Windows.Forms;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Pages.TicketCompletion
{
public partial class TicketCompletion : Window, IBlurInvoker, INotifyPropertyChanged
{
private bool isCanceled = false;
public partial class TicketCompletion : Window, IBlurInvoker, INotifyPropertyChanged
{
private const double MinWindowHeightDip = 220d;
private const double WindowWorkingAreaMarginDip = 12d;
private const double DialogNonContentReserveDip = 180d;
private bool isUpdatingDialogBounds;
private bool isCanceled = false;
private bool _WaitForClosing = false;
public bool WaitForClosing
@@ -42,13 +49,31 @@ namespace FasdDesktopUi.Pages.TicketCompletion
CloseCaseDialogUc.DataProvider = _dataProvider;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
cFocusInvoker.GotFocus += ElementGotFocus;
cFocusInvoker.LostFocus += ElementLostFocus;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
cFocusInvoker.GotFocus += ElementGotFocus;
cFocusInvoker.LostFocus += ElementLostFocus;
SizeChanged += TicketCompletion_SizeChanged;
Loaded += TicketCompletion_Loaded;
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
UpdateDialogMaxHeightToScreen();
}
protected override void OnLocationChanged(EventArgs e)
{
base.OnLocationChanged(e);
UpdateDialogMaxHeightToScreen();
}
private void TicketCompletion_Loaded(object sender, RoutedEventArgs e) => UpdateDialogMaxHeightToScreen();
private void TicketCompletion_SizeChanged(object sender, SizeChangedEventArgs e) => UpdateDialogMaxHeightToScreen();
#region ClosingBusy
@@ -101,20 +126,98 @@ namespace FasdDesktopUi.Pages.TicketCompletion
return null;
}
#region Close_Click
#region Close_Click
private void Close_Click()
{
isCanceled = true;
TrySetDialogResult(null);
Close();
}
private void Close_Click()
{
DialogResult = null;
isCanceled = true;
Close();
}
private void CloseButton_Click(object sender, InputEventArgs e) => Close_Click();
#endregion
#region Internal Focus Events
private void CloseButton_Click(object sender, InputEventArgs e) => Close_Click();
#endregion
private void TrySetDialogResult(bool? result)
{
try
{
DialogResult = result;
}
catch (InvalidOperationException)
{
// Window was not shown as dialog; ignore.
}
}
private void UpdateDialogMaxHeightToScreen()
{
if (isUpdatingDialogBounds)
return;
isUpdatingDialogBounds = true;
try
{
WinForms.Screen screen = null;
IntPtr currentHandle = new WindowInteropHelper(this).Handle;
if (currentHandle != IntPtr.Zero)
{
screen = WinForms.Screen.FromHandle(currentHandle);
}
else if (Owner != null)
{
IntPtr ownerHandle = new WindowInteropHelper(Owner).Handle;
if (ownerHandle != IntPtr.Zero)
screen = WinForms.Screen.FromHandle(ownerHandle);
}
screen = screen ?? WinForms.Screen.PrimaryScreen;
var workingArea = screen?.WorkingArea ?? WinForms.Screen.PrimaryScreen.WorkingArea;
var dpiScaleY = VisualTreeHelper.GetDpi(this).DpiScaleY;
var safeDpiScaleY = Math.Max(0.1, dpiScaleY);
var workingAreaTopDip = workingArea.Top / safeDpiScaleY;
var workingAreaBottomDip = workingArea.Bottom / safeDpiScaleY;
var workingAreaHeightDip = workingArea.Height / safeDpiScaleY;
var availableWindowHeightDip = workingAreaHeightDip - (WindowWorkingAreaMarginDip * 2);
MaxHeight = Math.Max(MinWindowHeightDip, availableWindowHeightDip);
if (!double.IsNaN(Top))
{
var minTop = workingAreaTopDip + WindowWorkingAreaMarginDip;
var maxBottom = workingAreaBottomDip - WindowWorkingAreaMarginDip;
if (Top < minTop)
Top = minTop;
var currentBottom = Top + ActualHeight;
if (currentBottom > maxBottom)
Top = Math.Max(minTop, maxBottom - ActualHeight);
}
double nonDialogReserve = DialogNonContentReserveDip;
if (CloseCaseDialogUc != null && CloseCaseDialogUc.IsLoaded)
{
var estimatedReserve = ActualHeight - CloseCaseDialogUc.ActualHeight;
if (estimatedReserve > 0)
nonDialogReserve = Math.Max(nonDialogReserve, estimatedReserve + WindowWorkingAreaMarginDip);
}
CloseCaseDialogUc?.SetDialogContentMaxHeight(MaxHeight - nonDialogReserve);
}
catch (Exception ex)
{
LogException(ex);
}
finally
{
isUpdatingDialogBounds = false;
}
}
#region Internal Focus Events
private void ElementGotFocus(object sender, EventArgs e)
{
@@ -200,15 +303,15 @@ namespace FasdDesktopUi.Pages.TicketCompletion
bool closedSuccessfull = await CloseCaseDialogUc.CloseCaseAsync(_dataProvider.Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User).Id);
if (closedSuccessfull)
{
SuccessPage.SuccessPage successPage = new SuccessPage.SuccessPage();
successPage.Show();
await _dataProvider?.CloseCaseAsync();
DialogResult = true;
Close();
}
}
if (closedSuccessfull)
{
SuccessPage.SuccessPage successPage = new SuccessPage.SuccessPage();
successPage.Show();
await _dataProvider?.CloseCaseAsync();
TrySetDialogResult(true);
Close();
}
}
catch (Exception E)
{
LogException(E);