aktueller Stand
This commit is contained in:
@@ -65,9 +65,14 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
public abstract Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token);
|
public abstract Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token);
|
||||||
|
|
||||||
public abstract Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults);
|
public abstract Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults);
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
public abstract Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count);
|
public abstract Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count);
|
||||||
public abstract Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope);
|
public abstract Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public abstract Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData);
|
public abstract Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData);
|
||||||
|
|
||||||
public abstract Task<cF4SDHealthCardRawData> GetHealthCardData(Guid healthCardId);
|
public abstract Task<cF4SDHealthCardRawData> GetHealthCardData(Guid healthCardId);
|
||||||
|
|||||||
@@ -1096,6 +1096,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
public override async Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
public override async Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -1209,6 +1212,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public override async Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData)
|
public override async Task<cF4SDHealthCardRawData> GetHealthCardData(cF4sdHealthCardRawDataRequest requestData)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
private readonly List<cF4SDHealthCardJsonRawData> MockupData = new List<cF4SDHealthCardJsonRawData>();
|
private readonly List<cF4SDHealthCardJsonRawData> MockupData = new List<cF4SDHealthCardJsonRawData>();
|
||||||
|
|
||||||
private readonly Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable> MockupPickup = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable>();
|
private readonly Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable> MockupPickup = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTable>();
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
private readonly Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>> TicketOverviewRelations =
|
private readonly Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>> TicketOverviewRelations =
|
||||||
new Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>>(StringComparer.OrdinalIgnoreCase);
|
new Dictionary<string, Dictionary<string, List<TicketOverviewRelationDefinition>>>(StringComparer.OrdinalIgnoreCase);
|
||||||
private readonly HashSet<Guid> _generatedTicketIds = new HashSet<Guid>();
|
private readonly HashSet<Guid> _generatedTicketIds = new HashSet<Guid>();
|
||||||
private readonly object _demoTicketSync = new object();
|
private readonly object _demoTicketSync = new object();
|
||||||
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
|
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
|
||||||
|
|
||||||
|
#endregion
|
||||||
public cFasdCockpitCommunicationDemo()
|
public cFasdCockpitCommunicationDemo()
|
||||||
{
|
{
|
||||||
if (LoadMockupData(out var loadedData))
|
if (LoadMockupData(out var loadedData))
|
||||||
@@ -93,6 +98,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
private void LoadTicketOverviewRelations()
|
private void LoadTicketOverviewRelations()
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -394,6 +402,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
int delay = Math.Max(240, Math.Min(baseMs + capped * perItem, 2000));
|
int delay = Math.Max(240, Math.Min(baseMs + capped * perItem, 2000));
|
||||||
return Task.Delay(delay);
|
return Task.Delay(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private bool LoadMockupData(out List<cF4SDHealthCardJsonRawData> sampleData)
|
private bool LoadMockupData(out List<cF4SDHealthCardJsonRawData> sampleData)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ namespace FasdDesktopUi
|
|||||||
public System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon() { Text = $"First Aid Service Desk" };
|
public System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon() { Text = $"First Aid Service Desk" };
|
||||||
public bool UseOsLanguage = string.IsNullOrEmpty(cFasdCockpitConfig.Instance.SelectedLanguage);
|
public bool UseOsLanguage = string.IsNullOrEmpty(cFasdCockpitConfig.Instance.SelectedLanguage);
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
private TrayTicketNotificationManager _ticketTrayNotification;
|
private TrayTicketNotificationManager _ticketTrayNotification;
|
||||||
private TileScope? _pendingTicketOverviewScope;
|
private TileScope? _pendingTicketOverviewScope;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private async void Application_Startup(object sender, StartupEventArgs e)
|
private async void Application_Startup(object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -181,18 +185,8 @@ namespace FasdDesktopUi
|
|||||||
if (searchView == null)
|
if (searchView == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var hasNotification = HasPendingTicketOverviewNotification();
|
if (TryHandleTicketOverviewNotificationClick(searchView))
|
||||||
if (hasNotification)
|
|
||||||
{
|
|
||||||
if (!searchView.IsVisible)
|
|
||||||
searchView.ActivateSearchView();
|
|
||||||
else
|
|
||||||
searchView.BringToFrontPreserveState();
|
|
||||||
|
|
||||||
searchView.ShowTicketOverviewPaneForScope(PendingTicketOverviewScope);
|
|
||||||
ClearTicketOverviewTrayNotification();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
#if isDemo
|
#if isDemo
|
||||||
if (searchView.IsVisible)
|
if (searchView.IsVisible)
|
||||||
@@ -281,6 +275,26 @@ namespace FasdDesktopUi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
private void NotifyIcon_BalloonTipClicked(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -332,6 +346,8 @@ namespace FasdDesktopUi
|
|||||||
|
|
||||||
public TileScope? PendingTicketOverviewScope => _pendingTicketOverviewScope;
|
public TileScope? PendingTicketOverviewScope => _pendingTicketOverviewScope;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.ToolStripItem SetUpNotifyIconLanguageOption()
|
private System.Windows.Forms.ToolStripItem SetUpNotifyIconLanguageOption()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -36,9 +36,26 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
private static SearchPageView _instance = null;
|
private static SearchPageView _instance = null;
|
||||||
private const int WM_NCHITTEST = 0x0084;
|
private const int WM_NCHITTEST = 0x0084;
|
||||||
private const int HTTRANSPARENT = -1;
|
private const int HTTRANSPARENT = -1;
|
||||||
|
|
||||||
|
#region Ticketübersicht
|
||||||
|
|
||||||
private readonly HashSet<TileScope> _ticketOverviewNotificationScopesPrimed = new HashSet<TileScope>();
|
private readonly HashSet<TileScope> _ticketOverviewNotificationScopesPrimed = new HashSet<TileScope>();
|
||||||
private bool _ticketOverviewFirstEventHandled;
|
private bool _ticketOverviewFirstEventHandled;
|
||||||
private readonly HashSet<TileScope> _ticketOverviewInitWasEmptyScopes = new HashSet<TileScope>();
|
private readonly HashSet<TileScope> _ticketOverviewInitWasEmptyScopes = new HashSet<TileScope>();
|
||||||
|
private bool _ticketOverviewAutoContinueActive;
|
||||||
|
private DispatcherTimer _ticketOverviewAutoContinueFallbackTimer;
|
||||||
|
private EventHandler _ticketOverviewAutoContinueCaseChangedHandler;
|
||||||
|
private bool _renderTicketOverviewUserNames = false;
|
||||||
|
private readonly HashSet<cSearchHistorySearchResultEntry> _ticketOverviewHistoryEntries = new HashSet<cSearchHistorySearchResultEntry>();
|
||||||
|
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
|
||||||
|
|
||||||
|
// Event zum auslösen wenn Toggle geändert wird
|
||||||
|
public event EventHandler<bool> FilterToggleCheckedChanged;
|
||||||
|
|
||||||
|
// Aktueller Zustand der Checkbox
|
||||||
|
public bool IsFilterChecked => FilterCheckbox.IsChecked == true;
|
||||||
|
|
||||||
|
#endregion
|
||||||
public static SearchPageView Instance
|
public static SearchPageView Instance
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -55,14 +72,6 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
private bool _isActivating = false;
|
private bool _isActivating = false;
|
||||||
|
|
||||||
private cF4sdApiSearchResultRelation preSelectedRelation = null;
|
private cF4sdApiSearchResultRelation preSelectedRelation = null;
|
||||||
private bool _renderTicketOverviewUserNames = false;
|
|
||||||
private readonly HashSet<cSearchHistorySearchResultEntry> _ticketOverviewHistoryEntries = new HashSet<cSearchHistorySearchResultEntry>();
|
|
||||||
private const string DemoTicketHasDetailsInfoKey = "Demo.HasTicketDetails";
|
|
||||||
// Event zum auslösen wenn Toggle geändert wird
|
|
||||||
public event EventHandler<bool> FilterToggleCheckedChanged;
|
|
||||||
|
|
||||||
// Aktueller Zustand der Checkbox
|
|
||||||
public bool IsFilterChecked => FilterCheckbox.IsChecked == true;
|
|
||||||
|
|
||||||
private readonly IRelationService _relationService = new RelationService();
|
private readonly IRelationService _relationService = new RelationService();
|
||||||
public SupportCaseSearchService SearchService { get; }
|
public SupportCaseSearchService SearchService { get; }
|
||||||
@@ -166,112 +175,12 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
BodyStack_SearchResults.Visibility = (isVisible || SearchResultBorder.IsVisible) ? Visibility.Visible : Visibility.Collapsed;
|
BodyStack_SearchResults.Visibility = (isVisible || SearchResultBorder.IsVisible) ? Visibility.Visible : Visibility.Collapsed;
|
||||||
ScheduleSearchResultMaxHeightUpdate();
|
ScheduleSearchResultMaxHeightUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ShowLoadingTextItem(string itemText)
|
public void ShowLoadingTextItem(string itemText)
|
||||||
{
|
{
|
||||||
SetSearchHistoryVisibility(false);
|
SetSearchHistoryVisibility(false);
|
||||||
ResultMenu.ShowLoadingTextItem(itemText);
|
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)
|
public void ShowSearchRelations(cSearchHistorySearchResultEntry searchHistoryEntry, IRelationService relationService, ISearchUiProvider searchUiProvider)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -409,10 +318,10 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
private void ShowExternalSearchInfo(string strInfo, cFasdApiSearchResultCollection resultEntry, enumF4sdSearchResultClass Class)
|
private void ShowExternalSearchInfo(string strInfo, cFasdApiSearchResultCollection resultEntry, enumF4sdSearchResultClass Class)
|
||||||
{
|
{
|
||||||
var filteredResults = new cFilteredResults(resultEntry) { AutoContinue = true };
|
var filteredResults = new cFilteredResults(resultEntry) { AutoContinue = true };
|
||||||
var _t = ShowExternalSearchInfoAsync(strInfo, filteredResults, Class);
|
var _t = ShowExternalSearchInfoAsync(strInfo, filteredResults, Class, suppressUi: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ShowExternalSearchInfoAsync(string strInfo, cFilteredResults result, enumF4sdSearchResultClass Class)
|
private async Task ShowExternalSearchInfoAsync(string strInfo, cFilteredResults result, enumF4sdSearchResultClass Class, bool suppressUi)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -428,7 +337,11 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
ResultMenu.SelectCurrentResultItem();
|
ResultMenu.SelectCurrentResultItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!suppressUi && !_ticketOverviewAutoContinueActive)
|
||||||
|
{
|
||||||
Show();
|
Show();
|
||||||
|
Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
@@ -903,6 +816,107 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
private void TicketOverviewUpdateService_OverviewCountsChanged(object sender, TicketOverviewCountsChangedEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -994,14 +1008,17 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
relation.Infos.TryGetValue("UserSid", out sids);
|
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)
|
if (ticketId == Guid.Empty)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
if (suppressUi)
|
||||||
|
BeginTicketOverviewAutoContinue(TimeSpan.FromSeconds(6));
|
||||||
|
|
||||||
return Task.Run(async () =>
|
return Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1012,10 +1029,19 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
if (_result is null || _result.Count == 0 || _result.First().Value.Count == 0)
|
if (_result is null || _result.Count == 0 || _result.First().Value.Count == 0)
|
||||||
{
|
{
|
||||||
LogEntry($"No corresponding user could be found for ticket '{ticketName}'", LogLevels.Warning);
|
LogEntry($"No corresponding user could be found for ticket '{ticketName}'", LogLevels.Warning);
|
||||||
|
if (suppressUi)
|
||||||
|
EndTicketOverviewAutoContinue(showSearch: true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userId = _result.Values.First().First().id;
|
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()
|
var _ticketRelation = new cF4sdApiSearchResultRelation()
|
||||||
{
|
{
|
||||||
Type = enumF4sdSearchResultClass.Ticket,
|
Type = enumF4sdSearchResultClass.Ticket,
|
||||||
@@ -1040,15 +1066,96 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
var filteredResults = new cFilteredResults(_result) { AutoContinue = true, PreSelectedRelation = _ticketRelation };
|
var filteredResults = new cFilteredResults(_result) { AutoContinue = true, PreSelectedRelation = _ticketRelation };
|
||||||
|
|
||||||
var strInfo = string.Format(cMultiLanguageSupport.GetItem("Searchbar.TicketSearch.Info"), ticketName);
|
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)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
LogException(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)
|
private void PrimeTicketOverviewScope(TileScope scope)
|
||||||
{
|
{
|
||||||
if (_ticketOverviewNotificationScopesPrimed.Add(scope))
|
if (_ticketOverviewNotificationScopesPrimed.Add(scope))
|
||||||
@@ -1266,72 +1373,6 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
return cMultiLanguageSupport.GetItem(translationKey) ?? rowLabel;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowTicketOverviewNotification(string message)
|
private void ShowTicketOverviewNotification(string message)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
if (string.IsNullOrWhiteSpace(message))
|
||||||
@@ -1655,6 +1696,74 @@ namespace FasdDesktopUi.Pages.SearchPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
private void UpdateSearchResults(cFilteredResults filteredResults)
|
||||||
{
|
{
|
||||||
this.Dispatcher.Invoke(new Action(() =>
|
this.Dispatcher.Invoke(new Action(() =>
|
||||||
|
|||||||
Reference in New Issue
Block a user