From 696629b5a8b0c6d9785667f2baec7c0f7419128d Mon Sep 17 00:00:00 2001 From: Meik Date: Tue, 3 Feb 2026 16:46:49 +0100 Subject: [PATCH] aktueller Stand --- .../FasdCockpitCommunicationBase.cs | 13 +- .../FasdCockpitCommunicationWeb.cs | 18 +- .../F4SDCockpitCommunicationDemo.cs | 53 +- FasdDesktopUi/App.xaml.cs | 60 +- .../Pages/SearchPage/SearchPageView.xaml.cs | 571 +++++++++++------- 5 files changed, 431 insertions(+), 284 deletions(-) diff --git a/FasdCockpitBase/FasdCockpitCommunicationBase.cs b/FasdCockpitBase/FasdCockpitCommunicationBase.cs index 5897a90..7c1a15b 100644 --- a/FasdCockpitBase/FasdCockpitCommunicationBase.cs +++ b/FasdCockpitBase/FasdCockpitCommunicationBase.cs @@ -62,13 +62,18 @@ namespace C4IT.FASD.Cockpit.Communication public abstract Task GetUserSearchResults(string Name, List SIDs); public abstract Task StartGatheringRelations(IEnumerable relatedTo, CancellationToken token); - public abstract Task GetStagedRelations(Guid id, CancellationToken token); - + public abstract Task GetStagedRelations(Guid id, CancellationToken token); + public abstract Task> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List searchResults); + + #region Ticketübersicht + public abstract Task> GetTicketOverviewRelations(string key, bool useRoleScope, int count); public abstract Task> GetTicketOverviewCounts(IEnumerable keys, bool useRoleScope); - - public abstract Task GetHealthCardData(cF4sdHealthCardRawDataRequest requestData); + + #endregion + + public abstract Task GetHealthCardData(cF4sdHealthCardRawDataRequest requestData); public abstract Task GetHealthCardData(Guid healthCardId); diff --git a/FasdCockpitCommunication/FasdCockpitCommunicationWeb.cs b/FasdCockpitCommunication/FasdCockpitCommunicationWeb.cs index 6c75dd3..93f9fe0 100644 --- a/FasdCockpitCommunication/FasdCockpitCommunicationWeb.cs +++ b/FasdCockpitCommunication/FasdCockpitCommunicationWeb.cs @@ -1094,8 +1094,11 @@ namespace C4IT.FASD.Cockpit.Communication LogMethodEnd(CM); } - return output; - } + return output; + } + + #region Ticketübersicht + public override async Task> GetTicketOverviewCounts(IEnumerable keys, bool useRoleScope) { var CM = MethodBase.GetCurrentMethod(); @@ -1209,10 +1212,13 @@ namespace C4IT.FASD.Cockpit.Communication return output; } - public override async Task GetHealthCardData(cF4sdHealthCardRawDataRequest requestData) - { - var CM = MethodBase.GetCurrentMethod(); - LogMethodBegin(CM); + + #endregion + + public override async Task GetHealthCardData(cF4sdHealthCardRawDataRequest requestData) + { + var CM = MethodBase.GetCurrentMethod(); + LogMethodBegin(CM); var apiError = 0; var timeStart = DateTime.UtcNow; diff --git a/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs b/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs index 84116d5..b6508fe 100644 --- a/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs +++ b/FasdCockpitCommunicationDemo/F4SDCockpitCommunicationDemo.cs @@ -23,14 +23,19 @@ namespace C4IT.FASD.Cockpit.Communication { private int ticketCounter = 475; - private readonly List MockupData = new List(); - - private readonly Dictionary MockupPickup = new Dictionary(); - private readonly Dictionary>> TicketOverviewRelations = - new Dictionary>>(StringComparer.OrdinalIgnoreCase); - private readonly HashSet _generatedTicketIds = new HashSet(); - private readonly object _demoTicketSync = new object(); - private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails"; + private readonly List MockupData = new List(); + + private readonly Dictionary MockupPickup = new Dictionary(); + + #region Ticketübersicht + + private readonly Dictionary>> TicketOverviewRelations = + 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() { if (LoadMockupData(out var loadedData)) @@ -91,12 +96,15 @@ namespace C4IT.FASD.Cockpit.Communication LogMethodEnd(CM); } - return null; - } - private void LoadTicketOverviewRelations() - { - var CM = MethodBase.GetCurrentMethod(); - LogMethodBegin(CM); + return null; + } + + #region Ticketübersicht + + private void LoadTicketOverviewRelations() + { + var CM = MethodBase.GetCurrentMethod(); + LogMethodBegin(CM); try { TicketOverviewRelations.Clear(); @@ -391,13 +399,16 @@ namespace C4IT.FASD.Cockpit.Communication 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); - } - private bool LoadMockupData(out List sampleData) - { - var CM = MethodBase.GetCurrentMethod(); - LogMethodBegin(CM); + int delay = Math.Max(240, Math.Min(baseMs + capped * perItem, 2000)); + return Task.Delay(delay); + } + + #endregion + + private bool LoadMockupData(out List sampleData) + { + var CM = MethodBase.GetCurrentMethod(); + LogMethodBegin(CM); sampleData = new List(); diff --git a/FasdDesktopUi/App.xaml.cs b/FasdDesktopUi/App.xaml.cs index 1b49613..9bf006c 100644 --- a/FasdDesktopUi/App.xaml.cs +++ b/FasdDesktopUi/App.xaml.cs @@ -39,8 +39,12 @@ namespace FasdDesktopUi public System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon() { Text = $"First Aid Service Desk" }; public bool UseOsLanguage = string.IsNullOrEmpty(cFasdCockpitConfig.Instance.SelectedLanguage); + #region Ticketübersicht + private TrayTicketNotificationManager _ticketTrayNotification; private TileScope? _pendingTicketOverviewScope; + + #endregion private async void Application_Startup(object sender, StartupEventArgs e) { @@ -181,18 +185,8 @@ namespace FasdDesktopUi if (searchView == null) return; - var hasNotification = HasPendingTicketOverviewNotification(); - if (hasNotification) - { - if (!searchView.IsVisible) - searchView.ActivateSearchView(); - else - searchView.BringToFrontPreserveState(); - - searchView.ShowTicketOverviewPaneForScope(PendingTicketOverviewScope); - ClearTicketOverviewTrayNotification(); + if (TryHandleTicketOverviewNotificationClick(searchView)) return; - } #if isDemo if (searchView.IsVisible) @@ -278,9 +272,29 @@ namespace FasdDesktopUi finally { LogMethodEnd(CM); - } - } - + } + } + + #region Ticketübersicht + + private bool TryHandleTicketOverviewNotificationClick(SearchPageView searchView) + { + if (searchView == null) + return false; + + if (!HasPendingTicketOverviewNotification()) + return false; + + if (!searchView.IsVisible) + searchView.ActivateSearchView(); + else + searchView.BringToFrontPreserveState(); + + searchView.ShowTicketOverviewPaneForScope(PendingTicketOverviewScope); + ClearTicketOverviewTrayNotification(); + return true; + } + private void NotifyIcon_BalloonTipClicked(object sender, EventArgs e) { try @@ -294,11 +308,11 @@ namespace FasdDesktopUi LogException(E); } } - - private bool HasPendingTicketOverviewNotification() - { - return _ticketTrayNotification?.HasNotification ?? false; - } + + private bool HasPendingTicketOverviewNotification() + { + return _ticketTrayNotification?.HasNotification ?? false; + } public void ShowTicketOverviewTrayNotification(string message) { @@ -331,9 +345,11 @@ namespace FasdDesktopUi } public TileScope? PendingTicketOverviewScope => _pendingTicketOverviewScope; - - private System.Windows.Forms.ToolStripItem SetUpNotifyIconLanguageOption() - { + + #endregion + + private System.Windows.Forms.ToolStripItem SetUpNotifyIconLanguageOption() + { try { var output = new System.Windows.Forms.ToolStripMenuItem() { Text = cMultiLanguageSupport.GetItem("Menu.SelectLanguage") }; diff --git a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs index 5ac2548..d5ec504 100644 --- a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs +++ b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs @@ -36,9 +36,26 @@ namespace FasdDesktopUi.Pages.SearchPage private static SearchPageView _instance = null; private const int WM_NCHITTEST = 0x0084; private const int HTTRANSPARENT = -1; + + #region Ticketübersicht + private readonly HashSet _ticketOverviewNotificationScopesPrimed = new HashSet(); private bool _ticketOverviewFirstEventHandled; private readonly HashSet _ticketOverviewInitWasEmptyScopes = new HashSet(); + private bool _ticketOverviewAutoContinueActive; + private DispatcherTimer _ticketOverviewAutoContinueFallbackTimer; + 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; + + // Aktueller Zustand der Checkbox + public bool IsFilterChecked => FilterCheckbox.IsChecked == true; + + #endregion public static SearchPageView Instance { get @@ -47,25 +64,17 @@ namespace FasdDesktopUi.Pages.SearchPage } } - private cF4sdPipeServer _pipeServer; - private cHotKeyManager _hotKeyManager; + private cF4sdPipeServer _pipeServer; + private cHotKeyManager _hotKeyManager; private CancellationTokenSource _searchCancellationTokenSource = new CancellationTokenSource(); private bool _isActivating = false; - private cF4sdApiSearchResultRelation preSelectedRelation = null; - 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; + private cF4sdApiSearchResultRelation preSelectedRelation = null; - // Aktueller Zustand der Checkbox - public bool IsFilterChecked => FilterCheckbox.IsChecked == true; - - private readonly IRelationService _relationService = new RelationService(); - public SupportCaseSearchService SearchService { get; } + private readonly IRelationService _relationService = new RelationService(); + public SupportCaseSearchService SearchService { get; } private SearchPageView() { @@ -166,114 +175,14 @@ namespace FasdDesktopUi.Pages.SearchPage BodyStack_SearchResults.Visibility = (isVisible || SearchResultBorder.IsVisible) ? Visibility.Visible : Visibility.Collapsed; ScheduleSearchResultMaxHeightUpdate(); } - - private bool CheckTicketOverviewAvailability() + public void ShowLoadingTextItem(string itemText) { - return cFasdCockpitConfig.Instance?.Global?.TicketConfiguration?.ShowOverview == true; + SetSearchHistoryVisibility(false); + ResultMenu.ShowLoadingTextItem(itemText); } - private void UpdateTicketOverviewAvailability() + public void ShowSearchRelations(cSearchHistorySearchResultEntry searchHistoryEntry, IRelationService relationService, ISearchUiProvider searchUiProvider) { - var enabled = CheckTicketOverviewAvailability(); - var service = TicketOverviewUpdateService.Instance; - service?.UpdateAvailability(enabled); - if (enabled) - _ = service?.FetchAsync(); - - if (!enabled) - { - if (Dispatcher.CheckAccess()) - { - ApplyTicketOverviewDisabledState(); - } - else - { - Dispatcher.Invoke(ApplyTicketOverviewDisabledState); - } - } - } - - private void ApplyTicketOverviewDisabledState() - { - _renderTicketOverviewUserNames = false; - _ticketOverviewNotificationScopesPrimed.Clear(); - _ticketOverviewFirstEventHandled = false; - _ticketOverviewInitWasEmptyScopes.Clear(); - SetTicketOverviewVisibility(false); - (Application.Current as App)?.ClearTicketOverviewTrayNotification(); - } - - private void SetTicketOverviewVisibility(bool isVisible) - { - var b = isVisible; - if (!CheckTicketOverviewAvailability()) - b = false; - - BodyStack_TicketOverview.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - TicketOverviewBorder.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - FilterCheckbox.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - RoleLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - OwnTicketsLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - TicketOverviewLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; - ScheduleSearchResultMaxHeightUpdate(); - } - - public void ShowLoadingTextItem(string itemText) - { - SetSearchHistoryVisibility(false); - ResultMenu.ShowLoadingTextItem(itemText); - } - - public void ShowTicketOverviewPane() - { - Dispatcher.Invoke(() => - { - bool overviewAlreadyVisible = TicketOverviewBorder.Visibility == Visibility.Visible; - - SetTicketOverviewVisibility(true); - - if (!overviewAlreadyVisible) - { - SetSearchResultVisibility(false); - SetSearchHistoryVisibility(false); - TicketOverviewUc?.ResetSelection(); - } - TicketOverviewUc?.RefreshHighlightState(IsFilterChecked); - - var app = Application.Current as FasdDesktopUi.App; - app?.ClearTicketOverviewTrayNotification(); - }); - } - - public void ShowTicketOverviewPaneForScope(TileScope? scope) - { - if (scope.HasValue) - { - Dispatcher.Invoke(() => - { - if (TicketOverviewBorder.Visibility == Visibility.Visible) - return; - - var useRoleScope = scope.Value == TileScope.Role; - if (FilterCheckbox != null && FilterCheckbox.IsChecked != useRoleScope) - FilterCheckbox.IsChecked = useRoleScope; - }); - } - - ShowTicketOverviewPane(); - } - - internal void CloseTicketOverviewResults() - { - _renderTicketOverviewUserNames = false; - ResultMenu.ShowSearchResults(new cFilteredResults(), null, this); - ResultMenu.SetHeaderText(string.Empty); - SetSearchResultVisibility(false); - SetTicketOverviewVisibility(true); - } - - public void ShowSearchRelations(cSearchHistorySearchResultEntry searchHistoryEntry, IRelationService relationService, ISearchUiProvider searchUiProvider) - { try { _renderTicketOverviewUserNames = searchHistoryEntry != null && _ticketOverviewHistoryEntries.Contains(searchHistoryEntry); @@ -406,34 +315,38 @@ namespace FasdDesktopUi.Pages.SearchPage } } - private void ShowExternalSearchInfo(string strInfo, cFasdApiSearchResultCollection resultEntry, enumF4sdSearchResultClass Class) - { - var filteredResults = new cFilteredResults(resultEntry) { AutoContinue = true }; - var _t = ShowExternalSearchInfoAsync(strInfo, filteredResults, Class); - } - - private async Task ShowExternalSearchInfoAsync(string strInfo, cFilteredResults result, enumF4sdSearchResultClass Class) - { - try - { - await this.Dispatcher.InvokeAsync(async () => + private void ShowExternalSearchInfo(string strInfo, cFasdApiSearchResultCollection resultEntry, enumF4sdSearchResultClass Class) + { + var filteredResults = new cFilteredResults(resultEntry) { AutoContinue = true }; + var _t = ShowExternalSearchInfoAsync(strInfo, filteredResults, Class, suppressUi: false); + } + + private async Task ShowExternalSearchInfoAsync(string strInfo, cFilteredResults result, enumF4sdSearchResultClass Class, bool suppressUi) + { + try + { + await this.Dispatcher.InvokeAsync(async () => { try { - await SearchBarUc.SetFixedSearchResultAsync(Class, strInfo, result); - + await SearchBarUc.SetFixedSearchResultAsync(Class, strInfo, result); + if (result.AutoContinue && result.Results?.Count == 1) - { - ResultMenu.IndexOfSelectedResultItem = 0; - ResultMenu.SelectCurrentResultItem(); - } - - Show(); - } - catch (Exception E) - { - LogException(E); - } + { + ResultMenu.IndexOfSelectedResultItem = 0; + ResultMenu.SelectCurrentResultItem(); + } + + if (!suppressUi && !_ticketOverviewAutoContinueActive) + { + Show(); + Activate(); + } + } + catch (Exception E) + { + LogException(E); + } }); } catch (Exception E) @@ -884,11 +797,11 @@ namespace FasdDesktopUi.Pages.SearchPage } } - private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e) - { - try - { - Dispatcher.Invoke(() => + private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e) + { + try + { + Dispatcher.Invoke(() => { var first = e.RelatedTo.FirstOrDefault(); var relationSearchResult = new cSearchHistorySearchResultEntry(first.DisplayName, first.DisplayName, e.RelatedTo.ToList(), e.StagedResultRelations.Relations.ToList(), this); @@ -900,9 +813,110 @@ namespace FasdDesktopUi.Pages.SearchPage catch (Exception ex) { LogException(ex); - } - } - + } + } + + #region Ticketübersicht + + private bool CheckTicketOverviewAvailability() + { + return cFasdCockpitConfig.Instance?.Global?.TicketConfiguration?.ShowOverview == true; + } + + private void UpdateTicketOverviewAvailability() + { + var enabled = CheckTicketOverviewAvailability(); + var service = TicketOverviewUpdateService.Instance; + service?.UpdateAvailability(enabled); + if (enabled) + _ = service?.FetchAsync(); + + if (!enabled) + { + if (Dispatcher.CheckAccess()) + { + ApplyTicketOverviewDisabledState(); + } + else + { + Dispatcher.Invoke(ApplyTicketOverviewDisabledState); + } + } + } + + private void ApplyTicketOverviewDisabledState() + { + _renderTicketOverviewUserNames = false; + _ticketOverviewNotificationScopesPrimed.Clear(); + _ticketOverviewFirstEventHandled = false; + _ticketOverviewInitWasEmptyScopes.Clear(); + SetTicketOverviewVisibility(false); + (Application.Current as App)?.ClearTicketOverviewTrayNotification(); + } + + private void SetTicketOverviewVisibility(bool isVisible) + { + var b = isVisible; + if (!CheckTicketOverviewAvailability()) + b = false; + + BodyStack_TicketOverview.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + TicketOverviewBorder.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + FilterCheckbox.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + RoleLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + OwnTicketsLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + TicketOverviewLabel.Visibility = b ? Visibility.Visible : Visibility.Collapsed; + ScheduleSearchResultMaxHeightUpdate(); + } + + public void ShowTicketOverviewPane() + { + Dispatcher.Invoke(() => + { + bool overviewAlreadyVisible = TicketOverviewBorder.Visibility == Visibility.Visible; + + SetTicketOverviewVisibility(true); + + if (!overviewAlreadyVisible) + { + SetSearchResultVisibility(false); + SetSearchHistoryVisibility(false); + TicketOverviewUc?.ResetSelection(); + } + TicketOverviewUc?.RefreshHighlightState(IsFilterChecked); + + var app = Application.Current as FasdDesktopUi.App; + app?.ClearTicketOverviewTrayNotification(); + }); + } + + public void ShowTicketOverviewPaneForScope(TileScope? scope) + { + if (scope.HasValue) + { + Dispatcher.Invoke(() => + { + if (TicketOverviewBorder.Visibility == Visibility.Visible) + return; + + var useRoleScope = scope.Value == TileScope.Role; + if (FilterCheckbox != null && FilterCheckbox.IsChecked != useRoleScope) + FilterCheckbox.IsChecked = useRoleScope; + }); + } + + ShowTicketOverviewPane(); + } + + internal void CloseTicketOverviewResults() + { + _renderTicketOverviewUserNames = false; + ResultMenu.ShowSearchResults(new cFilteredResults(), null, this); + ResultMenu.SetHeaderText(string.Empty); + SetSearchResultVisibility(false); + SetTicketOverviewVisibility(true); + } + private void TicketOverviewUpdateService_OverviewCountsChanged(object sender, TicketOverviewCountsChangedEventArgs e) { try @@ -994,14 +1008,17 @@ namespace FasdDesktopUi.Pages.SearchPage relation.Infos.TryGetValue("UserSid", out sids); } - return RunTicketSearchAsync(ticketName, ticketId, userName, sids); + return RunTicketSearchAsync(ticketName, ticketId, userName, sids, suppressUi: true); } - private Task RunTicketSearchAsync(string ticketName, Guid ticketId, string userName, string sids) + private Task RunTicketSearchAsync(string ticketName, Guid ticketId, string userName, string sids, bool suppressUi = false) { if (ticketId == Guid.Empty) return Task.CompletedTask; + if (suppressUi) + BeginTicketOverviewAutoContinue(TimeSpan.FromSeconds(6)); + return Task.Run(async () => { try @@ -1012,10 +1029,19 @@ namespace FasdDesktopUi.Pages.SearchPage if (_result is null || _result.Count == 0 || _result.First().Value.Count == 0) { LogEntry($"No corresponding user could be found for ticket '{ticketName}'", LogLevels.Warning); + if (suppressUi) + EndTicketOverviewAutoContinue(showSearch: true); return; } var userId = _result.Values.First().First().id; + if (userId == Guid.Empty) + { + LogEntry($"No valid user id could be found for ticket '{ticketName}'", LogLevels.Warning); + if (suppressUi) + EndTicketOverviewAutoContinue(showSearch: true); + return; + } var _ticketRelation = new cF4sdApiSearchResultRelation() { Type = enumF4sdSearchResultClass.Ticket, @@ -1040,15 +1066,96 @@ namespace FasdDesktopUi.Pages.SearchPage var filteredResults = new cFilteredResults(_result) { AutoContinue = true, PreSelectedRelation = _ticketRelation }; var strInfo = string.Format(cMultiLanguageSupport.GetItem("Searchbar.TicketSearch.Info"), ticketName); - await ShowExternalSearchInfoAsync(strInfo, filteredResults, enumF4sdSearchResultClass.Ticket); + await ShowExternalSearchInfoAsync(strInfo, filteredResults, enumF4sdSearchResultClass.Ticket, suppressUi); } catch (Exception E) { LogException(E); + if (suppressUi) + EndTicketOverviewAutoContinue(showSearch: true); } }); } + private void BeginTicketOverviewAutoContinue(TimeSpan fallbackTimeout) + { + if (Dispatcher.CheckAccess()) + BeginTicketOverviewAutoContinueCore(fallbackTimeout); + else + Dispatcher.Invoke(() => BeginTicketOverviewAutoContinueCore(fallbackTimeout)); + } + + private void BeginTicketOverviewAutoContinueCore(TimeSpan fallbackTimeout) + { + if (_ticketOverviewAutoContinueActive) + return; + + _ticketOverviewAutoContinueActive = true; + + SearchBarUc.IsHitTestVisible = false; + ResultMenu.IsHitTestVisible = false; + SearchHistory.IsHitTestVisible = false; + BodyStack_TicketOverview.IsHitTestVisible = false; + FilterCheckbox.IsHitTestVisible = false; + + SetSearchHistoryVisibility(false); + SetSearchResultVisibility(false); + + _ticketOverviewAutoContinueCaseChangedHandler = (sender, args) => EndTicketOverviewAutoContinue(showSearch: false); + cSupportCaseDataProvider.CaseChanged += _ticketOverviewAutoContinueCaseChangedHandler; + + _ticketOverviewAutoContinueFallbackTimer = new DispatcherTimer { Interval = fallbackTimeout }; + _ticketOverviewAutoContinueFallbackTimer.Tick += TicketOverviewAutoContinueFallbackTimer_Tick; + _ticketOverviewAutoContinueFallbackTimer.Start(); + } + + private void TicketOverviewAutoContinueFallbackTimer_Tick(object sender, EventArgs e) + { + EndTicketOverviewAutoContinue(showSearch: true); + } + + private void EndTicketOverviewAutoContinue(bool showSearch) + { + if (Dispatcher.CheckAccess()) + EndTicketOverviewAutoContinueCore(showSearch); + else + Dispatcher.Invoke(() => EndTicketOverviewAutoContinueCore(showSearch)); + } + + private void EndTicketOverviewAutoContinueCore(bool showSearch) + { + if (!_ticketOverviewAutoContinueActive) + return; + + _ticketOverviewAutoContinueActive = false; + + if (_ticketOverviewAutoContinueFallbackTimer != null) + { + _ticketOverviewAutoContinueFallbackTimer.Stop(); + _ticketOverviewAutoContinueFallbackTimer.Tick -= TicketOverviewAutoContinueFallbackTimer_Tick; + _ticketOverviewAutoContinueFallbackTimer = null; + } + + if (_ticketOverviewAutoContinueCaseChangedHandler != null) + { + cSupportCaseDataProvider.CaseChanged -= _ticketOverviewAutoContinueCaseChangedHandler; + _ticketOverviewAutoContinueCaseChangedHandler = null; + } + + SearchBarUc.IsHitTestVisible = true; + ResultMenu.IsHitTestVisible = true; + SearchHistory.IsHitTestVisible = true; + BodyStack_TicketOverview.IsHitTestVisible = true; + FilterCheckbox.IsHitTestVisible = true; + + if (showSearch) + { + SetSearchResultVisibility(true); + Show(); + Activate(); + } + } + private void PrimeTicketOverviewScope(TileScope scope) { if (_ticketOverviewNotificationScopesPrimed.Add(scope)) @@ -1249,11 +1356,11 @@ namespace FasdDesktopUi.Pages.SearchPage return "TicketOverview.Column.Heading.New"; } - private static string GetScopeRowLabel(TileScope scope, string rowKey, string rowLabel) - { - string suffix = null; - if (string.Equals(rowKey, "TicketOverview.Row.Heading.Tickets", StringComparison.OrdinalIgnoreCase)) - suffix = "Tickets"; + private static string GetScopeRowLabel(TileScope scope, string rowKey, string rowLabel) + { + 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)) @@ -1262,75 +1369,9 @@ namespace FasdDesktopUi.Pages.SearchPage var translationKey = scope == TileScope.Role ? $"TicketOverview.ScopeRow.Role.{suffix}" : $"TicketOverview.ScopeRow.Personal.{suffix}"; - - return cMultiLanguageSupport.GetItem(translationKey) ?? rowLabel; - } - - private IntPtr SearchViewWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - if (msg == WM_NCHITTEST) - { - if (!IsPointWithinInteractiveBounds(lParam)) - { - handled = true; - return new IntPtr(HTTRANSPARENT); - } - } - - return IntPtr.Zero; - } - - private bool IsPointWithinInteractiveBounds(IntPtr lParam) - { - if (!IsLoaded || MainBorder == null || !MainBorder.IsLoaded) - return true; - - if (MainBorder.ActualWidth <= 0 || MainBorder.ActualHeight <= 0) - return true; - - var screenPoint = ExtractScreenPoint(lParam); - var windowPoint = PointFromScreen(screenPoint); - - if (!(InputHitTest(windowPoint) is DependencyObject hitElement)) - return false; - - return IsDescendantOf(hitElement, MainBorder); - } - - private static Point ExtractScreenPoint(IntPtr lParam) - { - int value = unchecked((int)(long)lParam); - short x = (short)(value & 0xFFFF); - short y = (short)((value >> 16) & 0xFFFF); - return new Point(x, y); - } - - private static bool IsDescendantOf(DependencyObject element, DependencyObject ancestor) - { - while (element != null) - { - if (element == ancestor) - return true; - - element = GetParent(element); - } - - return false; - } - - private static DependencyObject GetParent(DependencyObject current) - { - if (current == null) - return null; - - if (current is Visual || current is System.Windows.Media.Media3D.Visual3D) - return VisualTreeHelper.GetParent(current); - - if (current is System.Windows.ContentElement contentElement) - return System.Windows.ContentOperations.GetParent(contentElement); - - return LogicalTreeHelper.GetParent(current); - } + + return cMultiLanguageSupport.GetItem(translationKey) ?? rowLabel; + } private void ShowTicketOverviewNotification(string message) { @@ -1654,11 +1695,79 @@ namespace FasdDesktopUi.Pages.SearchPage relation.Infos["UserGuid"] = userId.ToString(); } } - - private void UpdateSearchResults(cFilteredResults filteredResults) - { - this.Dispatcher.Invoke(new Action(() => - { + + #endregion + + private IntPtr SearchViewWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WM_NCHITTEST) + { + if (!IsPointWithinInteractiveBounds(lParam)) + { + handled = true; + return new IntPtr(HTTRANSPARENT); + } + } + + return IntPtr.Zero; + } + + private bool IsPointWithinInteractiveBounds(IntPtr lParam) + { + if (!IsLoaded || MainBorder == null || !MainBorder.IsLoaded) + return true; + + if (MainBorder.ActualWidth <= 0 || MainBorder.ActualHeight <= 0) + return true; + + var screenPoint = ExtractScreenPoint(lParam); + var windowPoint = PointFromScreen(screenPoint); + + if (!(InputHitTest(windowPoint) is DependencyObject hitElement)) + return false; + + return IsDescendantOf(hitElement, MainBorder); + } + + private static Point ExtractScreenPoint(IntPtr lParam) + { + int value = unchecked((int)(long)lParam); + short x = (short)(value & 0xFFFF); + short y = (short)((value >> 16) & 0xFFFF); + return new Point(x, y); + } + + private static bool IsDescendantOf(DependencyObject element, DependencyObject ancestor) + { + while (element != null) + { + if (element == ancestor) + return true; + + element = GetParent(element); + } + + return false; + } + + private static DependencyObject GetParent(DependencyObject current) + { + if (current == null) + return null; + + if (current is Visual || current is System.Windows.Media.Media3D.Visual3D) + return VisualTreeHelper.GetParent(current); + + if (current is System.Windows.ContentElement contentElement) + return System.Windows.ContentOperations.GetParent(contentElement); + + return LogicalTreeHelper.GetParent(current); + } + + private void UpdateSearchResults(cFilteredResults filteredResults) + { + this.Dispatcher.Invoke(new Action(() => + { try { _renderTicketOverviewUserNames = false;