From e6968e29eb32aed05932557e3a65d72f3e9a0f1d Mon Sep 17 00:00:00 2001 From: Meik Date: Thu, 19 Feb 2026 13:22:30 +0100 Subject: [PATCH] aktueller stand --- .../Ticket/CloseCaseDialogWithTicket.xaml.cs | 43 +- FasdDesktopUi/F4SD-Cockpit-Client.csproj | 72 +- .../DesktopWidgetPageView.xaml | 221 +++ .../DesktopWidgetPageView.xaml.cs | 179 ++ .../Pages/DetailsPage/DetailsPageView.xaml.cs | 96 +- .../DetailsPageNavigationHeading.xaml | 9 +- .../DetailsPageNavigationHeading.xaml.cs | 6 +- .../Pages/SearchPage/SearchPageView.xaml | 63 +- .../Pages/SearchPage/SearchPageView.xaml.cs | 1729 +++++++++-------- Setup_Client/Product.wxs | 2 +- Shared/SharedAssemblyInfo.cs | 4 +- 11 files changed, 1406 insertions(+), 1018 deletions(-) create mode 100644 FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml create mode 100644 FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml.cs diff --git a/FasdDesktopUi/Basics/UserControls/Ticket/CloseCaseDialogWithTicket.xaml.cs b/FasdDesktopUi/Basics/UserControls/Ticket/CloseCaseDialogWithTicket.xaml.cs index b38c5c6..e74c3cf 100644 --- a/FasdDesktopUi/Basics/UserControls/Ticket/CloseCaseDialogWithTicket.xaml.cs +++ b/FasdDesktopUi/Basics/UserControls/Ticket/CloseCaseDialogWithTicket.xaml.cs @@ -555,7 +555,7 @@ namespace FasdDesktopUi.Basics.UserControls parentWindow.Closing -= ParentWindow_Closing; } } - private void ParentWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) + private void ParentWindow_Closing(object sender, CancelEventArgs e) { foreach (SelectionPill pill in NewOrExistingOrNoneTicketWrap.Children.OfType()) { @@ -1097,11 +1097,9 @@ namespace FasdDesktopUi.Basics.UserControls if (!dataTable.Columns.TryGetValue("Name", out var nameColumn)) yield break; - cF4SDHealthCardRawData.cHealthCardTableColumn parentIdColumn = null; - cF4SDHealthCardRawData.cHealthCardTableColumn parentNameColumn = null; - if (!dataTable.Columns.TryGetValue("parentValue", out parentIdColumn)) + if (!dataTable.Columns.TryGetValue("parentValue", out cF4SDHealthCardRawData.cHealthCardTableColumn parentIdColumn)) dataTable.Columns.TryGetValue("Parent_Value", out parentIdColumn); - if (!dataTable.Columns.TryGetValue("parent", out parentNameColumn)) + if (!dataTable.Columns.TryGetValue("parent", out cF4SDHealthCardRawData.cHealthCardTableColumn parentNameColumn)) dataTable.Columns.TryGetValue("Parent", out parentNameColumn); for (int index = 0; index < idColumn.Values.Count; index++) @@ -2198,7 +2196,6 @@ namespace FasdDesktopUi.Basics.UserControls break; case ValidationPropertyNames.TicketStatusCombobox: - validateComboboxNotEmpty(TicketStatusCombobox); if (!(TicketStatusCombobox.SelectedItem is ComboBoxItem a)) break; @@ -2534,30 +2531,6 @@ namespace FasdDesktopUi.Basics.UserControls ValidateProperty(ValidationPropertyNames.ErrorTypeValue); } - private static void validateComboboxNotEmpty(object sender) - { - //var comboBox = sender as ComboBox; - //if (comboBox != null) - //{ - // if (!(comboBox.SelectedItem is ComboBoxItem selectedItem)) - // return; - - - - // // Überprüfe den Inhalt und setze die Hintergrundfarbe entsprechend - // if (selectedItem.Tag == null) - // { - // // Setze die Hintergrundfarbe auf Rot, um einen Validierungsfehler anzuzeigen - // comboBox.BorderBrush = SharedValidationBorderBrush; - // } - // else - // { - // // Setze die ursprüngliche Hintergrundfarbe zurück, wenn die Validierung erfolgreich ist - // comboBox.BorderBrush = (SolidColorBrush)new BrushConverter().ConvertFromString("#DEE2E6"); - // } - //} - } - private void TicketSelectionBorder_Click() { var _h = Dispatcher.Invoke(async () => @@ -2608,7 +2581,6 @@ namespace FasdDesktopUi.Basics.UserControls if (string.IsNullOrWhiteSpace(CaseNotesPreview.Text)) CaseNotesPreview.Text = string.Empty; - SelectedTicket.Infos[TicketInfoKeys.Summary] = CaseNotesPreview.Text; ValidateProperty(ValidationPropertyNames.CaseNotesPreview); } catch (Exception E) @@ -2655,13 +2627,10 @@ namespace FasdDesktopUi.Basics.UserControls private static void setTextboxErrorState(object sender, bool hasError) { - var textBox = sender as TextBox; - if (textBox == null) + if (!(sender is TextBox textBox)) return; - textBox.BorderBrush = hasError - ? SharedValidationBorderBrush - : DefaultTextBoxBorderBrush; + textBox.BorderBrush = hasError ? SharedValidationBorderBrush : DefaultTextBoxBorderBrush; } private void UpdateCategoryValidationVisualState(bool hasError) => @@ -2681,7 +2650,7 @@ namespace FasdDesktopUi.Basics.UserControls if (defaultBrush == null) { var borderBrush = border.BorderBrush; - defaultBrush = borderBrush != null ? borderBrush.CloneCurrentValue() : null; + defaultBrush = borderBrush?.CloneCurrentValue(); } if (!defaultThickness.HasValue) diff --git a/FasdDesktopUi/F4SD-Cockpit-Client.csproj b/FasdDesktopUi/F4SD-Cockpit-Client.csproj index b9cb4c1..d4079b7 100644 --- a/FasdDesktopUi/F4SD-Cockpit-Client.csproj +++ b/FasdDesktopUi/F4SD-Cockpit-Client.csproj @@ -218,22 +218,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -264,8 +264,8 @@ - - + + @@ -281,11 +281,13 @@ ComboBoxPageAble.xaml - - - HierarchicalSelectionControl.xaml - - + + DesktopWidgetPageView.xaml + + + HierarchicalSelectionControl.xaml + + DynamicChart.xaml @@ -495,15 +497,19 @@ MSBuild:Compile Designer - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + Designer MSBuild:Compile @@ -1059,4 +1065,4 @@ taskkill -im "F4SD-Cockpit-Client.exe" -f -FI "STATUS eq RUNNING" - + diff --git a/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml b/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml new file mode 100644 index 0000000..9b3092f --- /dev/null +++ b/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + diff --git a/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml.cs b/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml.cs new file mode 100644 index 0000000..f5c4986 --- /dev/null +++ b/FasdDesktopUi/Pages/DesktopWidgetPage/DesktopWidgetPageView.xaml.cs @@ -0,0 +1,179 @@ +using C4IT.MultiLanguage; +using FasdDesktopUi.Basics; +using FasdDesktopUi.Pages.SearchPage; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Forms; +using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using ContextMenu = System.Windows.Controls.ContextMenu; +using MenuItem = System.Windows.Controls.MenuItem; +using MessageBox = System.Windows.MessageBox; + +namespace FasdDesktopUi.Pages.DesktopWidgetPage +{ + /// + /// Interaction logic for DesktopWidgetPageView.xaml + /// + public partial class DesktopWidgetPageView : Window + { + + public bool IsWindowVisible + { + get { return (bool)GetValue(IsWindowVisibleProperty); } + set { SetValue(IsWindowVisibleProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsWindowVisible. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsWindowVisibleProperty = + DependencyProperty.Register(nameof(IsWindowVisible), typeof(bool), typeof(DesktopWidgetPageView), new PropertyMetadata(true)); + + + public bool AreAllWidgetsVisible + { + get { return (bool)GetValue(AreAllWidgetsVisibleProperty); } + set { SetValue(AreAllWidgetsVisibleProperty, value); } + } + + // Using a DependencyProperty as the backing store for AreAllWidgetsVisible. This enables animation, styling, binding, etc... + public static readonly DependencyProperty AreAllWidgetsVisibleProperty = + DependencyProperty.Register(nameof(AreAllWidgetsVisible), typeof(bool), typeof(DesktopWidgetPageView), new PropertyMetadata(false)); + + + + public bool ShowMainNotification + { + get { return (bool)GetValue(ShowMainNotificationProperty); } + set { SetValue(ShowMainNotificationProperty, value); } + } + + // Using a DependencyProperty as the backing store for ShowMainNotification. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ShowMainNotificationProperty = + DependencyProperty.Register(nameof(ShowMainNotification), typeof(bool), typeof(DesktopWidgetPageView), new PropertyMetadata(true)); + + + + + public DesktopWidgetPageView() + { + InitializeComponent(); + + SourceInitialized += (s, e) => + { + IntPtr handle = new WindowInteropHelper(this).Handle; + HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(cUtility.WindowProc)); + }; + } + + private bool IsAnyOtherVisible() => cSupportCaseDataProvider.detailsPage.IsVisible || SearchPageView.Instance.IsVisible; + protected override void OnInitialized(EventArgs e) + { + + + cSupportCaseDataProvider.detailsPage.IsVisibleChanged += (sender, args) => + { + this.Visibility = IsAnyOtherVisible() ? Visibility.Collapsed : Visibility.Visible; + }; + + SearchPageView.Instance.IsVisibleChanged += (sender, args) => + { + + this.Visibility = IsAnyOtherVisible() ? Visibility.Collapsed : Visibility.Visible; + }; + + + base.OnInitialized(e); + } + + private void F4SDWidget_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + AreAllWidgetsVisible = !AreAllWidgetsVisible; + ShowMainNotification = !ShowMainNotification; + } + + private void SearchWidget_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + SearchPageView.Instance.ActivateSearchView(); + } + + private void SettingsWidget_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + ContextMenu menu = SetupSettingsContextMenu(); + SettingsWidget.ContextMenu = menu; + SettingsWidget.ContextMenu.IsOpen = true; + } + + private ContextMenu SetupSettingsContextMenu() + { + ContextMenu menu = new ContextMenu(); + + MenuItem languageItem = new MenuItem(); + languageItem.Header = cMultiLanguageSupport.GetItem("Menu.SelectLanguage"); + languageItem.Items.Add(new MenuItem { Header = "DE" }); + languageItem.Items.Add(new MenuItem { Header = "EN" }); + menu.Items.Add(languageItem); + + MenuItem optionsItem = new MenuItem(); + optionsItem.Header = cMultiLanguageSupport.GetItem("Menu.Options"); + optionsItem.Click += (s, e) => MessageBox.Show(cMultiLanguageSupport.GetItem("Menu.Options")); + menu.Items.Add(optionsItem); + + MenuItem m42Item = new MenuItem(); + m42Item.Header = cMultiLanguageSupport.GetItem("M42Settings.SystemTray"); + m42Item.Click += (s, e) => MessageBox.Show(cMultiLanguageSupport.GetItem("M42Settings.SystemTray")); + menu.Items.Add(m42Item); + + MenuItem phoneItem = new MenuItem(); + phoneItem.Header = cMultiLanguageSupport.GetItem("PhoneSettings.SystemTray"); + phoneItem.Click += (s, e) => MessageBox.Show(cMultiLanguageSupport.GetItem("PhoneSettings.SystemTray")); + menu.Items.Add(phoneItem); + + return menu; + } + + private void ShowMessageBox(string message) + { + MessageBox.Show(message); + } + + private void RestartWidget_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + ContextMenu menu = SetupRestartContextMenu(); + RestartWidget.ContextMenu = menu; + RestartWidget.ContextMenu.IsOpen = true; + } + + private ContextMenu SetupRestartContextMenu() + { + ContextMenu menu = new ContextMenu(); + + MenuItem restartItem = new MenuItem(); + restartItem.Header = cMultiLanguageSupport.GetItem("Menu.Restart"); + restartItem.Click += (s, e) => MessageBox.Show(cMultiLanguageSupport.GetItem("Menu.Restart")); + menu.Items.Add(restartItem); + + MenuItem quitItem = new MenuItem(); + quitItem.Header = cMultiLanguageSupport.GetItem("Menu.Quit"); + quitItem.Click += (s, e) => MessageBox.Show(cMultiLanguageSupport.GetItem("Menu.Quit")); + menu.Items.Add(quitItem); + + return menu; + } + + private void TicketNotifyWidget_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + MessageBox.Show("Dies wurde leider noch nicht implementiert, sollte dich das stören setze es doch gerne selber um."); + } + + } +} diff --git a/FasdDesktopUi/Pages/DetailsPage/DetailsPageView.xaml.cs b/FasdDesktopUi/Pages/DetailsPage/DetailsPageView.xaml.cs index 8735bda..72e53ec 100644 --- a/FasdDesktopUi/Pages/DetailsPage/DetailsPageView.xaml.cs +++ b/FasdDesktopUi/Pages/DetailsPage/DetailsPageView.xaml.cs @@ -423,52 +423,52 @@ namespace FasdDesktopUi.Pages.DetailsPage #region BlurBorder Click - 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_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) { @@ -1048,8 +1048,8 @@ namespace FasdDesktopUi.Pages.DetailsPage Dispatcher.Invoke(UpdateHistoryWidth); - if (e is BooleanEventArgs booleanArgs && booleanArgs.BooleanArg is true) - BlurBorder_Click(keepTicketCompletion: true); + if (e is BooleanEventArgs booleanArgs && booleanArgs.BooleanArg is true) + BlurBorder_Click(keepTicketCompletion: true); isDataChangedEventRunning = false; diff --git a/FasdDesktopUi/Pages/DetailsPage/UserControls/DetailsPageNavigationHeading.xaml b/FasdDesktopUi/Pages/DetailsPage/UserControls/DetailsPageNavigationHeading.xaml index 5bb511f..3a21dac 100644 --- a/FasdDesktopUi/Pages/DetailsPage/UserControls/DetailsPageNavigationHeading.xaml +++ b/FasdDesktopUi/Pages/DetailsPage/UserControls/DetailsPageNavigationHeading.xaml @@ -208,7 +208,8 @@ Grid.Column="2" Margin="10 0" Background="#01000000" - Padding="5 0"> + Padding="5 0" + x:Name="VirtualSessionBorder"> + Padding="5 0" + x:Name="MobileDeviceBorder"> + Padding="5 0" + x:Name="TicketBorder"> - + @@ -107,27 +107,28 @@ Visibility="Visible" /> - - - - + + + + @@ -166,9 +167,9 @@ VerticalAlignment="Bottom" Visibility="Collapsed"> - + diff --git a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs index 71d6604..9f2d043 100644 --- a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs +++ b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml.cs @@ -33,26 +33,26 @@ namespace FasdDesktopUi.Pages.SearchPage { public partial class SearchPageView : Window, ISearchUiProvider { - private static SearchPageView _instance = null; - - #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(); - - // Event zum auslösen wenn Toggle geändert wird - public event EventHandler FilterToggleCheckedChanged; - - // Aktueller Zustand der Checkbox - public bool IsFilterChecked => FilterCheckbox.IsChecked == true; - - #endregion + private static SearchPageView _instance = null; + + #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(); + + // 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 @@ -61,125 +61,132 @@ 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 cF4sdApiSearchResultRelation preSelectedRelation = null; - private readonly IRelationService _relationService = new RelationService(); - public SupportCaseSearchService SearchService { get; } + private readonly IRelationService _relationService = new RelationService(); + public SupportCaseSearchService SearchService { get; } - private SearchPageView() - { - try - { + private SearchPageView() + { + try + { InitializeComponent(); SearchService = new SupportCaseSearchService(_relationService); - Visibility = Visibility.Visible; - _instance = this; - - GetPrimaryScreenSize(); - - // FilterToggleCheckBox-Events registrieren - FilterCheckbox.Checked += (s, e) => FilterToggleCheckedChanged?.Invoke(this, true); - FilterCheckbox.Unchecked += (s, e) => FilterToggleCheckedChanged?.Invoke(this, false); - - Loaded += (s, e) => - { - Hide(); - SearchBarUc.ActivateManualSearch(); - ScheduleSearchResultMaxHeightUpdate(); - }; - SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); - SearchBarUc.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); - BodyStack_TicketOverview.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); - SearchHistoryBorder.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); - - AddCustomEventHandlers(); - - if (TicketOverviewUpdateService.Instance != null) - { - TicketOverviewUpdateService.Instance.OverviewCountsChanged += TicketOverviewUpdateService_OverviewCountsChanged; - } - - UiSettingsChanged(null, null); - } - catch (Exception E) - { - LogException(E); - } + Visibility = Visibility.Visible; + _instance = this; + + GetPrimaryScreenSize(); + + // FilterToggleCheckBox-Events registrieren + FilterCheckbox.Checked += (s, e) => FilterToggleCheckedChanged?.Invoke(this, true); + FilterCheckbox.Unchecked += (s, e) => FilterToggleCheckedChanged?.Invoke(this, false); + + Loaded += (s, e) => + { + Hide(); + SearchBarUc.ActivateManualSearch(); + ScheduleSearchResultMaxHeightUpdate(); + }; + SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); + SearchBarUc.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); + BodyStack_TicketOverview.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); + SearchHistoryBorder.SizeChanged += (s, e) => ScheduleSearchResultMaxHeightUpdate(); + + AddCustomEventHandlers(); + + if (TicketOverviewUpdateService.Instance != null) + { + TicketOverviewUpdateService.Instance.OverviewCountsChanged += TicketOverviewUpdateService_OverviewCountsChanged; + } + + UiSettingsChanged(null, null); + } + catch (Exception E) + { + LogException(E); + } } - public void GetPrimaryScreenSize() - { - UpdateSearchResultMaxHeight(); - } - - private void ScheduleSearchResultMaxHeightUpdate() - { - if (Dispatcher == null || Dispatcher.HasShutdownStarted) - return; - - Dispatcher.BeginInvoke((Action)UpdateSearchResultMaxHeight, DispatcherPriority.Loaded); - } - - private void UpdateSearchResultMaxHeight() - { - if (SearchResultBorder == null) - return; - - var workAreaHeight = ActualHeight > 0 ? ActualHeight : SystemParameters.WorkArea.Height; - var reservedHeight = 0.0; - - reservedHeight += GetVisibleHeightWithMargin(SearchBarUc); - reservedHeight += GetVisibleHeightWithMargin(BodyStack_TicketOverview); - reservedHeight += GetVisibleHeightWithMargin(SearchHistoryBorder); - - if (MainBorder != null) - { - reservedHeight += MainBorder.Padding.Top + MainBorder.Padding.Bottom; - } - - var searchResultMargin = SearchResultBorder.Margin; - var availableHeight = workAreaHeight - reservedHeight - searchResultMargin.Top - searchResultMargin.Bottom; - availableHeight = Math.Max(0, availableHeight); - SearchResultBorder.MaxHeight = availableHeight; - } - - private static double GetVisibleHeightWithMargin(FrameworkElement element) - { - if (element == null || element.Visibility != Visibility.Visible) - return 0; - - var margin = element.Margin; - return element.ActualHeight + margin.Top + margin.Bottom; - } - - private void SetSearchResultVisibility(bool isVisible) - { - SearchResultBorder.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; - BodyStack_SearchResults.Visibility = (isVisible || SearchResultBorder.IsVisible) ? Visibility.Visible : Visibility.Collapsed; - ScheduleSearchResultMaxHeightUpdate(); - } - - public void SetSearchHistoryVisibility(bool isVisible) - { - SearchHistoryBorder.Visibility = isVisible && !SearchHistory.IsEmpty() ? Visibility.Visible : Visibility.Collapsed; - BodyStack_SearchResults.Visibility = (isVisible || SearchResultBorder.IsVisible) ? Visibility.Visible : Visibility.Collapsed; - ScheduleSearchResultMaxHeightUpdate(); - } - public void ShowLoadingTextItem(string itemText) - { - SetSearchHistoryVisibility(false); - ResultMenu.ShowLoadingTextItem(itemText); - } - - public void ShowSearchRelations(cSearchHistorySearchResultEntry searchHistoryEntry, IRelationService relationService, ISearchUiProvider searchUiProvider) - { + public void GetPrimaryScreenSize() + { + UpdateSearchResultMaxHeight(); + } + + private void ScheduleSearchResultMaxHeightUpdate() + { + if (Dispatcher == null || Dispatcher.HasShutdownStarted) + return; + + Dispatcher.BeginInvoke((Action)UpdateSearchResultMaxHeight, DispatcherPriority.Loaded); + } + + private void UpdateSearchResultMaxHeight() + { + if (SearchResultBorder == null) + return; + + var workAreaHeight = ActualHeight > 0 ? ActualHeight : SystemParameters.WorkArea.Height; + var reservedHeight = 0.0; + + reservedHeight += GetVisibleHeightWithMargin(SearchBarUc); + reservedHeight += GetVisibleHeightWithMargin(BodyStack_TicketOverview); + reservedHeight += GetVisibleHeightWithMargin(SearchHistoryBorder); + + if (MainBorder != null) + { + reservedHeight += MainBorder.Padding.Top + MainBorder.Padding.Bottom; + } + + var searchResultMargin = SearchResultBorder.Margin; + var availableHeight = workAreaHeight - reservedHeight - searchResultMargin.Top - searchResultMargin.Bottom; + availableHeight = Math.Max(0, availableHeight); + SearchResultBorder.MaxHeight = availableHeight; + } + + private static double GetVisibleHeightWithMargin(FrameworkElement element) + { + if (element == null || element.Visibility != Visibility.Visible) + return 0; + + var margin = element.Margin; + return element.ActualHeight + margin.Top + margin.Bottom; + } + + private void SetSearchResultVisibility(bool isVisible) + { + SearchResultBorder.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + BodyStack_SearchResults.Visibility = + (SearchResultBorder.Visibility == Visibility.Visible || SearchHistoryBorder.Visibility == Visibility.Visible) + ? Visibility.Visible + : Visibility.Collapsed; + ScheduleSearchResultMaxHeightUpdate(); + } + + public void SetSearchHistoryVisibility(bool isVisible) + { + SearchHistoryBorder.Visibility = isVisible && !SearchHistory.IsEmpty() ? Visibility.Visible : Visibility.Collapsed; + BodyStack_SearchResults.Visibility = + (SearchResultBorder.Visibility == Visibility.Visible || SearchHistoryBorder.Visibility == Visibility.Visible) + ? Visibility.Visible + : Visibility.Collapsed; + ScheduleSearchResultMaxHeightUpdate(); + } + public void ShowLoadingTextItem(string itemText) + { + SetSearchHistoryVisibility(false); + ResultMenu.ShowLoadingTextItem(itemText); + BodyStack_SearchResults.Visibility = Visibility.Visible; + } + + public void ShowSearchRelations(cSearchHistorySearchResultEntry searchHistoryEntry, IRelationService relationService, ISearchUiProvider searchUiProvider) + { try { _renderTicketOverviewUserNames = searchHistoryEntry != null && _ticketOverviewHistoryEntries.Contains(searchHistoryEntry); @@ -213,10 +220,10 @@ namespace FasdDesktopUi.Pages.SearchPage bool isEnabled = cHealthCardDataHelper.HasAvailableHealthCard(requiredInformationClasses); string disabledReason = null; - if (!isEnabled) - { - disabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? 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)) { @@ -260,10 +267,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; - } + if (!fallbackIsEnabled) + { + fallbackDisabledReason = cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard") ?? string.Empty; + } } catch { @@ -302,38 +309,37 @@ 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, suppressUi: false); - } - - private async Task ShowExternalSearchInfoAsync(string strInfo, cFilteredResults result, enumF4sdSearchResultClass Class, bool suppressUi) - { - 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); - - if (result.AutoContinue && result.Results?.Count == 1) - { - ResultMenu.IndexOfSelectedResultItem = 0; - ResultMenu.SelectCurrentResultItem(); - } - - if (!suppressUi && !_ticketOverviewAutoContinueActive) - { - Show(); - Activate(); - } - } - catch (Exception E) - { - LogException(E); - } + await SearchBarUc.SetFixedSearchResultAsync(Class, strInfo, result); + + if (!suppressUi && !_ticketOverviewAutoContinueActive) + { + Show(); + Activate(); + } + if (result.AutoContinue && result.Results?.Count == 1) + { + ResultMenu.IndexOfSelectedResultItem = 0; + ResultMenu.SelectCurrentResultItem(); + } + } + catch (Exception E) + { + LogException(E); + } }); } catch (Exception E) @@ -437,14 +443,14 @@ namespace FasdDesktopUi.Pages.SearchPage LogMethodBegin(CM); try { - var _h = Task.Run(async () => + _ = Task.Run(async () => { try { var lstSids = searchInfo.sids.Split(',').Select((v) => v.Trim()).ToList(); - var _result = await cFasdCockpitCommunicationBase.Instance.GetUserSearchResults(searchInfo.name, lstSids); + var searchResult = await cFasdCockpitCommunicationBase.Instance.GetUserSearchResults(searchInfo.name, lstSids); var strInfo = string.Format(cMultiLanguageSupport.GetItem("Searchbar.UserSearch.Info"), searchInfo.name); - ShowExternalSearchInfo(strInfo, _result, enumF4sdSearchResultClass.User); + ShowExternalSearchInfo(strInfo, searchResult, enumF4sdSearchResultClass.User); } catch (Exception E) { @@ -463,20 +469,20 @@ namespace FasdDesktopUi.Pages.SearchPage } - private void TicketSearch(cTicketSearchParameters searchInfo) - { - var CM = MethodBase.GetCurrentMethod(); - LogMethodBegin(CM); - try - { - if (!Guid.TryParse(searchInfo.ticketId, out var _ticketId)) - return; - _ = RunTicketSearchAsync(searchInfo.ticketName, _ticketId, searchInfo.userName, searchInfo.sids); - } - catch (Exception E) - { - LogException(E); - } + private void TicketSearch(cTicketSearchParameters searchInfo) + { + var CM = MethodBase.GetCurrentMethod(); + LogMethodBegin(CM); + try + { + if (!Guid.TryParse(searchInfo.ticketId, out var _ticketId)) + return; + _ = RunTicketSearchAsync(searchInfo.ticketName, _ticketId, searchInfo.userName, searchInfo.sids); + } + catch (Exception E) + { + LogException(E); + } finally { LogMethodEnd(CM); @@ -745,10 +751,10 @@ namespace FasdDesktopUi.Pages.SearchPage cFasdCockpitConfig.Instance.UiSettingsChanged += UiSettingsChanged; SearchBarUc.ChangedSearchValue = filteredResults => - { - UpdateSearchResults(filteredResults); - return Task.CompletedTask; - }; + { + UpdateSearchResults(filteredResults); + return Task.CompletedTask; + }; SearchBarUc.SearchValueChanged += HandleSearchValueChanged; SearchService.RelationsFound += HandleRelationsFound; @@ -784,11 +790,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); @@ -800,481 +806,480 @@ namespace FasdDesktopUi.Pages.SearchPage catch (Exception ex) { LogException(ex); - } - } - - #region Ticketübersicht - - private bool CheckTicketOverviewAvailability() - { - if (cFasdCockpitCommunicationBase.Instance?.IsDemo() == true) - return true; - - return cFasdCockpitConfig.Instance?.Global?.TicketConfiguration?.ShowOverview == true - && IsTicketIntegrationActive() - && cFasdCockpitConfig.Instance.HasM42Configuration(); - } - - private bool IsTicketIntegrationActive() - { - try - { - var healthCards = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values; - if (healthCards == null) - return false; - - return healthCards.Any(card => - card?.InformationClasses?.Contains(enumFasdInformationClass.Ticket) == true); - } - catch (Exception E) - { - LogException(E); - return false; - } - } - - 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(() => - { - 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 - { - ApplyLatestCounts(); - var positiveChanges = e.Changes?.Where(change => change.Delta > 0).ToList(); - var app = Application.Current as FasdDesktopUi.App; - var service = TicketOverviewUpdateService.Instance; - - if (!_ticketOverviewFirstEventHandled) - { - _ticketOverviewFirstEventHandled = true; - foreach (var scope in GetTicketOverviewEventScopes(e)) - { - PrimeTicketOverviewScope(scope); - TrackEmptyInitScope(scope, e?.CurrentCounts); - } - app?.ClearTicketOverviewTrayNotification(); - return; - } - - if (e.InitializedScope.HasValue) - { - PrimeTicketOverviewScope(e.InitializedScope.Value); - TrackEmptyInitScope(e.InitializedScope.Value, e?.CurrentCounts); - app?.ClearTicketOverviewTrayNotification(); - return; - } - - if (positiveChanges == null || positiveChanges.Count == 0) - { - app?.ClearTicketOverviewTrayNotification(); - return; - } - - if (service != null && !service.AreAllScopesInitialized) - { - app?.ClearTicketOverviewTrayNotification(); - return; - } - - var filteredChanges = FilterChangesForPrimedScopes(positiveChanges); - if (filteredChanges.Count == 0) - { - app?.ClearTicketOverviewTrayNotification(); - return; - } - - TicketOverviewUc?.SetHighlights(filteredChanges, IsFilterChecked); - - var pendingScope = ResolveSingleScope(filteredChanges); - app?.SetTicketOverviewNotificationScope(pendingScope); - - var message = BuildNotificationMessage(filteredChanges); - if (string.IsNullOrWhiteSpace(message)) - { - app?.ClearTicketOverviewTrayNotification(); - return; - } - - app?.ShowTicketOverviewTrayNotification(message); - ShowTicketOverviewNotification(message); - } - catch (Exception ex) - { - LogException(ex); - } - } - - private Task TicketSearchFromOverviewRelationAsync(cF4sdApiSearchResultRelation relation) - { - 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) - return Task.CompletedTask; - - string userName = null; - string sids = null; - - if (relation.Infos != null) - { - if (!relation.Infos.TryGetValue("UserDisplayName", out userName)) - relation.Infos.TryGetValue("UserAccount", out userName); - - if (!relation.Infos.TryGetValue("Sids", out sids)) - relation.Infos.TryGetValue("UserSid", out sids); - } - - 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) - return Task.CompletedTask; - - if (suppressUi) - BeginTicketOverviewAutoContinue(TimeSpan.FromSeconds(6)); - - return Task.Run(async () => - { - try - { - var lstSids = sids?.Split(',').Select((v) => v.Trim()).ToList(); - var _result = await cFasdCockpitCommunicationBase.Instance.GetUserSearchResults(userName, lstSids); - - 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, - Name = ticketName, - DisplayName = ticketName, - id = ticketId, - Status = enumF4sdSearchResultStatus.Active, - Identities = new cF4sdIdentityList - { - new cF4sdIdentityEntry() - { - Class = enumFasdInformationClass.User, - Id = userId - }, - new cF4sdIdentityEntry() - { - Class = enumFasdInformationClass.Ticket, - Id = ticketId - }, - } - }; - - 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, 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)) - { - TicketOverviewUc?.ClearHighlightsForScope(scope); - } - } - - private IReadOnlyList FilterChangesForPrimedScopes(IReadOnlyList changes) - { - if (changes == null || changes.Count == 0) - return Array.Empty(); - - var filteredChanges = new List(changes.Count); - var unprimedScopes = new HashSet(); - var silentInitScopes = new HashSet(); - - foreach (var change in changes) - { - if (_ticketOverviewInitWasEmptyScopes.Contains(change.Scope)) - { - silentInitScopes.Add(change.Scope); - continue; - } - - if (_ticketOverviewNotificationScopesPrimed.Contains(change.Scope)) - { - filteredChanges.Add(change); - } - else - { - unprimedScopes.Add(change.Scope); - } - } - - foreach (var scope in unprimedScopes) - { - PrimeTicketOverviewScope(scope); - } - - if (silentInitScopes.Count > 0) - { - foreach (var scope in silentInitScopes) - { - _ticketOverviewInitWasEmptyScopes.Remove(scope); - PrimeTicketOverviewScope(scope); - } - } - - return filteredChanges; - } - - private void TrackEmptyInitScope(TileScope scope, IReadOnlyDictionary counts) - { - if (IsScopeCountsEmpty(scope, counts)) - { - _ticketOverviewInitWasEmptyScopes.Add(scope); - } - } - - private static bool IsScopeCountsEmpty(TileScope scope, IReadOnlyDictionary counts) - { - if (counts == null || counts.Count == 0) - return true; - - foreach (var kvp in counts) - { - var value = scope == TileScope.Role ? kvp.Value.Role : kvp.Value.Personal; - if (value != 0) - return false; - } - - return true; - } - - private static IEnumerable GetTicketOverviewEventScopes(TicketOverviewCountsChangedEventArgs e) - { - if (e == null) - return Enumerable.Empty(); - - if (e.InitializedScope.HasValue) - return new[] { e.InitializedScope.Value }; - - if (e.Changes == null || e.Changes.Count == 0) - return Enumerable.Empty(); - - return e.Changes.Select(change => change.Scope).Distinct(); - } - - private static TileScope? ResolveSingleScope(IReadOnlyList changes) - { - if (changes == null || changes.Count == 0) - return null; - - var scope = changes[0].Scope; - for (int i = 1; i < changes.Count; i++) - { - if (changes[i].Scope != scope) - return null; - } - - return scope; - } + } + } + + #region Ticketübersicht + + private bool CheckTicketOverviewAvailability() + { + if (cFasdCockpitCommunicationBase.Instance?.IsDemo() == true) + return true; + + return cFasdCockpitConfig.Instance?.Global?.TicketConfiguration?.ShowOverview == true + && IsTicketIntegrationActive() + && cFasdCockpitConfig.Instance.HasM42Configuration(); + } + + private bool IsTicketIntegrationActive() + { + try + { + var healthCards = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values; + if (healthCards == null) + return false; + + return healthCards.Any(card => + card?.InformationClasses?.Contains(enumFasdInformationClass.Ticket) == true); + } + catch (Exception E) + { + LogException(E); + return false; + } + } + + 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) + { + if (!CheckTicketOverviewAvailability()) + isVisible = false; + + BodyStack_TicketOverview.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + TicketOverviewBorder.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + FilterCheckbox.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + RoleLabel.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + OwnTicketsLabel.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + TicketOverviewLabel.Visibility = isVisible ? 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(() => + { + 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 + { + ApplyLatestCounts(); + var positiveChanges = e.Changes?.Where(change => change.Delta > 0).ToList(); + var app = Application.Current as FasdDesktopUi.App; + var service = TicketOverviewUpdateService.Instance; + + if (!_ticketOverviewFirstEventHandled) + { + _ticketOverviewFirstEventHandled = true; + foreach (var scope in GetTicketOverviewEventScopes(e)) + { + PrimeTicketOverviewScope(scope); + TrackEmptyInitScope(scope, e?.CurrentCounts); + } + app?.ClearTicketOverviewTrayNotification(); + return; + } + + if (e.InitializedScope.HasValue) + { + PrimeTicketOverviewScope(e.InitializedScope.Value); + TrackEmptyInitScope(e.InitializedScope.Value, e?.CurrentCounts); + app?.ClearTicketOverviewTrayNotification(); + return; + } + + if (positiveChanges == null || positiveChanges.Count == 0) + { + app?.ClearTicketOverviewTrayNotification(); + return; + } + + if (service != null && !service.AreAllScopesInitialized) + { + app?.ClearTicketOverviewTrayNotification(); + return; + } + + var filteredChanges = FilterChangesForPrimedScopes(positiveChanges); + if (filteredChanges.Count == 0) + { + app?.ClearTicketOverviewTrayNotification(); + return; + } + + TicketOverviewUc?.SetHighlights(filteredChanges, IsFilterChecked); + + var pendingScope = ResolveSingleScope(filteredChanges); + app?.SetTicketOverviewNotificationScope(pendingScope); + + var message = BuildNotificationMessage(filteredChanges); + if (string.IsNullOrWhiteSpace(message)) + { + app?.ClearTicketOverviewTrayNotification(); + return; + } + + app?.ShowTicketOverviewTrayNotification(message); + ShowTicketOverviewNotification(message); + } + catch (Exception ex) + { + LogException(ex); + } + } + + private Task TicketSearchFromOverviewRelationAsync(cF4sdApiSearchResultRelation relation) + { + 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) + return Task.CompletedTask; + + string userName = null; + string sids = null; + + if (relation.Infos != null) + { + if (!relation.Infos.TryGetValue("UserDisplayName", out userName)) + relation.Infos.TryGetValue("UserAccount", out userName); + + if (!relation.Infos.TryGetValue("Sids", out sids)) + relation.Infos.TryGetValue("UserSid", out sids); + } + + 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) + return Task.CompletedTask; + + if (suppressUi) + BeginTicketOverviewAutoContinue(TimeSpan.FromSeconds(6)); + + return Task.Run(async () => + { + try + { + var lstSids = sids?.Split(',').Select((v) => v.Trim()).ToList(); + var _result = await cFasdCockpitCommunicationBase.Instance.GetUserSearchResults(userName, lstSids); + + 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, + Name = ticketName, + DisplayName = ticketName, + id = ticketId, + Status = enumF4sdSearchResultStatus.Active, + Identities = new cF4sdIdentityList + { + new cF4sdIdentityEntry() + { + Class = enumFasdInformationClass.User, + Id = userId + }, + new cF4sdIdentityEntry() + { + Class = enumFasdInformationClass.Ticket, + Id = ticketId + }, + } + }; + + 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, 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)) + { + TicketOverviewUc?.ClearHighlightsForScope(scope); + } + } + + private IReadOnlyList FilterChangesForPrimedScopes(IReadOnlyList changes) + { + if (changes == null || changes.Count == 0) + return Array.Empty(); + + var filteredChanges = new List(changes.Count); + var unprimedScopes = new HashSet(); + var silentInitScopes = new HashSet(); + + foreach (var change in changes) + { + if (_ticketOverviewInitWasEmptyScopes.Contains(change.Scope)) + { + silentInitScopes.Add(change.Scope); + continue; + } + + if (_ticketOverviewNotificationScopesPrimed.Contains(change.Scope)) + { + filteredChanges.Add(change); + } + else + { + unprimedScopes.Add(change.Scope); + } + } + + foreach (var scope in unprimedScopes) + { + PrimeTicketOverviewScope(scope); + } + + if (silentInitScopes.Count > 0) + { + foreach (var scope in silentInitScopes) + { + _ticketOverviewInitWasEmptyScopes.Remove(scope); + PrimeTicketOverviewScope(scope); + } + } + + return filteredChanges; + } + + private void TrackEmptyInitScope(TileScope scope, IReadOnlyDictionary counts) + { + if (IsScopeCountsEmpty(scope, counts)) + { + _ticketOverviewInitWasEmptyScopes.Add(scope); + } + } + + private static bool IsScopeCountsEmpty(TileScope scope, IReadOnlyDictionary counts) + { + if (counts == null || counts.Count == 0) + return true; + + foreach (var kvp in counts) + { + var value = scope == TileScope.Role ? kvp.Value.Role : kvp.Value.Personal; + if (value != 0) + return false; + } + + return true; + } + + private static IEnumerable GetTicketOverviewEventScopes(TicketOverviewCountsChangedEventArgs e) + { + if (e == null) + return Enumerable.Empty(); + + if (e.InitializedScope.HasValue) + return new[] { e.InitializedScope.Value }; + + if (e.Changes == null || e.Changes.Count == 0) + return Enumerable.Empty(); + + return e.Changes.Select(change => change.Scope).Distinct(); + } + + private static TileScope? ResolveSingleScope(IReadOnlyList changes) + { + if (changes == null || changes.Count == 0) + return null; + + var scope = changes[0].Scope; + for (int i = 1; i < changes.Count; i++) + { + if (changes[i].Scope != scope) + return null; + } + + return scope; + } private void ApplyLatestCounts() { @@ -1348,14 +1353,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; @@ -1372,22 +1377,22 @@ 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"; - 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"; + 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)) + suffix = "UnassignedTickets"; var translationKey = scope == TileScope.Role ? $"TicketOverview.ScopeRow.Role.{suffix}" : $"TicketOverview.ScopeRow.Personal.{suffix}"; - - return cMultiLanguageSupport.GetItem(translationKey) ?? rowLabel; - } + + return cMultiLanguageSupport.GetItem(translationKey) ?? rowLabel; + } private void ShowTicketOverviewNotification(string message) { @@ -1404,20 +1409,20 @@ namespace FasdDesktopUi.Pages.SearchPage { LogException(ex); } - } - private async void TicketOverview_SelectionRequested(object sender, TicketOverviewSelectionRequestedEventArgs e) - { - MethodBase CM = null; - if (cLogManager.DefaultLogger.IsDebug) - { - CM = MethodBase.GetCurrentMethod(); - LogMethodBegin(CM); - } - - try - { - var app = Application.Current as FasdDesktopUi.App; - app?.ClearTicketOverviewTrayNotification(); + } + private async void TicketOverview_SelectionRequested(object sender, TicketOverviewSelectionRequestedEventArgs e) + { + MethodBase CM = null; + if (cLogManager.DefaultLogger.IsDebug) + { + CM = MethodBase.GetCurrentMethod(); + LogMethodBegin(CM); + } + + try + { + var app = Application.Current as FasdDesktopUi.App; + app?.ClearTicketOverviewTrayNotification(); _renderTicketOverviewUserNames = true; SetSearchHistoryVisibility(false); @@ -1429,12 +1434,12 @@ namespace FasdDesktopUi.Pages.SearchPage ShowLoadingTextItem(cMultiLanguageSupport.GetItem("Searchbar.Loading.CaseData")); SetPendingInformationClasses(new HashSet { enumFasdInformationClass.Ticket }); - - var relations = await LoadRelationsForTileAsync(e.Key, e.UseRoleScope, Math.Max(0, e.Count)); - var firstRelation = relations.FirstOrDefault(); - string displayText = header; - if (firstRelation != null) - { + + var relations = await LoadRelationsForTileAsync(e.Key, e.UseRoleScope, Math.Max(0, e.Count)); + var firstRelation = relations.FirstOrDefault(); + string displayText = header; + if (firstRelation != null) + { string firstSummary = null; if (firstRelation.Infos != null && firstRelation.Infos.TryGetValue("Summary", out var summaryValue)) { @@ -1456,50 +1461,50 @@ namespace FasdDesktopUi.Pages.SearchPage { isSeen = true }; _ticketOverviewHistoryEntries.Add(entry); - var lookup = relations.ToLookup( - r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), - r => - { - 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; - } - string trailingUser = null; - if (_renderTicketOverviewUserNames && r.Infos != null && r.Infos.TryGetValue("UserDisplayName", out var userDisplayName)) - { - trailingUser = userDisplayName; - } - return (cMenuDataBase)new cMenuDataSearchRelation(r) - { - MenuText = r.DisplayName, - TrailingText = trailingUser, - UiAction = new cUiProcessTicketOverviewRelationAction(r.DisplayName, () => TicketSearchFromOverviewRelationAsync(r)) - { - DisplayType = isEnabled ? enumActionDisplayType.enabled : enumActionDisplayType.disabled, - Description = isEnabled ? string.Empty : disabledReason, - AlternativeDescription = isEnabled ? string.Empty : disabledReason - } - }; - } - ); + var lookup = relations.ToLookup( + r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), + r => + { + 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; + } + string trailingUser = null; + if (_renderTicketOverviewUserNames && r.Infos != null && r.Infos.TryGetValue("UserDisplayName", out var userDisplayName)) + { + trailingUser = userDisplayName; + } + return (cMenuDataBase)new cMenuDataSearchRelation(r) + { + MenuText = r.DisplayName, + TrailingText = trailingUser, + UiAction = new cUiProcessTicketOverviewRelationAction(r.DisplayName, () => TicketSearchFromOverviewRelationAsync(r)) + { + DisplayType = isEnabled ? enumActionDisplayType.enabled : enumActionDisplayType.disabled, + Description = isEnabled ? string.Empty : disabledReason, + AlternativeDescription = isEnabled ? string.Empty : disabledReason + } + }; + } + ); ResultMenu.UpdateSearchRelations(lookup); ResultMenu.SetHeaderText(header, hideDetailsCheckbox: true); UpdatePendingInformationClasses(new HashSet()); } catch (Exception ex) - { - LogException(ex); - CancledSearchAction(); - } - finally - { - LogMethodEnd(CM); - } - } + { + LogException(ex); + CancledSearchAction(); + } + finally + { + LogMethodEnd(CM); + } + } private string BuildHeaderText(string key, bool useRoleScope, int? count = null) { string scopeKey = useRoleScope ? "Searchbar.Header.Scope.Role" : "Searchbar.Header.Scope.Personal"; @@ -1564,11 +1569,11 @@ namespace FasdDesktopUi.Pages.SearchPage return "Searchbar.Header.Filter.Overview"; } - private async Task> LoadRelationsForTileAsync(string key, bool useRoleScope, int count) - { - var communication = cFasdCockpitCommunicationBase.Instance; - if (communication == null) - return new List(); + private async Task> LoadRelationsForTileAsync(string key, bool useRoleScope, int count) + { + var communication = cFasdCockpitCommunicationBase.Instance; + if (communication == null) + return new List(); try { var relations = await communication.GetTicketOverviewRelations(key, useRoleScope, Math.Max(0, count)).ConfigureAwait(false); @@ -1588,87 +1593,87 @@ namespace FasdDesktopUi.Pages.SearchPage LogException(ex); return new List(); } - } - - #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) - { - 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); - } - - #endregion - - private void UpdateSearchResults(cFilteredResults filteredResults) - { - this.Dispatcher.Invoke(new Action(() => - { + } + + #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) + { + 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); + } + + #endregion + + private void UpdateSearchResults(cFilteredResults filteredResults) + { + this.Dispatcher.Invoke(new Action(() => + { try { _renderTicketOverviewUserNames = false; @@ -1733,27 +1738,27 @@ namespace FasdDesktopUi.Pages.SearchPage Mouse.OverrideCursor = Cursors.Wait; - switch (e.UiAction) - { - case cUiProcessSearchResultAction searchResultAction: - searchResultAction.PreSelectedSearchRelation = preSelectedRelation; - break; - case cUiProcessSearchRelationAction _: - case cUiProcessSearchHistoryEntry _: - case cUiProcessTicketOverviewRelationAction _: - break; - default: - var _t = e.UiAction?.GetType().Name; - Debug.Assert(true, $"The UI action '{_t}' is not supported in detailed page"); - CancledSearchAction(); + switch (e.UiAction) + { + case cUiProcessSearchResultAction searchResultAction: + searchResultAction.PreSelectedSearchRelation = preSelectedRelation; + break; + case cUiProcessSearchRelationAction _: + case cUiProcessSearchHistoryEntry _: + case cUiProcessTicketOverviewRelationAction _: + break; + default: + var _t = e.UiAction?.GetType().Name; + Debug.Assert(true, $"The UI action '{_t}' is not supported in detailed page"); + CancledSearchAction(); return; } SetSearchResultVisibility(true); - var actionResult = await e.UiAction.RunUiActionAsync(sender, null, false, null); - if (!(e.UiAction is cUiProcessTicketOverviewRelationAction) && !actionResult) - CancledSearchAction(); - } + var actionResult = await e.UiAction.RunUiActionAsync(sender, null, false, null); + if (!(e.UiAction is cUiProcessTicketOverviewRelationAction) && !actionResult) + CancledSearchAction(); + } catch (Exception E) { LogException(E); @@ -1790,11 +1795,11 @@ namespace FasdDesktopUi.Pages.SearchPage } } - private void UiSettingsChanged(object sender, EventArgs e) - { - try - { - var positionAlignement = cFasdCockpitConfig.Instance.Global.SmallViewAlignment; + private void UiSettingsChanged(object sender, EventArgs e) + { + try + { + var positionAlignement = cFasdCockpitConfig.Instance.Global.SmallViewAlignment; switch (positionAlignement) { @@ -1805,16 +1810,16 @@ namespace FasdDesktopUi.Pages.SearchPage Dispatcher.Invoke(() => MainBorder.HorizontalAlignment = HorizontalAlignment.Right); break; default: - Dispatcher.Invoke(() => MainBorder.HorizontalAlignment = HorizontalAlignment.Left); - break; - } - - UpdateTicketOverviewAvailability(); - } - catch (Exception E) - { - LogException(E); - } + Dispatcher.Invoke(() => MainBorder.HorizontalAlignment = HorizontalAlignment.Left); + break; + } + + UpdateTicketOverviewAvailability(); + } + catch (Exception E) + { + LogException(E); + } } public void SetPendingInformationClasses(HashSet informationClasses) => Dispatcher.Invoke(() => ResultMenu.SetPendingInformationClasses(informationClasses)); diff --git a/Setup_Client/Product.wxs b/Setup_Client/Product.wxs index fc4885f..1326f9a 100644 --- a/Setup_Client/Product.wxs +++ b/Setup_Client/Product.wxs @@ -4,7 +4,7 @@ diff --git a/Shared/SharedAssemblyInfo.cs b/Shared/SharedAssemblyInfo.cs index a8296cb..180bf2b 100644 --- a/Shared/SharedAssemblyInfo.cs +++ b/Shared/SharedAssemblyInfo.cs @@ -6,6 +6,6 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("2.7.*")] -[assembly: AssemblyInformationalVersion("2.7.0.0")] +[assembly: AssemblyInformationalVersion("2.7.0.2")] -[assembly: AssemblyMinServerVersion("2.6.1.1")] \ No newline at end of file +[assembly: AssemblyMinServerVersion("2.7.0.0")]