diff --git a/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs b/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs index 5ce0ef1..f113cbd 100644 --- a/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs +++ b/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs @@ -35,7 +35,6 @@ namespace C4IT.FASD.Cockpit.Communication new Dictionary>>(StringComparer.OrdinalIgnoreCase); private readonly HashSet _generatedTicketIds = new HashSet(); private readonly object _demoTicketSync = new object(); - private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails"; #endregion public cFasdCockpitCommunicationDemo() @@ -47,6 +46,7 @@ namespace C4IT.FASD.Cockpit.Communication BuildCategoryLookup(); LoadTicketOverviewRelations(); LoadGeneratedTickets(); + EnsureOverviewTicketJournalEntries(); } public override bool IsDemo() => true; @@ -193,11 +193,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); @@ -268,9 +268,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(); + + 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 = $"

{text ?? string.Empty}

", + IsVisibleForUser = true, + CreationDate = creationTime, + CreationDaysSinceNow = Math.Max(0, (int)(DateTime.Now - creationTime).TotalDays) + }; + } private static cF4SDTicket ConvertToTicket(DemoTicketRecord record) { @@ -378,27 +481,31 @@ namespace C4IT.FASD.Cockpit.Communication await SimulateTicketOverviewLatencyAsync(count); return new List(); } - int requestedCount = count <= 0 ? definitions.Count : Math.Min(count, definitions.Count); - await SimulateTicketOverviewLatencyAsync(requestedCount); - var relations = new List(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(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 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 - { - ["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() - }, + Status = enumF4sdSearchResultStatus.Active, + Infos = new Dictionary + { + ["Summary"] = summary, + ["StatusId"] = definition.StatusId ?? string.Empty, + ["UserDisplayName"] = definition.UserDisplayName ?? string.Empty, + ["UserAccount"] = definition.UserAccount ?? string.Empty, + ["UserDomain"] = definition.UserDomain ?? string.Empty + }, Identities = new cF4sdIdentityList { new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = definition.TicketId }, @@ -416,32 +523,40 @@ 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) - { + 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 Task SimulateTicketOverviewLatencyAsync(int count) + { int baseMs = 420; int perItem = 100; int capped = Math.Max(0, Math.Min(count, 5)); @@ -714,21 +829,115 @@ namespace C4IT.FASD.Cockpit.Communication return output; } - public override async Task GetUserSearchResults(string Name, List 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() { new cFasdApiSearchResultEntry() { id = data.SampleDataId, Name = data.SampleDataName, DisplayName = data.SampleDataName, Type = searchResultClass } }; - } - } - + public override async Task GetUserSearchResults(string Name, List 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(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() + { + new cFasdApiSearchResultEntry() + { + id = data.SampleDataId, + Name = data.SampleDataName, + DisplayName = data.SampleDataName, + Type = searchResultClass + } + }; + } + } + await Task.CompletedTask; } catch (Exception E) @@ -758,8 +967,8 @@ namespace C4IT.FASD.Cockpit.Communication var output = new List(); - 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() { ["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() } } }); @@ -930,18 +1139,67 @@ 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 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 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() + { + ["Summary"] = demoTicket.Summary ?? string.Empty, + ["Status"] = demoTicket.Status.ToString(), + ["StatusId"] = ((int)demoTicket.Status).ToString(), + ["Asset"] = demoTicket.Asset ?? string.Empty + }, + Identities = new cF4sdIdentityList() + { + new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = userId }, + new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Ticket, Id = demoTicket.Id } + } + }); + } + } + + public override async Task GetHealthCardData(cF4sdHealthCardRawDataRequest requestData) + { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); @@ -968,14 +1226,29 @@ namespace C4IT.FASD.Cockpit.Communication 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: diff --git a/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewGeneratedTickets.json b/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewGeneratedTickets.json index 278a2a4..cf553d4 100644 --- a/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewGeneratedTickets.json +++ b/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewGeneratedTickets.json @@ -108,9 +108,6 @@ ] } }, - - /* --- Ab hier: 5 neue Klassiker --- */ - { "TileKey": "TicketsNew", "UseRoleScope": false, @@ -247,5 +244,118 @@ } } ], - "Tickets": [] + "Tickets": [ + { + "TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6", + "UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2", + "TileKey": "UnassignedTickets", + "UseRoleScope": false, + "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": "

Ein Pool-Notebook fuer die morgige Schulung ist nicht auffindbar. Das Ticket wurde noch keinem Bearbeiter zugewiesen.

", + "Priority": 2, + "Journal": [ + { + "Header": "Ticket erstellt", + "Description": "Demodatensatz fuer Ticketuebersicht (Eingang).", + "DescriptionHtml": "

Demodatensatz fuer Ticketuebersicht (Eingang).

", + "IsVisibleForUser": true + } + ] + } + }, + { + "TicketId": "ebe8818e-b197-411e-b56e-40b77b623ae2", + "UserId": "436e8d67-1b9b-4b1a-83e9-0b1e8fa0173b", + "TileKey": "UnassignedTickets", + "UseRoleScope": false, + "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": "

Der Etikettendrucker im Lager zeigt permanent Papierstau, obwohl kein Papier klemmt. Ticket ist neu und noch unzugewiesen.

", + "Priority": 2, + "Journal": [ + { + "Header": "Ticket erstellt", + "Description": "Demodatensatz fuer Ticketuebersicht (Eingang).", + "DescriptionHtml": "

Demodatensatz fuer Ticketuebersicht (Eingang).

", + "IsVisibleForUser": true + } + ] + } + }, + { + "TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab", + "UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec", + "TileKey": "UnassignedTicketsCritical", + "UseRoleScope": false, + "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": "

Der WLAN-Controller im Werk rebootet im 5-Minuten-Takt. Das Ticket ist kritisch markiert und noch nicht personell zugewiesen.

", + "Priority": 1, + "Journal": [ + { + "Header": "Stoerung eingegangen", + "Description": "Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).", + "DescriptionHtml": "

Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).

", + "IsVisibleForUser": true + } + ] + } + }, + { + "TicketId": "d427dc61-9842-4464-b37a-612878d3de0f", + "UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a", + "TileKey": "UnassignedTicketsCritical", + "UseRoleScope": false, + "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": "

Naechtlicher Buchungsjob endet mit Fehlercode. Ticket ist kritisch und liegt im Eingang zur Erstzuweisung.

", + "Priority": 1, + "Journal": [ + { + "Header": "Stoerung eingegangen", + "Description": "Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).", + "DescriptionHtml": "

Demodatensatz fuer Ticketuebersicht (Eingang Kritisch).

", + "IsVisibleForUser": true + } + ] + } + } + ] } diff --git a/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewRelations.json b/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewRelations.json index e1375ed..a03cbc7 100644 --- a/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewRelations.json +++ b/FasdCockpitCommunicationDemo/MockupTicketOverview/TicketOverviewRelations.json @@ -73,7 +73,7 @@ "TicketId": "2e9cb83d-ecb7-c93b-e8e4-08daaa97265f", "UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a", "DisplayName": "TCK00405", - "Summary": "OneDrive Synchronisation bleibt haengen", + "Summary": "Mein OneDrive synchronisiert nicht mehr", "UserDisplayName": "Ticket, Timo", "UserAccount": "TT007", "UserDomain": "CONTOSO", @@ -153,7 +153,7 @@ "TicketId": "de403992-98cb-4476-9e04-d645ab22e6de", "UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a", "DisplayName": "TCK00411", - "Summary": "Rueckfrage zur Passwort Ruecksetzung beantworten", + "Summary": "Passwort muss zur\u00fcckgesetzt werden", "UserDisplayName": "Ticket, Timo", "UserAccount": "TT007", "UserDomain": "CONTOSO", @@ -175,7 +175,7 @@ "TicketId": "de403992-98cb-4476-9e04-d645ab22e6de", "UserId": "42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a", "DisplayName": "TCK00411", - "Summary": "Rueckfrage zur Passwort Ruecksetzung beantworten", + "Summary": "Passwort muss zur\u00fcckgesetzt werden", "UserDisplayName": "Ticket, Timo", "UserAccount": "TT007", "UserDomain": "CONTOSO", @@ -207,7 +207,7 @@ }, { "TicketId": "a8deb50d-9f15-4371-9ebc-a28791f27d5c", - "UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92", + "UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2", "DisplayName": "INC00402", "Summary": "SharePoint Bereich Vertrieb laedt extrem langsam", "UserDisplayName": "Virtual, Vera", @@ -381,7 +381,7 @@ "Personal": [ { "TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6", - "UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92", + "UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2", "DisplayName": "TCK00414", "Summary": "Pool Notebook fuer Schulungsteilnehmer fehlt", "UserDisplayName": "Virtual, Vera", @@ -403,7 +403,7 @@ "Role": [ { "TicketId": "e2e49f85-1a81-47e8-935b-d76898c155f6", - "UserId": "76f86d28-862c-4fa2-9062-8367be7fbd92", + "UserId": "916db36b-fb6e-4212-81c1-e72acdab77d2", "DisplayName": "TCK00414", "Summary": "Pool Notebook fuer Schulungsteilnehmer fehlt", "UserDisplayName": "Virtual, Vera", @@ -425,7 +425,7 @@ "TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab", "UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec", "DisplayName": "TCK00416", - "Summary": "Ueberwachung meldet sporadische Alarme", + "Summary": "WLAN Controller im Werk startet zyklisch neu", "UserDisplayName": "Seifert, Dominik", "UserAccount": "DS014", "UserDomain": "CONTOSO", @@ -439,7 +439,7 @@ "TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab", "UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec", "DisplayName": "TCK00416", - "Summary": "Ueberwachung meldet sporadische Alarme", + "Summary": "WLAN Controller im Werk startet zyklisch neu", "UserDisplayName": "Seifert, Dominik", "UserAccount": "DS014", "UserDomain": "CONTOSO", @@ -451,7 +451,7 @@ "TicketId": "9e1d5d1b-5a22-430e-99ea-59840257caab", "UserId": "deece196-d8b6-4a9c-a2b9-3c2ae9c6d4ec", "DisplayName": "TCK00416", - "Summary": "Ueberwachung meldet sporadische Alarme", + "Summary": "WLAN Controller im Werk startet zyklisch neu", "UserDisplayName": "Seifert, Dominik", "UserAccount": "DS014", "UserDomain": "CONTOSO", @@ -461,7 +461,7 @@ "TicketId": "d427dc61-9842-4464-b37a-612878d3de0f", "UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a", "DisplayName": "TCK00417", - "Summary": "Produktionsroboter steht nach Not Aus", + "Summary": "SAP Buchungsjob bricht nachts wiederholt ab", "UserDisplayName": "Boss, Bernd", "UserAccount": "BB003", "UserDomain": "CONTOSO", diff --git a/FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs b/FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs index 12dea44..12e5243 100644 --- a/FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs +++ b/FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs @@ -33,7 +33,6 @@ namespace FasdDesktopUi.Basics.Services "UnassignedTickets", "UnassignedTicketsCritical" }; - private const string DemoTicketDetailsKey = "Demo.HasTicketDetails"; private readonly Dispatcher _dispatcher; private readonly Dictionary _currentCounts = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<(string Key, bool UseRoleScope), List> _demoRelations = new Dictionary<(string, bool), List>(); @@ -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; @@ -560,15 +547,14 @@ namespace FasdDesktopUi.Basics.Services Name = record.DisplayName, id = record.TicketId, Status = enumF4sdSearchResultStatus.Active, - Infos = new Dictionary(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 - }, + Infos = new Dictionary(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 + }, Identities = new cF4sdIdentityList { new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = record.TicketId }, diff --git a/FasdDesktopUi/Config/LanguageDefinitions.xml b/FasdDesktopUi/Config/LanguageDefinitions.xml index b48bc7b..7909aa9 100644 --- a/FasdDesktopUi/Config/LanguageDefinitions.xml +++ b/FasdDesktopUi/Config/LanguageDefinitions.xml @@ -473,12 +473,7 @@ Geschlossen - - No demo ticket details available - Keine Demo-Ticketdetails verfügbar - - - + Ticket overview updated Ticketübersicht aktualisiert diff --git a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs index 89b92b4..7e51e9c 100644 --- a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs +++ b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs @@ -47,7 +47,6 @@ namespace FasdDesktopUi.Pages.SearchPage private EventHandler _ticketOverviewAutoContinueCaseChangedHandler; private bool _renderTicketOverviewUserNames = false; private readonly HashSet _ticketOverviewHistoryEntries = new HashSet(); - private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails"; // Event zum auslösen wenn Toggle geändert wird public event EventHandler FilterToggleCheckedChanged; @@ -216,15 +215,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 +262,10 @@ namespace FasdDesktopUi.Pages.SearchPage { var required = new List { 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 { @@ -1470,15 +1459,10 @@ namespace FasdDesktopUi.Pages.SearchPage var required = new List { 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)) { @@ -1574,30 +1558,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> LoadRelationsForTileAsync(string key, bool useRoleScope, int count) { var communication = cFasdCockpitCommunicationBase.Instance;