inital
This commit is contained in:
32
FasdDesktopUi/App.config
Normal file
32
FasdDesktopUi/App.config
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="FasdDesktopUi.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.Windows.DoNotScaleForDpiChanges=false" />
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.1.0" newVersion="6.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
31
FasdDesktopUi/App.xaml
Normal file
31
FasdDesktopUi/App.xaml
Normal file
@@ -0,0 +1,31 @@
|
||||
<Application x:Class="FasdDesktopUi.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:FasdDesktopUi"
|
||||
xmlns:basic="clr-namespace:FasdDesktopUi.Basics.Models"
|
||||
Startup="Application_Startup"
|
||||
Exit="Application_Exit">
|
||||
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ResourceDictionaries\LightModeResources.xaml" />
|
||||
|
||||
<!--Color Resources have to load first, because Base refere to it-->
|
||||
<ResourceDictionary Source="ResourceDictionaries\BaseResources.xaml" />
|
||||
|
||||
<!--Modifing default Styles of exsisting controls-->
|
||||
<ResourceDictionary Source="ResourceDictionaries\ScrollViewerResources.xaml" />
|
||||
<ResourceDictionary Source="ResourceDictionaries\SliderResources.xaml" />
|
||||
<ResourceDictionary Source="ResourceDictionaries\CheckBoxResources.xaml" />
|
||||
<ResourceDictionary Source="ResourceDictionaries\RadioButtonResources.xaml" />
|
||||
<ResourceDictionary Source="ResourceDictionaries\ComboBoxResources.xaml" />
|
||||
<ResourceDictionary Source="ResourceDictionaries\TreeViewResources.xaml" />
|
||||
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
508
FasdDesktopUi/App.xaml.cs
Normal file
508
FasdDesktopUi/App.xaml.cs
Normal file
@@ -0,0 +1,508 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.FASD.Security;
|
||||
using C4IT.Graphics;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics;
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Pages.CustomMessageBox;
|
||||
using FasdDesktopUi.Pages.PhoneSettingsPage;
|
||||
using FasdDesktopUi.Pages.SearchPage;
|
||||
using FasdDesktopUi.Pages.SettingsPage;
|
||||
using FasdDesktopUi.Pages.ShortCutPage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
static public string PhoneMonitorPipeName;
|
||||
|
||||
|
||||
static public Mutex AppMutex = null;
|
||||
static public string PipeName = "";
|
||||
|
||||
static public System.Windows.Forms.ToolStripItem M42OptionMenuItem = null;
|
||||
|
||||
public System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon() { Text = $"First Aid Service Desk" };
|
||||
public bool UseOsLanguage = string.IsNullOrEmpty(cFasdCockpitConfig.Instance.SelectedLanguage);
|
||||
|
||||
private TrayTicketNotificationManager _ticketTrayNotification;
|
||||
|
||||
private async void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
InitializeLogger();
|
||||
|
||||
|
||||
/* Attach debugger befor start
|
||||
Console.WriteLine("Waiting for debugger to attach");
|
||||
while (!Debugger.IsAttached)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
Console.WriteLine("Debugger attached");
|
||||
*/
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
var ProductName = FileVersionInfo.GetVersionInfo(assembly.Location).ProductName;
|
||||
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
|
||||
var AssemblyGuid = attribute.Value;
|
||||
string MutexName = ProductName + AssemblyGuid.ToString();
|
||||
var SessionId = 0;
|
||||
try
|
||||
{
|
||||
SessionId = Process.GetCurrentProcess().SessionId;
|
||||
}
|
||||
catch { }
|
||||
|
||||
PipeName = MutexName + $".pipe.{SessionId}";
|
||||
PhoneMonitorPipeName = PipeName + ".PhoneMonitor." + Guid.NewGuid().ToString();
|
||||
|
||||
if (e.Args.Length > 0)
|
||||
{
|
||||
bool shouldShutdown = cAppStartUp.ProcessCommandLine(e.Args);
|
||||
if (shouldShutdown)
|
||||
{
|
||||
Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AppMutex = new Mutex(false, MutexName);
|
||||
if (!AppMutex.WaitOne(0))
|
||||
{
|
||||
LogEntry("Application already started, exiting...", LogLevels.Info);
|
||||
AppMutex.Dispose();
|
||||
AppMutex = null;
|
||||
Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogEntry("Cannot create application mutex, exiting...", LogLevels.Fatal);
|
||||
LogException(E);
|
||||
Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
cF4sdPipeClient.RegisterProtocol(cAppStartUp.constUrlProtocol, cAppStartUp.constUrlCommand);
|
||||
|
||||
cMultiLanguageSupport.CurrentLanguage = cFasdCockpitConfig.Instance.SelectedLanguage;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
FasdSecurity.Init();
|
||||
PrivateSecurePassword.Init();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
MessageBox.Show(cMultiLanguageSupport.GetItem("App.Startup.SecurityInitFailed.Text"), cMultiLanguageSupport.GetItem("App.Startup.SecurityInitFailed.Caption"), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Current.Shutdown();
|
||||
}
|
||||
|
||||
InitializeNotifyIcon();
|
||||
|
||||
//CustomMessageBox.ShowCustomContent("Close case", enumHealthCardStateLevel.None, null, true, new CloseCaseDialogWithTicket());
|
||||
|
||||
await cAppStartUp.StartAsync(e.Args);
|
||||
notifyIcon.Visible = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Mouse.OverrideCursor = null;
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
#region Logger
|
||||
|
||||
private void InitializeLogger()
|
||||
{
|
||||
cLogManagerFile.CreateInstance(false, SubFolder: "Logs", DebugFlags: new List<string>() { "apivalues", "apitiming" });
|
||||
cFasdCockpitCommunicationBase.Debug_apiValues = cLogManager.Instance.CheckDebugFlag("apivalues");
|
||||
cFasdCockpitCommunicationBase.Debug_apiTiming = cLogManager.Instance.CheckDebugFlag("apitiming");
|
||||
cLogManager.DefaultLogger.LogAssemblyInfo();
|
||||
|
||||
Dispatcher.UnhandledException += Dispatcher_UnhandledException;
|
||||
AppDomain.CurrentDomain.UnhandledException += (o, e) => LogException((Exception)e.ExceptionObject, LogLevels.Fatal);
|
||||
}
|
||||
|
||||
private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
LogException(e.Exception, LogLevels.Error);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NotifyIcon
|
||||
|
||||
public static void HideAllSettingViews()
|
||||
{
|
||||
SettingsPageView.Instance?.Hide();
|
||||
|
||||
}
|
||||
|
||||
private void NotifyIcon_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e is System.Windows.Forms.MouseEventArgs mouseEventArgs)
|
||||
if (mouseEventArgs.Button == System.Windows.Forms.MouseButtons.Right)
|
||||
return;
|
||||
|
||||
|
||||
var searchView = SearchPageView.Instance;
|
||||
if (searchView == null)
|
||||
return;
|
||||
|
||||
#if isDemo
|
||||
var hasNotification = HasPendingTicketOverviewNotification();
|
||||
|
||||
if (searchView.IsVisible && !hasNotification)
|
||||
{
|
||||
searchView.Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!searchView.IsVisible)
|
||||
searchView.ActivateSearchView();
|
||||
else
|
||||
searchView.BringToFrontPreserveState();
|
||||
|
||||
searchView.ShowTicketOverviewPane();
|
||||
|
||||
if (hasNotification)
|
||||
ClearTicketOverviewTrayNotification();
|
||||
#else
|
||||
if (SearchPageView.Instance.IsVisible)
|
||||
SearchPageView.Instance.Hide();
|
||||
else
|
||||
SearchPageView.Instance.ActivateSearchView();
|
||||
#endif
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeNotifyIcon()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
NotifyerSupport.LoadSetFromResource("Default", "FasdDesktopUi.Resources.logo_FASD.ico");
|
||||
NotifyerSupport.LoadSetFromResource("StartUp", "FasdDesktopUi.Resources.logo_F4SD_flip.ico");
|
||||
NotifyerSupport.LoadSetFromResource("OverlayOffline", "FasdDesktopUi.Resources.StateOverlays.Offline", NoRefresh: true)?.CreateSizeMap(0.45f);
|
||||
NotifyerSupport.RegisterNotifyControl(notifyIcon);
|
||||
NotifyerSupport.SetNotifyIcon("StartUp");
|
||||
|
||||
var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
|
||||
notifyIcon.Text += " version " + assemblyVersion;
|
||||
_ticketTrayNotification = new TrayTicketNotificationManager(notifyIcon);
|
||||
_ticketTrayNotification.CaptureBaseTooltip();
|
||||
_ticketTrayNotification.ApplyTooltip();
|
||||
notifyIcon.Click += NotifyIcon_Click;
|
||||
notifyIcon.BalloonTipClicked += NotifyIcon_BalloonTipClicked;
|
||||
|
||||
SetUpNotifyIconLanguageOption();
|
||||
|
||||
notifyIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip() { Visible = true };
|
||||
notifyIcon.ContextMenuStrip.Items.Add(SetUpNotifyIconLanguageOption());
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("Menu.Options"), null, NotifyIconOptions_Click);
|
||||
|
||||
M42OptionMenuItem = notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("M42Settings.SystemTray"), null, (sender, e) =>
|
||||
{
|
||||
if (cFasdCockpitCommunicationBase.CockpitUserInfo == null)
|
||||
return;
|
||||
M42SettingsPageView.Instance.Show();
|
||||
});
|
||||
M42OptionMenuItem.Visible = false;
|
||||
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("PhoneSettings.SystemTray"), null, (sender, e) =>
|
||||
{
|
||||
PhoneSettingsPage.Instance.Show();
|
||||
});
|
||||
|
||||
notifyIcon.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripSeparator());
|
||||
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("Menu.KeyBoardShortcuts"), null, (sender, e) =>
|
||||
{
|
||||
ShortCutPageView.Instance.Show();
|
||||
});
|
||||
notifyIcon.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripSeparator());
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("Menu.About"), null, NotifyIconAbout_Click);
|
||||
notifyIcon.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripSeparator());
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("Menu.Restart"), null, NotifyIconRestart_Click);
|
||||
notifyIcon.ContextMenuStrip.Items.Add(cMultiLanguageSupport.GetItem("Menu.Quit"), null, NotifyIconQuit_Click);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyIcon_BalloonTipClicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
SearchPageView.Instance?.BringToFrontPreserveState();
|
||||
SearchPageView.Instance?.ShowTicketOverviewPane();
|
||||
ClearTicketOverviewTrayNotification();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasPendingTicketOverviewNotification()
|
||||
{
|
||||
return _ticketTrayNotification?.HasNotification ?? false;
|
||||
}
|
||||
|
||||
public void ShowTicketOverviewTrayNotification(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ticketTrayNotification?.Show(message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearTicketOverviewTrayNotification()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ticketTrayNotification?.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private System.Windows.Forms.ToolStripItem SetUpNotifyIconLanguageOption()
|
||||
{
|
||||
try
|
||||
{
|
||||
var output = new System.Windows.Forms.ToolStripMenuItem() { Text = cMultiLanguageSupport.GetItem("Menu.SelectLanguage") };
|
||||
|
||||
var languages = cMultiLanguageSupport.GetSupportedLanguages();
|
||||
var stripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
var defaultFormat = cMultiLanguageSupport.GetItem("Menu.SelectLanguage.Default");
|
||||
stripMenuItem.Text = string.Format(defaultFormat, cMultiLanguageSupport.GetOsDefault());
|
||||
stripMenuItem.Image = cMultiLanguageSupport.GetImage(".");
|
||||
stripMenuItem.Click += ToolStripMenuLanguage_Click;
|
||||
if (UseOsLanguage)
|
||||
stripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
|
||||
output.DropDownItems.Add(stripMenuItem);
|
||||
foreach (var Entry in languages)
|
||||
{
|
||||
stripMenuItem = new System.Windows.Forms.ToolStripMenuItem
|
||||
{
|
||||
Text = Entry,
|
||||
Tag = Entry,
|
||||
Image = cMultiLanguageSupport.GetImage(Entry)
|
||||
};
|
||||
stripMenuItem.Click += ToolStripMenuLanguage_Click;
|
||||
if (!UseOsLanguage && (cMultiLanguageSupport.CurrentLanguage == Entry))
|
||||
stripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
output.DropDownItems.Add(stripMenuItem);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ToolStripMenuLanguage_Click(object sender, EventArgs e)
|
||||
{
|
||||
var OldLanguage = cMultiLanguageSupport.CurrentLanguage;
|
||||
string NewLanguage = null;
|
||||
|
||||
if (sender is System.Windows.Forms.ToolStripMenuItem selectedLanguageStripMenuItem)
|
||||
{
|
||||
if (selectedLanguageStripMenuItem.OwnerItem is System.Windows.Forms.ToolStripMenuItem parentStripMenuItem)
|
||||
{
|
||||
foreach (System.Windows.Forms.ToolStripMenuItem Entry in parentStripMenuItem.DropDownItems)
|
||||
{
|
||||
Entry.Checked = Entry == selectedLanguageStripMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedLanguageStripMenuItem.Tag is string stripMenuItemTag)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(stripMenuItemTag))
|
||||
NewLanguage = stripMenuItemTag;
|
||||
}
|
||||
}
|
||||
|
||||
UseOsLanguage = NewLanguage == null;
|
||||
cMultiLanguageSupport.CurrentLanguage = NewLanguage;
|
||||
|
||||
cFasdCockpitConfig.Instance.SelectedLanguage = NewLanguage;
|
||||
cFasdCockpitConfig.Instance.Save("SelectedLanguage");
|
||||
|
||||
if (OldLanguage == NewLanguage)
|
||||
return;
|
||||
|
||||
//var dialogResult = MessageBox.Show(cMultiLanguageSupport.GetItem("Menu.SelectLanguage.RestartDialog.Text"), cMultiLanguageSupport.GetItem("Menu.SelectLanguage.RestartDialog.Caption"), MessageBoxButton.YesNo, MessageBoxImage.Information);
|
||||
|
||||
var dialogResult = CustomMessageBox.Show(cMultiLanguageSupport.GetItem("Menu.SelectLanguage.RestartDialog.Text"), cMultiLanguageSupport.GetItem("Menu.SelectLanguage.RestartDialog.Caption"), enumHealthCardStateLevel.Info, null, true);
|
||||
|
||||
if (dialogResult == true)
|
||||
{
|
||||
System.Windows.Forms.Application.Restart();
|
||||
Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyIconOptions_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var settingsView = SettingsPageView.Create();
|
||||
|
||||
if (settingsView.IsVisible)
|
||||
settingsView.Hide();
|
||||
else
|
||||
settingsView.Show();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyIconAbout_Click(object sender, EventArgs e)
|
||||
{
|
||||
var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
|
||||
|
||||
var messageText = cMultiLanguageSupport.GetItem("Menu.TrademarkNotice");
|
||||
|
||||
CustomMessageBox.Show(messageText, $"First Aid Service Desk ({assemblyVersion})", enumHealthCardStateLevel.Info);
|
||||
}
|
||||
|
||||
private async void NotifyIconRestart_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shouldRestart = await cSupportCaseDataProvider.SupportTicketActiveNoticeAsync();
|
||||
|
||||
if (!shouldRestart)
|
||||
return;
|
||||
|
||||
System.Windows.Forms.Application.Restart();
|
||||
Current.Shutdown();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private async void NotifyIconQuit_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shouldQuit = await cSupportCaseDataProvider.SupportTicketActiveNoticeAsync();
|
||||
|
||||
if (!shouldQuit)
|
||||
return;
|
||||
|
||||
Current.Shutdown();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async void Application_Exit(object sender, ExitEventArgs e)
|
||||
{
|
||||
var closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
|
||||
|
||||
await cFasdCockpitCommunicationBase.Instance.TerminateAsync();
|
||||
|
||||
if (notifyIcon != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
cConnectionStatusHelper.Instance.IsActive = false;
|
||||
notifyIcon.Visible = false;
|
||||
notifyIcon.Dispose();
|
||||
cAppStartUp.Terminate();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (AppMutex != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
AppMutex.ReleaseMutex();
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
AppMutex.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var _now = DateTime.UtcNow;
|
||||
bool _validSend = true;
|
||||
while ((DateTime.UtcNow - _now).TotalSeconds < 6 && _validSend)
|
||||
_validSend = cF4sdPipeClient.Send("STOP", PhoneMonitorPipeName);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (closeUserSessionTask is ConfiguredTaskAwaitable _t)
|
||||
await _t;
|
||||
}
|
||||
}
|
||||
}
|
||||
896
FasdDesktopUi/AppStartUp.cs
Normal file
896
FasdDesktopUi/AppStartUp.cs
Normal file
@@ -0,0 +1,896 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Web;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using FasdDesktopUi.Basics;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Pages.CustomMessageBox;
|
||||
using FasdDesktopUi.Pages.DetailsPage.Models;
|
||||
using FasdDesktopUi.Pages.SplashScreenView;
|
||||
using FasdDesktopUi.Pages.M42AuthenticationPage;
|
||||
using FasdDesktopUi.Pages.SearchPage;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using C4IT.F4SD.TAPI;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
|
||||
namespace FasdDesktopUi
|
||||
{
|
||||
public class cAppStartUp
|
||||
{
|
||||
public const string constUrlProtocol = "F4SDSEND";
|
||||
public const string constUrlCommand = "sendurl";
|
||||
private static bool AreAppComponentsInitialized = false;
|
||||
|
||||
private static SplashScreenView splashScreen;
|
||||
|
||||
public static async Task<bool> StartAsync(string[] startArguments)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
#if isDemo
|
||||
cFasdCockpitCommunicationBase.Instance = new cFasdCockpitCommunicationDemo();
|
||||
#else
|
||||
cFasdCockpitCommunicationBase.Instance = new cFasdCockpitCommunicationWeb();
|
||||
#endif
|
||||
|
||||
if (!startArguments.Contains("SilentStart", StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
splashScreen = new SplashScreenView();
|
||||
splashScreen?.Show();
|
||||
}
|
||||
|
||||
var searchPageView = SearchPageView.Instance;
|
||||
var settingsPageView = FasdDesktopUi.Pages.SettingsPage.SettingsPageView.Create();
|
||||
|
||||
splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.CheckServerConnection"));
|
||||
if (!await InitializeCommunicationAsync())
|
||||
{
|
||||
LogEntry("Error when initializing communication components.", LogLevels.Fatal);
|
||||
CustomMessageBox.Show("Error when initializing communication components.", "Fatal Error", enumHealthCardStateLevel.Error);
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
if (cConnectionStatusHelper.Instance.ApiConnectionStatus >= cConnectionStatusHelper.enumOnlineStatus.illegalConfig)
|
||||
{
|
||||
splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.InitAppComponents"));
|
||||
if (!await InitializeUiElementsAsync())
|
||||
return false;
|
||||
}
|
||||
cConnectionStatusHelper.ApiConnectionStatusChanged += ApiConnectionStatusChanged;
|
||||
|
||||
// Aufruf der neuen Prominenteren Suche (work in progress)
|
||||
//var advancedPaged = new AdvancedSearchPage();
|
||||
//advancedPaged.Show();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
splashScreen?.Hide();
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ProcessCommandLine(string[] Args)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (DefaultLogger.IsDebug)
|
||||
{
|
||||
var _msg = new List<string>() { "command line arguments:" };
|
||||
foreach (var _entry in Args)
|
||||
_msg.Add(_entry);
|
||||
DefaultLogger.LogList(LogLevels.Debug, _msg);
|
||||
}
|
||||
|
||||
var Command = Args[0].ToLowerInvariant();
|
||||
bool shouldShutdown = true;
|
||||
|
||||
switch (Command)
|
||||
{
|
||||
case "search":
|
||||
if (Args.Length < 2)
|
||||
{
|
||||
LogEntry($"Missing search value on command line for command {Command}.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
var Search = Args[1];
|
||||
cAppStartUp.SendSearchValue(Search);
|
||||
break;
|
||||
case "phonesearch":
|
||||
try
|
||||
{
|
||||
if (Args.Length < 2)
|
||||
{
|
||||
LogEntry($"Missing search value on command line for command {Command}.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
var searchInfo = new cPhoneSearchParameters
|
||||
{
|
||||
phone = Args[1]
|
||||
};
|
||||
if (Args.Length >= 3)
|
||||
searchInfo.name = Args[2];
|
||||
SendPhoneSearchValues(searchInfo);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
break;
|
||||
case "computerdomainsearch":
|
||||
try
|
||||
{
|
||||
if (Args.Length < 2)
|
||||
{
|
||||
LogEntry($"Missing a search value on command line for command {Command}.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
var searchInfo = new cComputerDomainSearchParameters()
|
||||
{
|
||||
name = Args[1],
|
||||
domain = ""
|
||||
};
|
||||
if (Args.Length >= 3)
|
||||
searchInfo.domain = Args[2];
|
||||
cAppStartUp.SendComputerDomainSearchValues(searchInfo);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
break;
|
||||
case "usersidsearch":
|
||||
try
|
||||
{
|
||||
if (Args.Length < 2)
|
||||
{
|
||||
LogEntry($"Missing a search value on command line for command {Command}.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
var searchInfo = new cUserSidSearchParameters()
|
||||
{
|
||||
name = Args[1],
|
||||
sids = ""
|
||||
};
|
||||
if (Args.Length >= 3)
|
||||
searchInfo.sids = Args[2];
|
||||
cAppStartUp.SendUserSidSearchValues(searchInfo);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
break;
|
||||
case "ticketsearch":
|
||||
try
|
||||
{
|
||||
if (Args.Length < 4)
|
||||
{
|
||||
LogEntry($"Missing a search value on command line for command {Command}.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
var searchInfo = new cTicketSearchParameters()
|
||||
{
|
||||
ticketName = Args[1],
|
||||
ticketId = Args[2],
|
||||
userName = Args[3],
|
||||
sids = ""
|
||||
};
|
||||
if (Args.Length >= 5)
|
||||
searchInfo.sids = Args[4];
|
||||
cAppStartUp.SendTicketSearchValues(searchInfo);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
break;
|
||||
case constUrlCommand:
|
||||
if (Args.Length < 2)
|
||||
{
|
||||
LogEntry("Missing url on command line.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
var Url = Args[1];
|
||||
cAppStartUp.ProcessMessageUrl(Url);
|
||||
break;
|
||||
default:
|
||||
shouldShutdown = false;
|
||||
LogEntry($"Unknown command on commandline: {Command}", LogLevels.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
return shouldShutdown;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ProcessMessageUrl(string url)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (url.Length <= constUrlProtocol.Length + 3)
|
||||
{
|
||||
LogEntry($"No valid {constUrlProtocol} message.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var urlPrefix = url.Substring(0, constUrlProtocol.Length + 3).ToLowerInvariant();
|
||||
if (urlPrefix != constUrlProtocol.ToLowerInvariant() + "://")
|
||||
{
|
||||
LogEntry($"Unknown protocol prefix {urlPrefix}. Should be {constUrlProtocol}://", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var arr1 = url.Split('?');
|
||||
|
||||
if (arr1.Length < 2)
|
||||
{
|
||||
LogEntry("No valid url parameters.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var arrParams = arr1[1].Split('&');
|
||||
var dicParams = new Dictionary<string, string>();
|
||||
|
||||
foreach (var param in arrParams)
|
||||
{
|
||||
var arr2 = param.Split('=');
|
||||
if (arr2.Length != 2)
|
||||
{
|
||||
LogEntry($"Invalid url parameter: {param}", LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var name = HttpUtility.UrlDecode(arr2[0]).Trim().ToLowerInvariant();
|
||||
var value = HttpUtility.UrlDecode(arr2[1]).Trim();
|
||||
dicParams[name] = value;
|
||||
}
|
||||
|
||||
if (!dicParams.TryGetValue("command", out var commandType))
|
||||
{
|
||||
LogEntry("Missing command parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (commandType.ToLowerInvariant())
|
||||
{
|
||||
case "search":
|
||||
if (!dicParams.TryGetValue("value", out var searchValue))
|
||||
{
|
||||
LogEntry("Missing value parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
SendSearchValue(searchValue);
|
||||
break;
|
||||
case "phonesearch":
|
||||
{
|
||||
if (!dicParams.TryGetValue("phone", out var searchPhone))
|
||||
{
|
||||
LogEntry("Missing phone parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
if (!dicParams.TryGetValue("name", out var searchName))
|
||||
searchName = null;
|
||||
var searchInfo = new cPhoneSearchParameters() { phone = searchPhone, name = searchName };
|
||||
SendPhoneSearchValues(searchInfo);
|
||||
}
|
||||
break;
|
||||
case "usersidsearch":
|
||||
{
|
||||
if (!dicParams.TryGetValue("name", out var searchName))
|
||||
{
|
||||
LogEntry("Missing name parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
if (!dicParams.TryGetValue("sids", out var searchSids))
|
||||
searchSids = null;
|
||||
var searchInfo = new cUserSidSearchParameters() { name = searchName, sids = searchSids };
|
||||
SendUserSidSearchValues(searchInfo);
|
||||
}
|
||||
break;
|
||||
case "computerdomainsearch":
|
||||
{
|
||||
if (!dicParams.TryGetValue("name", out var searchName))
|
||||
{
|
||||
LogEntry("Missing name parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
if (!dicParams.TryGetValue("domain", out var searchDomain))
|
||||
searchDomain = null;
|
||||
var searchInfo = new cComputerDomainSearchParameters() { name = searchName, domain = searchDomain };
|
||||
SendComputerDomainSearchValues(searchInfo);
|
||||
}
|
||||
break;
|
||||
case "ticketsearch":
|
||||
{
|
||||
if (!dicParams.TryGetValue("tname", out var _tname))
|
||||
{
|
||||
LogEntry("Missing ticket name parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
if (!dicParams.TryGetValue("tid", out var _tid))
|
||||
{
|
||||
LogEntry("Missing ticket id parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
if (!dicParams.TryGetValue("uname", out var _uname))
|
||||
{
|
||||
LogEntry("Missing ticket id parameter in url.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var searchInfo = new cTicketSearchParameters()
|
||||
{
|
||||
ticketName = _tname,
|
||||
ticketId = _tid,
|
||||
userName = _uname
|
||||
};
|
||||
if (dicParams.TryGetValue("sids", out var _sids))
|
||||
searchInfo.sids = _sids;
|
||||
SendTicketSearchValues(searchInfo);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogEntry($"Unknown url command parameter: {commandType}.", LogLevels.Warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendSearchValue(string searchValue)
|
||||
{
|
||||
cF4sdPipeClient.Send("search:" + searchValue, App.PipeName);
|
||||
}
|
||||
|
||||
public static void SendPhoneSearchValues(cPhoneSearchParameters search)
|
||||
{
|
||||
var jsonSearch = JsonConvert.SerializeObject(search);
|
||||
cF4sdPipeClient.Send("phonesearch:" + jsonSearch, App.PipeName);
|
||||
}
|
||||
|
||||
public static void SendComputerDomainSearchValues(cComputerDomainSearchParameters search)
|
||||
{
|
||||
var jsonSearch = JsonConvert.SerializeObject(search);
|
||||
cF4sdPipeClient.Send("computerdomainsearch:" + jsonSearch, App.PipeName);
|
||||
}
|
||||
|
||||
public static void SendUserSidSearchValues(cUserSidSearchParameters search)
|
||||
{
|
||||
var jsonSearch = JsonConvert.SerializeObject(search);
|
||||
cF4sdPipeClient.Send("usersidsearch:" + jsonSearch, App.PipeName);
|
||||
}
|
||||
|
||||
public static void SendTicketSearchValues(cTicketSearchParameters search)
|
||||
{
|
||||
var jsonSearch = JsonConvert.SerializeObject(search);
|
||||
cF4sdPipeClient.Send("ticketsearch:" + jsonSearch, App.PipeName);
|
||||
}
|
||||
|
||||
private static async Task<bool> InitializeCommunicationAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!cFasdCockpitCommunicationBase.Instance.CheckConnectionInfo())
|
||||
{
|
||||
CustomMessageBox.Show("No valid server URL found in registry.", "First Aid Service Desk", enumHealthCardStateLevel.Error);
|
||||
LogEntry("No valid server URL found in registry.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var _csh = new cConnectionStatusHelper();
|
||||
_csh.M42FormBasedAuthentication += F4sdM42FormsAuthentication.M42FormBasedAuthenticationDelegate;
|
||||
cConnectionStatusHelper.Instance = _csh;
|
||||
|
||||
await cConnectionStatusHelper.Instance.RunConnectionStatusCheckAsync(splashScreen);
|
||||
cConnectionStatusHelper.Instance.OnApiConnectionStatusChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static async void ApiConnectionStatusChanged(cConnectionStatusHelper.enumOnlineStatus? Status)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (AreAppComponentsInitialized || Status != cConnectionStatusHelper.enumOnlineStatus.online)
|
||||
return;
|
||||
|
||||
await InitializeUiElementsAsync();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CheckSwyxIt()
|
||||
{
|
||||
try
|
||||
{
|
||||
var regObj = Registry.GetValue("HKEY_CLASSES_ROOT\\WOW6432Node\\CLSID\\{F8E552F8-4C00-11D3-80BC-00105A653379}\\VersionIndependentProgID", null, null);
|
||||
if ((regObj is string strObj) && (strObj.ToLowerInvariant() == "clmgr.clientlinemgr"))
|
||||
return true;
|
||||
regObj = Registry.GetValue("HKEY_CLASSES_ROOT\\CLSID\\{F8E552F8-4C00-11D3-80BC-00105A653379}\\VersionIndependentProgID", null, null);
|
||||
if ((regObj is string strObj2) && (strObj2.ToLowerInvariant() == "clmgr.clientlinemgr"))
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void TapiMessageHandler(C4TapiHelper.C4TapiLineInfo lineInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (lineInfo.eventType == C4TapiHelper.eTapiEventType.connected)
|
||||
{
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (lineInfo.IsOutbound && !cFasdCockpitConfig.Instance.PhoneSupport.SignalOutgoingCalls)
|
||||
{
|
||||
LogEntry("An outgoing call is signaled but signaling outgoing calls is not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
var phone = lineInfo.participantPhoneNumber;
|
||||
var phone2 = phone.Trim();
|
||||
if (!string.IsNullOrEmpty(cFasdCockpitConfig.Instance.PhoneSupport.ExternalCallPrefix) && phone2.StartsWith(cFasdCockpitConfig.Instance.PhoneSupport.ExternalCallPrefix))
|
||||
phone2 = phone2.Remove(0, cFasdCockpitConfig.Instance.PhoneSupport.ExternalCallPrefix.Length);
|
||||
|
||||
if (phone2.StartsWith("+"))
|
||||
{
|
||||
var _r = Math.Min(phone2.Length, 3);
|
||||
phone2 = phone2.Remove(0, _r);
|
||||
}
|
||||
else if (phone2.StartsWith("00"))
|
||||
{
|
||||
var _r = Math.Min(phone2.Length, 4);
|
||||
phone2 = phone2.Remove(0, _r);
|
||||
}
|
||||
if (phone2.StartsWith("0"))
|
||||
phone2 = phone2.Remove(0, 1);
|
||||
|
||||
var phone3 = "";
|
||||
foreach (var C in phone2)
|
||||
if ((C >= '0') && (C <= '9'))
|
||||
phone3 += C;
|
||||
|
||||
var phoneSearch = new cPhoneSearchParameters()
|
||||
{
|
||||
phone = phone3,
|
||||
name = lineInfo.participantName.Trim()
|
||||
};
|
||||
SendPhoneSearchValues(phoneSearch);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void StartPhoneCallMonitoring()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
// check phone support disabled
|
||||
if (cFasdCockpitConfig.Instance.PhoneSupport.DisablePhoneSupport)
|
||||
return;
|
||||
|
||||
var disposeTapi = false;
|
||||
try
|
||||
{
|
||||
// get the TAPI lines
|
||||
lock (C4TapiHelper.InstanceLock)
|
||||
{
|
||||
C4TapiHelper.Instance = new C4TapiHelper();
|
||||
disposeTapi = true;
|
||||
C4TapiHelper.Instance.Initialize(TapiMessageHandler);
|
||||
C4TapiHelper.Instance.GetLines();
|
||||
}
|
||||
|
||||
|
||||
// check prefer swyxit
|
||||
if (cFasdCockpitConfig.Instance.PhoneSupport.PreferSwyxitNative && CheckSwyxIt())
|
||||
{
|
||||
if (StartPhoneMonitorExternal("SwyxItNative"))
|
||||
return;
|
||||
}
|
||||
|
||||
// check if we autoconnect TAPI
|
||||
lock (C4TapiHelper.InstanceLock)
|
||||
{
|
||||
string _tapiLine = null;
|
||||
if (C4TapiHelper.Lines != null && !string.IsNullOrEmpty(cFasdCockpitConfig.Instance.PhoneSupport.PreferedTapiLine) && C4TapiHelper.Lines.Contains(cFasdCockpitConfig.Instance.PhoneSupport.PreferedTapiLine))
|
||||
_tapiLine = cFasdCockpitConfig.Instance.PhoneSupport.PreferedTapiLine;
|
||||
else if (C4TapiHelper.Lines != null && C4TapiHelper.Lines.Count == 1)
|
||||
_tapiLine = C4TapiHelper.Lines[0];
|
||||
|
||||
if (_tapiLine != null)
|
||||
{
|
||||
if (cFasdCockpitConfig.Instance.PhoneSupport.UseTapi32Bit)
|
||||
{
|
||||
if (StartPhoneMonitorExternal(_tapiLine))
|
||||
return;
|
||||
}
|
||||
|
||||
if (C4TapiHelper.Instance.ConnectLine(C4TapiHelper.Lines[0]))
|
||||
disposeTapi = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (C4TapiHelper.InstanceLock)
|
||||
{
|
||||
if (disposeTapi)
|
||||
{
|
||||
C4TapiHelper.Instance.Dispose();
|
||||
C4TapiHelper.Instance = null;
|
||||
}
|
||||
}
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static bool StartPhoneMonitorExternal(string Line)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var ass = Assembly.GetEntryAssembly();
|
||||
var path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(ass.Location)), "F4SD-PhoneMonitor.exe");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var preFix = cFasdCockpitConfig.Instance.PhoneSupport.ExternalCallPrefix ?? "";
|
||||
var signalExtern = cFasdCockpitConfig.Instance.PhoneSupport.SignalOutgoingCalls ? "1" : "0";
|
||||
var _cmd = "\"" + App.PipeName + "\" \"" + App.PhoneMonitorPipeName + "\" \"" + Line + "\" \"" + preFix + "\" \"" + signalExtern + "\"";
|
||||
var pr = Process.Start(path, _cmd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static async Task<bool> InitializeUiElementsAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.LoadAppViews"));
|
||||
|
||||
CheckHealthCardAvailability();
|
||||
UpdateRegistryGeometryBasedOnFirstDataOfDataProvider();
|
||||
|
||||
// adjust notify icon menu
|
||||
cF4sdUserInfo userInfo;
|
||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||
{
|
||||
userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cCockpitConfiguration.Instance?.m42ServerConfiguration?.Server))
|
||||
if (userInfo?.possibleLogons != null)
|
||||
{
|
||||
if (userInfo.possibleLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
|
||||
{
|
||||
if (App.M42OptionMenuItem != null)
|
||||
{
|
||||
App.M42OptionMenuItem.Visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await InitializeViewsAsync();
|
||||
|
||||
AreAppComponentsInitialized = true;
|
||||
|
||||
var PhoneThread = new Thread(StartPhoneCallMonitoring);
|
||||
PhoneThread.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void CheckHealthCardAvailability()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!cHealthCardDataHelper.HasAvailableHealthCard(new List<enumFasdInformationClass>() { enumFasdInformationClass.Ticket }))
|
||||
LogEntry("No available Health Card for Tickets was found.", LogLevels.Info);
|
||||
|
||||
if (!cHealthCardDataHelper.HasAvailableHealthCard(new List<enumFasdInformationClass>() { enumFasdInformationClass.Computer }))
|
||||
LogEntry("No available Health Card for computers was found.", LogLevels.Error);
|
||||
|
||||
if (!cHealthCardDataHelper.HasAvailableHealthCard(new List<enumFasdInformationClass>() { enumFasdInformationClass.User }))
|
||||
LogEntry("No available Health Card for users was found.", LogLevels.Error);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Terminate()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
lock (C4TapiHelper.InstanceLock)
|
||||
{
|
||||
if (C4TapiHelper.Instance != null)
|
||||
{
|
||||
C4TapiHelper.Instance.Dispose();
|
||||
C4TapiHelper.Instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
#region Views & Geometry
|
||||
|
||||
private static void UpdateRegistryGeometryBasedOnFirstDataOfDataProvider()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
//Get old geometry from registry
|
||||
DetailsPageGeometry lastGeometry = !string.IsNullOrEmpty(cFasdCockpitConfig.Instance.DetailsPageMaxGeometry) ?
|
||||
JsonConvert.DeserializeObject<DetailsPageGeometry>(cFasdCockpitConfig.Instance.DetailsPageMaxGeometry) :
|
||||
new DetailsPageGeometry()
|
||||
{
|
||||
DetailsCollectionGeometry = new DetailsPageDataHistoryCollectionGeometryModel() { SubtitleCount = new List<int>() },
|
||||
WidgetGeometryList = new List<DetailsPageWidgetGeometryModel>()
|
||||
};
|
||||
|
||||
//Get new geometry from DataList
|
||||
cHealthCard firstHealthCard = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.HealthCards.FirstOrDefault(healthCard => healthCard.Value.InformationClasses.Contains(enumFasdInformationClass.Computer)).Value;
|
||||
|
||||
|
||||
DetailsPageGeometry newGeometry = new DetailsPageGeometry()
|
||||
{
|
||||
DetailsCollectionGeometry = new DetailsPageDataHistoryCollectionGeometryModel() { SubtitleCount = new List<int>() },
|
||||
WidgetGeometryList = new List<DetailsPageWidgetGeometryModel>()
|
||||
};
|
||||
|
||||
foreach (var widgetData in firstHealthCard.CategoriesStatic.StateCategories)
|
||||
{
|
||||
if (widgetData.IsHidden)
|
||||
continue;
|
||||
newGeometry.WidgetGeometryList.Add(new DetailsPageWidgetGeometryModel() { WidgetTitleCount = widgetData.States.Count, WidgetDetailCount = widgetData.States.Count });
|
||||
}
|
||||
|
||||
newGeometry.DetailsCollectionGeometry.ColumnCount = firstHealthCard.MaxAgeInDays;
|
||||
foreach (var detailsData in firstHealthCard.CategoriesHistory.StateCategories)
|
||||
{
|
||||
if (detailsData.IsHidden)
|
||||
continue;
|
||||
var stateCount = detailsData.States.Count;
|
||||
foreach (var state in detailsData.States)
|
||||
{
|
||||
if (state.IsHidden)
|
||||
continue;
|
||||
if (state is cHealthCardStateAggregation aggregationState)
|
||||
stateCount += aggregationState.States.Count;
|
||||
}
|
||||
|
||||
newGeometry.DetailsCollectionGeometry.SubtitleCount.Add(stateCount);
|
||||
}
|
||||
|
||||
//Update new geometry
|
||||
var lastGeometryWidgetEnumerator = lastGeometry.WidgetGeometryList.GetEnumerator();
|
||||
foreach (var widgetGeometry in newGeometry.WidgetGeometryList)
|
||||
{
|
||||
if (lastGeometryWidgetEnumerator.MoveNext())
|
||||
{
|
||||
var lastWidgetGeometry = lastGeometryWidgetEnumerator.Current;
|
||||
widgetGeometry.WidgetTitleCount = cUtility.SmoothedInt(lastWidgetGeometry.WidgetTitleCount, widgetGeometry.WidgetTitleCount);
|
||||
widgetGeometry.WidgetDetailCount = cUtility.SmoothedInt(lastWidgetGeometry.WidgetDetailCount, widgetGeometry.WidgetDetailCount);
|
||||
}
|
||||
}
|
||||
|
||||
newGeometry.DetailsCollectionGeometry.ColumnCount = cUtility.SmoothedInt(lastGeometry.DetailsCollectionGeometry.ColumnCount, newGeometry.DetailsCollectionGeometry.ColumnCount);
|
||||
|
||||
var lastGeometryDetailsSubtitleEnumerator = lastGeometry.DetailsCollectionGeometry.SubtitleCount.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < newGeometry.DetailsCollectionGeometry.SubtitleCount.Count; i++)
|
||||
{
|
||||
if (lastGeometryDetailsSubtitleEnumerator.MoveNext())
|
||||
{
|
||||
int tempSubtitleCountValue = newGeometry.DetailsCollectionGeometry.SubtitleCount[i];
|
||||
int newSubtitleCountValue = cUtility.SmoothedInt(lastGeometryDetailsSubtitleEnumerator.Current, tempSubtitleCountValue);
|
||||
newGeometry.DetailsCollectionGeometry.SubtitleCount[i] = newSubtitleCountValue;
|
||||
}
|
||||
}
|
||||
|
||||
//Save new Geometry
|
||||
cFasdCockpitConfig.Instance.DetailsPageMaxGeometry = JsonConvert.SerializeObject(newGeometry);
|
||||
cFasdCockpitConfig.Instance.Save("DetailsPageMaxGeometry");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private static DetailsPageGeometry BaseDetailsPageGeometry()
|
||||
{
|
||||
try
|
||||
{
|
||||
string registryGeometryString = cFasdCockpitConfig.Instance.DetailsPageMaxGeometry;
|
||||
|
||||
DetailsPageGeometry output = !string.IsNullOrEmpty(registryGeometryString) ?
|
||||
JsonConvert.DeserializeObject<DetailsPageGeometry>(registryGeometryString) :
|
||||
new DetailsPageGeometry() { DetailsCollectionGeometry = new DetailsPageDataHistoryCollectionGeometryModel() { SubtitleCount = new List<int>() }, WidgetGeometryList = new List<DetailsPageWidgetGeometryModel>() };
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async Task InitializeViewsAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var _arrTasks = new List<Task>
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)delegate { cSupportCaseDataProvider.slimPage = new Pages.SlimPage.SlimPageView(); }, DispatcherPriority.Normal).Task,
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)delegate { cSupportCaseDataProvider.detailsPage = new Pages.DetailsPage.DetailsPageView(); }, DispatcherPriority.Normal).Task
|
||||
};
|
||||
await Task.WhenAll(_arrTasks);
|
||||
_arrTasks = new List<Task>
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)delegate { cSupportCaseDataProvider.detailsPage.SetGeometryValues(BaseDetailsPageGeometry()); }, DispatcherPriority.Normal).Task,
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)delegate { cSupportCaseDataProvider.slimPage.SetZoomValue(cFasdCockpitConfig.Instance.SlimPageZoom); }, DispatcherPriority.Normal).Task,
|
||||
Application.Current.Dispatcher.BeginInvoke((Action)delegate { cSupportCaseDataProvider.detailsPage.SetZoomValue(cFasdCockpitConfig.Instance.DetailsPageZoom); }, DispatcherPriority.Normal).Task
|
||||
};
|
||||
await Task.WhenAll(_arrTasks);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
20
FasdDesktopUi/Basics/BaseViewModel.cs
Normal file
20
FasdDesktopUi/Basics/BaseViewModel.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public class BaseViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string name = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
144
FasdDesktopUi/Basics/Browser.cs
Normal file
144
FasdDesktopUi/Basics/Browser.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using C4IT.Logging;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public class cBrowsers
|
||||
{
|
||||
List<cBrowser> browsers { get; set; }
|
||||
|
||||
public cBrowsers()
|
||||
{
|
||||
this.browsers = GetBrowsers();
|
||||
}
|
||||
|
||||
private List<cBrowser> GetBrowsers()
|
||||
{
|
||||
List<cBrowser> browsers = new List<cBrowser>();
|
||||
|
||||
try
|
||||
{
|
||||
RegistryKey browserKeys;
|
||||
browserKeys = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
|
||||
if (browserKeys is null)
|
||||
browserKeys = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Clients\StartMenuInternet");
|
||||
string[] browserNames = browserKeys.GetSubKeyNames();
|
||||
|
||||
foreach (string browserName in browserNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
cBrowser browser = new cBrowser();
|
||||
RegistryKey browserKey = browserKeys.OpenSubKey(browserName);
|
||||
browser.Name = (string)browserKey.GetValue(null);
|
||||
RegistryKey browserKeyPath = browserKey.OpenSubKey(@"shell\open\command");
|
||||
browser.Path = browserKeyPath.GetValue(null).ToString().StripQuotes();
|
||||
if (File.Exists(browser.Path))
|
||||
{
|
||||
browsers.Add(browser);
|
||||
if (browser.Path != null)
|
||||
try
|
||||
{
|
||||
browser.Version = FileVersionInfo.GetVersionInfo(browser.Path).FileVersion;
|
||||
}
|
||||
catch
|
||||
{
|
||||
browser.Version = "unknown";
|
||||
}
|
||||
else
|
||||
browser.Version = "unknown";
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return browsers;
|
||||
}
|
||||
|
||||
public cBrowser GetBrowserByName(string browserName)
|
||||
{
|
||||
foreach (cBrowser browser in this.browsers)
|
||||
{
|
||||
if (browser.Name.Equals(browserName, StringComparison.InvariantCultureIgnoreCase))
|
||||
return browser;
|
||||
}
|
||||
return new cBrowser("Internet Explorer", "iexplorer.exe");
|
||||
}
|
||||
|
||||
public void Start(string browserName, string Url)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (browserName is null || browserName.ToLowerInvariant() == "default")
|
||||
{
|
||||
Process.Start(Url);
|
||||
}
|
||||
else
|
||||
{
|
||||
Url = "--single-argument " + Url;
|
||||
|
||||
var browser = GetBrowserByName(browserName);
|
||||
if (!string.IsNullOrEmpty(browser.Path))
|
||||
Process.Start(browser.Path, Url);
|
||||
else
|
||||
Process.Start(Url);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cBrowser
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string Version { get; set; }
|
||||
|
||||
public cBrowser(string name = "", string path = "", string version = "")
|
||||
{
|
||||
Name = name;
|
||||
Path = path;
|
||||
Version = version;
|
||||
}
|
||||
}
|
||||
internal static class Extensions
|
||||
{
|
||||
///
|
||||
/// if string begins and ends with quotes, they are removed
|
||||
///
|
||||
internal static String StripQuotes(this String s)
|
||||
{
|
||||
if (s.EndsWith("\"") && s.StartsWith("\""))
|
||||
{
|
||||
return s.Substring(1, s.Length - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
|
||||
using C4IT.Logging;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class BoolOrToVisibilityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value is bool boolValue && boolValue)
|
||||
return Visibility.Visible;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class BooleanToBrushConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public Object TrueValue { get; set; } = new SolidColorBrush(Colors.LightGray);
|
||||
public Object FalseValue { get; set; } = new SolidColorBrush(Colors.Blue);
|
||||
|
||||
public object Convert(
|
||||
object value, Type targetType, object parameter,
|
||||
CultureInfo culture)
|
||||
{
|
||||
if (!(value is bool))
|
||||
return FalseValue;
|
||||
|
||||
return (bool)value ? TrueValue :
|
||||
FalseValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(
|
||||
object value, Type targetType, object parameter,
|
||||
CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class WebView2PathConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var _webViewConfigPath = cLogManagerFile.GetDefaultPath(false, SubFolder: "WebViewData");
|
||||
_webViewConfigPath = System.IO.Path.GetDirectoryName(_webViewConfigPath);
|
||||
return _webViewConfigPath;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
[ValueConversion(typeof(cDataCanvasDataModel), typeof(bool))]
|
||||
public class DataCanvasIsCloseButtonVisibileConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is cDataCanvasDataModel data) || !(parameter is enumDataCanvasTypes dataCanvasType))
|
||||
return null;
|
||||
|
||||
bool output = false;
|
||||
|
||||
switch (dataCanvasType)
|
||||
{
|
||||
case enumDataCanvasTypes.recommendation:
|
||||
if (data.QuickActionStatusMonitorData == null && data.DetailedData == null)
|
||||
output = true;
|
||||
break;
|
||||
case enumDataCanvasTypes.detailedData:
|
||||
if (data.QuickActionStatusMonitorData == null)
|
||||
output = true;
|
||||
break;
|
||||
case enumDataCanvasTypes.quickActionStatusMonitor:
|
||||
output = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public enum enumDataCanvasTypes
|
||||
{
|
||||
recommendation = 0,
|
||||
detailedData,
|
||||
quickActionStatusMonitor
|
||||
}
|
||||
}
|
||||
79
FasdDesktopUi/Basics/Converter/IconDataConverter.cs
Normal file
79
FasdDesktopUi/Basics/Converter/IconDataConverter.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using C4IT.FASD.Base;
|
||||
using F4SD_AdaptableIcon;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages conversion between <see cref="cFasdIcon"/> and <see cref="IconData"/>
|
||||
/// </summary>
|
||||
internal class IconDataConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts <see cref="cFasdIcon"/> to <see cref="IconData"/>
|
||||
/// </summary>
|
||||
/// <returns>The icon data of type <see cref="IconData"/></returns>
|
||||
internal static IconData Convert(cFasdIcon iconConfig)
|
||||
{
|
||||
switch (iconConfig.IconType)
|
||||
{
|
||||
case enumIconType.intern:
|
||||
if (Enum.TryParse(iconConfig.Name, out enumInternIcons intern))
|
||||
return new IconData(intern);
|
||||
break;
|
||||
case enumIconType.material:
|
||||
if (Enum.TryParse(iconConfig.Name, out MaterialIcons.MaterialIconType material))
|
||||
return new IconData(material);
|
||||
break;
|
||||
case enumIconType.gif:
|
||||
if (Enum.TryParse(iconConfig.Name, out enumInternGif gif))
|
||||
return new IconData(gif);
|
||||
break;
|
||||
}
|
||||
|
||||
return new IconData(enumInternIcons.none);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="cFasdIcon"/> to <see cref="IconData"/>
|
||||
/// </summary>
|
||||
/// <returns>The icon data of type <see cref="IconData"/></returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(IconData))
|
||||
return null;
|
||||
|
||||
if (!(value is cFasdIcon iconConfig))
|
||||
return new IconData(enumInternIcons.none);
|
||||
|
||||
return Convert(iconConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="IconData"/> to <see cref="cFasdIcon"/>
|
||||
/// </summary>
|
||||
/// <returns>The configuration of type <see cref="cFasdIcon"/></returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is IconData iconData))
|
||||
return null;
|
||||
|
||||
if (iconData.Intern != null)
|
||||
return new cFasdIcon() { IconType = enumIconType.intern, Name = iconData.Intern.ToString(), IsValid = true };
|
||||
else if (iconData.Material != null)
|
||||
return new cFasdIcon(iconData.Material.Value);
|
||||
else if (iconData.Gif != null)
|
||||
return new cFasdIcon() { IconType = enumIconType.gif, Name = iconData.Gif.ToString(), IsValid = true };
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
FasdDesktopUi/Basics/Converter/InternalEnumConverter.cs
Normal file
47
FasdDesktopUi/Basics/Converter/InternalEnumConverter.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class InternalEnumConverter
|
||||
{
|
||||
public static HorizontalAlignment GetHorizontalAlignment(enumF4sdHorizontalAlignment intern)
|
||||
{
|
||||
switch (intern)
|
||||
{
|
||||
case enumF4sdHorizontalAlignment.Default:
|
||||
return HorizontalAlignment.Left;
|
||||
case enumF4sdHorizontalAlignment.Right:
|
||||
return HorizontalAlignment.Right;
|
||||
case enumF4sdHorizontalAlignment.Center:
|
||||
return HorizontalAlignment.Center;
|
||||
case enumF4sdHorizontalAlignment.Left:
|
||||
return HorizontalAlignment.Left;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static enumF4sdHorizontalAlignment GetHorizontalAlignment(HorizontalAlignment alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case HorizontalAlignment.Left:
|
||||
return enumF4sdHorizontalAlignment.Left;
|
||||
case HorizontalAlignment.Center:
|
||||
return enumF4sdHorizontalAlignment.Center;
|
||||
case HorizontalAlignment.Right:
|
||||
return enumF4sdHorizontalAlignment.Right;
|
||||
case HorizontalAlignment.Stretch:
|
||||
return enumF4sdHorizontalAlignment.Left;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
FasdDesktopUi/Basics/Converter/InvertBoolConverter.cs
Normal file
29
FasdDesktopUi/Basics/Converter/InvertBoolConverter.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
[ValueConversion(typeof(bool), typeof(bool))]
|
||||
public class InvertBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(bool))
|
||||
throw new InvalidOperationException("The target must be a boolean");
|
||||
|
||||
return !(bool)value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(bool))
|
||||
throw new InvalidOperationException("The target must be a boolean");
|
||||
|
||||
return !(bool)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class LanguageDefinitionsConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(parameter is string techFieldDescriptor))
|
||||
return "N/A";
|
||||
|
||||
string fieldDescription = cMultiLanguageSupport.GetItem(techFieldDescriptor, techFieldDescriptor);
|
||||
|
||||
if (value is object[] valueArray)
|
||||
return string.Format(fieldDescription, valueArray);
|
||||
|
||||
if (value is List<object> valueList)
|
||||
return string.Format(fieldDescription, valueList.ToArray());
|
||||
|
||||
if (value is object valueString)
|
||||
return string.Format(fieldDescription, valueString);
|
||||
|
||||
return fieldDescription;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LogEntry($"An Error occured while setting the value ({value}) to field: {parameter}");
|
||||
}
|
||||
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class NullValueToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
return Visibility.Collapsed;
|
||||
else if (value is string valueString)
|
||||
if (string.IsNullOrWhiteSpace(valueString))
|
||||
return Visibility.Collapsed;
|
||||
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
FasdDesktopUi/Basics/Converter/PercentConverter.cs
Normal file
30
FasdDesktopUi/Basics/Converter/PercentConverter.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class PercentToDecimalConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is int percent)
|
||||
return percent / 100.0;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is double doubleValue)
|
||||
return doubleValue * 100;
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using C4IT.FASD.Base;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using FasdCockpitBase.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Converter
|
||||
{
|
||||
public class RevisionStatusToAdaptableIconConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is enumQuickActionRevisionStatus revisionStatus))
|
||||
return null;
|
||||
|
||||
switch (revisionStatus)
|
||||
{
|
||||
case enumQuickActionRevisionStatus.unknown:
|
||||
if (targetType == typeof(enumInternIcons?))
|
||||
return enumInternIcons.none;
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.inProgress:
|
||||
if (targetType == typeof(enumInternGif?))
|
||||
return enumInternGif.loadingSpinner;
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedSuccessfull:
|
||||
if (targetType == typeof(enumInternIcons?))
|
||||
return enumInternIcons.status_good;
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.canceled:
|
||||
case enumQuickActionRevisionStatus.finishedWithError:
|
||||
if(targetType == typeof(enumInternIcons?))
|
||||
return enumInternIcons.status_bad;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
FasdDesktopUi/Basics/CustomEvents/BooleanEventArgs.cs
Normal file
24
FasdDesktopUi/Basics/CustomEvents/BooleanEventArgs.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.CustomEvents
|
||||
{
|
||||
public class BooleanEventArgs : RoutedEventArgs
|
||||
{
|
||||
public bool BooleanArg { get; set; }
|
||||
|
||||
public BooleanEventArgs()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BooleanEventArgs(bool booleanArg)
|
||||
{
|
||||
BooleanArg = booleanArg;
|
||||
}
|
||||
|
||||
public BooleanEventArgs(RoutedEvent routedEvent, bool booleanArg) : base(routedEvent)
|
||||
{
|
||||
BooleanArg = booleanArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
FasdDesktopUi/Basics/CustomEvents/CustomEventManager.cs
Normal file
32
FasdDesktopUi/Basics/CustomEvents/CustomEventManager.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.CustomEvents
|
||||
{
|
||||
internal class CustomEventManager
|
||||
{
|
||||
public delegate void IndexChangedHandlerDelegate(object sender, IndexEventArgs args);
|
||||
|
||||
public static readonly RoutedEvent IndexChangedEvent = EventManager.RegisterRoutedEvent("IndexChanged", RoutingStrategy.Bubble, typeof(IndexChangedHandlerDelegate), typeof(UIElement));
|
||||
|
||||
public static void RaiseIndexChangedEvent(UIElement uiElement, int oldValue = -1, int newValue = -1)
|
||||
{
|
||||
uiElement.RaiseEvent(new IndexEventArgs(IndexChangedEvent) { OldValue = oldValue, NewValue = newValue });
|
||||
}
|
||||
|
||||
public delegate void MenuDataChangedHandlerDelegate(object sender, MenuDataEventArgs args);
|
||||
|
||||
public static readonly RoutedEvent MenuDataChangedEvent = EventManager.RegisterRoutedEvent("MenuDataChanged", RoutingStrategy.Bubble, typeof(MenuDataChangedHandlerDelegate), typeof(UIElement));
|
||||
|
||||
public static void RaiseMenuDataChangedEvent(UIElement uIElement, cMenuDataBase menuData)
|
||||
{
|
||||
uIElement.RaiseEvent(new MenuDataEventArgs(MenuDataChangedEvent) { MenuData = menuData });
|
||||
}
|
||||
}
|
||||
}
|
||||
20
FasdDesktopUi/Basics/CustomEvents/IndexEventArgs.cs
Normal file
20
FasdDesktopUi/Basics/CustomEvents/IndexEventArgs.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.CustomEvents
|
||||
{
|
||||
internal class IndexEventArgs : RoutedEventArgs
|
||||
{
|
||||
public int OldValue { get; set; } = -1;
|
||||
public int NewValue { get; set; } = -1;
|
||||
|
||||
public IndexEventArgs(RoutedEvent routedEvent) : base(routedEvent)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
20
FasdDesktopUi/Basics/CustomEvents/MenuDataEventArgs.cs
Normal file
20
FasdDesktopUi/Basics/CustomEvents/MenuDataEventArgs.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.CustomEvents
|
||||
{
|
||||
internal class MenuDataEventArgs : RoutedEventArgs
|
||||
{
|
||||
public cMenuDataBase MenuData { get; set; }
|
||||
|
||||
public MenuDataEventArgs(RoutedEvent routedEvent) : base(routedEvent)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.CustomEvents
|
||||
{
|
||||
// New Advanced-Search-Page IN PROGRESS
|
||||
// Notes for next steps in AdvancedSearchPageView-Class
|
||||
public class SearchFilterChangedEventArgs : RoutedEventArgs
|
||||
{
|
||||
public HashSet<enumFasdInformationClass> InformationClassesToShow { get; set; }
|
||||
|
||||
public SearchFilterChangedEventArgs(RoutedEvent routedEvent) : base(routedEvent)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
FasdDesktopUi/Basics/Enums/enumActionDisplayType.cs
Normal file
15
FasdDesktopUi/Basics/Enums/enumActionDisplayType.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Enums
|
||||
{
|
||||
public enum enumActionDisplayType
|
||||
{
|
||||
hidden,
|
||||
disabled,
|
||||
enabled
|
||||
}
|
||||
}
|
||||
8
FasdDesktopUi/Basics/Enums/enumAppColorMode.cs
Normal file
8
FasdDesktopUi/Basics/Enums/enumAppColorMode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace FasdDesktopUi.Basics.Enums
|
||||
{
|
||||
public enum enumAppColorMode
|
||||
{
|
||||
DarkMode,
|
||||
LightMode
|
||||
}
|
||||
}
|
||||
11
FasdDesktopUi/Basics/Enums/enumHighlightColor.cs
Normal file
11
FasdDesktopUi/Basics/Enums/enumHighlightColor.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace FasdDesktopUi.Basics.Enums
|
||||
{
|
||||
public enum enumHighlightColor
|
||||
{
|
||||
none = 0,
|
||||
blue = 1,
|
||||
green = 2,
|
||||
orange = 3,
|
||||
red = 4
|
||||
}
|
||||
}
|
||||
15
FasdDesktopUi/Basics/Enums/enumQuickTipElementType.cs
Normal file
15
FasdDesktopUi/Basics/Enums/enumQuickTipElementType.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Enums
|
||||
{
|
||||
public enum enumQuickTipElementType
|
||||
{
|
||||
Text,
|
||||
Automated,
|
||||
Manual
|
||||
}
|
||||
}
|
||||
83
FasdDesktopUi/Basics/ExternalToolExecutorEnh.cs
Normal file
83
FasdDesktopUi/Basics/ExternalToolExecutorEnh.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.HTTP;
|
||||
using C4IT.Security;
|
||||
using FasdCockpitCommunication;
|
||||
using FasdCockpitBase;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public class cExternalToolExecutorEnh : cExternalToolExecutor
|
||||
{
|
||||
public static async Task<cProcessResult> StartServerActionAsync(cF4sdQuickActionServer ServerAction, cSupportCaseDataProvider dataProvider, string ProgramTitle, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
cProcessResult _resultProcess = new cProcessResult(0);
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
var apiError = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var http = GetHttpHelper(false);
|
||||
|
||||
var searchResultInfoClass = cF4sdIdentityEntry.GetFromSearchResult(enumF4sdSearchResultClass.Computer);
|
||||
var parameter = new cF4SDServerQuickActionParameters() { Action = ServerAction.Action, Category = ServerAction.Category, ParamaterType = ServerAction.ParameterType, Identities = dataProvider.Identities, AdjustableParameter = ParameterDictionary };
|
||||
var payload = JsonConvert.SerializeObject(parameter);
|
||||
|
||||
var result = await http.PostJsonAsync("api/QuickAction/Run", payload, 15000, CancellationToken.None);
|
||||
|
||||
if (!result.IsOk)
|
||||
{
|
||||
apiError = (int)result.Status;
|
||||
_resultProcess.ReturnCode = (int)result.Status;
|
||||
|
||||
}
|
||||
_resultProcess.StandardOutput = result.Result;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
apiError = E.HResult;
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
|
||||
return _resultProcess;
|
||||
}
|
||||
|
||||
public static cHttpHelper GetHttpHelper(bool useToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
return new cHttpHelper(cFasdCockpitMachineConfiguration.Instance.ServerUrl, GetOneTimePw().GetCredential(), false);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static cOneTimePW GetOneTimePw()
|
||||
{
|
||||
return new cOneTimePW("OneTimePw", cSecurePassword.Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
192
FasdDesktopUi/Basics/Helper/DirectConnectionHelper.cs
Normal file
192
FasdDesktopUi/Basics/Helper/DirectConnectionHelper.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
public class cDirectConnectionHelper
|
||||
{
|
||||
#region Properties and Fields
|
||||
|
||||
private int? isTryingToConnectToDevice = null;
|
||||
|
||||
private readonly cSupportCaseDataProvider dataProvider;
|
||||
|
||||
private Guid directConnectionId = Guid.Empty;
|
||||
|
||||
private readonly System.Timers.Timer directConnectionRenewTimer = new System.Timers.Timer();
|
||||
|
||||
public bool IsDirectConnectionActive { get => directConnectionId.Equals(Guid.Empty) is false; }
|
||||
|
||||
#endregion
|
||||
|
||||
public event EventHandler DirectConnectionChanged;
|
||||
|
||||
public cDirectConnectionHelper(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.dataProvider = dataProvider;
|
||||
|
||||
directConnectionRenewTimer.Interval = 1000 * 60 * 3;
|
||||
directConnectionRenewTimer.Elapsed += async (sender, e) => await DirectConnectionExtendDurationAsync(60 * 5);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
try
|
||||
{
|
||||
directConnectionId = Guid.Empty;
|
||||
isTryingToConnectToDevice = null;
|
||||
DirectConnectionChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DirectConnectionStartAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
const int maxRetries = 60;
|
||||
int retryCount = 0;
|
||||
|
||||
bool shouldTryStartDirectConnection = true;
|
||||
while (shouldTryStartDirectConnection && retryCount < maxRetries)
|
||||
{
|
||||
shouldTryStartDirectConnection = !(await CouldStartDirectConnectionAsync());
|
||||
|
||||
if (shouldTryStartDirectConnection)
|
||||
await Task.Delay(1000 * 5);
|
||||
|
||||
retryCount++;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> CouldStartDirectConnectionAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dataProvider.Identities.Any(identity => identity.Class == enumFasdInformationClass.Computer) is false)
|
||||
{
|
||||
LogEntry("Direct Connection - There was no information class of type computer found.", LogLevels.Error);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter))
|
||||
{
|
||||
LogEntry("Direct Connection - NamedParameter 'AgentDeviceId' could not be found.", LogLevels.Error);
|
||||
}
|
||||
if (agentDeviceIdParameter == null || !int.TryParse(agentDeviceIdParameter.GetValue(), out int agentDeviceId))
|
||||
{
|
||||
LogEntry("Direct Connection - There was no valid AgentDeviceId found.", LogLevels.Error);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isTryingToConnectToDevice == agentDeviceId)
|
||||
return true;
|
||||
|
||||
isTryingToConnectToDevice = agentDeviceId;
|
||||
|
||||
var tempConnectionId = await cFasdCockpitCommunicationBase.Instance.TryActivateDirectConnection(agentDeviceId);
|
||||
|
||||
if (tempConnectionId is null)
|
||||
{
|
||||
LogEntry("Direct Connection - Failed to receive connection status.", LogLevels.Error);
|
||||
isTryingToConnectToDevice = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
directConnectionId = tempConnectionId.Value;
|
||||
|
||||
if (isTryingToConnectToDevice != agentDeviceId)
|
||||
return true;
|
||||
|
||||
isTryingToConnectToDevice = null;
|
||||
await DirectConnectionExtendDurationAsync(60 * 5);
|
||||
directConnectionRenewTimer.Start();
|
||||
DirectConnectionChanged?.Invoke(this, EventArgs.Empty);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task DirectConnectionStopAsync()
|
||||
{
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
directConnectionRenewTimer.Stop();
|
||||
|
||||
if (directConnectionId.Equals(Guid.Empty))
|
||||
return;
|
||||
|
||||
await cFasdCockpitCommunicationBase.Instance.StopDirectConnection(directConnectionId);
|
||||
Reset();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DirectConnectionExtendDurationAsync(int durationInSeconds)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (directConnectionId.Equals(Guid.Empty))
|
||||
return false;
|
||||
|
||||
var output = await cFasdCockpitCommunicationBase.Instance.DirectConnectionExtendDuration(directConnectionId, durationInSeconds);
|
||||
|
||||
if (output is false)
|
||||
Reset();
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
2602
FasdDesktopUi/Basics/Helper/HealthCardDataHelper.cs
Normal file
2602
FasdDesktopUi/Basics/Helper/HealthCardDataHelper.cs
Normal file
File diff suppressed because it is too large
Load Diff
33
FasdDesktopUi/Basics/Helper/IconHelper.cs
Normal file
33
FasdDesktopUi/Basics/Helper/IconHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using F4SD_AdaptableIcon;
|
||||
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
public static class IconHelper
|
||||
{
|
||||
public static void SetIconValue(AdaptableIcon icon, IconData iconData)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (iconData.Intern != null)
|
||||
icon.SelectedInternIcon = iconData.Intern;
|
||||
else if(iconData.Material != null)
|
||||
icon.SelectedMaterialIcon = iconData.Material;
|
||||
else if(iconData.Gif != null)
|
||||
icon.SelectedInternGif = iconData.Gif;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
239
FasdDesktopUi/Basics/Helper/MenuItemDataProvider.cs
Normal file
239
FasdDesktopUi/Basics/Helper/MenuItemDataProvider.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
using C4IT.FASD.Base;
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
internal class MenuItemDataProvider
|
||||
{
|
||||
private readonly cSupportCaseDataProvider _dataProvider;
|
||||
|
||||
private const int defaultPinnedActionCount = 3; //search, notepad, copyTicketInformation
|
||||
|
||||
public MenuItemDataProvider(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
_dataProvider = dataProvider;
|
||||
}
|
||||
|
||||
public List<cMenuDataBase> GetMenuItemData()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
List<cMenuDataBase> menuItemData = new List<cMenuDataBase>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var menuItemConfig in cF4SDCockpitXmlConfig.Instance.MenuItems.Values)
|
||||
{
|
||||
cMenuDataBase menuItem = GetMenuItem(menuItemConfig);
|
||||
if (menuItem is null)
|
||||
continue;
|
||||
|
||||
int pinnedIndex = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.QuickActionsPinned.IndexOf(menuItemConfig.Name);
|
||||
if (pinnedIndex > -1)
|
||||
pinnedIndex += defaultPinnedActionCount;
|
||||
menuItem.IconPositionIndex = pinnedIndex;
|
||||
menuItemData.Add(menuItem);
|
||||
}
|
||||
FillMenuSection(menuItemData);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return menuItemData;
|
||||
}
|
||||
|
||||
private cMenuDataBase GetMenuItem(cFasdBaseConfigMenuItem menuItemConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
cMenuDataBase menuItem = null;
|
||||
switch (menuItemConfig)
|
||||
{
|
||||
case cFasdQuickTip quickTip:
|
||||
menuItem = GetQuickTipMenuItem(quickTip);
|
||||
break;
|
||||
case cFasdQuickAction quickAction:
|
||||
menuItem = GetQuickActionMenuItem(quickAction);
|
||||
break;
|
||||
case cFasdMenuSection section:
|
||||
menuItem = GetSectionMenuItem(section);
|
||||
break;
|
||||
case cCopyTemplate copyTemplate:
|
||||
menuItem = GetCopyTemplateMenuItem(copyTemplate);
|
||||
break;
|
||||
}
|
||||
|
||||
if (menuItem != null)
|
||||
{
|
||||
if (!cHealthCardDataHelper.IsUiVisible(menuItemConfig, _dataProvider.NamedParameterEntries))
|
||||
menuItem.SetUiActionDisplayType(enumActionDisplayType.hidden);
|
||||
}
|
||||
return menuItem;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private cMenuDataBase GetCopyTemplateMenuItem(cCopyTemplate copyTemplate)
|
||||
{
|
||||
cMenuDataBase menuItem = new cMenuDataBase(copyTemplate);
|
||||
enumActionDisplayType displayType = HasRequiredInformationClasses(copyTemplate.InformationClasses)
|
||||
? enumActionDisplayType.enabled : enumActionDisplayType.disabled;
|
||||
menuItem.SetUiActionDisplayType(displayType);
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
private cMenuDataBase GetSectionMenuItem(cFasdMenuSection section)
|
||||
{
|
||||
return new cMenuDataContainer(section);
|
||||
}
|
||||
|
||||
private cMenuDataBase GetQuickActionMenuItem(cFasdQuickAction quickAction)
|
||||
{
|
||||
cMenuDataBase menuItem = new cMenuDataBase(quickAction);
|
||||
enumActionDisplayType displayType = HasAllRequirements(quickAction)
|
||||
? enumActionDisplayType.enabled : enumActionDisplayType.disabled;
|
||||
menuItem.SetUiActionDisplayType(displayType);
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
private cMenuDataBase GetQuickTipMenuItem(cFasdQuickTip quickTip)
|
||||
{
|
||||
return new cMenuDataBase(quickTip);
|
||||
//TODO: Quick Actions einfügen
|
||||
//TODO: DisplayType prüfen + setzen
|
||||
}
|
||||
|
||||
private bool HasRequiredInformationClasses(List<enumFasdInformationClass> required)
|
||||
{
|
||||
return !(required.Any(informationClass => _dataProvider.Identities.Any(identity => identity.Class == informationClass) == false));
|
||||
}
|
||||
|
||||
|
||||
private bool HasAllRequirements(cFasdQuickAction quickAction)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!HasRequiredInformationClasses(quickAction.InformationClasses))
|
||||
return false;
|
||||
|
||||
// if CheckNamedParamter the value of NamedParameter is set and if required equals one of the necessary values
|
||||
bool hasRequiredNamedParameter = quickAction.CheckNamedParameter is null
|
||||
|| (_dataProvider.NamedParameterEntries.TryGetValue(quickAction.CheckNamedParameter, out var namedParameterEntry)
|
||||
&& (quickAction.CheckNamedParameterValues is null || quickAction.CheckNamedParameterValues.Count == 0 || quickAction.CheckNamedParameterValues.Contains(namedParameterEntry.GetValue())));
|
||||
|
||||
if (!hasRequiredNamedParameter)
|
||||
return false;
|
||||
if (quickAction.CheckFilePath != null && !HasRequiredFilePath(quickAction.CheckFilePath))
|
||||
return false;
|
||||
if (quickAction.CheckRegistryEntry != null && !HasRequiredRegistryEntry(quickAction.CheckRegistryEntry))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasRequiredFilePath(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var specialFolders = Enum.GetValues(typeof(Environment.SpecialFolder)).Cast<Environment.SpecialFolder>();
|
||||
|
||||
foreach (var specialFolder in specialFolders)
|
||||
{
|
||||
var specialFolderName = "%" + specialFolder.ToString() + "%";
|
||||
var specialFolderPath = Environment.GetFolderPath(specialFolder);
|
||||
filePath = filePath.Replace(specialFolderName, specialFolderPath);
|
||||
}
|
||||
|
||||
filePath = Environment.ExpandEnvironmentVariables(filePath);
|
||||
return File.Exists(filePath);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasRequiredRegistryEntry(string registryEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(registryEntry))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var registryRootPath = registryEntry.Split('\\')[0];
|
||||
registryEntry = registryEntry.Replace(registryRootPath, "").Remove(0, 1);
|
||||
|
||||
switch (registryRootPath)
|
||||
{
|
||||
case "HKEY_LOCAL_MACHINE":
|
||||
case "HKLM":
|
||||
return Registry.LocalMachine.OpenSubKey(registryEntry) != null;
|
||||
case "HKEY_CURRENT_USER":
|
||||
case "HKCU":
|
||||
return Registry.CurrentUser.OpenSubKey(registryEntry) != null;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void FillMenuSection(List<cMenuDataBase> menuItemData)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var section in menuItemData.OfType<cMenuDataContainer>())
|
||||
{
|
||||
List<cMenuDataBase> subMenuData = menuItemData.Where(data =>
|
||||
(data?.UiAction?.DisplayType != enumActionDisplayType.hidden) && (data?.MenuSections?.Contains(section.ContainerName) ?? false)).ToList();
|
||||
|
||||
section.SubMenuData = subMenuData;
|
||||
if (section.UiAction is cSubMenuAction subMenuAction)
|
||||
subMenuAction.SubMenuData = subMenuData;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
74
FasdDesktopUi/Basics/Helper/QuickActionProtocollHelper.cs
Normal file
74
FasdDesktopUi/Basics/Helper/QuickActionProtocollHelper.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
public class cQuickActionProtocollHelper
|
||||
{
|
||||
private readonly cSupportCaseDataProvider dataProvider;
|
||||
|
||||
public cQuickActionProtocollHelper(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
this.dataProvider = dataProvider;
|
||||
}
|
||||
|
||||
public async Task<List<List<object>>> GetQuickActionHistoryAsync(string QuickActionName)
|
||||
{
|
||||
try
|
||||
{
|
||||
int agentDeviceId = int.MinValue;
|
||||
int? agentUserIdNullable = null;
|
||||
|
||||
if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter))
|
||||
_ = int.TryParse(agentDeviceIdParameter.GetValue(), out agentDeviceId);
|
||||
|
||||
if (dataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter))
|
||||
if (int.TryParse(agentUserIdParameter.GetValue(), out int agentUserId))
|
||||
agentUserIdNullable = agentUserId;
|
||||
|
||||
var output = await cFasdCockpitCommunicationBase.Instance.GetQuickActionHistory(QuickActionName, cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode.Value, agentDeviceId, agentUserIdNullable);
|
||||
|
||||
foreach (var historyLine in output)
|
||||
{
|
||||
var historyStatus = historyLine.FirstOrDefault();
|
||||
if (historyStatus is null || !(historyStatus is enumQuickActionRevisionStatus revisionStatus))
|
||||
continue;
|
||||
|
||||
switch (revisionStatus)
|
||||
{
|
||||
case enumQuickActionRevisionStatus.unknown:
|
||||
historyLine[0] = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Unknown");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.inProgress:
|
||||
historyLine[0] = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.InProgress");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedSuccessfull:
|
||||
historyLine[0] = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedWithError:
|
||||
historyLine[0] = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output.Reverse();
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
306
FasdDesktopUi/Basics/Helper/RichTextBoxHelper.cs
Normal file
306
FasdDesktopUi/Basics/Helper/RichTextBoxHelper.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
public static class cRichTextBoxHelper
|
||||
{
|
||||
#region Unicode
|
||||
|
||||
public static void TraverseBlockAsUnicode(BlockCollection blocks, StringBuilder stringBuilder, bool isBlockFromList = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (Block block in blocks)
|
||||
{
|
||||
if (block is Paragraph paragraph)
|
||||
{
|
||||
TraverseParagraphAsUnicode(paragraph, stringBuilder);
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
else if (block is List list)
|
||||
{
|
||||
TraverseListAsUnicode(list, stringBuilder);
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
else if (block is BlockUIContainer container)
|
||||
{
|
||||
if (container.Child is System.Windows.Controls.Image image)
|
||||
{
|
||||
TraverseImageAsUnicode(image, stringBuilder);
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseParagraphAsUnicode(Paragraph paragraph, StringBuilder stringBuilder)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var inline in paragraph.Inlines)
|
||||
{
|
||||
if (inline is Run run)
|
||||
{
|
||||
stringBuilder.Append(run.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseListAsUnicode(List list, StringBuilder stringBuilder)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (list.MarkerStyle == TextMarkerStyle.Decimal)
|
||||
{
|
||||
|
||||
for (int i = 0; i < list.ListItems.Count; i++)
|
||||
{
|
||||
|
||||
stringBuilder.Append(i + 1 + ". ");
|
||||
TraverseBlockAsUnicode(list.ListItems.ElementAt(i).Blocks, stringBuilder, true);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in list.ListItems)
|
||||
{
|
||||
|
||||
stringBuilder.Append("- ");
|
||||
TraverseBlockAsUnicode(item.Blocks, stringBuilder, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseImageAsUnicode(System.Windows.Controls.Image image, StringBuilder stringBuilder)
|
||||
{
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
stringBuilder.Append("[Image]");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Html
|
||||
|
||||
public static void TraverseBlockAsHtml(BlockCollection blocks, StringBuilder stringBuilder, bool isBlockFromList = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (block is Paragraph paragraph)
|
||||
{
|
||||
if (!isBlockFromList)
|
||||
stringBuilder.Append("<p>");
|
||||
|
||||
TraverseParagraphAsHtml(paragraph, stringBuilder);
|
||||
|
||||
if (!isBlockFromList)
|
||||
stringBuilder.Append("</p>");
|
||||
}
|
||||
else if (block is List list)
|
||||
{
|
||||
stringBuilder.Append(list.MarkerStyle == TextMarkerStyle.Decimal ? "<ol>" : "<ul>");
|
||||
TraverseListAsHtml(list, stringBuilder);
|
||||
stringBuilder.Append(list.MarkerStyle == TextMarkerStyle.Decimal ? "</ol>" : "</ul>");
|
||||
}
|
||||
else if (block is BlockUIContainer container)
|
||||
{
|
||||
if (container.Child is System.Windows.Controls.Image image)
|
||||
{
|
||||
|
||||
TraverseImageAsHtml(image, stringBuilder);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseParagraphAsHtml(Paragraph paragraph, StringBuilder stringBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var inline in paragraph.Inlines)
|
||||
{
|
||||
TraverseInlineAsHtml(inline, stringBuilder);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseInlineAsHtml(Inline inline, StringBuilder stringBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (inline is Run run)
|
||||
TraverseRunAsHtml(run, stringBuilder);
|
||||
else if (inline is Span span)
|
||||
{
|
||||
foreach (var spanInline in span.Inlines)
|
||||
{
|
||||
TraverseInlineAsHtml(spanInline, stringBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseListAsHtml(List list, StringBuilder stringBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var listItem in list.ListItems)
|
||||
{
|
||||
stringBuilder.AppendLine("<li>");
|
||||
TraverseBlockAsHtml(listItem.Blocks, stringBuilder, true);
|
||||
stringBuilder.Append("</li>");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraverseImageAsHtml(System.Windows.Controls.Image image, StringBuilder stringBuilder)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
byte[] arr;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
var bmp = image.Source as BitmapImage;
|
||||
PngBitmapEncoder encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(bmp));
|
||||
encoder.Save(ms);
|
||||
arr = ms.ToArray();
|
||||
}
|
||||
|
||||
stringBuilder.AppendLine("<img src=\"data:image/png;base64,");
|
||||
stringBuilder.Append(Convert.ToBase64String(arr));
|
||||
stringBuilder.Append("\"/>");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void TraverseRunAsHtml(Run run, StringBuilder stringBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
string styleString = string.Empty;
|
||||
string runString = run.Text;
|
||||
|
||||
if (run.FontWeight == FontWeights.Bold)
|
||||
{
|
||||
runString = runString.Insert(0, "<strong>");
|
||||
runString += "</strong>";
|
||||
}
|
||||
|
||||
if (run.FontStyle == FontStyles.Italic)
|
||||
{
|
||||
runString = runString.Insert(0, "<em>");
|
||||
runString += "</em>";
|
||||
}
|
||||
|
||||
if (run.TextDecorations != null && run.TextDecorations.Count > 0)
|
||||
{
|
||||
if (run.TextDecorations.FirstOrDefault()?.Location == TextDecorationLocation.Underline)
|
||||
{
|
||||
runString = runString.Insert(0, "<u>");
|
||||
runString += "</u>";
|
||||
}
|
||||
}
|
||||
|
||||
if (run.FontSize != 12)
|
||||
styleString += $"font-size: {run.FontSize}px; ";
|
||||
|
||||
// default font size
|
||||
//if (run.FontFamily != null)
|
||||
// styleString += $"font-family: {run.FontFamily}; ";
|
||||
|
||||
//default color instead null:
|
||||
//if (run.Foreground != null)
|
||||
// styleString += $"color: {run.Foreground}; ";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(styleString))
|
||||
{
|
||||
styleString = styleString.Insert(0, "style=\"");
|
||||
styleString += "\"";
|
||||
}
|
||||
|
||||
stringBuilder.AppendLine("<span " + styleString + ">");
|
||||
stringBuilder.Append(runString);
|
||||
stringBuilder.Append("</span>");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
210
FasdDesktopUi/Basics/Helper/TrayTicketNotificationManager.cs
Normal file
210
FasdDesktopUi/Basics/Helper/TrayTicketNotificationManager.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using C4IT.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
internal sealed class TrayTicketNotificationManager
|
||||
{
|
||||
private readonly NotifyIcon _notifyIcon;
|
||||
private readonly object _syncRoot = new object();
|
||||
private string _baseTooltip;
|
||||
private string _currentTooltip;
|
||||
private bool _overlayInitialized;
|
||||
|
||||
private const string OverlayKey = "TicketChanges";
|
||||
private const string OverlaySetName = "OverlayTicketChanges";
|
||||
|
||||
public TrayTicketNotificationManager(NotifyIcon notifyIcon)
|
||||
{
|
||||
_notifyIcon = notifyIcon ?? throw new ArgumentNullException(nameof(notifyIcon));
|
||||
}
|
||||
|
||||
public bool HasNotification
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_syncRoot)
|
||||
return !string.IsNullOrWhiteSpace(_currentTooltip);
|
||||
}
|
||||
}
|
||||
|
||||
public void CaptureBaseTooltip()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_baseTooltip = _notifyIcon.Text;
|
||||
}
|
||||
}
|
||||
|
||||
public void Show(string message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureOverlaySet();
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_currentTooltip = BuildTooltip(message);
|
||||
}
|
||||
|
||||
NotifyerSupport.SetNotifyIconOverlay(OverlayKey, OverlaySetName, NotifyerSupport.enumIconAlignment.TopRight, priority: 100);
|
||||
ApplyTooltip();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_currentTooltip = null;
|
||||
}
|
||||
|
||||
NotifyerSupport.SetNotifyIconOverlay(OverlayKey, null, NotifyerSupport.enumIconAlignment.TopRight);
|
||||
ApplyTooltip();
|
||||
}
|
||||
|
||||
public void ApplyTooltip()
|
||||
{
|
||||
if (_notifyIcon == null)
|
||||
return;
|
||||
|
||||
string tooltip;
|
||||
lock (_syncRoot)
|
||||
{
|
||||
tooltip = string.IsNullOrWhiteSpace(_currentTooltip)
|
||||
? _baseTooltip
|
||||
: $"F4SD - {_currentTooltip}";
|
||||
}
|
||||
|
||||
_notifyIcon.Text = TrimTooltip(tooltip);
|
||||
}
|
||||
|
||||
private void EnsureOverlaySet()
|
||||
{
|
||||
if (_overlayInitialized)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var overlayFactories = new Dictionary<int, Func<Bitmap>>();
|
||||
var sizeMap = new SortedDictionary<int, int>();
|
||||
|
||||
foreach (var size in NotifyerSupport.DefaultIconSizes)
|
||||
{
|
||||
var overlaySize = CalculateOverlayDiameter(size);
|
||||
if (overlaySize <= 0)
|
||||
continue;
|
||||
|
||||
sizeMap[size] = overlaySize;
|
||||
|
||||
if (!overlayFactories.ContainsKey(overlaySize))
|
||||
{
|
||||
var localSize = overlaySize;
|
||||
overlayFactories[localSize] = () => CreateBadgeBitmap(localSize);
|
||||
}
|
||||
}
|
||||
|
||||
var iconSet = NotifyerSupport.RegisterDynamicSet(OverlaySetName, overlayFactories, NoRefresh: true)
|
||||
?? NotifyerSupport.GetIconSet(OverlaySetName);
|
||||
|
||||
if (iconSet != null)
|
||||
{
|
||||
iconSet.SizeMap = sizeMap;
|
||||
_overlayInitialized = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildTooltip(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parts = message
|
||||
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(part => part.Trim())
|
||||
.Where(part => part.Length > 0);
|
||||
|
||||
var summary = string.Join(" | ", parts);
|
||||
if (summary.Length > 140)
|
||||
summary = summary.Substring(0, 139) + "…";
|
||||
|
||||
return summary;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
private static string TrimTooltip(string tooltip)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tooltip))
|
||||
return tooltip;
|
||||
|
||||
tooltip = tooltip.Replace("\r", " ").Replace("\n", " ");
|
||||
tooltip = tooltip.Trim();
|
||||
|
||||
return tooltip.Length <= 63
|
||||
? tooltip
|
||||
: tooltip.Substring(0, 63);
|
||||
}
|
||||
|
||||
private static int CalculateOverlayDiameter(int baseSize)
|
||||
{
|
||||
if (baseSize <= 0)
|
||||
return 0;
|
||||
|
||||
if (baseSize <= 18)
|
||||
return 8;
|
||||
if (baseSize <= 26)
|
||||
return 10;
|
||||
if (baseSize <= 36)
|
||||
return 11;
|
||||
|
||||
var diameter = (int)Math.Round(baseSize * 0.22f);
|
||||
return Math.Max(9, Math.Min(diameter, baseSize));
|
||||
}
|
||||
|
||||
private static Bitmap CreateBadgeBitmap(int size)
|
||||
{
|
||||
var diameter = Math.Max(2, size);
|
||||
var bitmap = new Bitmap(diameter, diameter, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
bitmap.SetResolution(96f, 96f);
|
||||
|
||||
using (var graphics = Graphics.FromImage(bitmap))
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.Clear(Color.Transparent);
|
||||
|
||||
int margin = 0;
|
||||
if (diameter >= 12)
|
||||
margin = Math.Max(1, (int)Math.Round(diameter * 0.08f));
|
||||
else if (diameter >= 9)
|
||||
margin = 1;
|
||||
|
||||
var circleSize = Math.Max(1, diameter - (margin * 2));
|
||||
var circleRect = new Rectangle(margin, margin, circleSize, circleSize);
|
||||
|
||||
using (var brush = new SolidBrush(Color.FromArgb(235, 220, 0, 0)))
|
||||
{
|
||||
graphics.FillEllipse(brush, circleRect);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
316
FasdDesktopUi/Basics/Helper/UiElementHelper.cs
Normal file
316
FasdDesktopUi/Basics/Helper/UiElementHelper.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
|
||||
using MaterialIcons;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
using System.Reflection;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Helper
|
||||
{
|
||||
public class cUiElementHelper
|
||||
{
|
||||
public static FrameworkElement GetEditableControl(cEditableValueInformationBase editableValueInformation, bool isEditOnly, FrameworkElement parent, double? fontSize = null, FontWeight? fontWeight = null)
|
||||
{
|
||||
FrameworkElement output = null;
|
||||
var textBlockStyle = (Style)Application.Current.FindResource("DetailsPage.Widget.Title");
|
||||
var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");
|
||||
|
||||
try
|
||||
{
|
||||
switch (editableValueInformation)
|
||||
{
|
||||
case cEditValueInformationText editValueText:
|
||||
output = GetEditTextBox(editableValueInformation.CurrentValue.ToString(), string.Empty, fontSize ?? 12, fontWeight ?? FontWeights.Normal, false, true);
|
||||
break;
|
||||
case cEditValueInformationSelection editValueSelection:
|
||||
{
|
||||
if (editValueSelection.SelectionValues is null || editValueSelection.SelectionValues?.Count <= 0)
|
||||
return null;
|
||||
|
||||
ComboBox editComboBox = new ComboBox();
|
||||
foreach (var listValue in editValueSelection.SelectionValues)
|
||||
{
|
||||
ComboBoxItem tempComboBoxItem = new ComboBoxItem() { Content = listValue.Value, Tag = listValue.Key };
|
||||
editComboBox.Items.Add(tempComboBoxItem);
|
||||
}
|
||||
|
||||
var currentSelectedValue = editValueSelection.SelectionValues.FirstOrDefault(value => value.Key?.Equals(editValueSelection.CurrentValue) ?? false);
|
||||
editComboBox.SelectedIndex = editValueSelection.SelectionValues.IndexOf(currentSelectedValue);
|
||||
|
||||
editComboBox.DropDownOpened += (sender, e) => cFocusInvoker.InvokeGotFocus(parent, e);
|
||||
editComboBox.DropDownClosed += (sender, e) => cFocusInvoker.InvokeLostFocus(parent, e);
|
||||
|
||||
output = editComboBox;
|
||||
|
||||
if (!isEditOnly)
|
||||
break;
|
||||
|
||||
StackPanel tempStackPanel = new StackPanel();
|
||||
TextBlock tempTextBlock = new TextBlock() { Text = editValueSelection.Description, Style = textBlockStyle };
|
||||
tempStackPanel.Children.Add(tempTextBlock);
|
||||
tempStackPanel.Children.Add(editComboBox);
|
||||
|
||||
output = tempStackPanel;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static FrameworkElement GetEditTextBox(string contentText, string placeHolderText, double fontSize, FontWeight fontWeight, bool isPrimaryContent, bool isEditOnly)
|
||||
{
|
||||
ScrollViewer output = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto };
|
||||
try
|
||||
{
|
||||
Grid mainGrid = new Grid();
|
||||
var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");
|
||||
var textBoxStylePrimary = (Style)Application.Current.FindResource("Customizable.Editable.TextBox.Background");
|
||||
var textBoxStyleEditOnly = (Style)Application.Current.FindResource("Customizable.Editable.TextBox.EditOnly");
|
||||
|
||||
TextBlock placeHolderTextBlock = new TextBlock() { Text = placeHolderText, FontSize = fontSize, FontWeight = fontWeight, IsHitTestVisible = false, Opacity = 0.7, Margin = new Thickness(13, 16, 13, 14) };
|
||||
placeHolderTextBlock.SetResourceReference(TextBlock.ForegroundProperty, "FontColor.Menu.Categories");
|
||||
|
||||
TextBox contentTextBox = new TextBox() { Text = contentText, FontSize = fontSize, FontWeight = fontWeight, Style = textBoxStyle };
|
||||
|
||||
if (isPrimaryContent)
|
||||
contentTextBox.Style = textBoxStylePrimary;
|
||||
|
||||
if (isEditOnly)
|
||||
contentTextBox.Style = textBoxStyleEditOnly;
|
||||
|
||||
contentTextBox.TextChanged += (sender, e) => placeHolderTextBlock.Visibility = string.IsNullOrEmpty(contentTextBox.Text) ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
AdaptableIcon editIcon = new AdaptableIcon() { SelectedMaterialIcon = MaterialIconType.ic_edit, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top, Visibility = isEditOnly ? Visibility.Visible : Visibility.Hidden, BorderPadding = new Thickness(7.5, 7.5, 0, 7.5) };
|
||||
editIcon.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
|
||||
|
||||
mainGrid.Children.Add(contentTextBox);
|
||||
mainGrid.Children.Add(placeHolderTextBlock);
|
||||
mainGrid.Children.Add(editIcon);
|
||||
|
||||
output.Content = mainGrid;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static bool DrawCustomizableContainerComponent(IContainerData data, FrameworkElement parentElement, out FrameworkElement createdControl, Action<(FrameworkElement valueControl, FrameworkElement editControl)> addEditableControls = null)
|
||||
{
|
||||
createdControl = null;
|
||||
try
|
||||
{
|
||||
var textBlockStyle = (Style)Application.Current.FindResource("DetailsPage.Widget.Title");
|
||||
var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case cContainerIcon containerIconData:
|
||||
{
|
||||
enumInternIcons? internIcon = null;
|
||||
enumInternGif? internGif = null;
|
||||
MaterialIconType? materialIcon = null;
|
||||
|
||||
|
||||
if (Enum.TryParse<enumInternIcons>(containerIconData.IconName, out var tempInternIcon))
|
||||
internIcon = tempInternIcon;
|
||||
|
||||
if (Enum.TryParse<enumInternGif>(containerIconData.IconName, out var tempInternGif))
|
||||
internGif = tempInternGif;
|
||||
|
||||
if (Enum.TryParse<MaterialIconType>(containerIconData.IconName, out var tempMaterialIcon))
|
||||
materialIcon = tempMaterialIcon;
|
||||
|
||||
createdControl = new AdaptableIcon()
|
||||
{
|
||||
SelectedInternIcon = internIcon,
|
||||
SelectedInternGif = internGif,
|
||||
SelectedMaterialIcon = materialIcon,
|
||||
ToolTip = containerIconData.ToolTipText,
|
||||
BorderPadding = new Thickness(0),
|
||||
IconHeight = 14,
|
||||
IconWidth = 14,
|
||||
Margin = new Thickness(0, 0, 5, 0)
|
||||
};
|
||||
|
||||
string iconResourceName = "Color.Menu.Icon";
|
||||
switch (containerIconData.HighlightColor)
|
||||
{
|
||||
case enumHighlightColor.blue:
|
||||
iconResourceName = "Color.Blue";
|
||||
break;
|
||||
case enumHighlightColor.green:
|
||||
iconResourceName = "Color.Green";
|
||||
break;
|
||||
case enumHighlightColor.orange:
|
||||
iconResourceName = "Color.Orange";
|
||||
break;
|
||||
case enumHighlightColor.red:
|
||||
iconResourceName = "Color.Red";
|
||||
break;
|
||||
}
|
||||
|
||||
if (createdControl is AdaptableIcon createdAdaptable)
|
||||
createdAdaptable.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, iconResourceName);
|
||||
break;
|
||||
}
|
||||
case cContainerPrimaryContent primaryContentData:
|
||||
{
|
||||
if (primaryContentData.Value is cContainerValue primaryContentValueData)
|
||||
{
|
||||
string contentText = primaryContentValueData.IsEditOnly ? string.Empty : primaryContentValueData.DisplayValue;
|
||||
string placeHolderText = primaryContentValueData.IsEditOnly ? primaryContentValueData.DisplayValue : string.Empty;
|
||||
|
||||
createdControl = GetEditTextBox(contentText, placeHolderText, primaryContentValueData.FontSize, primaryContentValueData.FontWeight, true, primaryContentValueData.IsEditOnly);
|
||||
|
||||
if (primaryContentValueData.IsEditOnly)
|
||||
break;
|
||||
|
||||
if (primaryContentValueData.EditableValueInformation is null)
|
||||
break;
|
||||
|
||||
var editControl = GetEditableControl(primaryContentValueData.EditableValueInformation, true, parentElement, primaryContentValueData.FontSize, primaryContentValueData.FontWeight);
|
||||
editControl.Visibility = Visibility.Collapsed;
|
||||
|
||||
Grid tempCreatedControl = new Grid();
|
||||
tempCreatedControl.Children.Add(createdControl);
|
||||
tempCreatedControl.Children.Add(editControl);
|
||||
addEditableControls?.Invoke((createdControl, editControl));
|
||||
|
||||
createdControl = tempCreatedControl;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempCreatedControl = new Border()
|
||||
{
|
||||
Padding = new Thickness(10),
|
||||
Margin = new Thickness(0, 5, 0, 5),
|
||||
CornerRadius = new CornerRadius(7.5)
|
||||
};
|
||||
tempCreatedControl.SetResourceReference(Control.BackgroundProperty, "BackgroundColor.DetailsPage.Widget.Title");
|
||||
DrawCustomizableContainerComponent(primaryContentData.Value, parentElement, out var childElement, addEditableControls);
|
||||
tempCreatedControl.Child = childElement;
|
||||
|
||||
createdControl = tempCreatedControl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cContainerStackPanel stackPanelData:
|
||||
{
|
||||
var tempCreatedControl = new StackPanel() { Orientation = stackPanelData.Orientation };
|
||||
|
||||
foreach (var stackPanelElement in stackPanelData.StackPanelData)
|
||||
{
|
||||
bool wasAbleToDraw = DrawCustomizableContainerComponent(stackPanelElement, parentElement, out var childElement, addEditableControls);
|
||||
|
||||
if (!wasAbleToDraw)
|
||||
continue;
|
||||
|
||||
tempCreatedControl.Children.Add(childElement);
|
||||
}
|
||||
|
||||
createdControl = tempCreatedControl;
|
||||
break;
|
||||
}
|
||||
case cContainerValue containerValueData:
|
||||
{
|
||||
var tempCreatedControl = new Grid();
|
||||
|
||||
if (containerValueData.IsEditOnly)
|
||||
{
|
||||
createdControl = cUiElementHelper.GetEditableControl(containerValueData.EditableValueInformation, true, parentElement);
|
||||
break;
|
||||
}
|
||||
|
||||
var valueControl = new TextBlock()
|
||||
{
|
||||
Text = containerValueData.DisplayValue,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
FontSize = containerValueData.FontSize,
|
||||
FontWeight = containerValueData.FontWeight,
|
||||
Margin = new Thickness(0, 0, 5, 0),
|
||||
Style = textBlockStyle
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(containerValueData.Description))
|
||||
valueControl.ToolTip = containerValueData.Description;
|
||||
|
||||
if (containerValueData.EditableValueInformation != null)
|
||||
{
|
||||
var editControl = cUiElementHelper.GetEditableControl(containerValueData.EditableValueInformation, false, parentElement, containerValueData.FontSize, containerValueData.FontWeight);
|
||||
addEditableControls?.Invoke((valueControl, editControl));
|
||||
tempCreatedControl.Children.Add(editControl);
|
||||
}
|
||||
|
||||
tempCreatedControl.Children.Add(valueControl);
|
||||
createdControl = tempCreatedControl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return createdControl != null;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void AddChildToFrameworkElement(FrameworkElement parentElement, FrameworkElement childElement)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (parentElement is Panel parentPanel)
|
||||
parentPanel.Children.Add(childElement);
|
||||
else if (parentElement is Decorator parentDecorator)
|
||||
parentDecorator.Child = childElement;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public static T GetFirstParentOfType<T>(FrameworkElement element) where T : UIElement
|
||||
{
|
||||
try
|
||||
{
|
||||
if (element.Parent is null)
|
||||
return null;
|
||||
|
||||
if (element.Parent is T parentElement)
|
||||
return parentElement;
|
||||
|
||||
if (element.Parent is FrameworkElement parentFrameworkElement)
|
||||
return GetFirstParentOfType<T>(parentFrameworkElement);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
320
FasdDesktopUi/Basics/HotKeyManager.cs
Normal file
320
FasdDesktopUi/Basics/HotKeyManager.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
using C4IT.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public class cHotKeyManager
|
||||
{
|
||||
private readonly IntPtr handle;
|
||||
private readonly List<cHotKeyDefinition> hotKeyDefinitions;
|
||||
|
||||
public cHotKeyManager(IntPtr handle, List<cHotKeyDefinition> hotKeyDefinitions)
|
||||
{
|
||||
this.handle = handle;
|
||||
this.hotKeyDefinitions = hotKeyDefinitions;
|
||||
AddHotKeyHook();
|
||||
RegisterHotKeys();
|
||||
}
|
||||
|
||||
private void AddHotKeyHook()
|
||||
{
|
||||
HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc));
|
||||
}
|
||||
|
||||
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
try
|
||||
{
|
||||
const int WM_HOTKEY = 0x0312;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_HOTKEY:
|
||||
HotKeyPressed(wParam.ToInt32());
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private void HotKeyPressed(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var hotKeyDefinition = hotKeyDefinitions.FirstOrDefault(def => def.Id.Equals(id));
|
||||
hotKeyDefinition?.HotKeyAction.Invoke();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
private static extern bool RegisterHotKey([In] IntPtr hWnd, [In] int id, [In] uint fsModifiers, [In] uint vk);
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
private static extern bool UnregisterHotKey([In] IntPtr hWnd, [In] int id);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern short GetKeyState(VirtualKeyStates nVirtKey);
|
||||
|
||||
private void RegisterHotKeys()
|
||||
{
|
||||
foreach (var hotKeyDefinition in hotKeyDefinitions)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint modifier = 0;
|
||||
|
||||
foreach (var modifierKey in hotKeyDefinition.Modifier)
|
||||
{
|
||||
modifier += (uint)modifierKey;
|
||||
}
|
||||
|
||||
var vk = (uint)KeyInterop.VirtualKeyFromKey(hotKeyDefinition.Key);
|
||||
|
||||
if (RegisterHotKey(handle, hotKeyDefinition.Id, modifier | 0x4000, vk) == false)
|
||||
LogEntry("Couldn't register HotKey with ID " + hotKeyDefinition.Id, LogLevels.Warning);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnRegisterHotKeys()
|
||||
{
|
||||
foreach (var hotKeyDefinition in hotKeyDefinitions)
|
||||
{
|
||||
try
|
||||
{
|
||||
UnregisterHotKey(handle, hotKeyDefinition.Id);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsKeyDown(VirtualKeyStates key)
|
||||
{
|
||||
var output = GetKeyState(key) < 0;
|
||||
return output;
|
||||
}
|
||||
|
||||
public class cHotKeyDefinition
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Key Key { get; set; }
|
||||
public List<ModifierKeys> Modifier { get; set; }
|
||||
public Action HotKeyAction { get; set; }
|
||||
}
|
||||
|
||||
public enum VirtualKeyStates : int
|
||||
{
|
||||
VK_LBUTTON = 0x01,
|
||||
VK_RBUTTON = 0x02,
|
||||
VK_CANCEL = 0x03,
|
||||
VK_MBUTTON = 0x04,
|
||||
//
|
||||
VK_XBUTTON1 = 0x05,
|
||||
VK_XBUTTON2 = 0x06,
|
||||
//
|
||||
VK_BACK = 0x08,
|
||||
VK_TAB = 0x09,
|
||||
//
|
||||
VK_CLEAR = 0x0C,
|
||||
VK_RETURN = 0x0D,
|
||||
//
|
||||
VK_SHIFT = 0x10,
|
||||
VK_CONTROL = 0x11,
|
||||
VK_MENU = 0x12,
|
||||
VK_PAUSE = 0x13,
|
||||
VK_CAPITAL = 0x14,
|
||||
//
|
||||
VK_KANA = 0x15,
|
||||
VK_HANGEUL = 0x15, /* old name - should be here for compatibility */
|
||||
VK_HANGUL = 0x15,
|
||||
VK_JUNJA = 0x17,
|
||||
VK_FINAL = 0x18,
|
||||
VK_HANJA = 0x19,
|
||||
VK_KANJI = 0x19,
|
||||
//
|
||||
VK_ESCAPE = 0x1B,
|
||||
//
|
||||
VK_CONVERT = 0x1C,
|
||||
VK_NONCONVERT = 0x1D,
|
||||
VK_ACCEPT = 0x1E,
|
||||
VK_MODECHANGE = 0x1F,
|
||||
//
|
||||
VK_SPACE = 0x20,
|
||||
VK_PRIOR = 0x21,
|
||||
VK_NEXT = 0x22,
|
||||
VK_END = 0x23,
|
||||
VK_HOME = 0x24,
|
||||
VK_LEFT = 0x25,
|
||||
VK_UP = 0x26,
|
||||
VK_RIGHT = 0x27,
|
||||
VK_DOWN = 0x28,
|
||||
VK_SELECT = 0x29,
|
||||
VK_PRINT = 0x2A,
|
||||
VK_EXECUTE = 0x2B,
|
||||
VK_SNAPSHOT = 0x2C,
|
||||
VK_INSERT = 0x2D,
|
||||
VK_DELETE = 0x2E,
|
||||
VK_HELP = 0x2F,
|
||||
//
|
||||
VK_LWIN = 0x5B,
|
||||
VK_RWIN = 0x5C,
|
||||
VK_APPS = 0x5D,
|
||||
//
|
||||
VK_SLEEP = 0x5F,
|
||||
//
|
||||
VK_NUMPAD0 = 0x60,
|
||||
VK_NUMPAD1 = 0x61,
|
||||
VK_NUMPAD2 = 0x62,
|
||||
VK_NUMPAD3 = 0x63,
|
||||
VK_NUMPAD4 = 0x64,
|
||||
VK_NUMPAD5 = 0x65,
|
||||
VK_NUMPAD6 = 0x66,
|
||||
VK_NUMPAD7 = 0x67,
|
||||
VK_NUMPAD8 = 0x68,
|
||||
VK_NUMPAD9 = 0x69,
|
||||
VK_MULTIPLY = 0x6A,
|
||||
VK_ADD = 0x6B,
|
||||
VK_SEPARATOR = 0x6C,
|
||||
VK_SUBTRACT = 0x6D,
|
||||
VK_DECIMAL = 0x6E,
|
||||
VK_DIVIDE = 0x6F,
|
||||
VK_F1 = 0x70,
|
||||
VK_F2 = 0x71,
|
||||
VK_F3 = 0x72,
|
||||
VK_F4 = 0x73,
|
||||
VK_F5 = 0x74,
|
||||
VK_F6 = 0x75,
|
||||
VK_F7 = 0x76,
|
||||
VK_F8 = 0x77,
|
||||
VK_F9 = 0x78,
|
||||
VK_F10 = 0x79,
|
||||
VK_F11 = 0x7A,
|
||||
VK_F12 = 0x7B,
|
||||
VK_F13 = 0x7C,
|
||||
VK_F14 = 0x7D,
|
||||
VK_F15 = 0x7E,
|
||||
VK_F16 = 0x7F,
|
||||
VK_F17 = 0x80,
|
||||
VK_F18 = 0x81,
|
||||
VK_F19 = 0x82,
|
||||
VK_F20 = 0x83,
|
||||
VK_F21 = 0x84,
|
||||
VK_F22 = 0x85,
|
||||
VK_F23 = 0x86,
|
||||
VK_F24 = 0x87,
|
||||
//
|
||||
VK_NUMLOCK = 0x90,
|
||||
VK_SCROLL = 0x91,
|
||||
//
|
||||
VK_OEM_NEC_EQUAL = 0x92, // '=' key on numpad
|
||||
//
|
||||
VK_OEM_FJ_JISHO = 0x92, // 'Dictionary' key
|
||||
VK_OEM_FJ_MASSHOU = 0x93, // 'Unregister word' key
|
||||
VK_OEM_FJ_TOUROKU = 0x94, // 'Register word' key
|
||||
VK_OEM_FJ_LOYA = 0x95, // 'Left OYAYUBI' key
|
||||
VK_OEM_FJ_ROYA = 0x96, // 'Right OYAYUBI' key
|
||||
//
|
||||
VK_LSHIFT = 0xA0,
|
||||
VK_RSHIFT = 0xA1,
|
||||
VK_LCONTROL = 0xA2,
|
||||
VK_RCONTROL = 0xA3,
|
||||
VK_LMENU = 0xA4,
|
||||
VK_RMENU = 0xA5,
|
||||
//
|
||||
VK_BROWSER_BACK = 0xA6,
|
||||
VK_BROWSER_FORWARD = 0xA7,
|
||||
VK_BROWSER_REFRESH = 0xA8,
|
||||
VK_BROWSER_STOP = 0xA9,
|
||||
VK_BROWSER_SEARCH = 0xAA,
|
||||
VK_BROWSER_FAVORITES = 0xAB,
|
||||
VK_BROWSER_HOME = 0xAC,
|
||||
//
|
||||
VK_VOLUME_MUTE = 0xAD,
|
||||
VK_VOLUME_DOWN = 0xAE,
|
||||
VK_VOLUME_UP = 0xAF,
|
||||
VK_MEDIA_NEXT_TRACK = 0xB0,
|
||||
VK_MEDIA_PREV_TRACK = 0xB1,
|
||||
VK_MEDIA_STOP = 0xB2,
|
||||
VK_MEDIA_PLAY_PAUSE = 0xB3,
|
||||
VK_LAUNCH_MAIL = 0xB4,
|
||||
VK_LAUNCH_MEDIA_SELECT = 0xB5,
|
||||
VK_LAUNCH_APP1 = 0xB6,
|
||||
VK_LAUNCH_APP2 = 0xB7,
|
||||
//
|
||||
VK_OEM_1 = 0xBA, // ';:' for US
|
||||
VK_OEM_PLUS = 0xBB, // '+' any country
|
||||
VK_OEM_COMMA = 0xBC, // ',' any country
|
||||
VK_OEM_MINUS = 0xBD, // '-' any country
|
||||
VK_OEM_PERIOD = 0xBE, // '.' any country
|
||||
VK_OEM_2 = 0xBF, // '/?' for US
|
||||
VK_OEM_3 = 0xC0, // '`~' for US
|
||||
//
|
||||
VK_OEM_4 = 0xDB, // '[{' for US
|
||||
VK_OEM_5 = 0xDC, // '\|' for US
|
||||
VK_OEM_6 = 0xDD, // ']}' for US
|
||||
VK_OEM_7 = 0xDE, // ''"' for US
|
||||
VK_OEM_8 = 0xDF,
|
||||
//
|
||||
VK_OEM_AX = 0xE1, // 'AX' key on Japanese AX kbd
|
||||
VK_OEM_102 = 0xE2, // "<>" or "\|" on RT 102-key kbd.
|
||||
VK_ICO_HELP = 0xE3, // Help key on ICO
|
||||
VK_ICO_00 = 0xE4, // 00 key on ICO
|
||||
//
|
||||
VK_PROCESSKEY = 0xE5,
|
||||
//
|
||||
VK_ICO_CLEAR = 0xE6,
|
||||
//
|
||||
VK_PACKET = 0xE7,
|
||||
//
|
||||
VK_OEM_RESET = 0xE9,
|
||||
VK_OEM_JUMP = 0xEA,
|
||||
VK_OEM_PA1 = 0xEB,
|
||||
VK_OEM_PA2 = 0xEC,
|
||||
VK_OEM_PA3 = 0xED,
|
||||
VK_OEM_WSCTRL = 0xEE,
|
||||
VK_OEM_CUSEL = 0xEF,
|
||||
VK_OEM_ATTN = 0xF0,
|
||||
VK_OEM_FINISH = 0xF1,
|
||||
VK_OEM_COPY = 0xF2,
|
||||
VK_OEM_AUTO = 0xF3,
|
||||
VK_OEM_ENLW = 0xF4,
|
||||
VK_OEM_BACKTAB = 0xF5,
|
||||
//
|
||||
VK_ATTN = 0xF6,
|
||||
VK_CRSEL = 0xF7,
|
||||
VK_EXSEL = 0xF8,
|
||||
VK_EREOF = 0xF9,
|
||||
VK_PLAY = 0xFA,
|
||||
VK_ZOOM = 0xFB,
|
||||
VK_NONAME = 0xFC,
|
||||
VK_PA1 = 0xFD,
|
||||
VK_OEM_CLEAR = 0xFE
|
||||
}
|
||||
}
|
||||
}
|
||||
439
FasdDesktopUi/Basics/Models/ConnectionStatusHelper.cs
Normal file
439
FasdDesktopUi/Basics/Models/ConnectionStatusHelper.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Graphics;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using C4IT.Security;
|
||||
|
||||
using FasdCockpitBase.Models;
|
||||
|
||||
using FasdDesktopUi.Pages.SettingsPage;
|
||||
using FasdDesktopUi.Pages.SplashScreenView;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cConnectionStatusHelper
|
||||
{
|
||||
public enum enumOnlineStatus
|
||||
{
|
||||
notSpecified = 0,
|
||||
offline,
|
||||
connectionError,
|
||||
incompatibleServerVersion,
|
||||
serverNotConfigured,
|
||||
serverStarting,
|
||||
illegalConfig,
|
||||
unauthorized,
|
||||
online
|
||||
}
|
||||
|
||||
public enum enumCheckReason
|
||||
{
|
||||
firstStart = 0,
|
||||
lateInit,
|
||||
heartBeat
|
||||
}
|
||||
|
||||
public bool IsActive = true;
|
||||
|
||||
public readonly Version MinServerVersion = new Version("0.0.0.0");
|
||||
|
||||
private enum enumCheckRunning { no = 0, running, again };
|
||||
|
||||
private enumCheckReason checkReason = enumCheckReason.firstStart;
|
||||
|
||||
public delegate void ConnectionStatusDelegate(enumOnlineStatus? Status);
|
||||
public static event ConnectionStatusDelegate ApiConnectionStatusChanged;
|
||||
|
||||
public delegate cF4SdUserInfoChange M42FormBasedAuthenticationDelegate();
|
||||
public event M42FormBasedAuthenticationDelegate M42FormBasedAuthentication;
|
||||
|
||||
public static cConnectionStatusHelper Instance { get; set; }
|
||||
|
||||
public bool IsAuthorizationSupported { get; private set; } = false;
|
||||
private System.Timers.Timer timer;
|
||||
|
||||
#region Lock Elements Connecion Status
|
||||
private readonly object connectionStatusCheckLock = new object();
|
||||
private enumCheckRunning IsConnectionStatusCheckRunning = enumCheckRunning.no;
|
||||
#endregion
|
||||
|
||||
public enumOnlineStatus ApiConnectionStatus = enumOnlineStatus.notSpecified;
|
||||
|
||||
public cConnectionStatusHelper()
|
||||
{
|
||||
ApiConnectionStatus = enumOnlineStatus.offline;
|
||||
cFasdCockpitCommunicationBase.Instance.CheckConnectionStatus = RunConnectionStatusCheckAsync;
|
||||
timer = new System.Timers.Timer();
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
var arrMinClientVersion = assembly.GetCustomAttributes(typeof(AssemblyMinServerVersion), false);
|
||||
if (arrMinClientVersion != null && arrMinClientVersion.Length >= 1)
|
||||
{
|
||||
var attrMinClientVersion = (AssemblyMinServerVersion)(arrMinClientVersion[0]);
|
||||
MinServerVersion = new Version(attrMinClientVersion.minServerVersion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) => await RunConnectionStatusCheckAsync();
|
||||
|
||||
public async Task RunConnectionStatusCheckAsync()
|
||||
{
|
||||
await RunConnectionStatusCheckAsync(null);
|
||||
}
|
||||
|
||||
private (int timerInterval, int shortInterval) GetTimerIntervalFromRegistry(int defaultInterval, int defaultShortInterval)
|
||||
{
|
||||
int timerInterval = defaultInterval;
|
||||
int shortInterval = defaultShortInterval;
|
||||
|
||||
if (!cLogManager.DefaultLogger.IsDebug)
|
||||
return (timerInterval, shortInterval);
|
||||
|
||||
try
|
||||
{
|
||||
var regBase = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32);
|
||||
var regKey = regBase.OpenSubKey("SOFTWARE\\Consulting4IT GmbH\\First Aid Service Desk\\Cockpit", false);
|
||||
|
||||
if (regKey is null || !int.TryParse(regKey.GetValue("DebugConnectionCheck", 0).ToString(), out var regValue))
|
||||
return (timerInterval, shortInterval);
|
||||
|
||||
if (regValue <= 0)
|
||||
return (timerInterval, shortInterval);
|
||||
|
||||
timerInterval = regValue * 1000;
|
||||
shortInterval = timerInterval / 10;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return (timerInterval, shortInterval);
|
||||
}
|
||||
|
||||
private void HandleConnectionStatus(enumConnectionStatus status, ref int timerInterval, int timerInteralShort)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case enumConnectionStatus.unknown:
|
||||
case enumConnectionStatus.serverNotFound:
|
||||
if (ApiConnectionStatus != enumOnlineStatus.offline)
|
||||
ApiConnectionStatus = enumOnlineStatus.offline;
|
||||
timerInterval = timerInteralShort;
|
||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverNotFound'");
|
||||
break;
|
||||
case enumConnectionStatus.serverResponseError:
|
||||
ApiConnectionStatus = enumOnlineStatus.connectionError;
|
||||
timerInterval = timerInteralShort;
|
||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverResponseError'");
|
||||
break;
|
||||
case enumConnectionStatus.incompatibleServerVersion:
|
||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'incompatibleServerVersion'");
|
||||
ApiConnectionStatus = enumOnlineStatus.incompatibleServerVersion;
|
||||
break;
|
||||
case enumConnectionStatus.serverStarting:
|
||||
ApiConnectionStatus = enumOnlineStatus.serverStarting;
|
||||
break;
|
||||
case enumConnectionStatus.serverNotConfigured:
|
||||
ApiConnectionStatus = enumOnlineStatus.serverNotConfigured;
|
||||
break;
|
||||
case enumConnectionStatus.connected:
|
||||
if (cCockpitConfiguration.Instance == null || cF4SDCockpitXmlConfig.Instance == null)
|
||||
ApiConnectionStatus = enumOnlineStatus.illegalConfig;
|
||||
else if (ApiConnectionStatus != enumOnlineStatus.online)
|
||||
ApiConnectionStatus = enumOnlineStatus.online;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RunConnectionStatusCheckAsync(SplashScreenView splashScreen)
|
||||
{
|
||||
if (!IsActive)
|
||||
return;
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
(int timerInterval, int shortTimerInterval) = GetTimerIntervalFromRegistry(300000, 30000);
|
||||
enumOnlineStatus oldConnectionStatus = ApiConnectionStatus;
|
||||
|
||||
try
|
||||
{
|
||||
timer.Stop();
|
||||
lock (connectionStatusCheckLock)
|
||||
{
|
||||
switch (IsConnectionStatusCheckRunning)
|
||||
{
|
||||
case enumCheckRunning.again:
|
||||
LogEntry("RunConnectionStatusCheckAsync is already running. Status is 'again'.");
|
||||
return;
|
||||
case enumCheckRunning.running:
|
||||
LogEntry("RunConnectionStatusCheckAsync is already running. Status is 'running'.");
|
||||
IsConnectionStatusCheckRunning = enumCheckRunning.again;
|
||||
return;
|
||||
default:
|
||||
IsConnectionStatusCheckRunning = enumCheckRunning.running;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cCheckConnectionResult connectionResult = await cFasdCockpitCommunicationBase.Instance.CheckConnection(MinServerVersion);
|
||||
IsAuthorizationSupported = connectionResult?.ApiConnectionInfo?.SupportAuthorisation ?? false;
|
||||
|
||||
HandleConnectionStatus(connectionResult.ConnectionStatus, ref timerInterval, shortTimerInterval);
|
||||
if (connectionResult.ConnectionStatus != enumConnectionStatus.connected)
|
||||
return;
|
||||
|
||||
if (checkReason < enumCheckReason.heartBeat && ApiConnectionStatus == enumOnlineStatus.illegalConfig)
|
||||
{
|
||||
// download the xml config files
|
||||
Task<bool> loadConfigFilesTask = Task.Run(async () => await cFasdCockpitConfig.Instance.LoadConfigFilesAsync(cFasdCockpitCommunicationBase.Instance));
|
||||
// get the cockpit base configuration from server
|
||||
Task<bool> getCockpitConfig = Task.Run(async () => await cFasdCockpitConfig.Instance.GetCockpitConfigurationAsync());
|
||||
|
||||
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.LoadConfigs")));
|
||||
var configTasks = await Task.WhenAll(loadConfigFilesTask, getCockpitConfig);
|
||||
|
||||
if (configTasks.Any(t => t == false))
|
||||
return;
|
||||
if (cFasdCockpitConfig.Instance?.Global != null && cCockpitConfiguration.Instance?.GlobalConfig != null)
|
||||
{
|
||||
cFasdCockpitConfig.Instance.Global.Load(cCockpitConfiguration.Instance.GlobalConfig);
|
||||
cFasdCockpitConfig.Instance.Global.Save();
|
||||
}
|
||||
}
|
||||
|
||||
cF4sdUserInfo userInfo;
|
||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||
{
|
||||
userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
|
||||
}
|
||||
if (IsAuthorizationSupported)
|
||||
{
|
||||
if (userInfo is null || DateTime.UtcNow > userInfo.RenewUntil)
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.AuthenticateUser")));
|
||||
ApiConnectionStatus = enumOnlineStatus.unauthorized;
|
||||
const string cockpitUserRole = "Cockpit.User";
|
||||
#if isNewFeature
|
||||
const string cockpitTicketAgentRole = "Cockpit.TicketAgent";
|
||||
#endif
|
||||
userInfo = await cFasdCockpitCommunicationBase.Instance.WinLogon();
|
||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||
{
|
||||
cFasdCockpitCommunicationBase.CockpitUserInfo = userInfo;
|
||||
}
|
||||
if (userInfo?.Roles is null || !userInfo.Roles.Contains(cockpitUserRole))
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.NoAuthorization")));
|
||||
LogEntry($"Cockpit User ({userInfo?.Name} with Id {userInfo?.Id}, has not the required permissions.", LogLevels.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Run(async () => await cFasdCockpitConfig.Instance.InstantiateAnalyticsAsync(cFasdCockpitConfig.SessionId));
|
||||
ApiConnectionStatus = enumOnlineStatus.online;
|
||||
#if isNewFeature
|
||||
if (userInfo.Roles.Contains(cockpitTicketAgentRole))
|
||||
cCockpitConfiguration.Instance.ticketSupport.EditTicket = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (userInfo == null)
|
||||
{
|
||||
string cockpitUserName = Environment.UserName;
|
||||
string cockpitUserDomain = Environment.UserDomainName;
|
||||
Guid cockpitUserId = await cFasdCockpitCommunicationBase.Instance.GetUserIdByAccount(cockpitUserName, cockpitUserDomain);
|
||||
if (cockpitUserId == Guid.Empty)
|
||||
LogEntry($"Could not get UserId for cockpit user '{cockpitUserName}@{cockpitUserDomain}'.", LogLevels.Warning);
|
||||
else
|
||||
{
|
||||
userInfo = new cF4sdUserInfo()
|
||||
{
|
||||
Id = cockpitUserId,
|
||||
AccountType = cF4sdUserInfo.enumAccountType.unknown,
|
||||
};
|
||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||
{
|
||||
cFasdCockpitCommunicationBase.CockpitUserInfo = userInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
ApiConnectionStatus = enumOnlineStatus.online;
|
||||
}
|
||||
|
||||
if (App.M42OptionMenuItem != null)
|
||||
App.M42OptionMenuItem.Enabled = userInfo != null;
|
||||
|
||||
// check, if the are logons needed
|
||||
bool m42Valid = await CheckAndRefreshM42LogonAsync();
|
||||
await cFasdCockpitConfig.Instance.CheckAgentScriptAvailabilityAsync();
|
||||
await cFasdCockpitConfig.Instance.CheckServerQuickActionAvailabilityAsync();
|
||||
await cFasdCockpitCommunicationBase.Instance.InitializeAfterOnlineAsync();
|
||||
cFasdCockpitConfig.Instance.OnUiSettingsChanged();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (connectionStatusCheckLock)
|
||||
{
|
||||
if (IsConnectionStatusCheckRunning == enumCheckRunning.again)
|
||||
timerInterval = 1;
|
||||
IsConnectionStatusCheckRunning = enumCheckRunning.no;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
if (IsActive)
|
||||
{
|
||||
if (ApiConnectionStatus == enumOnlineStatus.online)
|
||||
NotifyerSupport.SetNotifyIcon("Default", null, NotifyerSupport.enumIconAlignment.BottomRight);
|
||||
else
|
||||
NotifyerSupport.SetNotifyIcon("Default", "OverlayOffline", NotifyerSupport.enumIconAlignment.BottomRight);
|
||||
if (ApiConnectionStatus != oldConnectionStatus)
|
||||
OnApiConnectionStatusChanged();
|
||||
}
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Interval = timerInterval;
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> CheckAndRefreshM42LogonAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
|
||||
|
||||
if (userInfo == null)
|
||||
return false;
|
||||
|
||||
// do we have a valid M42 token?
|
||||
if (userInfo?.ValidLogonsUntil != null && userInfo.ValidLogonsUntil.TryGetValue(enumAdditionalAuthentication.M42WinLogon, out var logonPeriod))
|
||||
{
|
||||
if (logonPeriod.renewUntil > DateTime.UtcNow)
|
||||
return true;
|
||||
}
|
||||
|
||||
// do we need a logon?
|
||||
var isNeeded = false;
|
||||
if (cFasdCockpitConfig.Instance?.M42Config == null)
|
||||
return false;
|
||||
|
||||
cF4sdCockpitConfigM42 config = cFasdCockpitConfig.Instance.M42Config;
|
||||
if (config.Control == enumM42AuthenticationControl.always)
|
||||
isNeeded = true;
|
||||
else if (config.Control == enumM42AuthenticationControl.auto)
|
||||
{
|
||||
if (userInfo?.additionalLogons == null)
|
||||
return false;
|
||||
|
||||
if (userInfo.additionalLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
|
||||
isNeeded = true;
|
||||
}
|
||||
|
||||
if (!isNeeded)
|
||||
return false;
|
||||
|
||||
// yes, we need a new logon
|
||||
cF4sdCockpitM42BearerTokenInfo tokenInfo = null;
|
||||
cF4SdUserInfoChange userChange = null;
|
||||
switch (config.Method)
|
||||
{
|
||||
case enumM42AuthenticationMethod.passthrough:
|
||||
tokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonPassthrough();
|
||||
break;
|
||||
case enumM42AuthenticationMethod.basic:
|
||||
var user = config.BasicUser;
|
||||
var pw = PrivateSecurePassword.Instance.Decode(config.BasicPassword);
|
||||
tokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonBasic(user, pw);
|
||||
break;
|
||||
case enumM42AuthenticationMethod.token:
|
||||
var token = PrivateSecurePassword.Instance.Decode(config.ApiToken);
|
||||
tokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonToken(token);
|
||||
break;
|
||||
case enumM42AuthenticationMethod.forms:
|
||||
var FormBasedAuth = M42FormBasedAuthentication;
|
||||
userChange = FormBasedAuth?.Invoke();
|
||||
break;
|
||||
}
|
||||
|
||||
if (tokenInfo?.Token != null && tokenInfo.ValidUntil > DateTime.UtcNow)
|
||||
{
|
||||
var tokenRegistration = new cF4SDTokenRegistration()
|
||||
{
|
||||
UserId = userInfo.Id,
|
||||
TokenType = cF4SDTokenRegistration.enumTokenType.M42Bearer,
|
||||
Secret = tokenInfo.Token
|
||||
};
|
||||
|
||||
userChange = await cFasdCockpitCommunicationBase.Instance.RegisterExternalTokenAsync(tokenRegistration);
|
||||
}
|
||||
|
||||
if (userChange != null)
|
||||
{
|
||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||
{
|
||||
userChange.ChangeUserInfo(cFasdCockpitCommunicationBase.CockpitUserInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnApiConnectionStatusChanged()
|
||||
{
|
||||
ConnectionStatusDelegate handler = ApiConnectionStatusChanged;
|
||||
handler?.Invoke(ApiConnectionStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
FasdDesktopUi/Basics/Models/ContainerDataModels.cs
Normal file
148
FasdDesktopUi/Basics/Models/ContainerDataModels.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using C4IT.FASD.Base;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
using MaterialIcons;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public interface IContainerData
|
||||
{
|
||||
bool HasValue { get; }
|
||||
}
|
||||
public interface IContainerHelperClass
|
||||
{
|
||||
int MaxValueCount { get; }
|
||||
bool IsValueRequired { get; }
|
||||
}
|
||||
public interface IContainerCollectionElementData
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class cContainerCollectionData : List<cContainerData>
|
||||
{
|
||||
public int ColumnSpan { get; set; }
|
||||
}
|
||||
|
||||
public class cContainerData : List<IContainerData>
|
||||
{
|
||||
public string ContainerName { get; set; }
|
||||
public bool IsMaximizable { get; set; }
|
||||
public bool IsAddable { get; set; }
|
||||
public bool IsDeletable { get; set; }
|
||||
}
|
||||
|
||||
public class cContainerStackPanel : IContainerData
|
||||
{
|
||||
public Orientation Orientation { get; set; }
|
||||
public List<IContainerData> StackPanelData { get; set; }
|
||||
|
||||
public bool HasValue { get => StackPanelData?.Any(data => data.HasValue) ?? false; }
|
||||
}
|
||||
|
||||
public class cContainerPrimaryContent : IContainerData
|
||||
{
|
||||
public IContainerData Value { get; set; }
|
||||
|
||||
public bool HasValue { get => Value.HasValue; }
|
||||
}
|
||||
|
||||
public class cContainerValue : IContainerData
|
||||
{
|
||||
public string DisplayValue { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string MaximizeValue { get; set; }
|
||||
public double FontSize { get; set; } = 16;
|
||||
public FontWeight FontWeight { get; set; } = FontWeights.Normal;
|
||||
public bool IsEditOnly { get; set; } = false;
|
||||
public cEditableValueInformationBase EditableValueInformation { get; set; }
|
||||
|
||||
public bool HasValue { get => !string.IsNullOrWhiteSpace(DisplayValue); }
|
||||
}
|
||||
|
||||
public class cContainerIcon : IContainerData
|
||||
{
|
||||
public string IconName { get; set; }
|
||||
public enumIconType IconType { get; set; }
|
||||
public enumHighlightColor HighlightColor { get; set; } = enumHighlightColor.none;
|
||||
public string ToolTipText { get; set; }
|
||||
|
||||
public cContainerIcon()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public cContainerIcon(enumInternIcons internIcon, enumHighlightColor highlightColor = enumHighlightColor.none)
|
||||
{
|
||||
try
|
||||
{
|
||||
IconType = enumIconType.intern;
|
||||
IconName = internIcon.ToString();
|
||||
HighlightColor = highlightColor;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public cContainerIcon(MaterialIconType materialIcon, enumHighlightColor highlightColor = enumHighlightColor.none)
|
||||
{
|
||||
try
|
||||
{
|
||||
IconType = enumIconType.material;
|
||||
IconName = materialIcon.ToString();
|
||||
HighlightColor = highlightColor;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasValue { get => !string.IsNullOrWhiteSpace(IconName); }
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
public class cContainerValueHelper : cContainerValue, IContainerHelperClass
|
||||
{
|
||||
public int MaxValueCount { get => RawValues.Count; }
|
||||
public RawValueType DisplayType { get; set; }
|
||||
public List<object> RawValues { get; set; } = new List<object>();
|
||||
public List<object> RawMaximizeValues { get; set; } = new List<object>();
|
||||
public bool IsValueRequired { get; set; }
|
||||
}
|
||||
|
||||
public class cContainerIconHelper : IContainerHelperClass
|
||||
{
|
||||
public int MaxValueCount { get => Icons.Count; }
|
||||
public List<cContainerIcon> Icons { get; set; } = new List<cContainerIcon>();
|
||||
public bool IsValueRequired { get; set; }
|
||||
}
|
||||
|
||||
public class cContainerStackPanelHelper : cContainerStackPanel, IContainerHelperClass
|
||||
{
|
||||
public int MaxValueCount { get => StackPanelHelperData.Max(value => value.MaxValueCount); }
|
||||
public List<IContainerHelperClass> StackPanelHelperData { get; set; } = new List<IContainerHelperClass>();
|
||||
public bool IsValueRequired { get; set; }
|
||||
}
|
||||
|
||||
public class cContainerContentHelper : cContainerPrimaryContent, IContainerHelperClass
|
||||
{
|
||||
public int MaxValueCount { get => Content?.MaxValueCount ?? 1; }
|
||||
public IContainerHelperClass Content { get; set; }
|
||||
public bool IsValueRequired { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
191
FasdDesktopUi/Basics/Models/DataCanvasDataModel.cs
Normal file
191
FasdDesktopUi/Basics/Models/DataCanvasDataModel.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cDataCanvasDataModel
|
||||
{
|
||||
public cRecommendationDataModel RecommendationData { get; set; }
|
||||
|
||||
public Func<Task<cDetailedDataModel>> GetDetailedDataAsync { get; set; }
|
||||
|
||||
public Func<Task<cDetailedChartModel>> GetDatailedChartDataAsync { get; set; }
|
||||
|
||||
public Func<Task<cChartModel>> GetChartDataAsync { get; set; }
|
||||
|
||||
public cDetailedDataModel DetailedData { get; set; }
|
||||
|
||||
public cDetailedChartModel DetailedChartData { get; set; }
|
||||
|
||||
public cChartModel ChartData { get; set; }
|
||||
|
||||
public cQuickActionStatusMonitorModel QuickActionStatusMonitorData { get; set; }
|
||||
}
|
||||
|
||||
public class cRecommendationDataModel
|
||||
{
|
||||
public string Category { get; set; }
|
||||
public string Recommendation { get; set; }
|
||||
}
|
||||
|
||||
public class cDetailedDataModel
|
||||
{
|
||||
public string Heading { get; set; }
|
||||
|
||||
public bool HasColumnHeaders = true;
|
||||
|
||||
public List<object> FullDetailedData { get; set; }
|
||||
}
|
||||
|
||||
public class cDetailedChartModel
|
||||
{
|
||||
public List<object[]> Data { get; set; }
|
||||
public int TimeIndex { get; set; }
|
||||
public int ValueIndex { get; set; }
|
||||
public int DurationIndex { get; set; }
|
||||
public double WarningThreshold { get; set; }
|
||||
public double ErrorThreshold { get; set; }
|
||||
public bool IsThresholdActive { get; set; }
|
||||
public string ChartTitle { get; set; }
|
||||
}
|
||||
|
||||
public class cChartModel
|
||||
{
|
||||
public List<object[]> Data { get; set; }
|
||||
public int TimeIndex { get; set; }
|
||||
public int ValueIndex { get; set; }
|
||||
public int DurationIndex { get; set; }
|
||||
public double WarningThreshold { get; set; }
|
||||
public double ErrorThreshold { get; set; }
|
||||
public bool IsThresholdActive { get; set; }
|
||||
public bool IsDirectionUp { get; set; }
|
||||
public string ChartTitle { get; set; }
|
||||
public int StepLengthScale { get; set; }
|
||||
public int StepLengthLine { get; set; }
|
||||
public int MaxValue { get; set; }
|
||||
public int MinValue { get; set; }
|
||||
public string UnitFormat { get; set; }
|
||||
}
|
||||
|
||||
public class cQuickActionStatusMonitorModel
|
||||
{
|
||||
public class cQuickActionStep : INotifyPropertyChanged
|
||||
{
|
||||
public enum enumActionStepType
|
||||
{
|
||||
main,
|
||||
connectingToClient,
|
||||
waitingForUserAcceptance,
|
||||
running,
|
||||
finished
|
||||
}
|
||||
|
||||
private enumQuickActionRevisionStatus status;
|
||||
public enumQuickActionRevisionStatus Status
|
||||
{
|
||||
get => status; set
|
||||
{
|
||||
status = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Status)));
|
||||
}
|
||||
}
|
||||
|
||||
public string DisplayName { get; private set; }
|
||||
public string QuickActionName { get; private set; }
|
||||
public enumActionStepType StepType { get; private set; }
|
||||
public List<cQuickActionStep> SubSteps { get; set; }
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public cQuickActionStep(string displayName, string quickActionName, enumActionStepType stepType)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
QuickActionName = quickActionName;
|
||||
StepType = stepType;
|
||||
}
|
||||
|
||||
public static void SetQuickActionStepStatuses(List<cQuickActionStep> actionSteps, string quickActionName, enumActionStepType type, enumQuickActionRevisionStatus status = enumQuickActionRevisionStatus.finishedSuccessfull)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var step in actionSteps)
|
||||
{
|
||||
if (step.StepType.Equals(type) && step.QuickActionName.Equals(quickActionName))
|
||||
step.Status = status;
|
||||
|
||||
if (step.SubSteps?.Count > 0)
|
||||
SetQuickActionStepStatuses(step.SubSteps, quickActionName, type, status);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CancelRemainingQuickActionSteps(List<cQuickActionStep> actionSteps)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (actionSteps is null || actionSteps.Count <= 0)
|
||||
return;
|
||||
|
||||
foreach (var step in actionSteps)
|
||||
{
|
||||
if (step.Status == enumQuickActionRevisionStatus.inProgress)
|
||||
step.Status = enumQuickActionRevisionStatus.canceled;
|
||||
|
||||
CancelRemainingQuickActionSteps(step.SubSteps);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetAllQuickActionStepStatuses(List<cQuickActionStep> actionSteps, enumQuickActionRevisionStatus status = enumQuickActionRevisionStatus.inProgress)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var step in actionSteps)
|
||||
{
|
||||
step.Status = status;
|
||||
|
||||
if (step.SubSteps?.Count > 0)
|
||||
SetAllQuickActionStepStatuses(step.SubSteps, status);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresUserPermission { get; set; }
|
||||
|
||||
public cFasdQuickAction QuickActionDefinition { get; set; }
|
||||
|
||||
public string ActionName { get; set; }
|
||||
|
||||
public List<cQuickActionStep> ActionSteps { get; set; }
|
||||
|
||||
public Dictionary<string, cAdjustableParameter> QuickActionParameters { get; set; }
|
||||
|
||||
public delegate Task<List<object>> RunQuickActionDelegate(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null);
|
||||
|
||||
public RunQuickActionDelegate RunQuickAction { get; set; }
|
||||
}
|
||||
}
|
||||
31
FasdDesktopUi/Basics/Models/DataHistoryValueModel.cs
Normal file
31
FasdDesktopUi/Basics/Models/DataHistoryValueModel.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cDataHistoryValueModel
|
||||
{
|
||||
public string Content { get; set; }
|
||||
|
||||
private string contentDecription;
|
||||
public string ContentDescription
|
||||
{
|
||||
get { return contentDecription ?? Content; }
|
||||
set { contentDecription = value; }
|
||||
}
|
||||
|
||||
public bool IsLoading { get; set; } = false;
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enumHighlightColor? HighlightColor { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public cUiActionBase UiAction { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public cStateThresholdValues ThresholdValues { get; set; }
|
||||
}
|
||||
}
|
||||
27
FasdDesktopUi/Basics/Models/EditableValueInformation.cs
Normal file
27
FasdDesktopUi/Basics/Models/EditableValueInformation.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public abstract class cEditableValueInformationBase
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public object CurrentValue { get; set; }
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public cValueAddress DatabaseInfo { get; set; }
|
||||
}
|
||||
|
||||
public class cEditValueInformationSelection : cEditableValueInformationBase
|
||||
{
|
||||
public List<KeyValuePair<object, string>> SelectionValues { get; set; }
|
||||
}
|
||||
|
||||
public class cEditValueInformationText : cEditableValueInformationBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
19
FasdDesktopUi/Basics/Models/HeadingDataModel.cs
Normal file
19
FasdDesktopUi/Basics/Models/HeadingDataModel.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cHeadingDataModel
|
||||
{
|
||||
public string HeadingText { get; set; }
|
||||
public enumFasdInformationClass InformationClass { get; set; }
|
||||
public bool IsOnline { get; set; }
|
||||
public cF4sdIdentityList Identities { get; set; }
|
||||
}
|
||||
|
||||
public class cSwapCaseInfo
|
||||
{
|
||||
public enumFasdInformationClass SelectedCaseInformationClass { get; set; }
|
||||
public List<cHeadingDataModel> HeadingDatas { get; set; }
|
||||
}
|
||||
}
|
||||
88
FasdDesktopUi/Basics/Models/HotKeyInformation.cs
Normal file
88
FasdDesktopUi/Basics/Models/HotKeyInformation.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using C4IT.MultiLanguage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cHotKeyCategoryInformation
|
||||
{
|
||||
public cMultiLanguageDictionary Names { get; set; } = new cMultiLanguageDictionary();
|
||||
public List<cHotKeyInformation> HotKeyInformation { get; set; }
|
||||
}
|
||||
|
||||
public class cHotKeyInformation
|
||||
{
|
||||
public cMultiLanguageDictionary Names { get; set; } = new cMultiLanguageDictionary();
|
||||
public List<ModifierKeys> Modifiers { get; set; } = new List<ModifierKeys>();
|
||||
public Key HotKey { get; set; }
|
||||
public Key? AlternativeKey { get; set; }
|
||||
|
||||
public string GetKeyDisplayString(Key key)
|
||||
{
|
||||
string output = key.ToString();
|
||||
try
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Key.Tab:
|
||||
output = "Tab ↹";
|
||||
break;
|
||||
case Key.Enter:
|
||||
output = "Enter ↲";
|
||||
break;
|
||||
case Key.Escape:
|
||||
output = "ESC";
|
||||
break;
|
||||
case Key.Space:
|
||||
output = " ";
|
||||
break;
|
||||
case Key.Left:
|
||||
output = "←";
|
||||
break;
|
||||
case Key.Up:
|
||||
output = "↑";
|
||||
break;
|
||||
case Key.Right:
|
||||
output = "→";
|
||||
break;
|
||||
case Key.Down:
|
||||
output = "↓";
|
||||
break;
|
||||
case Key.Multiply:
|
||||
output = "*";
|
||||
break;
|
||||
case Key.OemPlus:
|
||||
case Key.Add:
|
||||
output = "+";
|
||||
break;
|
||||
case Key.OemMinus:
|
||||
case Key.Separator:
|
||||
case Key.Subtract:
|
||||
output = "-";
|
||||
break;
|
||||
case Key.Decimal:
|
||||
output = ",";
|
||||
break;
|
||||
case Key.Divide:
|
||||
output = "/";
|
||||
break;
|
||||
case Key.NumPad0:
|
||||
case Key.D0:
|
||||
output = "0";
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
FasdDesktopUi/Basics/Models/IBlurrable.cs
Normal file
36
FasdDesktopUi/Basics/Models/IBlurrable.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.UI;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public interface IBlurrable
|
||||
{
|
||||
bool IsBlurred { get; set; }
|
||||
|
||||
List<IBlurInvoker> BlurInvokers { get; set; }
|
||||
|
||||
void UpdateBlurStatus(object sender);
|
||||
}
|
||||
|
||||
public interface IBlurInvoker
|
||||
{
|
||||
bool BlurInvoker_IsActive { get; }
|
||||
|
||||
void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e);
|
||||
}
|
||||
|
||||
public static class BlurInvoker
|
||||
{
|
||||
public static event EventHandler BlurInvokerVisibilityChanged = delegate { };
|
||||
|
||||
public static void InvokeVisibilityChanged(object sender, EventArgs e)
|
||||
{
|
||||
BlurInvokerVisibilityChanged?.Invoke(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
174
FasdDesktopUi/Basics/Models/IFocusInvoker.cs
Normal file
174
FasdDesktopUi/Basics/Models/IFocusInvoker.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public interface IFocusInvoker
|
||||
{
|
||||
int? ParentIndex { get; }
|
||||
UIElement ParentElement { get; }
|
||||
}
|
||||
|
||||
public static class cFocusInvoker
|
||||
{
|
||||
public static EventHandler GotFocus = delegate { };
|
||||
public static EventHandler LostFocus = delegate { };
|
||||
|
||||
private static void ReAllocate(this IFocusInvoker focusInvoker)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(focusInvoker is FrameworkElement focusInvokerElement))
|
||||
return;
|
||||
|
||||
if (focusInvoker.ParentElement is null)
|
||||
return;
|
||||
|
||||
if (focusInvokerElement.Parent is Panel actualParentPanel)
|
||||
actualParentPanel.Children.Remove(focusInvokerElement);
|
||||
else if (focusInvokerElement.Parent is Decorator actualParentDecorator)
|
||||
actualParentDecorator.Child = null;
|
||||
else
|
||||
return;
|
||||
|
||||
if (focusInvoker.ParentElement is Panel parentPanel)
|
||||
{
|
||||
if (focusInvoker.ParentIndex != null)
|
||||
{
|
||||
parentPanel.Children.RemoveAt(focusInvoker.ParentIndex.Value);
|
||||
parentPanel.Children.Insert(focusInvoker.ParentIndex.Value, focusInvokerElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
parentPanel.Children.Add(focusInvokerElement);
|
||||
}
|
||||
}
|
||||
else if (focusInvoker.ParentElement is Decorator parentDecorator)
|
||||
{
|
||||
parentDecorator.Child = focusInvokerElement;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReAllocate(this FrameworkElement focusInvokerElement)
|
||||
{
|
||||
try
|
||||
{
|
||||
var preFocusParent = GetPreFocusParent(focusInvokerElement);
|
||||
|
||||
if (preFocusParent is null)
|
||||
return;
|
||||
|
||||
if (focusInvokerElement.Parent is Panel actualParentPanel)
|
||||
actualParentPanel.Children.Remove(focusInvokerElement);
|
||||
else if (focusInvokerElement.Parent is Decorator actualParentDecorator)
|
||||
actualParentDecorator.Child = null;
|
||||
else
|
||||
return;
|
||||
|
||||
if (preFocusParent is Panel parentPanel)
|
||||
{
|
||||
var preFocusChildIndex = GetPreFocusChildIndex(focusInvokerElement);
|
||||
|
||||
if (preFocusChildIndex != null)
|
||||
{
|
||||
parentPanel.Children.RemoveAt(preFocusChildIndex.Value);
|
||||
parentPanel.Children.Insert(preFocusChildIndex.Value, focusInvokerElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
parentPanel.Children.Add(focusInvokerElement);
|
||||
}
|
||||
}
|
||||
else if (preFocusParent is Decorator parentDecorator)
|
||||
{
|
||||
parentDecorator.Child = focusInvokerElement;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InvokeGotFocus(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender is FrameworkElement senderElement)
|
||||
{
|
||||
SetPreFocusParent(senderElement, senderElement.Parent);
|
||||
|
||||
if (senderElement.Parent is Panel actualParentPanel)
|
||||
SetPreFocusChildIndex(senderElement, actualParentPanel.Children.IndexOf(senderElement));
|
||||
}
|
||||
|
||||
GotFocus?.Invoke(sender, e);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InvokeLostFocus(object sender, EventArgs e)
|
||||
{
|
||||
LostFocus?.Invoke(sender, e);
|
||||
|
||||
if (sender is IFocusInvoker focusSender)
|
||||
focusSender.ReAllocate();
|
||||
else if (sender is FrameworkElement senderElement)
|
||||
senderElement.ReAllocate();
|
||||
}
|
||||
|
||||
#region Attached Properties
|
||||
|
||||
#region PreFocusChildIndex
|
||||
|
||||
private static int? GetPreFocusChildIndex(DependencyObject obj)
|
||||
{
|
||||
return (int?)obj.GetValue(PreFocusChildIndexProperty);
|
||||
}
|
||||
|
||||
private static void SetPreFocusChildIndex(DependencyObject obj, int? value)
|
||||
{
|
||||
obj.SetValue(PreFocusChildIndexProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PreFocusChildIndexProperty =
|
||||
DependencyProperty.RegisterAttached("PreFocusChildIndex", typeof(int?), typeof(UIElement), new PropertyMetadata(null));
|
||||
|
||||
#endregion
|
||||
|
||||
#region PreFocusParent
|
||||
|
||||
private static DependencyObject GetPreFocusParent(DependencyObject obj)
|
||||
{
|
||||
return (DependencyObject)obj.GetValue(PreFocusParentProperty);
|
||||
}
|
||||
|
||||
private static void SetPreFocusParent(DependencyObject obj, DependencyObject value)
|
||||
{
|
||||
obj.SetValue(PreFocusParentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PreFocusParentProperty =
|
||||
DependencyProperty.RegisterAttached("PreFocusParent", typeof(DependencyObject), typeof(UIElement), new PropertyMetadata(null));
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
199
FasdDesktopUi/Basics/Models/MenuDataModel.cs
Normal file
199
FasdDesktopUi/Basics/Models/MenuDataModel.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using C4IT.FASD.Base;
|
||||
using F4SD_AdaptableIcon;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using FasdDesktopUi.Basics.Converter;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
//todo: check what properties can/should be set via constructor
|
||||
|
||||
public class cMenuDataBase
|
||||
{
|
||||
public string MenuText { get; set; }
|
||||
|
||||
public string SubMenuText { get; set; }
|
||||
|
||||
public string TrailingText { get; set; }
|
||||
|
||||
public IconData MenuIcon { get; set; }
|
||||
|
||||
public double MenuIconSize { get; set; } = 1.0;
|
||||
|
||||
public int IconPositionIndex { get; set; }
|
||||
|
||||
public object Data { get; set; }
|
||||
|
||||
public List<string> MenuSections { get; set; }
|
||||
|
||||
public cUiActionBase UiAction { get; set; }
|
||||
|
||||
public cMenuDataBase()
|
||||
{
|
||||
}
|
||||
public cMenuDataBase(cFasdBaseConfigMenuItem menuItem)
|
||||
{
|
||||
MenuText = menuItem.Names.GetValue(Default: null);
|
||||
MenuIcon = IconDataConverter.Convert(menuItem.Icon);
|
||||
MenuSections = menuItem.Sections;
|
||||
}
|
||||
|
||||
public cMenuDataBase(cFasdQuickAction quickAction, Enums.enumActionDisplayType display) : this(quickAction)
|
||||
{
|
||||
SetUiActionDisplayType(display);
|
||||
}
|
||||
|
||||
|
||||
public cMenuDataBase(cFasdQuickAction quickAction) : this((cFasdBaseConfigMenuItem)quickAction)
|
||||
{
|
||||
var tempUiAction = cUiActionBase.GetUiAction(quickAction);
|
||||
tempUiAction.Name = quickAction.Name;
|
||||
tempUiAction.Description = quickAction.Descriptions?.GetValue(Default: null);
|
||||
tempUiAction.AlternativeDescription = quickAction.AlternativeDescriptions?.GetValue(Default: null);
|
||||
UiAction = tempUiAction;
|
||||
}
|
||||
|
||||
public cMenuDataBase(cCopyTemplate copyTemplate) : this((cFasdBaseConfigMenuItem)copyTemplate)
|
||||
{
|
||||
UiAction = new cUiCopyAction(copyTemplate) { Name = copyTemplate.Name, Description = copyTemplate.Descriptions.GetValue(Default: null), DisplayType = Enums.enumActionDisplayType.enabled };
|
||||
}
|
||||
|
||||
public cMenuDataBase(cFasdMenuSection menuSection) : this((cFasdBaseConfigMenuItem)menuSection)
|
||||
{
|
||||
IconPositionIndex = -1;
|
||||
}
|
||||
|
||||
public cMenuDataBase(cFasdQuickTip quickTip) : this((cFasdBaseConfigMenuItem)quickTip)
|
||||
{
|
||||
UiAction = new cUiQuickTipAction(quickTip) { DisplayType = Enums.enumActionDisplayType.enabled };
|
||||
}
|
||||
|
||||
public void SetUiActionDisplayType(Enums.enumActionDisplayType display)
|
||||
{
|
||||
if (this.UiAction != null)
|
||||
this.UiAction.DisplayType = display;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cMenuDataContainer : cMenuDataBase
|
||||
{
|
||||
public string ContainerName { get; private set; }
|
||||
public List<cMenuDataBase> SubMenuData { get; set; }
|
||||
|
||||
public cMenuDataContainer()
|
||||
{
|
||||
UiAction = new cSubMenuAction(true) { Name = MenuText, DisplayType = Enums.enumActionDisplayType.enabled };
|
||||
}
|
||||
|
||||
public cMenuDataContainer(cFasdMenuSection menuSection) : base(menuSection)
|
||||
{
|
||||
ContainerName = menuSection.TechName;
|
||||
UiAction = new cSubMenuAction(true) { Name = MenuText, DisplayType = Enums.enumActionDisplayType.enabled };
|
||||
}
|
||||
}
|
||||
|
||||
public class cMenuDataSearchResult : cMenuDataBase
|
||||
{
|
||||
public cMenuDataSearchResult(string menuText, ISearchUiProvider SearchUiProvider, List<cFasdApiSearchResultEntry> searchResults) : base()
|
||||
{
|
||||
if (searchResults?.Count <= 0)
|
||||
return;
|
||||
|
||||
MenuText = menuText;
|
||||
UiAction = new cUiProcessSearchResultAction(menuText, SearchUiProvider, searchResults);
|
||||
var firstSearchResult = searchResults.First();
|
||||
MenuIcon = GetMenuIcon(firstSearchResult.Type, firstSearchResult.Infos);
|
||||
}
|
||||
|
||||
static public IconData GetMenuIcon(enumF4sdSearchResultClass searchResultClass, Dictionary<string, string> infos)
|
||||
{
|
||||
switch (searchResultClass)
|
||||
{
|
||||
case enumF4sdSearchResultClass.Computer:
|
||||
return new IconData(enumInternIcons.misc_computer);
|
||||
case enumF4sdSearchResultClass.User:
|
||||
return new IconData(enumInternIcons.misc_user);
|
||||
case enumF4sdSearchResultClass.Phone:
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_phone);
|
||||
case enumF4sdSearchResultClass.Ticket:
|
||||
return new IconData(enumInternIcons.misc_ticket);
|
||||
case enumF4sdSearchResultClass.MobileDevice:
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_smartphone);
|
||||
case enumF4sdSearchResultClass.VirtualSession:
|
||||
if (!infos.TryGetValue("Status", out string status))
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_off);
|
||||
else if (status == nameof(enumCitrixSessionStatus.Active))
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_queue);
|
||||
else
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_off);
|
||||
default:
|
||||
return new IconData(MaterialIcons.MaterialIconType.ic_more_vert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class cMenuDataSearchRelation : cMenuDataBase
|
||||
{
|
||||
public readonly DateTime LastUsed;
|
||||
public readonly double UsingLevel = 0;
|
||||
public readonly Dictionary<string, string> Infos = null;
|
||||
public bool IsMatchingRelation = false;
|
||||
public bool IsUsedForCaseEnrichment = false;
|
||||
|
||||
public readonly cF4sdApiSearchResultRelation searchResultRelation = null;
|
||||
|
||||
public cMenuDataSearchRelation(cF4sdApiSearchResultRelation searchResultRelation)
|
||||
{
|
||||
try
|
||||
{
|
||||
UiAction = null;
|
||||
|
||||
if (searchResultRelation is null)
|
||||
return;
|
||||
|
||||
this.searchResultRelation = searchResultRelation;
|
||||
MenuText = searchResultRelation.DisplayName;
|
||||
Data = searchResultRelation;
|
||||
LastUsed = searchResultRelation.LastUsed;
|
||||
UsingLevel = searchResultRelation.UsingLevel;
|
||||
Infos = searchResultRelation.Infos;
|
||||
MenuIcon = cMenuDataSearchResult.GetMenuIcon(searchResultRelation.Type, searchResultRelation.Infos);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class cMenuDataLoading : cMenuDataBase
|
||||
{
|
||||
public cMenuDataLoading(string LoadingText)
|
||||
{
|
||||
MenuText = LoadingText;
|
||||
}
|
||||
}
|
||||
|
||||
public class cFilteredResults
|
||||
{
|
||||
public bool AutoContinue { get; set; } = false;
|
||||
public cFasdApiSearchResultCollection Results { get; set; }
|
||||
|
||||
public cF4sdApiSearchResultRelation PreSelectedRelation { get; set; }
|
||||
|
||||
public cFilteredResults()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public cFilteredResults(cFasdApiSearchResultCollection _results)
|
||||
{
|
||||
Results = _results ?? new cFasdApiSearchResultCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
223
FasdDesktopUi/Basics/Models/NamedParameterEntry.cs
Normal file
223
FasdDesktopUi/Basics/Models/NamedParameterEntry.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
|
||||
using FasdCockpitBase;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public abstract class cNamedParameterEntryBase : FasdCockpitBase.cExternalToolExecutor.iNamedParameter
|
||||
{
|
||||
internal readonly cSupportCaseDataProvider dataProvider;
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public cNamedParameterEntryBase(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
this.dataProvider = dataProvider;
|
||||
}
|
||||
|
||||
public abstract string GetValue();
|
||||
public abstract string GetHtmlValue();
|
||||
public virtual (string Title, string Value) GetTitleValuePair()
|
||||
{
|
||||
return (Title, GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
public class cNamedParameterEntryPointer : cNamedParameterEntryBase
|
||||
{
|
||||
private readonly cValueAddress valueAdress;
|
||||
private readonly RawValueType display;
|
||||
|
||||
public cNamedParameterEntryPointer(cSupportCaseDataProvider dataProvider, cValueAddress valueAdress, RawValueType display = RawValueType.STRING) : base(dataProvider)
|
||||
{
|
||||
this.valueAdress = valueAdress;
|
||||
this.valueAdress = valueAdress;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public override string GetValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
IRawValueFormatter formatter = new RawValueFormatter();
|
||||
formatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
||||
|
||||
var outputTable = dataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName(valueAdress.ValueTable, true);
|
||||
if (outputTable != null)
|
||||
if (outputTable.Columns.TryGetValue(valueAdress.ValueColumn, out var outpuColumn))
|
||||
output = formatter.GetDisplayValue(outpuColumn.Values[valueAdress.DayIndex], display);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public override string GetHtmlValue()
|
||||
{
|
||||
return GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
public class cNamedParameterEntryCopyTemplate : cNamedParameterEntryBase
|
||||
{
|
||||
private readonly string copyTemplateName;
|
||||
|
||||
public cNamedParameterEntryCopyTemplate(cSupportCaseDataProvider dataProvider, string copyTemplateName) : base(dataProvider)
|
||||
{
|
||||
this.copyTemplateName = copyTemplateName;
|
||||
}
|
||||
|
||||
public override string GetValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates.TryGetValue(copyTemplateName, out var selectedCopyTemplate) ?? false)
|
||||
if (selectedCopyTemplate.CopyContentList.TryGetValue(enumCopyContentFormat.UNICODE, out var selectedCopyContent))
|
||||
output = dataProvider.HealthCardDataHelper.ReplaceNamedParameters(selectedCopyContent.Content, false);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public override string GetHtmlValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates.TryGetValue(copyTemplateName, out var selectedCopyTemplate) ?? false)
|
||||
{
|
||||
if (selectedCopyTemplate.CopyContentList.TryGetValue(enumCopyContentFormat.HTML, out var selectedCopyContent))
|
||||
output = dataProvider.HealthCardDataHelper.ReplaceNamedParameters(selectedCopyContent.Content, true);
|
||||
else if (selectedCopyTemplate.CopyContentList.TryGetValue(enumCopyContentFormat.UNICODE, out var selectedCopyContentUnicode))
|
||||
output = dataProvider.HealthCardDataHelper.ReplaceNamedParameters(selectedCopyContentUnicode.Content, false);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public class cNamedParameterEntryQuickActionResult : cNamedParameterEntryBase
|
||||
{
|
||||
public cNamedParameterEntryQuickActionResult(cSupportCaseDataProvider dataProvider) : base(dataProvider)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string GetValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionResult = F4SDProtocoll.Instance.GetLatestOfTypeAsDataObject<QuickActionProtocollEntry>(false);
|
||||
output = quickActionResult.GetText();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public override string GetHtmlValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionResult = F4SDProtocoll.Instance.GetLatestOfTypeAsDataObject<QuickActionProtocollEntry>(true);
|
||||
output = quickActionResult.GetText(TextDataFormat.Html);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public class cNamedParameterEntryQuickActionResultProtocol : cNamedParameterEntryBase
|
||||
{
|
||||
public cNamedParameterEntryQuickActionResultProtocol(cSupportCaseDataProvider dataProvider) : base(dataProvider)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string GetValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionResult = F4SDProtocoll.Instance.GetAllAsDataObject(false); // dataProvider.QuickActionProtocollHelper.GetFullProtocollQuickActionResult();
|
||||
output = quickActionResult.GetText();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public override string GetHtmlValue()
|
||||
{
|
||||
var output = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionResult = F4SDProtocoll.Instance.GetAllAsDataObject(false); // dataProvider.QuickActionProtocollHelper.GetFullProtocollQuickActionResult();
|
||||
output = quickActionResult.GetText(TextDataFormat.Html);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public class cNamedParameterList : Dictionary<string, cNamedParameterEntryBase>
|
||||
{
|
||||
public cNamedParameterList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public cNamedParameterList(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
Add("F4SD_QuickActionProtocolLast", new cNamedParameterEntryQuickActionResult(dataProvider));
|
||||
Add("F4SD_QuickActionProtocol", new cNamedParameterEntryQuickActionResultProtocol(dataProvider));
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, FasdCockpitBase.cExternalToolExecutor.iNamedParameter> ToInterfaceDictionary()
|
||||
{
|
||||
var output = new Dictionary<string, FasdCockpitBase.cExternalToolExecutor.iNamedParameter>();
|
||||
foreach (var entry in this)
|
||||
output.Add(entry.Key, entry.Value);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
FasdDesktopUi/Basics/Models/QuickActionCopyData.cs
Normal file
19
FasdDesktopUi/Basics/Models/QuickActionCopyData.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cQuickActionCopyData
|
||||
{
|
||||
public DateTime ExecutionTime { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string AffectedDeviceName { get; set; }
|
||||
public bool WasRunningOnAffectedDevice { get; set; }
|
||||
public QuickActionStatusMonitor.cQuickActionOutput QuickActionOutput { get; set; }
|
||||
public List<QuickActionStatusMonitor.cQuickActionMeasureValue> MeasureValues { get; set; }
|
||||
}
|
||||
}
|
||||
11
FasdDesktopUi/Basics/Models/StateThresholdValues.cs
Normal file
11
FasdDesktopUi/Basics/Models/StateThresholdValues.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using C4IT.FASD.Base;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cStateThresholdValues
|
||||
{
|
||||
public object Value;
|
||||
public cHealthCardStateBase StateDefinition;
|
||||
public int ReferenceDays;
|
||||
}
|
||||
}
|
||||
233
FasdDesktopUi/Basics/Models/TicketOverviewModel.cs
Normal file
233
FasdDesktopUi/Basics/Models/TicketOverviewModel.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class TicketOverviewModel : INotifyPropertyChanged
|
||||
{
|
||||
#region Selections-Properties
|
||||
|
||||
private bool _ticketsNewSelected;
|
||||
public bool TicketsNewSelected
|
||||
{
|
||||
get => _ticketsNewSelected;
|
||||
set { if (_ticketsNewSelected != value) { _ticketsNewSelected = value; OnPropertyChanged(nameof(TicketsNewSelected)); } }
|
||||
}
|
||||
|
||||
private bool _ticketsActiveSelected;
|
||||
public bool TicketsActiveSelected
|
||||
{
|
||||
get => _ticketsActiveSelected;
|
||||
set { if (_ticketsActiveSelected != value) { _ticketsActiveSelected = value; OnPropertyChanged(nameof(TicketsActiveSelected)); } }
|
||||
}
|
||||
|
||||
private bool _ticketsCriticalSelected;
|
||||
public bool TicketsCriticalSelected
|
||||
{
|
||||
get => _ticketsCriticalSelected;
|
||||
set { if (_ticketsCriticalSelected != value) { _ticketsCriticalSelected = value; OnPropertyChanged(nameof(TicketsCriticalSelected)); } }
|
||||
}
|
||||
|
||||
private bool _ticketsNewInfoSelected;
|
||||
public bool TicketsNewInfoSelected
|
||||
{
|
||||
get => _ticketsNewInfoSelected;
|
||||
set { if (_ticketsNewInfoSelected != value) { _ticketsNewInfoSelected = value; OnPropertyChanged(nameof(TicketsNewInfoSelected)); } }
|
||||
}
|
||||
|
||||
private bool _incidentNewSelected;
|
||||
public bool IncidentNewSelected
|
||||
{
|
||||
get => _incidentNewSelected;
|
||||
set { if (_incidentNewSelected != value) { _incidentNewSelected = value; OnPropertyChanged(nameof(IncidentNewSelected)); } }
|
||||
}
|
||||
|
||||
private bool _incidentActiveSelected;
|
||||
public bool IncidentActiveSelected
|
||||
{
|
||||
get => _incidentActiveSelected;
|
||||
set { if (_incidentActiveSelected != value) { _incidentActiveSelected = value; OnPropertyChanged(nameof(IncidentActiveSelected)); } }
|
||||
}
|
||||
|
||||
private bool _incidentCriticalSelected;
|
||||
public bool IncidentCriticalSelected
|
||||
{
|
||||
get => _incidentCriticalSelected;
|
||||
set { if (_incidentCriticalSelected != value) { _incidentCriticalSelected = value; OnPropertyChanged(nameof(IncidentCriticalSelected)); } }
|
||||
}
|
||||
|
||||
private bool _incidentNewInfoSelected;
|
||||
public bool IncidentNewInfoSelected
|
||||
{
|
||||
get => _incidentNewInfoSelected;
|
||||
set { if (_incidentNewInfoSelected != value) { _incidentNewInfoSelected = value; OnPropertyChanged(nameof(IncidentNewInfoSelected)); } }
|
||||
}
|
||||
|
||||
private bool _unassignedTicketsSelected;
|
||||
public bool UnassignedTicketsSelected
|
||||
{
|
||||
get => _unassignedTicketsSelected;
|
||||
set { if (_unassignedTicketsSelected != value) { _unassignedTicketsSelected = value; OnPropertyChanged(nameof(UnassignedTicketsSelected)); } }
|
||||
}
|
||||
|
||||
private bool _unassignedTicketsCriticalSelected;
|
||||
public bool UnassignedTicketsCriticalSelected
|
||||
{
|
||||
get => _unassignedTicketsCriticalSelected;
|
||||
set { if (_unassignedTicketsCriticalSelected != value) { _unassignedTicketsCriticalSelected = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalSelected)); } }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Highlight-Properties
|
||||
private bool _ticketsNewHighlighted;
|
||||
public bool TicketsNewHighlighted { get => _ticketsNewHighlighted; set { if (_ticketsNewHighlighted != value) { _ticketsNewHighlighted = value; OnPropertyChanged(nameof(TicketsNewHighlighted)); } } }
|
||||
|
||||
private bool _ticketsActiveHighlighted;
|
||||
public bool TicketsActiveHighlighted { get => _ticketsActiveHighlighted; set { if (_ticketsActiveHighlighted != value) { _ticketsActiveHighlighted = value; OnPropertyChanged(nameof(TicketsActiveHighlighted)); } } }
|
||||
|
||||
private bool _ticketsCriticalHighlighted;
|
||||
public bool TicketsCriticalHighlighted { get => _ticketsCriticalHighlighted; set { if (_ticketsCriticalHighlighted != value) { _ticketsCriticalHighlighted = value; OnPropertyChanged(nameof(TicketsCriticalHighlighted)); } } }
|
||||
|
||||
private bool _ticketsNewInfoHighlighted;
|
||||
public bool TicketsNewInfoHighlighted { get => _ticketsNewInfoHighlighted; set { if (_ticketsNewInfoHighlighted != value) { _ticketsNewInfoHighlighted = value; OnPropertyChanged(nameof(TicketsNewInfoHighlighted)); } } }
|
||||
|
||||
private bool _incidentNewHighlighted;
|
||||
public bool IncidentNewHighlighted { get => _incidentNewHighlighted; set { if (_incidentNewHighlighted != value) { _incidentNewHighlighted = value; OnPropertyChanged(nameof(IncidentNewHighlighted)); } } }
|
||||
|
||||
private bool _incidentActiveHighlighted;
|
||||
public bool IncidentActiveHighlighted { get => _incidentActiveHighlighted; set { if (_incidentActiveHighlighted != value) { _incidentActiveHighlighted = value; OnPropertyChanged(nameof(IncidentActiveHighlighted)); } } }
|
||||
|
||||
private bool _incidentCriticalHighlighted;
|
||||
public bool IncidentCriticalHighlighted { get => _incidentCriticalHighlighted; set { if (_incidentCriticalHighlighted != value) { _incidentCriticalHighlighted = value; OnPropertyChanged(nameof(IncidentCriticalHighlighted)); } } }
|
||||
|
||||
private bool _incidentNewInfoHighlighted;
|
||||
public bool IncidentNewInfoHighlighted { get => _incidentNewInfoHighlighted; set { if (_incidentNewInfoHighlighted != value) { _incidentNewInfoHighlighted = value; OnPropertyChanged(nameof(IncidentNewInfoHighlighted)); } } }
|
||||
|
||||
private bool _unassignedTicketsHighlighted;
|
||||
public bool UnassignedTicketsHighlighted { get => _unassignedTicketsHighlighted; set { if (_unassignedTicketsHighlighted != value) { _unassignedTicketsHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsHighlighted)); } } }
|
||||
|
||||
private bool _unassignedTicketsCriticalHighlighted;
|
||||
public bool UnassignedTicketsCriticalHighlighted { get => _unassignedTicketsCriticalHighlighted; set { if (_unassignedTicketsCriticalHighlighted != value) { _unassignedTicketsCriticalHighlighted = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalHighlighted)); } } }
|
||||
#endregion
|
||||
|
||||
#region Change Hint Properties
|
||||
private string _ticketsNewChangeHint;
|
||||
public string TicketsNewChangeHint { get => _ticketsNewChangeHint; set { if (_ticketsNewChangeHint != value) { _ticketsNewChangeHint = value; OnPropertyChanged(nameof(TicketsNewChangeHint)); } } }
|
||||
|
||||
private string _ticketsActiveChangeHint;
|
||||
public string TicketsActiveChangeHint { get => _ticketsActiveChangeHint; set { if (_ticketsActiveChangeHint != value) { _ticketsActiveChangeHint = value; OnPropertyChanged(nameof(TicketsActiveChangeHint)); } } }
|
||||
|
||||
private string _ticketsCriticalChangeHint;
|
||||
public string TicketsCriticalChangeHint { get => _ticketsCriticalChangeHint; set { if (_ticketsCriticalChangeHint != value) { _ticketsCriticalChangeHint = value; OnPropertyChanged(nameof(TicketsCriticalChangeHint)); } } }
|
||||
|
||||
private string _ticketsNewInfoChangeHint;
|
||||
public string TicketsNewInfoChangeHint { get => _ticketsNewInfoChangeHint; set { if (_ticketsNewInfoChangeHint != value) { _ticketsNewInfoChangeHint = value; OnPropertyChanged(nameof(TicketsNewInfoChangeHint)); } } }
|
||||
|
||||
private string _incidentNewChangeHint;
|
||||
public string IncidentNewChangeHint { get => _incidentNewChangeHint; set { if (_incidentNewChangeHint != value) { _incidentNewChangeHint = value; OnPropertyChanged(nameof(IncidentNewChangeHint)); } } }
|
||||
|
||||
private string _incidentActiveChangeHint;
|
||||
public string IncidentActiveChangeHint { get => _incidentActiveChangeHint; set { if (_incidentActiveChangeHint != value) { _incidentActiveChangeHint = value; OnPropertyChanged(nameof(IncidentActiveChangeHint)); } } }
|
||||
|
||||
private string _incidentCriticalChangeHint;
|
||||
public string IncidentCriticalChangeHint { get => _incidentCriticalChangeHint; set { if (_incidentCriticalChangeHint != value) { _incidentCriticalChangeHint = value; OnPropertyChanged(nameof(IncidentCriticalChangeHint)); } } }
|
||||
|
||||
private string _incidentNewInfoChangeHint;
|
||||
public string IncidentNewInfoChangeHint { get => _incidentNewInfoChangeHint; set { if (_incidentNewInfoChangeHint != value) { _incidentNewInfoChangeHint = value; OnPropertyChanged(nameof(IncidentNewInfoChangeHint)); } } }
|
||||
|
||||
private string _unassignedTicketsChangeHint;
|
||||
public string UnassignedTicketsChangeHint { get => _unassignedTicketsChangeHint; set { if (_unassignedTicketsChangeHint != value) { _unassignedTicketsChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsChangeHint)); } } }
|
||||
|
||||
private string _unassignedTicketsCriticalChangeHint;
|
||||
public string UnassignedTicketsCriticalChangeHint { get => _unassignedTicketsCriticalChangeHint; set { if (_unassignedTicketsCriticalChangeHint != value) { _unassignedTicketsCriticalChangeHint = value; OnPropertyChanged(nameof(UnassignedTicketsCriticalChangeHint)); } } }
|
||||
#endregion
|
||||
|
||||
#region Ticket & Incident-Properties
|
||||
|
||||
// Ticket Properties
|
||||
private int _ticketsNew;
|
||||
public int TicketsNew { get => _ticketsNew; set { _ticketsNew = value; OnPropertyChanged(nameof(TicketsNew)); } }
|
||||
|
||||
private int _ticketsActive;
|
||||
public int TicketsActive { get => _ticketsActive; set { _ticketsActive = value; OnPropertyChanged(nameof(TicketsActive)); } }
|
||||
|
||||
private int _ticketsCritical;
|
||||
public int TicketsCritical { get => _ticketsCritical; set { _ticketsCritical = value; OnPropertyChanged(nameof(TicketsCritical)); } }
|
||||
|
||||
private int _ticketsNewInfo;
|
||||
public int TicketsNewInfo { get => _ticketsNewInfo; set { _ticketsNewInfo = value; OnPropertyChanged(nameof(TicketsNewInfo)); } }
|
||||
|
||||
// Incident Properties
|
||||
private int _incidentNew;
|
||||
public int IncidentNew { get => _incidentNew; set { _incidentNew = value; OnPropertyChanged(nameof(IncidentNew)); } }
|
||||
|
||||
private int _incidentActive;
|
||||
public int IncidentActive { get => _incidentActive; set { _incidentActive = value; OnPropertyChanged(nameof(IncidentActive)); } }
|
||||
|
||||
private int _incidentCritical;
|
||||
public int IncidentCritical { get => _incidentCritical; set { _incidentCritical = value; OnPropertyChanged(nameof(IncidentCritical)); } }
|
||||
|
||||
private int _incidentNewInfo;
|
||||
public int IncidentNewInfo { get => _incidentNewInfo; set { _incidentNewInfo = value; OnPropertyChanged(nameof(IncidentNewInfo)); } }
|
||||
|
||||
// Unassigned Ticket Properties
|
||||
private int _unassignedTickets;
|
||||
public int UnassignedTickets { get => _unassignedTickets; set { _unassignedTickets = value; OnPropertyChanged(nameof(UnassignedTickets)); } }
|
||||
|
||||
private int _unassignedTicketsCritical;
|
||||
public int UnassignedTicketsCritical { get => _unassignedTicketsCritical; set { _unassignedTicketsCritical = value; OnPropertyChanged(nameof(UnassignedTicketsCritical)); } }
|
||||
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected void OnPropertyChanged(string propertyName) =>
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
#endregion
|
||||
|
||||
#region Helper-Methods
|
||||
|
||||
public void ResetSelection()
|
||||
{
|
||||
TicketsNewSelected = false;
|
||||
TicketsActiveSelected = false;
|
||||
TicketsCriticalSelected = false;
|
||||
TicketsNewInfoSelected = false;
|
||||
|
||||
IncidentNewSelected = false;
|
||||
IncidentActiveSelected = false;
|
||||
IncidentCriticalSelected = false;
|
||||
IncidentNewInfoSelected = false;
|
||||
|
||||
UnassignedTicketsSelected = false;
|
||||
UnassignedTicketsCriticalSelected = false;
|
||||
}
|
||||
|
||||
public void ResetHighlights()
|
||||
{
|
||||
TicketsNewHighlighted = false;
|
||||
TicketsActiveHighlighted = false;
|
||||
TicketsCriticalHighlighted = false;
|
||||
TicketsNewInfoHighlighted = false;
|
||||
|
||||
IncidentNewHighlighted = false;
|
||||
IncidentActiveHighlighted = false;
|
||||
IncidentCriticalHighlighted = false;
|
||||
IncidentNewInfoHighlighted = false;
|
||||
|
||||
UnassignedTicketsHighlighted = false;
|
||||
UnassignedTicketsCriticalHighlighted = false;
|
||||
|
||||
TicketsNewChangeHint = null;
|
||||
TicketsActiveChangeHint = null;
|
||||
TicketsCriticalChangeHint = null;
|
||||
TicketsNewInfoChangeHint = null;
|
||||
|
||||
IncidentNewChangeHint = null;
|
||||
IncidentActiveChangeHint = null;
|
||||
IncidentCriticalChangeHint = null;
|
||||
IncidentNewInfoChangeHint = null;
|
||||
|
||||
UnassignedTicketsChangeHint = null;
|
||||
UnassignedTicketsCriticalChangeHint = null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class TicketOverviewSelectionRequestedEventArgs : RoutedEventArgs
|
||||
{
|
||||
public string Key { get; }
|
||||
public bool UseRoleScope { get; }
|
||||
public int Count { get; }
|
||||
|
||||
public TicketOverviewSelectionRequestedEventArgs(RoutedEvent routedEvent, object source,
|
||||
string key, bool useRoleScope, int count)
|
||||
: base(routedEvent, source)
|
||||
{
|
||||
Key = key;
|
||||
UseRoleScope = useRoleScope;
|
||||
Count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
FasdDesktopUi/Basics/Models/WidgetValueModel.cs
Normal file
21
FasdDesktopUi/Basics/Models/WidgetValueModel.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
|
||||
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Models
|
||||
{
|
||||
public class cWidgetValueModel
|
||||
{
|
||||
public int ValueIndex { get; set; }
|
||||
public string TechnicalName { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Value { get; set; }
|
||||
public bool IsLoading { get; set; } = false;
|
||||
public cEditableValueInformationBase EditValueInformation { get; set; }
|
||||
public enumHighlightColor? HighlightIn { get; set; }
|
||||
public cUiActionBase UiActionTitle { get; set; } = null;
|
||||
public cUiActionBase UiActionValue { get; set; } = null;
|
||||
public cHealthCardDetailsTable ValuedDetails { get; set; } = null;
|
||||
}
|
||||
}
|
||||
290
FasdDesktopUi/Basics/NamedPipes.cs
Normal file
290
FasdDesktopUi/Basics/NamedPipes.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
using System.IO.Pipes;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using C4IT.Logging;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
static public class cF4sdPipeClient
|
||||
{
|
||||
static public bool Send(string SendStr, string PipeName, int TimeOut = 1000)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
if (DefaultLogger.IsDebug)
|
||||
{
|
||||
var _msg = new List<string>() { $"send to pipe {PipeName}", SendStr };
|
||||
DefaultLogger.LogList(LogLevels.Debug, _msg);
|
||||
}
|
||||
|
||||
NamedPipeClientStream pipeStream = new NamedPipeClientStream
|
||||
(".", PipeName, PipeDirection.Out, PipeOptions.WriteThrough);
|
||||
|
||||
// The connect function will indefinitely wait for the pipe to become available
|
||||
// If that is not acceptable specify a maximum waiting time (in ms)
|
||||
pipeStream.Connect(TimeOut);
|
||||
|
||||
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
|
||||
pipeStream.Write(_buffer, 0, _buffer.Length);
|
||||
pipeStream.Flush();
|
||||
pipeStream.Close();
|
||||
pipeStream.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (TimeoutException oEX)
|
||||
{
|
||||
if (cLogManager.DefaultLogger.IsDebug)
|
||||
cLogManager.DefaultLogger.LogException(oEX);
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public void RegisterProtocol(string protocolString, string urlCommand)
|
||||
{
|
||||
try
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
var u = new Uri(codeBase);
|
||||
var Path = u.LocalPath;
|
||||
var RegBase = Registry.CurrentUser.OpenSubKey("Software\\Classes", true);
|
||||
var RegHandler = RegBase.CreateSubKey(protocolString.ToUpperInvariant());
|
||||
RegHandler.SetValue("", $"URL: {protocolString.ToUpperInvariant()} Protocol Handler");
|
||||
RegHandler.SetValue("URL Protocol", "");
|
||||
var RegHandler2 = RegHandler.CreateSubKey("DefaultIcon");
|
||||
RegHandler2.SetValue("", Path);
|
||||
var RegHandler3 = RegHandler.CreateSubKey("shell\\open\\command");
|
||||
RegHandler3.SetValue("", $"\"{Path}\" {urlCommand.ToLowerInvariant()} \"%1\"");
|
||||
|
||||
RegHandler = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Internet Explorer\\ProtocolExecute\\{protocolString.ToLowerInvariant()}");
|
||||
RegHandler.SetValue("WarnOnOpen", 0,RegistryValueKind.DWord);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void DelegateMessage(string Reply);
|
||||
|
||||
public class cF4sdPipeServer : IDisposable
|
||||
{
|
||||
public event DelegateMessage PipeMessage;
|
||||
string _pipeName;
|
||||
NamedPipeServerStream pipeServer;
|
||||
bool _LowerIntegrity;
|
||||
int _MaxSize;
|
||||
|
||||
public void Listen(string PipeName, int MaxSize = 255, bool LowerIntegrity = false, int Timeout = 10000)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Set to class level var so we can re-use in the async callback method
|
||||
_pipeName = PipeName;
|
||||
_MaxSize = MaxSize;
|
||||
_LowerIntegrity = LowerIntegrity;
|
||||
|
||||
if (pipeServer != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
pipeServer.Close();
|
||||
pipeServer.Dispose();
|
||||
pipeServer = null;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
bool _connected = false;
|
||||
bool _firstTry = true;
|
||||
var _startTime = DateTime.UtcNow;
|
||||
while ((DateTime.UtcNow - _startTime).TotalMilliseconds < Timeout && !_connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_firstTry)
|
||||
Thread.Sleep(200);
|
||||
_firstTry = false;
|
||||
|
||||
// Create the new async pipe
|
||||
if (pipeServer == null)
|
||||
pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
if (_LowerIntegrity)
|
||||
InterProcessSecurity.SetLowIntegrityLevel(pipeServer.SafePipeHandle);
|
||||
|
||||
// Wait for a connection
|
||||
var _res = pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
|
||||
_connected = _res != null;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
if (!_connected)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogEntry(LogLevels.Error, $"The pipe '{PipeName}' could not be opened in listen mode.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception oEX)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(oEX);
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitForConnectionCallBack(IAsyncResult iar)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the pipe
|
||||
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
|
||||
// End waiting for the connection
|
||||
pipeServer.EndWaitForConnection(iar);
|
||||
|
||||
byte[] buffer = new byte[_MaxSize];
|
||||
|
||||
// Read the incoming message
|
||||
int count = pipeServer.Read(buffer, 0, _MaxSize);
|
||||
|
||||
// Convert byte buffer to string
|
||||
string stringData = Encoding.UTF8.GetString(buffer, 0, count);
|
||||
|
||||
// Pass message back to calling form
|
||||
PipeMessage.Invoke(stringData);
|
||||
|
||||
// Kill original sever and create new wait server
|
||||
pipeServer.Close();
|
||||
pipeServer = null;
|
||||
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,
|
||||
1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
|
||||
if (_LowerIntegrity)
|
||||
InterProcessSecurity.SetLowIntegrityLevel(pipeServer.SafePipeHandle);
|
||||
|
||||
// Recursively wait for the connection again and again....
|
||||
pipeServer.BeginWaitForConnection(
|
||||
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (pipeServer != null)
|
||||
{
|
||||
pipeServer.Close();
|
||||
pipeServer.Dispose();
|
||||
pipeServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static class InterProcessSecurity
|
||||
{
|
||||
|
||||
public const string LOW_INTEGRITY_SSL_SACL = "S:(ML;;NW;;;LW)";
|
||||
|
||||
public static int ERROR_SUCCESS = 0x0;
|
||||
|
||||
public const int LABEL_SECURITY_INFORMATION = 0x00000010;
|
||||
|
||||
public enum SE_OBJECT_TYPE
|
||||
{
|
||||
SE_UNKNOWN_OBJECT_TYPE = 0,
|
||||
SE_FILE_OBJECT,
|
||||
SE_SERVICE,
|
||||
SE_PRINTER,
|
||||
SE_REGISTRY_KEY,
|
||||
SE_LMSHARE,
|
||||
SE_KERNEL_OBJECT,
|
||||
SE_WINDOW_OBJECT,
|
||||
SE_DS_OBJECT,
|
||||
SE_DS_OBJECT_ALL,
|
||||
SE_PROVIDER_DEFINED_OBJECT,
|
||||
SE_WMIGUID_OBJECT,
|
||||
SE_REGISTRY_WOW64_32KEY
|
||||
}
|
||||
|
||||
[DllImport("advapi32.dll", EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern Boolean ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String strSecurityDescriptor,
|
||||
UInt32 sDRevision,
|
||||
ref IntPtr securityDescriptor,
|
||||
ref UInt32 securityDescriptorSize);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "LocalFree")]
|
||||
public static extern UInt32 LocalFree(IntPtr hMem);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "SetSecurityInfo")]
|
||||
public static extern int SetSecurityInfo(SafeHandle hFileMappingObject,
|
||||
SE_OBJECT_TYPE objectType,
|
||||
Int32 securityInfo,
|
||||
IntPtr psidOwner,
|
||||
IntPtr psidGroup,
|
||||
IntPtr pDacl,
|
||||
IntPtr pSacl);
|
||||
[DllImport("advapi32.dll", EntryPoint = "GetSecurityDescriptorSacl")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern Boolean GetSecurityDescriptorSacl(
|
||||
IntPtr pSecurityDescriptor,
|
||||
out IntPtr lpbSaclPresent,
|
||||
out IntPtr pSacl,
|
||||
out IntPtr lpbSaclDefaulted);
|
||||
|
||||
public static void SetLowIntegrityLevel(SafeHandle hObject)
|
||||
{
|
||||
IntPtr pSD = IntPtr.Zero;
|
||||
uint securityDescriptorSize = 0;
|
||||
|
||||
if (ConvertStringSecurityDescriptorToSecurityDescriptor(LOW_INTEGRITY_SSL_SACL, 1, ref pSD, ref securityDescriptorSize))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GetSecurityDescriptorSacl(pSD, out IntPtr lpbSaclPresent, out IntPtr pSacl, out IntPtr lpbSaclDefaulted))
|
||||
{
|
||||
var err = SetSecurityInfo(hObject,
|
||||
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
|
||||
LABEL_SECURITY_INFORMATION,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
pSacl);
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
LocalFree(pSD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
24
FasdDesktopUi/Basics/PrivateSecurePassword.cs
Normal file
24
FasdDesktopUi/Basics/PrivateSecurePassword.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.FASD.Security;
|
||||
using C4IT.Security;
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public static class PrivateSecurePassword
|
||||
{
|
||||
public static cSecurePassword Instance { get; private set; } = null;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
Instance = new cSecurePassword(FasdSecurity.FFH);
|
||||
Instance.SetRsaKey(FasdSecurity.FFK, "C4itF4sdCockpitClient");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
359
FasdDesktopUi/Basics/SearchHistoryManager.cs
Normal file
359
FasdDesktopUi/Basics/SearchHistoryManager.cs
Normal file
@@ -0,0 +1,359 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using FasdDesktopUi.Basics.Services.SupportCaseSearchService;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public interface ISearchUiProvider
|
||||
{
|
||||
SupportCaseSearchService SearchService { get; }
|
||||
void SetSearchHistoryVisibility(bool isVisible);
|
||||
void ShowLoadingTextItem(string itemText);
|
||||
void ShowSearchRelations(cSearchHistorySearchResultEntry SearchHistoryEntry, IRelationService relationService, ISearchUiProvider SearchUiProvider);
|
||||
void SetPendingInformationClasses(HashSet<enumFasdInformationClass> informationClasses);
|
||||
void UpdatePendingInformationClasses(HashSet<enumFasdInformationClass> informationClasses);
|
||||
}
|
||||
|
||||
public class cSearchManager
|
||||
{
|
||||
public const int constMaxHistoryEntryCount = 5; // max. number of entries in the search result history
|
||||
public const int RefreshPeriod = 60; // time in seconds until the data should be refreshed
|
||||
|
||||
private static cSearchManager _Instance = null;
|
||||
public static cSearchManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_Instance is null) ? _Instance = new cSearchManager() : _Instance;
|
||||
}
|
||||
}
|
||||
|
||||
public List<cSearchHistoryEntryBase> HistoryList { get; private set; } = new List<cSearchHistoryEntryBase>();
|
||||
|
||||
private cSearchManager()
|
||||
{
|
||||
}
|
||||
|
||||
public void AddEntry(cSearchHistoryEntryBase Entry)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
// restict the max. history length
|
||||
while (HistoryList.Count >= constMaxHistoryEntryCount)
|
||||
HistoryList.RemoveAt(0);
|
||||
|
||||
// check if we have already the same entry in the list
|
||||
cSearchHistoryEntryBase alreadyExists = null;
|
||||
foreach (var _entry in HistoryList)
|
||||
if (_entry.DisplayText == Entry.DisplayText)
|
||||
{
|
||||
alreadyExists = _entry;
|
||||
break;
|
||||
}
|
||||
// and remove the duplacated entry
|
||||
if (alreadyExists != null)
|
||||
HistoryList.Remove(alreadyExists);
|
||||
|
||||
// and the new entry at least
|
||||
HistoryList.Add(Entry);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReplaceEntry(cSearchHistoryEntryBase Entry, cSearchHistoryEntryBase EntryToReplace)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
HistoryList.Remove(EntryToReplace);
|
||||
AddEntry(Entry);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private class cUserInfo
|
||||
{
|
||||
internal string account;
|
||||
internal string domain;
|
||||
internal string type;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (this is null && obj is null)
|
||||
return true;
|
||||
|
||||
if (this is null || obj is null)
|
||||
return false;
|
||||
|
||||
if (!(obj is cUserInfo userInfo))
|
||||
return false;
|
||||
|
||||
return (type == userInfo.type && account == userInfo.account && domain == userInfo.domain);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private static cUserInfo GetUserInfo(cF4sdApiSearchResultRelation searchRelation)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (searchRelation?.Infos is null)
|
||||
return null;
|
||||
|
||||
searchRelation.Infos.TryGetValue("UserAccountType", out var _accountType);
|
||||
searchRelation.Infos.TryGetValue("UserAccount", out var _account);
|
||||
searchRelation.Infos.TryGetValue("UserDomain", out var _domain);
|
||||
switch (searchRelation.Type)
|
||||
{
|
||||
case enumF4sdSearchResultClass.User:
|
||||
if (string.IsNullOrEmpty(_account))
|
||||
searchRelation.Infos.TryGetValue("account", out _account);
|
||||
if (string.IsNullOrEmpty(_domain))
|
||||
searchRelation.Infos.TryGetValue("domain", out _domain);
|
||||
break;
|
||||
case enumF4sdSearchResultClass.Computer:
|
||||
case enumF4sdSearchResultClass.MobileDevice:
|
||||
case enumF4sdSearchResultClass.VirtualSession:
|
||||
if (string.IsNullOrEmpty(_account))
|
||||
searchRelation.Infos.TryGetValue("relation_account", out _account);
|
||||
if (string.IsNullOrEmpty(_domain))
|
||||
searchRelation.Infos.TryGetValue("relation_domain", out _domain);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return new cUserInfo()
|
||||
{
|
||||
account = _account,
|
||||
domain = _domain,
|
||||
type = _accountType
|
||||
};
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add identifier to relation name, if there are relations with different user infos.
|
||||
/// </summary>
|
||||
/// <param name="relations"></param>
|
||||
internal static void ResolveRelations(List<cF4sdApiSearchResultRelation> relations)
|
||||
{
|
||||
try
|
||||
{
|
||||
cUserInfo firstUserInfo = null;
|
||||
var resolveAccount = false;
|
||||
foreach (var relation in relations)
|
||||
{
|
||||
relation.DisplayName = relation.Name;
|
||||
|
||||
if (relation.Type is enumF4sdSearchResultClass.Ticket)
|
||||
continue;
|
||||
|
||||
var userInfo = GetUserInfo(relation);
|
||||
if (firstUserInfo is null)
|
||||
firstUserInfo = userInfo;
|
||||
|
||||
resolveAccount = resolveAccount || !firstUserInfo.Equals(userInfo);
|
||||
}
|
||||
|
||||
if (!resolveAccount)
|
||||
return;
|
||||
|
||||
foreach (var relation in relations)
|
||||
{
|
||||
if (relation.Type is enumF4sdSearchResultClass.Ticket || relation.Type is enumF4sdSearchResultClass.VirtualSession || relation.Type is enumF4sdSearchResultClass.MobileDevice)
|
||||
continue;
|
||||
|
||||
string relationName = relation.Name;
|
||||
|
||||
var userInfo = GetUserInfo(relation);
|
||||
switch (userInfo.type)
|
||||
{
|
||||
case "Local":
|
||||
relationName = cMultiLanguageSupport.GetItem("UserSerach.AdvancedInfo.LocalUser");
|
||||
break;
|
||||
case "Azure":
|
||||
relationName = cMultiLanguageSupport.GetItem("UserSerach.AdvancedInfo.AzureUser");
|
||||
break;
|
||||
default:
|
||||
relationName = cMultiLanguageSupport.GetItem("UserSerach.AdvancedInfo.AdUser");
|
||||
break;
|
||||
|
||||
}
|
||||
relationName = string.Format(relationName, relation.DisplayName, userInfo.account, userInfo.domain);
|
||||
relation.DisplayName = relationName;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<List<cF4sdApiSearchResultRelation>> GetCaseRelationsAsync(List<cFasdApiSearchResultEntry> SearchResults, cF4sdApiSearchResultRelation CaseRelation = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var firstSearchResultData = SearchResults.First();
|
||||
|
||||
// get SearchResult relation data
|
||||
var CaseRelations = await cFasdCockpitCommunicationBase.Instance.GetSearchResultRelations(firstSearchResultData.Type, SearchResults);
|
||||
|
||||
// add the passed CaseRelation if it not within the result
|
||||
var addRelation = CaseRelation != null;
|
||||
if (addRelation)
|
||||
foreach (var _caseRelation in CaseRelations)
|
||||
{
|
||||
if (_caseRelation.isEqual(CaseRelation))
|
||||
{
|
||||
addRelation = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addRelation)
|
||||
CaseRelations.Add(CaseRelation);
|
||||
|
||||
// if we have no relation, create a 'dummy' relation to relate to the search result itself
|
||||
if (CaseRelations?.Count == 0)
|
||||
{
|
||||
var _dummyRelation = new cF4sdApiSearchResultRelation(firstSearchResultData);
|
||||
CaseRelations.Add(_dummyRelation);
|
||||
}
|
||||
|
||||
if (CaseRelations?.Count > 0)
|
||||
CaseRelations = CaseRelations.OrderByDescending(relation => relation.Type)
|
||||
.ThenBy(relation => relation.LastUsed)
|
||||
.ThenBy(relation => relation.UsingLevel)
|
||||
.ToList();
|
||||
|
||||
return CaseRelations;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class cSearchHistoryEntryBase
|
||||
{
|
||||
public string DisplayText { get; private set; }
|
||||
public bool isSeen { get; set; } = false;
|
||||
|
||||
protected DateTime LastRefresh = DateTime.MinValue;
|
||||
public List<cFasdApiSearchResultEntry> SelectedSearchResult { get; private set; }
|
||||
public List<cF4sdApiSearchResultRelation> Relations { get; protected set; }
|
||||
|
||||
public ISearchUiProvider SearchUiProvider { get; private set; }
|
||||
|
||||
public cSearchHistoryEntryBase(string DisplayText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, ISearchUiProvider SearchUiProvider)
|
||||
{
|
||||
this.DisplayText = DisplayText;
|
||||
this.isSeen = isSeen;
|
||||
this.SelectedSearchResult = selectedSearchResult;
|
||||
this.Relations = relations;
|
||||
this.SearchUiProvider = SearchUiProvider;
|
||||
LastRefresh = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public abstract Task RefreshAsync();
|
||||
|
||||
public bool ShouldRefresh()
|
||||
{
|
||||
return (DateTime.UtcNow - LastRefresh).TotalSeconds > cSearchManager.RefreshPeriod;
|
||||
}
|
||||
}
|
||||
|
||||
public class cSearchHistorySearchResultEntry : cSearchHistoryEntryBase
|
||||
{
|
||||
public string HeaderText { get; private set; }
|
||||
|
||||
public cSearchHistorySearchResultEntry(string DisplayText, string HeaderText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, ISearchUiProvider SearchUiProvider) : base(DisplayText, selectedSearchResult, relations, SearchUiProvider)
|
||||
{
|
||||
this.HeaderText = HeaderText;
|
||||
LastRefresh = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public async override Task RefreshAsync()
|
||||
{
|
||||
if (ShouldRefresh())
|
||||
{
|
||||
var RetVal = await cSearchManager.GetCaseRelationsAsync(SelectedSearchResult);
|
||||
if (RetVal != null)
|
||||
{
|
||||
Relations = RetVal;
|
||||
LastRefresh = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cSearchHistoryRelationEntry : cSearchHistoryEntryBase
|
||||
{
|
||||
public cF4sdApiSearchResultRelation SelectedRelation { get; private set; }
|
||||
|
||||
public cSearchHistoryRelationEntry(string DisplayText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, cF4sdApiSearchResultRelation selectedRealtion, ISearchUiProvider SearchUiProvider) : base(DisplayText, selectedSearchResult, relations, SearchUiProvider)
|
||||
{
|
||||
SelectedRelation = selectedRealtion;
|
||||
}
|
||||
|
||||
public async override Task RefreshAsync()
|
||||
{
|
||||
if (ShouldRefresh())
|
||||
{
|
||||
var RetVal = await cSearchManager.GetCaseRelationsAsync(SelectedSearchResult, SelectedRelation);
|
||||
if (RetVal != null)
|
||||
{
|
||||
Relations = RetVal;
|
||||
LastRefresh = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.Models
|
||||
{
|
||||
public sealed class TicketOverviewCountsChangedEventArgs : EventArgs
|
||||
{
|
||||
public TicketOverviewCountsChangedEventArgs(IReadOnlyList<TileCountChange> changes, IReadOnlyDictionary<string, TileCounts> currentCounts)
|
||||
{
|
||||
Changes = changes;
|
||||
CurrentCounts = currentCounts;
|
||||
}
|
||||
|
||||
public IReadOnlyList<TileCountChange> Changes { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, TileCounts> CurrentCounts { get; }
|
||||
}
|
||||
|
||||
public readonly struct TileCountChange
|
||||
{
|
||||
public TileCountChange(string key, TileScope scope, int oldCount, int newCount)
|
||||
{
|
||||
Key = key;
|
||||
Scope = scope;
|
||||
OldCount = oldCount;
|
||||
NewCount = newCount;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
|
||||
public TileScope Scope { get; }
|
||||
|
||||
public int OldCount { get; }
|
||||
|
||||
public int NewCount { get; }
|
||||
|
||||
public int Delta => NewCount - OldCount;
|
||||
}
|
||||
|
||||
public readonly struct TileCounts
|
||||
{
|
||||
public static TileCounts Empty => new TileCounts(0, 0);
|
||||
|
||||
public TileCounts(int personal, int role)
|
||||
{
|
||||
Personal = personal;
|
||||
Role = role;
|
||||
}
|
||||
|
||||
public int Personal { get; }
|
||||
|
||||
public int Role { get; }
|
||||
}
|
||||
|
||||
public enum TileScope
|
||||
{
|
||||
Personal,
|
||||
Role
|
||||
}
|
||||
}
|
||||
109
FasdDesktopUi/Basics/Services/ProtocollService/F4SDProtocoll.cs
Normal file
109
FasdDesktopUi/Basics/Services/ProtocollService/F4SDProtocoll.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.ProtocollService
|
||||
{
|
||||
internal class F4SDProtocoll
|
||||
{
|
||||
private readonly ICollection<IProtocollEntry> _protocollEntries = new List<IProtocollEntry>();
|
||||
|
||||
public static F4SDProtocoll Instance { get; private set; } = new F4SDProtocoll();
|
||||
|
||||
private F4SDProtocoll() { }
|
||||
|
||||
internal void Add(IProtocollEntry entry) => _protocollEntries.Add(entry);
|
||||
internal void Add(IEnumerable<IProtocollEntry> entries)
|
||||
{
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Clear() => _protocollEntries.Clear();
|
||||
|
||||
internal T GetLatestOfType<T>() where T : IProtocollEntry => _protocollEntries.OfType<T>().LastOrDefault();
|
||||
|
||||
internal IEnumerable<T> GetOfType<T>(int? count = null) where T : IProtocollEntry
|
||||
{
|
||||
if(count.HasValue)
|
||||
return _protocollEntries.OfType<T>().Reverse().Take(count.Value).Reverse();
|
||||
return _protocollEntries.OfType<T>();
|
||||
}
|
||||
|
||||
internal IEnumerable<IProtocollEntry> GetAll() => _protocollEntries;
|
||||
|
||||
internal DataObject GetLatestOfTypeAsDataObject<T>(bool skipHtmlFrame) where T : IProtocollEntry
|
||||
{
|
||||
IProtocollEntry entry = _protocollEntries.OfType<T>().LastOrDefault();
|
||||
|
||||
if (entry is null)
|
||||
return new DataObject();
|
||||
|
||||
return GetDataObjectOf(new IProtocollEntry[] { entry }, skipHtmlFrame);
|
||||
}
|
||||
|
||||
internal DataObject GetOfTypeAsDataObject<T>(bool skipHtmlFrame, int? count = null) where T : IProtocollEntry
|
||||
=> GetDataObjectOf(GetOfType<T>(count).Cast<IProtocollEntry>(), skipHtmlFrame);
|
||||
|
||||
internal DataObject GetAllAsDataObject(bool skipHtmlFrame)
|
||||
=> GetDataObjectOf(_protocollEntries, skipHtmlFrame);
|
||||
|
||||
private DataObject GetDataObjectOf(IEnumerable<IProtocollEntry> entries, bool skipHtmlFrame, int? count = null)
|
||||
{
|
||||
DataObject dataObject = new DataObject();
|
||||
|
||||
const string asciiSeparator = "\n\n\n";
|
||||
const string htmlSeparator = "<br/><hr/><br/>";
|
||||
|
||||
try
|
||||
{
|
||||
string ascii = string.Empty;
|
||||
string html = string.Empty;
|
||||
|
||||
if (count.HasValue)
|
||||
entries = entries.Reverse().Take(count.Value).Reverse();
|
||||
|
||||
foreach (IProtocollEntry entry in entries)
|
||||
{
|
||||
string entryAscii = entry.GetAscii();
|
||||
if (!string.IsNullOrEmpty(entryAscii))
|
||||
{
|
||||
ascii += entryAscii;
|
||||
ascii += asciiSeparator;
|
||||
}
|
||||
|
||||
string entryHtml = entry.GetHtml();
|
||||
if (!string.IsNullOrEmpty(entryHtml))
|
||||
{
|
||||
html += entryHtml;
|
||||
html += htmlSeparator;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii.EndsWith(asciiSeparator))
|
||||
ascii = ascii.Remove(ascii.Length - asciiSeparator.Length);
|
||||
|
||||
if (html.EndsWith(htmlSeparator))
|
||||
html = html.Remove(html.Length - htmlSeparator.Length);
|
||||
|
||||
dataObject.SetText(ascii);
|
||||
|
||||
if (!string.IsNullOrEmpty(html))
|
||||
{
|
||||
html = skipHtmlFrame ? html : cUtility.GetHtmlFrame(html);
|
||||
dataObject.SetText(html, TextDataFormat.Html);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.ProtocollService
|
||||
{
|
||||
internal interface IProtocollEntry
|
||||
{
|
||||
string GetAscii();
|
||||
string GetHtml();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.ProtocollService
|
||||
{
|
||||
internal class QuickActionProtocollEntry : IProtocollEntry
|
||||
{
|
||||
private readonly cFasdQuickAction _quickActionDefinition;
|
||||
private readonly cQuickActionCopyData _quickActionCopyData;
|
||||
private readonly IRawValueFormatter _rawValueFormatter = new RawValueFormatter();
|
||||
|
||||
const string AsciiSeperator = "\n\n";
|
||||
|
||||
public QuickActionProtocollEntry(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData)
|
||||
{
|
||||
_quickActionDefinition = quickActionDefinition;
|
||||
_quickActionCopyData = quickActionCopyData;
|
||||
}
|
||||
|
||||
internal static cQuickActionCopyData GetCopyData(cFasdQuickAction quickActionDefinition, cSupportCaseDataProvider dataProvider, bool wasRunningOnAffectedDevice, cQuickActionOutput quickActionOutput, List<cQuickActionMeasureValue> measureValues)
|
||||
{
|
||||
cQuickActionCopyData quickActionCopyData = new cQuickActionCopyData();
|
||||
try
|
||||
{
|
||||
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
|
||||
|
||||
quickActionCopyData.Name = quickActionDefinition.Names.GetValue();
|
||||
quickActionCopyData.ExecutionTime = DateTime.UtcNow;
|
||||
|
||||
if (dataProvider.HealthCardDataHelper.HeadingData.TryGetValue(enumFasdInformationClass.Computer, out var computerHeadingData))
|
||||
quickActionCopyData.AffectedDeviceName = computerHeadingData.HeadingText;
|
||||
|
||||
quickActionCopyData.WasRunningOnAffectedDevice = wasRunningOnAffectedDevice;
|
||||
quickActionCopyData.QuickActionOutput = quickActionOutput;
|
||||
quickActionCopyData.MeasureValues = measureValues;
|
||||
|
||||
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return quickActionCopyData;
|
||||
}
|
||||
|
||||
internal cQuickActionResult GetResult()
|
||||
{
|
||||
return new cQuickActionResult()
|
||||
{
|
||||
QuickActionId = _quickActionDefinition.Id,
|
||||
QuickActionName = _quickActionDefinition.Name,
|
||||
QuickActionExecutionType = (int)_quickActionDefinition.ExecutionType,
|
||||
wasRunningOnAffectedDevice = _quickActionCopyData.WasRunningOnAffectedDevice,
|
||||
AffectedDeviceName = _quickActionCopyData.AffectedDeviceName,
|
||||
ExecutionTime = DateTime.UtcNow,
|
||||
ResultCode = (int?)(_quickActionCopyData.QuickActionOutput?.ResultCode),
|
||||
ErrorMessage = _quickActionCopyData.QuickActionOutput?.ErrorDescription,
|
||||
Output = GetQuickActionHtmlOutput(_quickActionCopyData.QuickActionOutput),
|
||||
MeasureValues = GetQuickActionHtmlValueComparison(_quickActionCopyData.MeasureValues)
|
||||
};
|
||||
}
|
||||
|
||||
public string GetAscii() => GetQuickActionAscii(_quickActionCopyData);
|
||||
|
||||
public string GetHtml() => GetQuickActionHtml(_quickActionCopyData);
|
||||
|
||||
private bool ShouldHideQuickActionOutput(string outputValueKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_quickActionDefinition.ColumnOutputFormattings is null)
|
||||
return false;
|
||||
|
||||
if (!_quickActionDefinition.ShowAllOutputContent && !_quickActionDefinition.ColumnOutputFormattings.ContainsKey(outputValueKey))
|
||||
return true;
|
||||
|
||||
if (_quickActionDefinition.ColumnOutputFormattings.TryGetValue(outputValueKey, out var columnFormatting))
|
||||
return columnFormatting.Hidden;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Ascii
|
||||
|
||||
private string GetQuickActionAscii(cQuickActionCopyData copyData)
|
||||
{
|
||||
string ascii = string.Empty;
|
||||
|
||||
ascii += GetQuickActionAsciiDescription(copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
|
||||
ascii += GetQuickActionAsciiError(copyData.QuickActionOutput?.ErrorDescription);
|
||||
ascii += GetQuickActionAsciiOutput(copyData.QuickActionOutput);
|
||||
ascii += GetQuickActionAsciiValueComparisonString(copyData.MeasureValues);
|
||||
|
||||
return ascii;
|
||||
}
|
||||
|
||||
private string GetQuickActionAsciiDescription(string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
|
||||
{
|
||||
string asciiDescription = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionStatusString = string.Empty;
|
||||
|
||||
switch (quickActionStatus)
|
||||
{
|
||||
case null:
|
||||
case enumQuickActionSuccess.successfull:
|
||||
quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Successfull");
|
||||
break;
|
||||
case enumQuickActionSuccess.error:
|
||||
quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Error");
|
||||
break;
|
||||
}
|
||||
|
||||
var rawDescription = wasRunningOnAffectedDevice ? cMultiLanguageSupport.GetItem("QuickAction.Remote.Copy.Description") : cMultiLanguageSupport.GetItem("QuickAction.Local.Copy.Description");
|
||||
asciiDescription = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return asciiDescription;
|
||||
}
|
||||
|
||||
private string GetQuickActionAsciiError(string errorMessage)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
errorMessage.Insert(0, AsciiSeperator);
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
private string GetQuickActionAsciiOutput(QuickActionStatusMonitor.cQuickActionOutput quickActionOutput)
|
||||
{
|
||||
string output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(quickActionOutput?.ErrorDescription))
|
||||
return output;
|
||||
|
||||
switch (quickActionOutput)
|
||||
{
|
||||
case QuickActionStatusMonitor.cQuickActionOutputSingle singleOutput:
|
||||
{
|
||||
if (singleOutput.Value is null)
|
||||
return output;
|
||||
|
||||
output += AsciiSeperator;
|
||||
output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + " ";
|
||||
output += singleOutput.GetDisplayValue(_quickActionDefinition.ColumnOutputFormattings);
|
||||
|
||||
break;
|
||||
}
|
||||
case QuickActionStatusMonitor.cQuickActionOutputList listOutput:
|
||||
{
|
||||
output += AsciiSeperator;
|
||||
output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + "\n";
|
||||
|
||||
|
||||
foreach (var value in listOutput.Values[0])
|
||||
{
|
||||
if (ShouldHideQuickActionOutput(value.Key))
|
||||
continue;
|
||||
|
||||
if (_quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
|
||||
output += outputFormatting.Names.GetValue();
|
||||
else
|
||||
output += value.Key;
|
||||
|
||||
output += " | ";
|
||||
}
|
||||
|
||||
for (int i = 0; i < listOutput.Values.Count; i++)
|
||||
{
|
||||
output += "\n";
|
||||
|
||||
for (int j = 0; j < listOutput.Values[i].Count; j++)
|
||||
{
|
||||
string valueKey = listOutput.Values[0][j].Key;
|
||||
|
||||
if (ShouldHideQuickActionOutput(valueKey))
|
||||
continue;
|
||||
|
||||
string displayValue = listOutput.GetDisplayValue(i, j, _quickActionDefinition.ColumnOutputFormattings);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(displayValue))
|
||||
continue;
|
||||
|
||||
output += displayValue;
|
||||
output += " | ";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case QuickActionStatusMonitor.cQuickActionOutputObject objectOutput:
|
||||
{
|
||||
output += AsciiSeperator;
|
||||
output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + "\n";
|
||||
|
||||
for (int i = 0; i < objectOutput.Values.Count; i++)
|
||||
{
|
||||
var value = objectOutput.Values[i];
|
||||
|
||||
if (ShouldHideQuickActionOutput(value.Key))
|
||||
continue;
|
||||
|
||||
string columnTitle = string.Empty;
|
||||
|
||||
if (_quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
|
||||
columnTitle = outputFormatting.Names.GetValue();
|
||||
else
|
||||
columnTitle = value.Key;
|
||||
|
||||
if (!string.IsNullOrEmpty(columnTitle))
|
||||
output += $"{columnTitle}: ";
|
||||
|
||||
string displayValue = objectOutput.GetDisplayValue(i, _quickActionDefinition.ColumnOutputFormattings);
|
||||
output += !string.IsNullOrWhiteSpace(displayValue) ? displayValue : null;
|
||||
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private string GetQuickActionAsciiValueComparisonString(List<QuickActionStatusMonitor.cQuickActionMeasureValue> measureValues)
|
||||
{
|
||||
string output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (measureValues is null || measureValues.Count <= 0)
|
||||
return output;
|
||||
|
||||
output += AsciiSeperator + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure");
|
||||
|
||||
_rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
||||
|
||||
foreach (var measureValue in measureValues)
|
||||
{
|
||||
try
|
||||
{
|
||||
string value = _rawValueFormatter.GetDisplayValue(measureValue.Value, measureValue.Display);
|
||||
string postValue = _rawValueFormatter.GetDisplayValue(measureValue.PostValue, measureValue.Display);
|
||||
string difference = string.Empty;
|
||||
|
||||
if (measureValue.Difference != null)
|
||||
difference = $" (∆ {_rawValueFormatter.GetDisplayValue(measureValue.Difference, measureValue.Display)})";
|
||||
|
||||
output += "\n" + measureValue.Names.GetValue(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage) + ": " + value + " ➜ " + postValue + difference;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Html
|
||||
|
||||
private string GetQuickActionHtml(cQuickActionCopyData copyData)
|
||||
{
|
||||
string output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
output += GetQuickActionHtmlDescription(copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
|
||||
output += GetQuickActionHtmlError(copyData.QuickActionOutput?.ErrorDescription);
|
||||
output += GetQuickActionHtmlOutput(copyData.QuickActionOutput);
|
||||
output += GetQuickActionHtmlValueComparison(copyData.MeasureValues);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private string GetQuickActionHtmlDescription(string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
|
||||
{
|
||||
string output = string.Empty;
|
||||
try
|
||||
{
|
||||
var quickActionStatusString = string.Empty;
|
||||
|
||||
switch (quickActionStatus)
|
||||
{
|
||||
case null:
|
||||
case enumQuickActionSuccess.successfull:
|
||||
quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Successfull");
|
||||
break;
|
||||
case enumQuickActionSuccess.error:
|
||||
quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Error");
|
||||
break;
|
||||
}
|
||||
|
||||
var rawDescription = wasRunningOnAffectedDevice ? cMultiLanguageSupport.GetItem("QuickAction.Remote.Copy.Description.Html") : cMultiLanguageSupport.GetItem("QuickAction.Local.Copy.Description.Html");
|
||||
output = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static string GetQuickActionHtmlError(string errorMessage)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
errorMessage = $"<br/><p style=\"color:red\">{errorMessage}</p>";
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
private string GetQuickActionHtmlOutput(QuickActionStatusMonitor.cQuickActionOutput quickActionOutput)
|
||||
{
|
||||
string output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(quickActionOutput?.ErrorDescription))
|
||||
return output;
|
||||
|
||||
output += "<br/>";
|
||||
|
||||
switch (quickActionOutput)
|
||||
{
|
||||
case QuickActionStatusMonitor.cQuickActionOutputSingle singleOutput:
|
||||
{
|
||||
if (singleOutput.Value is null)
|
||||
return output;
|
||||
|
||||
var displayValue = singleOutput.GetDisplayValue(_quickActionDefinition?.ColumnOutputFormattings);
|
||||
output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + " " + displayValue + "</p>";
|
||||
break;
|
||||
}
|
||||
case QuickActionStatusMonitor.cQuickActionOutputList listOutput:
|
||||
{
|
||||
output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + "</p>";
|
||||
|
||||
output += "<table border=\"1\">";
|
||||
output += "<tr>";
|
||||
|
||||
foreach (var value in listOutput.Values[0])
|
||||
{
|
||||
if (ShouldHideQuickActionOutput(value.Key))
|
||||
continue;
|
||||
|
||||
string headingValue = value.Key;
|
||||
if (_quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
|
||||
headingValue = outputFormatting.Names.GetValue();
|
||||
|
||||
output += "<th align=\"left\">";
|
||||
output += headingValue;
|
||||
output += "</th>";
|
||||
}
|
||||
|
||||
output += "</tr>";
|
||||
|
||||
for (int i = 0; i < listOutput.Values.Count; i++)
|
||||
{
|
||||
output += "<tr>";
|
||||
|
||||
for (int j = 0; j < listOutput.Values[i].Count; j++)
|
||||
{
|
||||
string valueKey = listOutput.Values[0][j].Key;
|
||||
if (ShouldHideQuickActionOutput(valueKey))
|
||||
continue;
|
||||
|
||||
string displayValue = listOutput.GetDisplayValue(i, j, _quickActionDefinition.ColumnOutputFormattings);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(displayValue))
|
||||
continue;
|
||||
|
||||
output += "<td>";
|
||||
output += displayValue;
|
||||
output += "</td>";
|
||||
}
|
||||
|
||||
output += "</tr>";
|
||||
}
|
||||
|
||||
output += "</table>";
|
||||
break;
|
||||
}
|
||||
case QuickActionStatusMonitor.cQuickActionOutputObject objectOutput:
|
||||
{
|
||||
output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + "</p>";
|
||||
|
||||
output += "<table border=\"1\">";
|
||||
|
||||
for (int i = 0; i < objectOutput.Values.Count; i++)
|
||||
{
|
||||
var value = objectOutput.Values[i];
|
||||
|
||||
if (ShouldHideQuickActionOutput(value.Key))
|
||||
continue;
|
||||
|
||||
string headingValue = value.Key;
|
||||
if (_quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
|
||||
headingValue = outputFormatting.Names.GetValue();
|
||||
|
||||
output += "<tr>";
|
||||
output += "<td>";
|
||||
output += headingValue;
|
||||
output += "</td>";
|
||||
|
||||
output += "<td>";
|
||||
string displayValue = objectOutput.GetDisplayValue(i, _quickActionDefinition.ColumnOutputFormattings);
|
||||
output += !string.IsNullOrWhiteSpace(displayValue) ? displayValue : null;
|
||||
output += "</td>";
|
||||
|
||||
output += "</tr>";
|
||||
}
|
||||
|
||||
output += "</table>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private string GetQuickActionHtmlValueComparison(List<QuickActionStatusMonitor.cQuickActionMeasureValue> measureValues)
|
||||
{
|
||||
string output = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
if (measureValues is null || measureValues.Count <= 0)
|
||||
return output;
|
||||
|
||||
output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure.Html") + "</p>";
|
||||
|
||||
_rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
||||
|
||||
foreach (var measureValue in measureValues)
|
||||
{
|
||||
try
|
||||
{
|
||||
string value = _rawValueFormatter.GetDisplayValue(measureValue.Value, measureValue.Display);
|
||||
string postValue = _rawValueFormatter.GetDisplayValue(measureValue.PostValue, measureValue.Display);
|
||||
string difference = string.Empty;
|
||||
|
||||
if (measureValue.Difference != null)
|
||||
difference = $" (∆ {_rawValueFormatter.GetDisplayValue(measureValue.Difference, measureValue.Display)})";
|
||||
|
||||
output += "<p>";
|
||||
output += "<b>" + measureValue.Names.GetValue(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage) + ": </b>" + value + " ➜ " + postValue + difference;
|
||||
output += "</p>";
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.MultiLanguage;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.ProtocollService
|
||||
{
|
||||
internal class QuickTipStepProtocollEntry : IProtocollEntry
|
||||
{
|
||||
private readonly cQuickTipElement _quickTipElementDefinition;
|
||||
private readonly bool _wasSuccessfull;
|
||||
|
||||
public QuickTipStepProtocollEntry(cQuickTipElement quickTipElementDefinition, bool wasSuccessfull)
|
||||
{
|
||||
_quickTipElementDefinition = quickTipElementDefinition;
|
||||
_wasSuccessfull = wasSuccessfull;
|
||||
}
|
||||
|
||||
public string GetAscii()
|
||||
{
|
||||
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
|
||||
try
|
||||
{
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
|
||||
string ascii = _wasSuccessfull ? cMultiLanguageSupport.GetItem("QuickTips.Copy.ManualStep.Successfull") : cMultiLanguageSupport.GetItem("QuickTips.Copy.ManualStep.Unsuccessfull");
|
||||
return string.Format(ascii, _quickTipElementDefinition?.Names?.GetValue());
|
||||
}
|
||||
finally
|
||||
{
|
||||
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetHtml()
|
||||
=> GetAscii();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace FasdDesktopUi.Basics.Services.ProtocollService
|
||||
{
|
||||
internal class TextualProtocollEntry : IProtocollEntry
|
||||
{
|
||||
private readonly string _asciiText;
|
||||
private readonly string _htmlText;
|
||||
|
||||
public TextualProtocollEntry(string asciiText, string htmlText)
|
||||
{
|
||||
_asciiText = asciiText;
|
||||
_htmlText = htmlText;
|
||||
}
|
||||
|
||||
public string GetAscii() => _asciiText;
|
||||
|
||||
public string GetHtml() => _htmlText;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.RelationService
|
||||
{
|
||||
public interface IRelationService
|
||||
{
|
||||
event EventHandler<StagedSearchResultRelationsEventArgs> RelationsFound;
|
||||
|
||||
IEnumerable<cF4sdApiSearchResultRelation> GetLoadedRelations();
|
||||
Task<cF4sdStagedSearchResultRelationTaskId> LoadRelationsAsync(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token = default);
|
||||
IRelationService Clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.RelationService
|
||||
{
|
||||
public class RelationEventArgs : EventArgs
|
||||
{
|
||||
public ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> Relations { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
[assembly: InternalsVisibleTo("F4SD.Cockpit.Client.Test")]
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.RelationService
|
||||
{
|
||||
internal class RelationService : IRelationService
|
||||
{
|
||||
private IEnumerable<cF4sdApiSearchResultRelation> _relations = new List<cF4sdApiSearchResultRelation>();
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously loads relations for the specified search results.
|
||||
/// </summary>
|
||||
/// <remarks>This method initiates a task to gather relations for the provided search results and
|
||||
/// periodically checks for the completion of the task. Once relations are retrieved, an event <see cref="RelationsFound"/>
|
||||
/// is raised to notify listeners of the progress.</remarks>
|
||||
/// <returns>Task id and pending information classes</returns>
|
||||
public async Task<cF4sdStagedSearchResultRelationTaskId> LoadRelationsAsync(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
_relations = new List<cF4sdApiSearchResultRelation>();
|
||||
cF4sdStagedSearchResultRelationTaskId gatherRelationTask = await cFasdCockpitCommunicationBase.Instance.StartGatheringRelations(relatedTo, token);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
const int maxRetryCount = 10;
|
||||
for (int i = 0; i < maxRetryCount; i++)
|
||||
{
|
||||
cF4sdStagedSearchResultRelations stagedRelations = await cFasdCockpitCommunicationBase.Instance.GetStagedRelations(gatherRelationTask.Id, token);
|
||||
stagedRelations.MergeAsRelationInfosWith(relatedTo);
|
||||
|
||||
_relations = _relations.Union(stagedRelations.Relations);
|
||||
RelationsFound?.Invoke(this, new StagedSearchResultRelationsEventArgs() { RelatedTo = relatedTo, StagedResultRelations = stagedRelations });
|
||||
|
||||
if (stagedRelations?.IsComplete ?? false)
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return gatherRelationTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<cF4sdApiSearchResultRelation> GetLoadedRelations() => _relations;
|
||||
|
||||
public IRelationService Clone()
|
||||
{
|
||||
RelationService copy = (RelationService)MemberwiseClone();
|
||||
copy._relations = _relations.Select(r => r).ToList();
|
||||
return copy;
|
||||
}
|
||||
|
||||
public event EventHandler<StagedSearchResultRelationsEventArgs> RelationsFound;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.RelationService
|
||||
{
|
||||
public class StagedSearchResultRelationsEventArgs : EventArgs
|
||||
{
|
||||
public IEnumerable<cFasdApiSearchResultEntry> RelatedTo { get; set; }
|
||||
public cF4sdStagedSearchResultRelations StagedResultRelations { get; set; }
|
||||
public IRelationService RelationService { get; set; }
|
||||
}
|
||||
}
|
||||
21
FasdDesktopUi/Basics/Services/SupportCase/ISupportCase.cs
Normal file
21
FasdDesktopUi/Basics/Services/SupportCase/ISupportCase.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using C4IT.FASD.Base;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.SupportCase
|
||||
{
|
||||
public interface ISupportCase
|
||||
{
|
||||
cSupportCaseDataProvider SupportCaseDataProviderArtifact { get; }
|
||||
void Initialize();
|
||||
void AddCaseRelations(ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations);
|
||||
ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations();
|
||||
IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> GetSupportCaseHealthcardData(object identities, object valueAddress);
|
||||
void UpdateSupportCaseDataCache();
|
||||
|
||||
event EventHandler<RelationEventArgs> CaseRelationsAdded;
|
||||
event EventHandler<object> SupportCaseDataCacheHasChanged;
|
||||
}
|
||||
}
|
||||
125
FasdDesktopUi/Basics/Services/SupportCase/SupportCase.cs
Normal file
125
FasdDesktopUi/Basics/Services/SupportCase/SupportCase.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using C4IT.FASD.Base;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.SupportCase
|
||||
{
|
||||
public class SupportCase : ISupportCase
|
||||
{
|
||||
private readonly Dictionary<enumFasdInformationClass, IList<cF4sdApiSearchResultRelation>> _caseRelations = new Dictionary<enumFasdInformationClass, IList<cF4sdApiSearchResultRelation>>();
|
||||
//private readonly Lookup<IdentitySet, cF4SDHealthCardRawData.cHealthCardTable> _supportCaseDataCache;
|
||||
|
||||
internal readonly Guid Id;
|
||||
private readonly IRelationService _relationService;
|
||||
public cSupportCaseDataProvider SupportCaseDataProviderArtifact { get; }
|
||||
|
||||
internal SupportCase(Guid id, IRelationService relationService, cSupportCaseDataProvider supportCaseDataProvider)
|
||||
{
|
||||
Id = id;
|
||||
_relationService = relationService;
|
||||
SupportCaseDataProviderArtifact = supportCaseDataProvider;
|
||||
|
||||
AddCaseRelations(_relationService?.GetLoadedRelations());
|
||||
}
|
||||
|
||||
~SupportCase()
|
||||
{
|
||||
if (_relationService != null)
|
||||
_relationService.RelationsFound -= HandleRelationsFound;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (_relationService != null)
|
||||
_relationService.RelationsFound += HandleRelationsFound;
|
||||
}
|
||||
|
||||
public ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations()
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerable<(enumFasdInformationClass InformationClass, cF4sdApiSearchResultRelation Relation)> flatList
|
||||
= _caseRelations.SelectMany(i => i.Value.Select(v => (i.Key, v)));
|
||||
|
||||
return flatList.ToLookup(v => v.InformationClass, v => v.Relation);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void AddCaseRelations(ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (relations is null)
|
||||
return;
|
||||
|
||||
foreach (var relationType in relations)
|
||||
{
|
||||
if (_caseRelations.TryGetValue(relationType.Key, out var caseRelation))
|
||||
caseRelation = caseRelation.Union(relationType, new SearchResultRelationEqualityComparer()).ToList();
|
||||
else
|
||||
_caseRelations.Add(relationType.Key, relationType.ToList());
|
||||
|
||||
if (SupportCaseDataProviderArtifact?.CaseRelations?.TryGetValue(relationType.Key, out var caseRelations) ?? false)
|
||||
caseRelations = caseRelations.Union(relationType, new SearchResultRelationEqualityComparer()).ToList();
|
||||
else
|
||||
SupportCaseDataProviderArtifact?.CaseRelations?.Add(relationType.Key, relationType.ToList());
|
||||
}
|
||||
|
||||
CaseRelationsAdded?.Invoke(this, new RelationEventArgs() { Relations = relations });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSupportCaseDataCache()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> GetSupportCaseHealthcardData(object identities, object valueAddress)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e)
|
||||
{
|
||||
AddCaseRelations(e.StagedResultRelations.Relations);
|
||||
|
||||
if (e.StagedResultRelations.IsComplete)
|
||||
_relationService.RelationsFound -= HandleRelationsFound;
|
||||
}
|
||||
|
||||
private void AddCaseRelations(IEnumerable<cF4sdApiSearchResultRelation> relations)
|
||||
=> AddCaseRelations(relations?.ToLookup(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), r => r));
|
||||
|
||||
public event EventHandler<RelationEventArgs> CaseRelationsAdded;
|
||||
public event EventHandler<object> SupportCaseDataCacheHasChanged; // Lookup for IdentitySet and tables which has been updated
|
||||
|
||||
private class SearchResultRelationEqualityComparer : IEqualityComparer<cF4sdApiSearchResultRelation>
|
||||
{
|
||||
public bool Equals(cF4sdApiSearchResultRelation x, cF4sdApiSearchResultRelation y)
|
||||
{
|
||||
return x.isEqual(y);
|
||||
}
|
||||
|
||||
public int GetHashCode(cF4sdApiSearchResultRelation obj)
|
||||
{
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using C4IT.FASD.Base;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.SupportCase
|
||||
{
|
||||
public static class SupportCaseFactory
|
||||
{
|
||||
private static readonly Dictionary<Guid, ISupportCase> _supportCases = new Dictionary<Guid, ISupportCase>();
|
||||
|
||||
private static ISupportCase Create(cF4sdIdentityEntry primaryIdentity, IRelationService relationService, cSupportCaseDataProvider supportCaseDataProvider)
|
||||
{
|
||||
SupportCase supportCase = new SupportCase(primaryIdentity.Id, relationService.Clone(), supportCaseDataProvider);
|
||||
_supportCases.Add(primaryIdentity.Id, supportCase);
|
||||
supportCase.Initialize();
|
||||
return supportCase;
|
||||
}
|
||||
|
||||
public static ISupportCase Get(cF4sdIdentityEntry primaryIdentity, IRelationService relationService, cSupportCaseDataProvider supportCaseDataProvider)
|
||||
{
|
||||
if (primaryIdentity is null)
|
||||
throw new InvalidEnumArgumentException($"{nameof(primaryIdentity)} must not be null.");
|
||||
|
||||
if (primaryIdentity.Class != enumFasdInformationClass.User)
|
||||
throw new InvalidEnumArgumentException($"{nameof(primaryIdentity)} must be of class {nameof(enumFasdInformationClass.User)}.");
|
||||
|
||||
if (_supportCases.TryGetValue(primaryIdentity.Id, out var supportCase))
|
||||
{
|
||||
supportCase.Initialize();
|
||||
return supportCase;
|
||||
}
|
||||
|
||||
return Create(primaryIdentity, relationService, supportCaseDataProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services.SupportCaseSearchService
|
||||
{
|
||||
public class SupportCaseSearchService
|
||||
{
|
||||
private readonly IRelationService _relationService;
|
||||
|
||||
public SupportCaseSearchService(IRelationService relationService)
|
||||
{
|
||||
_relationService = relationService;
|
||||
_relationService.RelationsFound += HandleRelationsFound;
|
||||
}
|
||||
|
||||
~SupportCaseSearchService()
|
||||
{
|
||||
_relationService.RelationsFound -= HandleRelationsFound;
|
||||
}
|
||||
|
||||
public static async Task<cFasdApiSearchResultCollection> GetSearchResultsAsync(string searchQuery, CancellationToken token = default)
|
||||
{
|
||||
Guid? searchId = null;
|
||||
try
|
||||
{
|
||||
searchId = await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStart(searchQuery, token);
|
||||
|
||||
if (searchId is null)
|
||||
return new cFasdApiSearchResultCollection();
|
||||
|
||||
return await cFasdCockpitCommunicationBase.Instance.GetSearchResultsResult(searchId.Value, token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
if (searchId != null)
|
||||
await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStop(searchId.Value, CancellationToken.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return new cFasdApiSearchResultCollection();
|
||||
}
|
||||
|
||||
public async Task<cF4sdStagedSearchResultRelationTaskId> LoadRelationsAsync(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token = default)
|
||||
=> await _relationService.LoadRelationsAsync(relatedTo, token);
|
||||
|
||||
private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e)
|
||||
{
|
||||
e.RelationService = _relationService;
|
||||
RelationsFound.Invoke(this, e);
|
||||
}
|
||||
|
||||
public event EventHandler<StagedSearchResultRelationsEventArgs> RelationsFound;
|
||||
}
|
||||
}
|
||||
600
FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs
Normal file
600
FasdDesktopUi/Basics/Services/TicketOverviewUpdateService.cs
Normal file
@@ -0,0 +1,600 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.Models;
|
||||
#if isDemo
|
||||
using System.Net;
|
||||
using FasdCockpitCommunicationDemo;
|
||||
using System.Text.RegularExpressions;
|
||||
#endif
|
||||
|
||||
namespace FasdDesktopUi.Basics.Services
|
||||
{
|
||||
public sealed class TicketOverviewUpdateService
|
||||
{
|
||||
private static readonly TimeSpan RefreshInterval = TimeSpan.FromMinutes(5);
|
||||
private static readonly string[] OverviewKeys = new[]
|
||||
{
|
||||
"TicketsNew",
|
||||
"TicketsActive",
|
||||
"TicketsCritical",
|
||||
"TicketsNewInfo",
|
||||
"IncidentNew",
|
||||
"IncidentActive",
|
||||
"IncidentCritical",
|
||||
"IncidentNewInfo",
|
||||
"UnassignedTickets",
|
||||
"UnassignedTicketsCritical"
|
||||
};
|
||||
private const string DemoTicketDetailsKey = "Demo.HasTicketDetails";
|
||||
private readonly Dispatcher _dispatcher;
|
||||
private readonly Dictionary<string, TileCounts> _currentCounts = new Dictionary<string, TileCounts>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Dictionary<(string Key, bool UseRoleScope), List<cF4sdApiSearchResultRelation>> _demoRelations = new Dictionary<(string, bool), List<cF4sdApiSearchResultRelation>>();
|
||||
private DispatcherTimer _timer;
|
||||
private bool _isFetching;
|
||||
private bool _fetchRetryPending;
|
||||
private bool _isDemo;
|
||||
private bool _initialized;
|
||||
private readonly Random _random = new Random();
|
||||
#if isDemo
|
||||
private readonly List<DemoTicketRecord> _persistedDemoTickets = new List<DemoTicketRecord>();
|
||||
private readonly List<DemoTicketTemplate> _demoTemplates = new List<DemoTicketTemplate>();
|
||||
private readonly HashSet<string> _usedSummaries = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private const int SimulationHotkeyDelayMs = 400;
|
||||
private int _pendingSimulations;
|
||||
private DispatcherTimer _simulationFlushTimer;
|
||||
#endif
|
||||
|
||||
private TicketOverviewUpdateService()
|
||||
{
|
||||
_dispatcher = Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher;
|
||||
foreach (var key in OverviewKeys)
|
||||
{
|
||||
_currentCounts[key] = TileCounts.Empty;
|
||||
}
|
||||
#if isDemo
|
||||
_simulationFlushTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(SimulationHotkeyDelayMs), DispatcherPriority.Background, SimulationFlushTimer_Tick, _dispatcher)
|
||||
{
|
||||
IsEnabled = false
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
static TicketOverviewUpdateService()
|
||||
{
|
||||
#if isDemo
|
||||
Instance = new TicketOverviewUpdateService();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static TicketOverviewUpdateService Instance { get; } = null;
|
||||
|
||||
public event EventHandler<TicketOverviewCountsChangedEventArgs> OverviewCountsChanged;
|
||||
|
||||
public IReadOnlyDictionary<string, TileCounts> CurrentCounts => _currentCounts;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_initialized)
|
||||
return;
|
||||
|
||||
_initialized = true;
|
||||
#if isDemo
|
||||
_isDemo = true;
|
||||
LoadPersistedDemoTickets();
|
||||
#else
|
||||
_isDemo = cFasdCockpitCommunicationBase.Instance?.IsDemo() == true;
|
||||
#endif
|
||||
|
||||
if (!_isDemo)
|
||||
{
|
||||
_timer = new DispatcherTimer(RefreshInterval, DispatcherPriority.Background, async (s, e) => await FetchAsync().ConfigureAwait(false), _dispatcher);
|
||||
_timer.Start();
|
||||
_ = FetchAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = FetchAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task FetchAsync()
|
||||
{
|
||||
if (_isFetching)
|
||||
return;
|
||||
|
||||
var communication = cFasdCockpitCommunicationBase.Instance;
|
||||
if (communication == null)
|
||||
{
|
||||
ScheduleFetchRetry();
|
||||
return;
|
||||
}
|
||||
|
||||
_isFetching = true;
|
||||
try
|
||||
{
|
||||
_isDemo = communication?.IsDemo() == true;
|
||||
if (_isDemo && _timer != null)
|
||||
{
|
||||
_timer.Stop();
|
||||
_timer = null;
|
||||
}
|
||||
var counts = await Task.Run(() => RetrieveCountsAsync()).ConfigureAwait(false);
|
||||
if (counts != null)
|
||||
{
|
||||
await _dispatcher.InvokeAsync(() => ProcessCounts(counts));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isFetching = false;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, TileCounts> RetrieveCountsAsync()
|
||||
{
|
||||
var communication = cFasdCockpitCommunicationBase.Instance;
|
||||
if (communication == null)
|
||||
return null;
|
||||
|
||||
var result = new Dictionary<string, TileCounts>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var key in OverviewKeys)
|
||||
{
|
||||
var personalTask = communication.GetTicketOverviewRelations(key, useRoleScope: false, count: 0);
|
||||
var roleTask = communication.GetTicketOverviewRelations(key, useRoleScope: true, count: 0);
|
||||
Task.WaitAll(personalTask, roleTask);
|
||||
|
||||
int personalCount = personalTask.Result?.Count ?? 0;
|
||||
int roleCount = roleTask.Result?.Count ?? 0;
|
||||
|
||||
if (_isDemo)
|
||||
{
|
||||
personalCount += GetDemoRelationCount(key, useRoleScope: false);
|
||||
roleCount += GetDemoRelationCount(key, useRoleScope: true);
|
||||
}
|
||||
|
||||
result[key] = new TileCounts(personalCount, roleCount);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ProcessCounts(Dictionary<string, TileCounts> newCounts)
|
||||
{
|
||||
var changes = new List<TileCountChange>();
|
||||
bool hasPrevious = _currentCounts.Values.Any(tc => tc.Personal > 0 || tc.Role > 0);
|
||||
|
||||
foreach (var key in OverviewKeys)
|
||||
{
|
||||
var previous = _currentCounts[key];
|
||||
var current = newCounts.TryGetValue(key, out var value) ? value : TileCounts.Empty;
|
||||
|
||||
if (previous.Personal != current.Personal)
|
||||
{
|
||||
changes.Add(new TileCountChange(key, TileScope.Personal, previous.Personal, current.Personal));
|
||||
}
|
||||
|
||||
if (previous.Role != current.Role)
|
||||
{
|
||||
changes.Add(new TileCountChange(key, TileScope.Role, previous.Role, current.Role));
|
||||
}
|
||||
|
||||
_currentCounts[key] = current;
|
||||
}
|
||||
|
||||
if (!hasPrevious)
|
||||
return;
|
||||
|
||||
if (changes.Count == 0)
|
||||
return;
|
||||
|
||||
var args = new TicketOverviewCountsChangedEventArgs(changes, new Dictionary<string, TileCounts>(_currentCounts));
|
||||
OverviewCountsChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
public void SimulateDemoTicket()
|
||||
{
|
||||
_isDemo = cFasdCockpitCommunicationBase.Instance?.IsDemo() == true;
|
||||
if (!_isDemo)
|
||||
return;
|
||||
|
||||
#if isDemo
|
||||
if (_demoTemplates.Count == 0)
|
||||
{
|
||||
LoadDemoTemplates();
|
||||
if (_demoTemplates.Count == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingSimulations++;
|
||||
|
||||
if (_simulationFlushTimer != null)
|
||||
{
|
||||
_simulationFlushTimer.Stop();
|
||||
_simulationFlushTimer.Interval = TimeSpan.FromMilliseconds(SimulationHotkeyDelayMs);
|
||||
_simulationFlushTimer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessDemoSimulations(_pendingSimulations);
|
||||
_pendingSimulations = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public IEnumerable<cF4sdApiSearchResultRelation> GetDemoRelations(string key, bool useRoleScope)
|
||||
{
|
||||
if (!_isDemo)
|
||||
return Enumerable.Empty<cF4sdApiSearchResultRelation>();
|
||||
|
||||
lock (_demoRelations)
|
||||
{
|
||||
if (_demoRelations.TryGetValue((key, useRoleScope), out var list))
|
||||
return list.ToList();
|
||||
}
|
||||
|
||||
return Enumerable.Empty<cF4sdApiSearchResultRelation>();
|
||||
}
|
||||
|
||||
#if isDemo
|
||||
private void LoadPersistedDemoTickets()
|
||||
{
|
||||
var data = TicketOverviewDataStore.LoadData();
|
||||
|
||||
_demoTemplates.Clear();
|
||||
if (data.Templates != null)
|
||||
_demoTemplates.AddRange(data.Templates);
|
||||
|
||||
_persistedDemoTickets.Clear();
|
||||
_usedSummaries.Clear();
|
||||
if (data.Tickets == null)
|
||||
return;
|
||||
|
||||
foreach (var record in data.Tickets)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(record.Summary))
|
||||
_usedSummaries.Add(record.Summary);
|
||||
|
||||
_persistedDemoTickets.Add(record);
|
||||
AddRelationForRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadDemoTemplates()
|
||||
{
|
||||
var templates = TicketOverviewDataStore.LoadTemplates();
|
||||
if (templates == null || templates.Count == 0)
|
||||
return;
|
||||
|
||||
_demoTemplates.Clear();
|
||||
_demoTemplates.AddRange(templates);
|
||||
}
|
||||
|
||||
private void SimulationFlushTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
_simulationFlushTimer.Stop();
|
||||
var count = _pendingSimulations;
|
||||
_pendingSimulations = 0;
|
||||
ProcessDemoSimulations(count);
|
||||
}
|
||||
|
||||
private void ProcessDemoSimulations(int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (_demoTemplates.Count == 0)
|
||||
{
|
||||
LoadDemoTemplates();
|
||||
if (_demoTemplates.Count == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
var appliedChanges = new List<TileCountChange>();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var template = _demoTemplates[_random.Next(_demoTemplates.Count)];
|
||||
var record = CreateDemoTicketRecord(template);
|
||||
if (record == null)
|
||||
continue;
|
||||
|
||||
if (!TicketOverviewDataStore.AppendTicket(record))
|
||||
continue;
|
||||
|
||||
var change = RegisterDemoTicket(record);
|
||||
if (change.HasValue)
|
||||
appliedChanges.Add(change.Value);
|
||||
}
|
||||
|
||||
if (appliedChanges.Count == 0)
|
||||
return;
|
||||
|
||||
var args = new TicketOverviewCountsChangedEventArgs(appliedChanges, new Dictionary<string, TileCounts>(_currentCounts));
|
||||
OverviewCountsChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
private void AddRelationForRecord(DemoTicketRecord record)
|
||||
{
|
||||
if (record == null)
|
||||
return;
|
||||
|
||||
var relation = CreateRelationFromRecord(record);
|
||||
var scopeKey = (record.TileKey, record.UseRoleScope);
|
||||
|
||||
lock (_demoRelations)
|
||||
{
|
||||
if (!_demoRelations.TryGetValue(scopeKey, out var list))
|
||||
{
|
||||
list = new List<cF4sdApiSearchResultRelation>();
|
||||
_demoRelations[scopeKey] = list;
|
||||
}
|
||||
|
||||
if (list.Any(existing => existing.id == relation.id))
|
||||
return;
|
||||
|
||||
list.Add(relation);
|
||||
}
|
||||
}
|
||||
|
||||
private cF4sdApiSearchResultRelation CreateRelationFromRecord(DemoTicketRecord record)
|
||||
{
|
||||
var relation = new cF4sdApiSearchResultRelation
|
||||
{
|
||||
Type = enumF4sdSearchResultClass.Ticket,
|
||||
DisplayName = record.DisplayName,
|
||||
Name = record.DisplayName,
|
||||
id = record.TicketId,
|
||||
Status = enumF4sdSearchResultStatus.Active,
|
||||
Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["Summary"] = record.Summary ?? string.Empty,
|
||||
["StatusId"] = record.StatusId ?? string.Empty,
|
||||
["UserDisplayName"] = record.UserDisplayName ?? string.Empty,
|
||||
["UserAccount"] = record.UserAccount ?? string.Empty,
|
||||
["UserDomain"] = record.UserDomain ?? string.Empty,
|
||||
[DemoTicketDetailsKey] = bool.TrueString
|
||||
},
|
||||
Identities = new cF4sdIdentityList
|
||||
{
|
||||
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = record.TicketId },
|
||||
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = record.UserId }
|
||||
}
|
||||
};
|
||||
|
||||
return relation;
|
||||
}
|
||||
|
||||
private DemoTicketDetail CloneDetail(DemoTicketDetail source)
|
||||
{
|
||||
if (source == null)
|
||||
return new DemoTicketDetail();
|
||||
|
||||
return new DemoTicketDetail
|
||||
{
|
||||
AffectedUser = source.AffectedUser,
|
||||
Asset = source.Asset,
|
||||
Category = source.Category,
|
||||
Classification = source.Classification,
|
||||
Description = source.Description,
|
||||
DescriptionHtml = source.DescriptionHtml,
|
||||
Priority = source.Priority,
|
||||
Solution = source.Solution,
|
||||
SolutionHtml = source.SolutionHtml,
|
||||
Journal = source.Journal?.Select(entry => new DemoTicketJournalEntry
|
||||
{
|
||||
Header = entry?.Header,
|
||||
Description = entry?.Description,
|
||||
DescriptionHtml = entry?.DescriptionHtml,
|
||||
IsVisibleForUser = entry?.IsVisibleForUser ?? true,
|
||||
CreationDate = entry?.CreationDate ?? default
|
||||
}).ToList() ?? new List<DemoTicketJournalEntry>()
|
||||
};
|
||||
}
|
||||
|
||||
private TileCountChange? RegisterDemoTicket(DemoTicketRecord record)
|
||||
{
|
||||
if (record == null)
|
||||
return null;
|
||||
|
||||
_persistedDemoTickets.Add(record);
|
||||
AddRelationForRecord(record);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(record.Summary))
|
||||
_usedSummaries.Add(record.Summary);
|
||||
|
||||
if (cFasdCockpitCommunicationBase.Instance is cFasdCockpitCommunicationDemo demoCommunication)
|
||||
{
|
||||
demoCommunication.RegisterGeneratedTicket(record);
|
||||
}
|
||||
|
||||
if (!_currentCounts.TryGetValue(record.TileKey, out var previousCounts))
|
||||
previousCounts = TileCounts.Empty;
|
||||
|
||||
TileCounts updatedCounts;
|
||||
int oldValue;
|
||||
int newValue;
|
||||
TileScope scope;
|
||||
|
||||
if (record.UseRoleScope)
|
||||
{
|
||||
updatedCounts = new TileCounts(previousCounts.Personal, previousCounts.Role + 1);
|
||||
oldValue = previousCounts.Role;
|
||||
newValue = updatedCounts.Role;
|
||||
scope = TileScope.Role;
|
||||
}
|
||||
else
|
||||
{
|
||||
updatedCounts = new TileCounts(previousCounts.Personal + 1, previousCounts.Role);
|
||||
oldValue = previousCounts.Personal;
|
||||
newValue = updatedCounts.Personal;
|
||||
scope = TileScope.Personal;
|
||||
}
|
||||
|
||||
_currentCounts[record.TileKey] = updatedCounts;
|
||||
|
||||
return new TileCountChange(record.TileKey, scope, oldValue, newValue);
|
||||
}
|
||||
|
||||
private string EnsureUniqueSummary(string preferredSummary)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(preferredSummary))
|
||||
preferredSummary = "Demo Ticket";
|
||||
|
||||
if (!_usedSummaries.Contains(preferredSummary))
|
||||
{
|
||||
_usedSummaries.Add(preferredSummary);
|
||||
return preferredSummary;
|
||||
}
|
||||
|
||||
var nextFreeSummary = _demoTemplates
|
||||
.Select(t => t?.Summary)
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.FirstOrDefault(s => !_usedSummaries.Contains(s));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(nextFreeSummary))
|
||||
{
|
||||
_usedSummaries.Add(nextFreeSummary);
|
||||
return nextFreeSummary;
|
||||
}
|
||||
|
||||
var baseSummary = preferredSummary;
|
||||
var suffix = 2;
|
||||
var candidate = baseSummary;
|
||||
while (_usedSummaries.Contains(candidate))
|
||||
{
|
||||
candidate = $"{baseSummary} #{suffix}";
|
||||
suffix++;
|
||||
}
|
||||
|
||||
_usedSummaries.Add(candidate);
|
||||
return candidate;
|
||||
}
|
||||
|
||||
|
||||
private DemoTicketRecord CreateDemoTicketRecord(DemoTicketTemplate template)
|
||||
{
|
||||
if (template == null)
|
||||
return null;
|
||||
|
||||
var relationId = Guid.NewGuid();
|
||||
var createdAt = DateTime.UtcNow;
|
||||
var prefix = string.IsNullOrWhiteSpace(template.DisplayNamePrefix) ? "TCK" : template.DisplayNamePrefix.Trim();
|
||||
prefix = prefix.ToUpperInvariant();
|
||||
var displayName = TicketOverviewDataStore.GetNextDisplayName(prefix);
|
||||
var summary = EnsureUniqueSummary(template.Summary ?? string.Empty);
|
||||
var detail = CloneDetail(template.Detail);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.AffectedUser))
|
||||
detail.AffectedUser = template.UserDisplayName ?? "Ticket, Timo";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.Description) && !string.IsNullOrWhiteSpace(detail.DescriptionHtml))
|
||||
{
|
||||
detail.Description = Regex.Replace(detail.DescriptionHtml, "<.*?>", string.Empty);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.Description))
|
||||
detail.Description = summary;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.DescriptionHtml))
|
||||
{
|
||||
detail.DescriptionHtml = $"<p>{WebUtility.HtmlEncode(detail.Description)}</p>";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.Solution) && !string.IsNullOrWhiteSpace(detail.SolutionHtml))
|
||||
{
|
||||
detail.Solution = Regex.Replace(detail.SolutionHtml, "<.*?>", string.Empty);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.Solution))
|
||||
detail.Solution = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(detail.SolutionHtml) && !string.IsNullOrWhiteSpace(detail.Solution))
|
||||
{
|
||||
detail.SolutionHtml = $"<p>{WebUtility.HtmlEncode(detail.Solution)}</p>";
|
||||
}
|
||||
|
||||
if (detail.Journal == null || detail.Journal.Count == 0)
|
||||
{
|
||||
detail.Journal = new List<DemoTicketJournalEntry>
|
||||
{
|
||||
new DemoTicketJournalEntry
|
||||
{
|
||||
Header = "Ticket erstellt",
|
||||
Description = detail.Description ?? "Automatisch generiertes Demoticket.",
|
||||
DescriptionHtml = detail.DescriptionHtml ?? "<p>Automatisch generiertes Demoticket.</p>",
|
||||
IsVisibleForUser = true,
|
||||
CreationDate = createdAt
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var entry in detail.Journal)
|
||||
{
|
||||
if (entry.CreationDate == default)
|
||||
entry.CreationDate = createdAt;
|
||||
}
|
||||
|
||||
return new DemoTicketRecord
|
||||
{
|
||||
TicketId = relationId,
|
||||
TileKey = string.IsNullOrWhiteSpace(template.TileKey) ? "TicketsNew" : template.TileKey,
|
||||
UseRoleScope = template.UseRoleScope,
|
||||
DisplayName = displayName,
|
||||
Summary = summary,
|
||||
StatusId = string.IsNullOrWhiteSpace(template.StatusId) ? "New" : template.StatusId,
|
||||
UserDisplayName = template.UserDisplayName ?? detail.AffectedUser ?? "Ticket, Timo",
|
||||
UserAccount = template.UserAccount ?? "TT007",
|
||||
UserDomain = template.UserDomain ?? "CONTOSO",
|
||||
UserId = template.UserId ?? Guid.Parse("42c760d6-90e8-469f-b2fe-ac7d4cc6cb0a"),
|
||||
CreatedAt = createdAt,
|
||||
Detail = detail
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public Dictionary<string, int> GetCountsForScope(bool useRoleScope)
|
||||
{
|
||||
return _currentCounts.ToDictionary(kvp => kvp.Key, kvp => useRoleScope ? kvp.Value.Role : kvp.Value.Personal, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private int GetDemoRelationCount(string key, bool useRoleScope)
|
||||
{
|
||||
lock (_demoRelations)
|
||||
{
|
||||
if (_demoRelations.TryGetValue((key, useRoleScope), out var list))
|
||||
return list.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void ScheduleFetchRetry()
|
||||
{
|
||||
if (_fetchRetryPending)
|
||||
return;
|
||||
|
||||
_fetchRetryPending = true;
|
||||
_ = _dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(250).ConfigureAwait(false);
|
||||
await FetchAsync().ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_fetchRetryPending = false;
|
||||
}
|
||||
}, DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
}
|
||||
601
FasdDesktopUi/Basics/SupportCaseDataProvider.cs
Normal file
601
FasdDesktopUi/Basics/SupportCaseDataProvider.cs
Normal file
@@ -0,0 +1,601 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using System.Diagnostics;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.MultiLanguage;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Pages;
|
||||
using FasdDesktopUi.Pages.CustomMessageBox;
|
||||
using FasdDesktopUi.Config;
|
||||
using FasdDesktopUi.Pages.SearchPage;
|
||||
using FasdDesktopUi.Pages.TicketCompletion;
|
||||
using Newtonsoft.Json;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using FasdDesktopUi.Basics.Services.SupportCase;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
|
||||
|
||||
namespace FasdDesktopUi.Basics
|
||||
{
|
||||
public sealed class cSupportCaseDataProvider
|
||||
{
|
||||
public class cSearchResultRelationsByClass : Dictionary<enumFasdInformationClass, List<cF4sdApiSearchResultRelation>>
|
||||
{
|
||||
}
|
||||
|
||||
public FlowDocument CaseNotes { get; private set; } = new FlowDocument();
|
||||
|
||||
private static cSupportCaseDataProvider CurrentProvider;
|
||||
|
||||
public static Pages.SlimPage.SlimPageView slimPage { get; set; }
|
||||
public static Pages.DetailsPage.DetailsPageView detailsPage { get; set; }
|
||||
|
||||
|
||||
private static readonly Dictionary<Guid, cSupportCaseDataProvider> DataProviders = new Dictionary<Guid, cSupportCaseDataProvider>();
|
||||
|
||||
public EventHandler<bool> NotepadDocumentUpdated { get; set; }
|
||||
|
||||
#region Properties
|
||||
|
||||
private readonly object caseIdLockObject = new object();
|
||||
public Guid CaseId { get; private set; }
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return CaseId != Guid.Empty || slimPage?.IsActive is true || detailsPage?.IsActive is true;
|
||||
}
|
||||
}
|
||||
|
||||
public SupportCasePageBase ActiveSupportCaseWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (detailsPage?.IsVisible is true)
|
||||
return detailsPage;
|
||||
if (slimPage?.IsVisible is true)
|
||||
return slimPage;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
System.Timers.Timer caseAliveTimer;
|
||||
|
||||
public cHealthCardDataHelper HealthCardDataHelper { get; private set; }
|
||||
public cDirectConnectionHelper DirectConnectionHelper { get; private set; }
|
||||
public cQuickActionProtocollHelper QuickActionProtocollHelper { get; private set; }
|
||||
|
||||
public cSearchResultRelationsByClass CaseRelations { get; } = new cSearchResultRelationsByClass();
|
||||
|
||||
public cNamedParameterList NamedParameterEntries { get; private set; } = new cNamedParameterList();
|
||||
|
||||
public cF4sdIdentityList Identities { get; set; }
|
||||
|
||||
#if DEBUG
|
||||
public string lastCaseRelationsJson = null;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
public static event EventHandler CaseChanged;
|
||||
|
||||
private cSupportCaseDataProvider()
|
||||
{
|
||||
HealthCardDataHelper = new cHealthCardDataHelper(this);
|
||||
DirectConnectionHelper = new cDirectConnectionHelper(this);
|
||||
QuickActionProtocollHelper = new cQuickActionProtocollHelper(this);
|
||||
}
|
||||
|
||||
public static async Task<cSupportCaseDataProvider> GetDataProviderForAsync(List<cF4sdApiSearchResultRelation> storedRelations, cF4sdApiSearchResultRelation selectedRelation, IRelationService relationService)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (selectedRelation == null)
|
||||
{
|
||||
Debug.Assert(true, "The selected relation must not be null here!");
|
||||
LogEntry("The selected relation must not be null here!", LogLevels.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
// get the identities of the selected relation
|
||||
var Identities = selectedRelation.Identities.Clone();
|
||||
|
||||
// get the main indentities from all identites (normally this is the user, in a special case, where a computer was searched and found without any user activities, it could be the computer)
|
||||
var MainIdentity = Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User);
|
||||
if (MainIdentity == null)
|
||||
MainIdentity = Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Computer);
|
||||
if (MainIdentity == null)
|
||||
MainIdentity = Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.VirtualSession);
|
||||
if (MainIdentity == null)
|
||||
MainIdentity = Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.MobileDevice);
|
||||
if (MainIdentity == null)
|
||||
{
|
||||
LogEntry("Couldn't find neither a user identity nor a computer identity for the selected realtion.", LogLevels.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
var firstHealthCardInformationClass = cF4sdIdentityEntry.GetFromSearchResult(selectedRelation.Type);
|
||||
// if we have the special relation computer -> user, the initial information class is changed to computer ( user -> computer )
|
||||
if (firstHealthCardInformationClass == enumFasdInformationClass.User)
|
||||
if (Identities.Any(v => (v.Class == enumFasdInformationClass.Computer)))
|
||||
firstHealthCardInformationClass = enumFasdInformationClass.Computer;
|
||||
if (Identities.Any(v => (v.Class == enumFasdInformationClass.VirtualSession)))
|
||||
firstHealthCardInformationClass = enumFasdInformationClass.VirtualSession;
|
||||
if (Identities.Any(v => (v.Class == enumFasdInformationClass.MobileDevice)))
|
||||
firstHealthCardInformationClass = enumFasdInformationClass.MobileDevice;
|
||||
|
||||
var requiredInformationClasses = new List<enumFasdInformationClass>() { firstHealthCardInformationClass };
|
||||
|
||||
// if we have an opened support case, close it immediately
|
||||
if (cSupportCaseDataProvider.CurrentProvider != null)
|
||||
{
|
||||
await cSupportCaseDataProvider.CurrentProvider.CloseCaseAsync();
|
||||
cSupportCaseDataProvider.CurrentProvider = null;
|
||||
}
|
||||
|
||||
if (!DataProviders.TryGetValue(MainIdentity.Id, out var _result))
|
||||
{
|
||||
_result = new cSupportCaseDataProvider();
|
||||
DataProviders.Add(MainIdentity.Id, _result);
|
||||
}
|
||||
|
||||
_result.NamedParameterEntries = new cNamedParameterList(_result);
|
||||
|
||||
_result.StartCase(MainIdentity.Id);
|
||||
|
||||
var supportCase = SupportCaseFactory.Get(MainIdentity, relationService, _result);
|
||||
cSupportCaseDataProvider.detailsPage.SetSupportCase(supportCase);
|
||||
cSupportCaseDataProvider.slimPage.SetSupportCase(supportCase);
|
||||
|
||||
var Status = await _result.SetViewDataAsync(requiredInformationClasses, Identities, true);
|
||||
if (!Status)
|
||||
return null;
|
||||
|
||||
CurrentProvider = _result;
|
||||
|
||||
// start the direct connection
|
||||
if (_result.DirectConnectionHelper.IsDirectConnectionActive is false)
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await _result.DirectConnectionHelper.DirectConnectionStartAsync();
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
// start the slim or detaild page
|
||||
bool shouldSkipSlimView = Identities.Any(identity => identity.Class is enumFasdInformationClass.Ticket) || cFasdCockpitConfig.Instance.Global.ShouldSkipSlimView;
|
||||
if (shouldSkipSlimView)
|
||||
cSupportCaseDataProvider.detailsPage?.Show();
|
||||
else
|
||||
cSupportCaseDataProvider.slimPage.Show();
|
||||
|
||||
return _result;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void StartCase(Guid userId)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
lock (caseIdLockObject)
|
||||
{
|
||||
CaseId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
if (cFasdCockpitConfig.IsAnalyticsActive)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var caseParameter = new cF4SDCaseParameters() { CaseId = CaseId, SessionId = cFasdCockpitConfig.SessionId, UserId = userId };
|
||||
var successfullyStartedCase = await cFasdCockpitCommunicationBase.Instance.StartCase(caseParameter);
|
||||
|
||||
if (successfullyStartedCase is false)
|
||||
{
|
||||
LogEntry($"Could not start case '{caseParameter.CaseId}' for user '{caseParameter.UserId}' in session '{caseParameter.SessionId}'.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
caseAliveTimer = new System.Timers.Timer(1000 * 60 * 1);
|
||||
caseAliveTimer.Elapsed += (async (sender, e) => { await cFasdCockpitCommunicationBase.Instance.KeepAliveCase(CaseId); });
|
||||
caseAliveTimer.Start();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TimerView.ResetTimer();
|
||||
CaseChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CloseCaseAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
Guid tempCaseId;
|
||||
lock (caseIdLockObject)
|
||||
{
|
||||
tempCaseId = CaseId;
|
||||
if (CaseId.Equals(Guid.Empty))
|
||||
return;
|
||||
|
||||
CaseId = Guid.Empty;
|
||||
}
|
||||
|
||||
|
||||
detailsPage?.EndPause();
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
tasks.Add(DirectConnectionHelper.DirectConnectionStopAsync());
|
||||
|
||||
if (cFasdCockpitConfig.IsAnalyticsActive)
|
||||
{
|
||||
var workTimes = TimerView.GetWorkTimes();
|
||||
var nettoTime = workTimes["NettoWorkingTime"];
|
||||
|
||||
var caseParameter = new cF4SDCaseStatusParameters() { CaseId = tempCaseId, StatusId = CaseStatus.Finished, ActiveTime = (double)nettoTime };
|
||||
tasks.Add(cFasdCockpitCommunicationBase.Instance.UpdateCase(caseParameter, TimerView.caseTimes));
|
||||
caseAliveTimer?.Stop();
|
||||
caseAliveTimer?.Dispose();
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
ResetCachedData();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetCachedData()
|
||||
{
|
||||
try
|
||||
{
|
||||
CaseNotes = new FlowDocument();
|
||||
NotepadDocumentUpdated?.Invoke(this, true);
|
||||
DirectConnectionHelper.Reset();
|
||||
HealthCardDataHelper.Reset();
|
||||
F4SDProtocoll.Instance.Clear();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
static bool IsFlowDocumentNotEmpty(FlowDocument doc)
|
||||
{
|
||||
if (doc == null)
|
||||
return false;
|
||||
|
||||
// Erstellt einen TextRange, der den gesamten Inhalt des Dokuments abdeckt
|
||||
TextRange textRange = new TextRange(doc.ContentStart, doc.ContentEnd);
|
||||
return !string.IsNullOrWhiteSpace(textRange.Text);
|
||||
}
|
||||
public static async Task<bool> SupportTicketActiveNoticeAsync()
|
||||
{
|
||||
// returns true, if we can continue with the search process
|
||||
// returns false, if we have to stop the search process, because the current case remains opened
|
||||
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (cSupportCaseDataProvider.CurrentProvider?.IsActive != true)
|
||||
return true;
|
||||
|
||||
Mouse.OverrideCursor = null;
|
||||
var ownerWindow = cSupportCaseDataProvider.CurrentProvider.ActiveSupportCaseWindow;
|
||||
var ButtonText = new List<string>()
|
||||
{
|
||||
cMultiLanguageSupport.GetItem("Searchbar.NewSearch.ActiveSupportCase.CloseCase"),
|
||||
cMultiLanguageSupport.GetItem("Searchbar.NewSearch.ActiveSupportCase.CancelCase"),
|
||||
cMultiLanguageSupport.GetItem("Searchbar.NewSearch.ActiveSupportCase.ContinueCase")
|
||||
};
|
||||
int ResultIndex = 1;
|
||||
var completitionPolicy = cFasdCockpitConfig.Instance.Global.TicketConfiguration.CompletitionPolicy;
|
||||
if (completitionPolicy == enumShowDocumentCaseDialog.always ||
|
||||
(completitionPolicy == enumShowDocumentCaseDialog.ifRequired &&
|
||||
(F4SDProtocoll.Instance.GetOfType<QuickActionProtocollEntry>().Count() > 0 ||
|
||||
IsFlowDocumentNotEmpty(CurrentProvider.CaseNotes))))
|
||||
{
|
||||
ResultIndex = CustomMessageBox.Show(cMultiLanguageSupport.GetItem("Searchbar.NewSearch.ActiveSupportCase"), ButtonText, "First Aid Service Desk", enumHealthCardStateLevel.Warning, Owner: ownerWindow, TopMost: true, CenterScreen: ownerWindow is Pages.SlimPage.SlimPageView, MaxWidth: 700);
|
||||
}
|
||||
switch (ResultIndex)
|
||||
{
|
||||
case 0: // close case with ticket completion
|
||||
var _res = CloseCaseWithTicket(ownerWindow);
|
||||
if (_res)
|
||||
{
|
||||
ownerWindow?.Hide();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 1: // close case immediately
|
||||
await cSupportCaseDataProvider.CurrentProvider?.CloseCaseAsync();
|
||||
ownerWindow?.Hide();
|
||||
return true;
|
||||
default: // return to current support case
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task<bool> CloseSupportCaseAsync()
|
||||
{
|
||||
MethodBase CM = null; if (DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
var doClose = await SupportTicketActiveNoticeAsync();
|
||||
|
||||
if (doClose)
|
||||
{
|
||||
if (cSearchManager.Instance?.HistoryList?.LastOrDefault()?.isSeen != true)
|
||||
{
|
||||
SearchPageView.Instance.ActivateSearchView();
|
||||
}
|
||||
}
|
||||
return doClose;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CloseCaseWithTicket(Window ownerWindow)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var closeCaseDialogResult = TicketCompletion.Show(cSupportCaseDataProvider.CurrentProvider, ownerWindow);
|
||||
|
||||
if (closeCaseDialogResult != null)
|
||||
{
|
||||
var _h = cSupportCaseDataProvider.CurrentProvider?.CloseCaseAsync();
|
||||
}
|
||||
|
||||
return closeCaseDialogResult != null;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> SetViewDataAsync(List<enumFasdInformationClass> requiredInformationClasses, cF4sdIdentityList Identities, bool isNewCase)
|
||||
{
|
||||
try
|
||||
{
|
||||
var couldGetHealthCard = HealthCardDataHelper.TryGetHealthcard(requiredInformationClasses);
|
||||
|
||||
if (!couldGetHealthCard)
|
||||
{
|
||||
LogEntry("Couldn't find a matching healthcard.", LogLevels.Error);
|
||||
CustomMessageBox.Show(cMultiLanguageSupport.GetItem("SearchBar.NoValidHealthcard"), "Load new case", enumHealthCardStateLevel.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
var requiredTables = cHealthCard.GetRequiredTables(HealthCardDataHelper.SelectedHealthCard);
|
||||
|
||||
if (cF4SDCustomDialogConfig.Instance != null)
|
||||
{
|
||||
var requiredTablesForCustomDialogs = cF4SDCustomDialogConfig.Instance.GetRequiredTables(HealthCardDataHelper.SelectedHealthCard.InformationClasses);
|
||||
foreach (var table in requiredTablesForCustomDialogs)
|
||||
{
|
||||
requiredTables.Add(table);
|
||||
}
|
||||
}
|
||||
|
||||
var isOk = await HealthCardDataHelper.GetHealthCardRawDataAsync(new cF4sdHealthCardRawDataRequest()
|
||||
{
|
||||
Identities = Identities,
|
||||
Tables = requiredTables.ToList(),
|
||||
MaxAge = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.SearchResultAge ?? 14
|
||||
});
|
||||
|
||||
if (isNewCase)
|
||||
HealthCardDataHelper.LastDataRequest = DateTime.Now;
|
||||
|
||||
if (isOk == false)
|
||||
{
|
||||
string identityString = "";
|
||||
|
||||
foreach (var identity in Identities)
|
||||
{
|
||||
identityString += "\n" + identity.Id + " (Type: " + identity.Class + ")";
|
||||
}
|
||||
|
||||
LogEntry($"Error trying to receive healthcard data for following identities: {identityString}", LogLevels.Error);
|
||||
CustomMessageBox.Show($"Error trying to receive healthcard data for following identities: {identityString}", "Data Error", enumHealthCardStateLevel.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
var slimPageData = await HealthCardDataHelper.GetSlimPageDataAsync();
|
||||
var detailsPageData = await HealthCardDataHelper.GetDetailsPageDataAsync();
|
||||
|
||||
slimPage?.SetPropertyValues(slimPageData);
|
||||
detailsPage?.SetPropertyValues(detailsPageData);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task ChangeHealthCardAsync(enumFasdInformationClass informationClass)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
await SetViewDataAsync(new List<enumFasdInformationClass>() { informationClass }, Identities, false);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task ExchangeCaseIdentitiesAsync(cF4sdApiSearchResultRelation searchResultRelation)
|
||||
{
|
||||
|
||||
#if DEBUG
|
||||
var jsonRels = JsonConvert.SerializeObject(CaseRelations);
|
||||
if (lastCaseRelationsJson != null && lastCaseRelationsJson.Equals(jsonRels) is false)
|
||||
LogEntry($"CaseRelations changed: {jsonRels}", LogLevels.Debug);
|
||||
lastCaseRelationsJson = jsonRels;
|
||||
var jsonResult = JsonConvert.SerializeObject(searchResultRelation);
|
||||
var jsonIds = JsonConvert.SerializeObject(Identities);
|
||||
#endif
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var ComputerRemoved = false;
|
||||
var ComputerAdded = false;
|
||||
List<enumFasdInformationClass> updatedInformationClasses = new List<enumFasdInformationClass>();
|
||||
foreach (var relationIdentity in searchResultRelation.Identities)
|
||||
{
|
||||
var existingIdentity = Identities.FirstOrDefault(identity => identity.Class == relationIdentity.Class);
|
||||
|
||||
if (existingIdentity != null)
|
||||
{
|
||||
if (existingIdentity.Id.Equals(relationIdentity.Id) is false)
|
||||
{
|
||||
updatedInformationClasses.Add(existingIdentity.Class);
|
||||
ComputerRemoved |= relationIdentity.Class == enumFasdInformationClass.Computer;
|
||||
ComputerAdded |= relationIdentity.Class == enumFasdInformationClass.Computer;
|
||||
}
|
||||
relationIdentity.CopyTo(existingIdentity);
|
||||
}
|
||||
else
|
||||
{
|
||||
Identities.Add(relationIdentity.CreateCopy());
|
||||
ComputerAdded |= relationIdentity.Class == enumFasdInformationClass.Computer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HealthCardDataHelper.RemoveTablesWithUpdatedIdentities(updatedInformationClasses);
|
||||
|
||||
if (ComputerRemoved)
|
||||
await CurrentProvider?.DirectConnectionHelper?.DirectConnectionStopAsync();
|
||||
|
||||
var searchResultInfoClass = cF4sdIdentityEntry.GetFromSearchResult(searchResultRelation.Type);
|
||||
await SetViewDataAsync(new List<enumFasdInformationClass>() { searchResultInfoClass }, Identities, false);
|
||||
|
||||
if (ComputerAdded)
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DirectConnectionHelper.DirectConnectionStartAsync();
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if DEBUG
|
||||
jsonRels = JsonConvert.SerializeObject(CaseRelations);
|
||||
jsonResult = JsonConvert.SerializeObject(searchResultRelation);
|
||||
jsonIds = JsonConvert.SerializeObject(Identities);
|
||||
if (lastCaseRelationsJson != null && lastCaseRelationsJson.Equals(jsonRels) is false)
|
||||
LogEntry($"CaseRelations changed: {jsonRels}", LogLevels.Debug);
|
||||
lastCaseRelationsJson = jsonRels;
|
||||
#endif
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
#region Case Notes
|
||||
|
||||
public static event EventHandler CaseNotesChanged;
|
||||
|
||||
public void SaveCaseNotes() => CaseNotesChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
72
FasdDesktopUi/Basics/UiActions/ChangeHealthCardAction.cs
Normal file
72
FasdDesktopUi/Basics/UiActions/ChangeHealthCardAction.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Pages.DetailsPage;
|
||||
using FasdDesktopUi.Pages.DetailsPage.UserControls;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cChangeHealthCardAction : cUiActionBase
|
||||
{
|
||||
public cF4sdApiSearchResultRelation ResultRelation { get; private set; } = null;
|
||||
|
||||
public cChangeHealthCardAction(cF4sdApiSearchResultRelation resultRelation)
|
||||
{
|
||||
ResultRelation = resultRelation;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (dataProvider == null)
|
||||
return false;
|
||||
if (ResultRelation == null)
|
||||
return false;
|
||||
if (!(UiLocation is DetailsPageView detailsPage))
|
||||
return false;
|
||||
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
|
||||
detailsPage.NavigationHeadingUc.ResetSelectors();
|
||||
|
||||
await dataProvider.ExchangeCaseIdentitiesAsync(ResultRelation);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Mouse.OverrideCursor = null;
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using F4SD_AdaptableIcon.Enums;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cCopyQuickActionProtocolAction : cUiActionBase
|
||||
{
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dataProvider is null)
|
||||
return false;
|
||||
|
||||
var protocolItems = F4SDProtocoll.Instance.GetAllAsDataObject(false); // dataProvider.QuickActionProtocollHelper.GetFullProtocollQuickActionResult();
|
||||
|
||||
if (protocolItems is null || string.IsNullOrWhiteSpace(protocolItems.GetText()))
|
||||
protocolItems.SetText(cMultiLanguageSupport.GetItem("QuickAction.Copy.Protocol.Empty"));
|
||||
|
||||
System.Windows.Forms.Clipboard.SetDataObject(protocolItems, true);
|
||||
|
||||
if (sender is CustomMenuItem senderElement)
|
||||
await cUtility.ChangeIconToCheckAsync(senderElement.MenuItemIcon);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
87
FasdDesktopUi/Basics/UiActions/ShowCustomDialog.cs
Normal file
87
FasdDesktopUi/Basics/UiActions/ShowCustomDialog.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Caching;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Config;
|
||||
using FasdDesktopUi.Pages.DetailsPage;
|
||||
using FasdDesktopUi.Pages.DetailsPage.ViewModels;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cShowCustomDialog : cUiActionBase
|
||||
{
|
||||
private string dialogName;
|
||||
|
||||
public cShowCustomDialog(string dialogName)
|
||||
{
|
||||
this.dialogName = dialogName;
|
||||
}
|
||||
|
||||
private List<cContainerData> GetDialogDataByName(string name, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
List<cContainerData> output = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(name) || dataProvider is null)
|
||||
return null;
|
||||
|
||||
if (cF4SDCustomDialogConfig.Instance?.CustomDialogContainers is null)
|
||||
return null;
|
||||
|
||||
if (cF4SDCustomDialogConfig.Instance.CustomDialogContainers.TryGetValue(name, out var containerConfig))
|
||||
output = dataProvider.HealthCardDataHelper.GetContainerDataFromConfig(containerConfig);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dialogData = GetDialogDataByName(dialogName, dataProvider);
|
||||
|
||||
if (dialogData is null)
|
||||
return false;
|
||||
|
||||
var dialogElement = new CustomDialog() { ContainerData = dialogData.FirstOrDefault(), HasYesNoButtons = true, HasYesNoText = true };
|
||||
|
||||
if (UiLocation is Decorator locationElement)
|
||||
{
|
||||
dialogElement.ParentElement = locationElement;
|
||||
locationElement.Child = dialogElement;
|
||||
}
|
||||
|
||||
if (cSupportCaseDataProvider.detailsPage?.QuickActionDecorator?.Child is null)
|
||||
return false;
|
||||
|
||||
cSupportCaseDataProvider.detailsPage.QuickActionDecorator.Child = dialogElement;
|
||||
cSupportCaseDataProvider.detailsPage.QuickActionDecorator.Visibility = Visibility.Visible;
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
538
FasdDesktopUi/Basics/UiActions/ShowDetailedDataAction.cs
Normal file
538
FasdDesktopUi/Basics/UiActions/ShowDetailedDataAction.cs
Normal file
@@ -0,0 +1,538 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cShowDetailedDataAction : cUiActionBase
|
||||
{
|
||||
private static readonly Dictionary<cF4sdIdentityList, Dictionary<string, cF4SDHealthCardRawData.cHealthCardDetailsTable>> CachedDetails = new Dictionary<cF4sdIdentityList, Dictionary<string, cF4SDHealthCardRawData.cHealthCardDetailsTable>>();
|
||||
|
||||
private cSupportCaseDataProvider DataProvider;
|
||||
|
||||
private readonly cHealthCardStateBase StateDefinition;
|
||||
|
||||
private int DayIndex { get; set; }
|
||||
|
||||
private string DetailsTitle { get; set; }
|
||||
|
||||
private string Recommendation { get; set; }
|
||||
|
||||
private cHealthCardDetailsTable ValuedDetailsData = null;
|
||||
|
||||
public cShowDetailedDataAction(cHealthCardStateBase StateDefinition, int DayIndex = 0, cHealthCardDetailsTable ValuedDetailsData = null)
|
||||
{
|
||||
this.StateDefinition = StateDefinition;
|
||||
this.DayIndex = DayIndex;
|
||||
this.DetailsTitle = StateDefinition.Names.GetValue();
|
||||
this.Recommendation = StateDefinition.Descriptions.GetValue();
|
||||
if (this.Recommendation == String.Empty)
|
||||
this.Recommendation = null;
|
||||
this.ValuedDetailsData = ValuedDetailsData;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is Decorator decorator))
|
||||
return false;
|
||||
|
||||
DataProvider = dataProvider;
|
||||
DataProvider.HealthCardDataHelper.DataRefreshed += (s, e) => CachedDetails.Clear();
|
||||
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
|
||||
if (StateDefinition.Details is cHealthCardDetailsValued)
|
||||
{
|
||||
if (ValuedDetailsData == null)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!await LoadDetailsDataAsync())
|
||||
return false;
|
||||
}
|
||||
|
||||
cDetailedDataModel detailedData = null;
|
||||
cDetailedChartModel detailedChartData = null;
|
||||
cChartModel chartData = null;
|
||||
if (StateDefinition.Details is cHealthCardDetailsValued)
|
||||
{
|
||||
detailedData = GetValuedDataModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
detailedData = GetDetailedData();
|
||||
detailedChartData = GetDetailedChartData();
|
||||
chartData = GetChartData();
|
||||
}
|
||||
cRecommendationDataModel recommendationDataModel = Recommendation != null ? new cRecommendationDataModel() { Category = DetailsTitle, Recommendation = Recommendation } : null;
|
||||
|
||||
if (decorator.Child is DataCanvas existingDataCanvas)
|
||||
{
|
||||
var tempDataCanvasData = new cDataCanvasDataModel() { QuickActionStatusMonitorData = null, DetailedData = detailedData, DetailedChartData = detailedChartData, ChartData = chartData, RecommendationData = recommendationDataModel };
|
||||
if (!(StateDefinition.Details is cHealthCardDetailsValued))
|
||||
{
|
||||
tempDataCanvasData.GetDetailedDataAsync = GetRefreshedDetailedDataAsync;
|
||||
tempDataCanvasData.GetChartDataAsync = GetRefreshedChartDataAsync;
|
||||
tempDataCanvasData.GetDatailedChartDataAsync = GetRefreshedDetailsChartDataAsync;
|
||||
}
|
||||
|
||||
existingDataCanvas.DataCanvasData = tempDataCanvasData;
|
||||
existingDataCanvas.IsDetailedLayout = isDetailedLayout;
|
||||
existingDataCanvas.DataProvider = DataProvider;
|
||||
existingDataCanvas.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataCanvas dataCanvas = new DataCanvas() { DataCanvasData = new cDataCanvasDataModel() { DetailedData = detailedData, DetailedChartData = detailedChartData, ChartData = chartData, RecommendationData = recommendationDataModel }, IsDetailedLayout = isDetailedLayout, DataProvider = DataProvider };
|
||||
if (!(StateDefinition.Details is cHealthCardDetailsValued))
|
||||
{
|
||||
dataCanvas.DataCanvasData.GetDetailedDataAsync = GetRefreshedDetailedDataAsync;
|
||||
dataCanvas.DataCanvasData.GetChartDataAsync = GetRefreshedChartDataAsync;
|
||||
dataCanvas.DataCanvasData.GetDatailedChartDataAsync = GetRefreshedDetailsChartDataAsync;
|
||||
}
|
||||
|
||||
decorator.Child = dataCanvas;
|
||||
}
|
||||
|
||||
decorator.Visibility = Visibility.Visible;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Mouse.OverrideCursor = null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> LoadDetailsDataAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (StateDefinition == null || StateDefinition.Details == null)
|
||||
return false;
|
||||
|
||||
if (!(StateDefinition.Details is cHealthCardDetails _details) || _details.Table == null)
|
||||
return false;
|
||||
|
||||
if (CachedDetails.TryGetValue(DataProvider.Identities, out var cachedDetailsForIdentities))
|
||||
{
|
||||
if (cachedDetailsForIdentities.TryGetValue(_details.Table, out _))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
cachedDetailsForIdentities = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardDetailsTable>();
|
||||
|
||||
cF4sdHealthCardRawDataRequest requestData = new cF4sdHealthCardRawDataRequest()
|
||||
{
|
||||
Identities = DataProvider.Identities,
|
||||
MaxAge = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge,
|
||||
Tables = StateDefinition.GetRequiredTables()
|
||||
};
|
||||
|
||||
var detailsData = await cFasdCockpitCommunicationBase.Instance.GetDetailsData(requestData);
|
||||
|
||||
if (detailsData.Any(data => data.Name == _details.Table) || detailsData.Any(data => data.Name == StateDefinition.DetailedChartDetails?.ValueTable) || detailsData.Any(data => data.Name == StateDefinition.ChartDetails?.ValueTable))
|
||||
{
|
||||
if (StateDefinition.Details != null && detailsData.Any(data => data.Name == _details.Table))
|
||||
{
|
||||
if (!cachedDetailsForIdentities.ContainsKey(_details.Table))
|
||||
cachedDetailsForIdentities.Add(_details.Table, detailsData.First(data => data.Name == _details.Table));
|
||||
if (!CachedDetails.ContainsKey(DataProvider.Identities))
|
||||
CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities);
|
||||
}
|
||||
if (StateDefinition.DetailedChartDetails != null && detailsData.Any(data => data.Name == StateDefinition.DetailedChartDetails.ValueTable))
|
||||
{
|
||||
if (!cachedDetailsForIdentities.ContainsKey(StateDefinition.DetailedChartDetails.ValueTable))
|
||||
cachedDetailsForIdentities.Add(StateDefinition.DetailedChartDetails.ValueTable, detailsData.First(data => data.Name == StateDefinition.DetailedChartDetails.ValueTable));
|
||||
if (!CachedDetails.ContainsKey(DataProvider.Identities))
|
||||
CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities);
|
||||
}
|
||||
if (StateDefinition.ChartDetails != null && detailsData.Any(data => data.Name == StateDefinition.ChartDetails.ValueTable))
|
||||
{
|
||||
if (!cachedDetailsForIdentities.ContainsKey(StateDefinition.ChartDetails.ValueTable))
|
||||
cachedDetailsForIdentities.Add(StateDefinition.ChartDetails.ValueTable, detailsData.First(data => data.Name == StateDefinition.ChartDetails.ValueTable));
|
||||
if (!CachedDetails.ContainsKey(DataProvider.Identities))
|
||||
CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateProcessorStateDefinition()
|
||||
{
|
||||
// correct an error in older definitions of table agnt-computer-event-details-processorUsage
|
||||
try
|
||||
{
|
||||
var oldFromColumn = StateDefinition.Details.FirstOrDefault(column => column.Name == "From");
|
||||
var oldToColumn = StateDefinition.Details.FirstOrDefault(column => column.Name == "To");
|
||||
|
||||
if (oldFromColumn is null || oldToColumn is null)
|
||||
return;
|
||||
|
||||
if (oldFromColumn.Column != "Duration" || oldToColumn.Column != "time")
|
||||
return;
|
||||
|
||||
oldFromColumn.Column = "time";
|
||||
oldToColumn.Column = "Duration.add";
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessDetailValue(string processintType, ref object rawValue, DateTime timeColumnValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (rawValue is Int64 milliSec)
|
||||
{
|
||||
switch (processintType)
|
||||
{
|
||||
case "add":
|
||||
rawValue = timeColumnValue.AddMilliseconds(milliSec);
|
||||
break;
|
||||
case "sub":
|
||||
rawValue = timeColumnValue.AddMilliseconds(-milliSec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private cDetailedDataModel GetValuedDataModel()
|
||||
{
|
||||
if (!(StateDefinition.Details is cHealthCardDetailsValued _details) || ValuedDetailsData == null)
|
||||
return null;
|
||||
|
||||
if (ValuedDetailsData.Columns.Count > 1)
|
||||
return null;
|
||||
|
||||
var _rowHeadings = _details.Select(v => v.Names.GetValue() as object).ToList();
|
||||
cDetailedDataModel output = new cDetailedDataModel()
|
||||
{
|
||||
Heading = StateDefinition.Names.GetValue(),
|
||||
FullDetailedData = new List<object>(),
|
||||
HasColumnHeaders = _rowHeadings.Count > 1
|
||||
};
|
||||
|
||||
if (_rowHeadings.Count > 1)
|
||||
output.FullDetailedData.Add(_rowHeadings);
|
||||
|
||||
var _data = ValuedDetailsData.Values[0];
|
||||
foreach (var _row in _data)
|
||||
output.FullDetailedData.Add(new List<object>() { _row[0] });
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private cDetailedDataModel GetDetailedData()
|
||||
{
|
||||
try
|
||||
{
|
||||
const string timeColumnName = "time";
|
||||
cDetailedDataModel output = new cDetailedDataModel() { FullDetailedData = new List<object>() };
|
||||
|
||||
string dateAddtionFormat = cMultiLanguageSupport.GetItem("DetailsPage.History.Details");
|
||||
string dateAddition = string.Format(dateAddtionFormat, DateTime.Today.AddDays(-DayIndex).ToString("d", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)));
|
||||
string detailedDataHeading = "Details - " + DetailsTitle + dateAddition;
|
||||
output.Heading = detailedDataHeading;
|
||||
|
||||
if (!(StateDefinition.Details is cHealthCardDetails _details) || _details.Table == null)
|
||||
return null;
|
||||
|
||||
// correct an error in older definitions of table agnt-computer-event-details-processorUsage
|
||||
if (_details.Table == "agnt-computer-event-details-processorUsage")
|
||||
UpdateProcessorStateDefinition();
|
||||
|
||||
var headerValues = StateDefinition.Details.Select(value => value.Names.GetValue());
|
||||
output.FullDetailedData.Add(headerValues.ToList<object>());
|
||||
|
||||
var detailsData = CachedDetails[DataProvider.Identities][_details.Table];
|
||||
|
||||
if (!detailsData.Values.TryGetValue(DayIndex, out var details))
|
||||
return output;
|
||||
|
||||
int columnCount = StateDefinition.Details.Count;
|
||||
List<int> rawColumnIndexes = new List<int>(columnCount);
|
||||
List<RawValueType> displayTypes = new List<RawValueType>(columnCount);
|
||||
List<string> valueProcessings = new List<string>(columnCount);
|
||||
int timeColumnIndex = detailsData.Columns.IndexOf(timeColumnName);
|
||||
int filterColumnIndex = detailsData.Columns.IndexOf(StateDefinition.Details?.Filter?.FilterColumn);
|
||||
|
||||
foreach (var columnDefinition in StateDefinition.Details)
|
||||
{
|
||||
var splitColumnName = columnDefinition.Column.Split('.');
|
||||
|
||||
var rawColumnIndex = detailsData.Columns.IndexOf(splitColumnName[0]);
|
||||
var displayType = columnDefinition.DisplayType;
|
||||
var valueProcessing = splitColumnName.Length > 1 ? splitColumnName[1] : null;
|
||||
|
||||
rawColumnIndexes.Add(rawColumnIndex);
|
||||
displayTypes.Add(cUtility.GetRawValueType(displayType));
|
||||
valueProcessings.Add(valueProcessing);
|
||||
}
|
||||
|
||||
foreach (var detailsRow in details)
|
||||
{
|
||||
var displayValuesOfRow = new List<object>(columnCount);
|
||||
|
||||
var displayTypeEnumerator = displayTypes.GetEnumerator();
|
||||
var valueProcessingsEnumerator = valueProcessings.GetEnumerator();
|
||||
bool shouldHideRow = false;
|
||||
|
||||
if (StateDefinition.Details.Filter != null && !rawColumnIndexes.Contains(filterColumnIndex))
|
||||
{
|
||||
bool columnValueMatchesFilterValue = StateDefinition.Details.Filter.FilterValues.Contains(detailsRow[filterColumnIndex]);
|
||||
if (!columnValueMatchesFilterValue)
|
||||
shouldHideRow = true;
|
||||
}
|
||||
|
||||
IRawValueFormatter rawValueFormatter = new RawValueFormatter();
|
||||
rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
||||
|
||||
foreach (var index in rawColumnIndexes)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (shouldHideRow)
|
||||
continue;
|
||||
|
||||
if (detailsRow.Length < index || !displayTypeEnumerator.MoveNext() || !valueProcessingsEnumerator.MoveNext())
|
||||
continue;
|
||||
|
||||
var rawDetailValue = detailsRow[index];
|
||||
|
||||
if (index == filterColumnIndex
|
||||
&& !StateDefinition.Details.Filter.FilterValues.Contains(rawDetailValue))
|
||||
{
|
||||
shouldHideRow = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (valueProcessingsEnumerator.Current != null)
|
||||
if (detailsRow[timeColumnIndex] is DateTime timeColumnValue)
|
||||
ProcessDetailValue(valueProcessingsEnumerator.Current, ref rawDetailValue, timeColumnValue);
|
||||
|
||||
var displayValue = rawValueFormatter.GetDisplayValue(rawDetailValue, displayTypeEnumerator.Current);
|
||||
displayValuesOfRow.Add(displayValue);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldHideRow)
|
||||
continue;
|
||||
|
||||
output.FullDetailedData.Add(displayValuesOfRow);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private cDetailedChartModel GetDetailedChartData()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (StateDefinition?.DetailedChartDetails is null)
|
||||
return null;
|
||||
|
||||
var detailsDataTable = CachedDetails[DataProvider.Identities][StateDefinition.DetailedChartDetails.ValueTable];
|
||||
|
||||
int valueIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.ValueColumn);
|
||||
int timeIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.TimeColumn);
|
||||
int durationIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.DurationColumn);
|
||||
string title = StateDefinition.Names.GetValue();
|
||||
bool isThresholdActive = StateDefinition is cHealthCardStateLevel;
|
||||
|
||||
var output = new cDetailedChartModel()
|
||||
{
|
||||
Data = detailsDataTable.Values[DayIndex],
|
||||
ValueIndex = valueIndex,
|
||||
TimeIndex = timeIndex,
|
||||
DurationIndex = durationIndex,
|
||||
ChartTitle = title,
|
||||
IsThresholdActive = isThresholdActive,
|
||||
};
|
||||
|
||||
if (StateDefinition is cHealthCardStateLevel stateLevelDefinition)
|
||||
{
|
||||
output.WarningThreshold = stateLevelDefinition.Warning;
|
||||
output.ErrorThreshold = stateLevelDefinition.Error;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private cChartModel GetChartData()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (StateDefinition?.ChartDetails is null)
|
||||
return null;
|
||||
|
||||
var detailsDataTable = CachedDetails[DataProvider.Identities][StateDefinition.ChartDetails.ValueTable];
|
||||
|
||||
int valueIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.ValueColumn);
|
||||
int timeIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.TimeColumn);
|
||||
int durationIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.DurationColumn);
|
||||
string title = StateDefinition.Names.GetValue();
|
||||
bool isThresholdActive = false;
|
||||
double warningThreshold = 0;
|
||||
double errorThreshold = 0;
|
||||
bool isDirectionUp = true;
|
||||
if (StateDefinition is cHealthCardStateLevel stateLevel)
|
||||
{
|
||||
isThresholdActive = true;
|
||||
warningThreshold = stateLevel.Warning;
|
||||
errorThreshold = stateLevel.Error;
|
||||
isDirectionUp = stateLevel.IsDirectionUp;
|
||||
}
|
||||
int stepLengthScale = StateDefinition.ChartDetails.StepLengthScale;
|
||||
int stepLengthLine = StateDefinition.ChartDetails.StepLengthLine;
|
||||
int maxValue = StateDefinition.ChartDetails.MaxValue;
|
||||
int minValue = StateDefinition.ChartDetails.MinValue;
|
||||
string unitFormat = StateDefinition.UnitFormat;
|
||||
|
||||
|
||||
var output = new cChartModel()
|
||||
{
|
||||
Data = detailsDataTable.Values[DayIndex],
|
||||
ValueIndex = valueIndex,
|
||||
TimeIndex = timeIndex,
|
||||
DurationIndex = durationIndex,
|
||||
ChartTitle = title,
|
||||
WarningThreshold = warningThreshold,
|
||||
ErrorThreshold = errorThreshold,
|
||||
IsThresholdActive = isThresholdActive,
|
||||
IsDirectionUp = isDirectionUp,
|
||||
StepLengthScale = stepLengthScale,
|
||||
StepLengthLine = stepLengthLine,
|
||||
MaxValue = maxValue,
|
||||
MinValue = minValue,
|
||||
UnitFormat = unitFormat,
|
||||
|
||||
};
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<cDetailedDataModel> GetRefreshedDetailedDataAsync()
|
||||
{
|
||||
cDetailedDataModel output = null;
|
||||
try
|
||||
{
|
||||
CachedDetails.Remove(DataProvider.Identities);
|
||||
|
||||
if (await LoadDetailsDataAsync())
|
||||
return GetDetailedData();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private async Task<cDetailedChartModel> GetRefreshedDetailsChartDataAsync()
|
||||
{
|
||||
cDetailedChartModel output = null;
|
||||
|
||||
try
|
||||
{
|
||||
CachedDetails.Remove(DataProvider.Identities);
|
||||
|
||||
if (await LoadDetailsDataAsync())
|
||||
return GetDetailedChartData();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private async Task<cChartModel> GetRefreshedChartDataAsync()
|
||||
{
|
||||
cChartModel output = null;
|
||||
|
||||
try
|
||||
{
|
||||
CachedDetails.Remove(DataProvider.Identities);
|
||||
|
||||
if (await LoadDetailsDataAsync())
|
||||
return GetChartData();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Pages.DetailsPage;
|
||||
using FasdDesktopUi.Pages.DetailsPage.UserControls;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cShowHeadingSelectionMenuAction : cUiActionBase
|
||||
{
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is DetailsPageView detailsPage))
|
||||
return false;
|
||||
|
||||
detailsPage.IsBlurred = true;
|
||||
Panel.SetZIndex(detailsPage.NavigationHeadingUc, 4);
|
||||
detailsPage.NavigationHeadingUc.ClearValue(DetailsPageView.EffectProperty);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
FasdDesktopUi/Basics/UiActions/ShowRecommendationAction.cs
Normal file
66
FasdDesktopUi/Basics/UiActions/ShowRecommendationAction.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using C4IT.Logging;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cShowRecommendationAction : cUiActionBase
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Recommendation { get; set; }
|
||||
|
||||
public cShowRecommendationAction(string Title, string Recommendation)
|
||||
{
|
||||
this.Title = Title;
|
||||
this.Recommendation = Recommendation;
|
||||
}
|
||||
|
||||
public async override Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is Decorator decorator))
|
||||
return false;
|
||||
|
||||
cRecommendationDataModel recommendationDataModel = Recommendation != null ? new cRecommendationDataModel() { Category = Title, Recommendation = Recommendation } : null;
|
||||
|
||||
if (decorator.Child is DataCanvas existingDataCanvas)
|
||||
{
|
||||
var tempDataCanvasData = new cDataCanvasDataModel() { QuickActionStatusMonitorData = null, DetailedData = null, RecommendationData = recommendationDataModel };
|
||||
existingDataCanvas.DataCanvasData = tempDataCanvasData;
|
||||
existingDataCanvas.IsDetailedLayout = isDetailedLayout;
|
||||
existingDataCanvas.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataCanvas dataCanvas = new DataCanvas() { DataCanvasData = new cDataCanvasDataModel() { DetailedData = null, RecommendationData = recommendationDataModel }, IsDetailedLayout = isDetailedLayout };
|
||||
decorator.Child = dataCanvas;
|
||||
}
|
||||
|
||||
decorator.Visibility = Visibility.Visible;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
FasdDesktopUi/Basics/UiActions/SubMenuAction.cs
Normal file
54
FasdDesktopUi/Basics/UiActions/SubMenuAction.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using C4IT.Logging;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cSubMenuAction : cUiActionBase
|
||||
{
|
||||
public bool UseTempData { get; private set; }
|
||||
public List<cMenuDataBase> SubMenuData { get; set; }
|
||||
|
||||
public cSubMenuAction(bool UseTempData)
|
||||
{
|
||||
this.UseTempData = UseTempData;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is QuickActionSelector quickActionSelector))
|
||||
return false;
|
||||
|
||||
quickActionSelector.Visibility = Visibility.Visible;
|
||||
quickActionSelector.TempQuickActionSelectorHeading = UseTempData ? quickActionSelector.QuickActionSelectorHeading : null;
|
||||
quickActionSelector.TempQuickActionList = UseTempData ? quickActionSelector.QuickActionList : null;
|
||||
|
||||
quickActionSelector.QuickActionSelectorHeading = Name;
|
||||
quickActionSelector.QuickActionList = SubMenuData;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
FasdDesktopUi/Basics/UiActions/UiActionBase.cs
Normal file
64
FasdDesktopUi/Basics/UiActions/UiActionBase.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using C4IT.FASD.Base;
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public abstract class cUiActionBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string AlternativeDescription { get; set; }
|
||||
public enumActionDisplayType DisplayType { get; set; }
|
||||
|
||||
public static cUiActionBase GetUiAction(cFasdQuickAction quickAction)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (quickAction is cF4sdQuickActionLocalWebRequest webRequestQuickAction)
|
||||
return new cUiLocalWebRequestQuickAction(webRequestQuickAction);
|
||||
else if (quickAction is cFasdQuickActionLocal localQuickAction)
|
||||
return new cUiLocalQuickAction(localQuickAction);
|
||||
else if (quickAction is cF4sdQuickActionRemote remoteQuickAction)
|
||||
return new cUiRemoteQuickAction(remoteQuickAction);
|
||||
else if (quickAction is cF4sdQuickActionChained chainQuickAction)
|
||||
return new cUiChainQuickAction(chainQuickAction);
|
||||
else if (quickAction is cF4sdQuickActionDemo QuickActionDemo)
|
||||
return new cUiDemoQuickAction(QuickActionDemo);
|
||||
else if (quickAction is cF4sdQuickActionServer serverQuickAction)
|
||||
return new cUiServerQuickAction(serverQuickAction);
|
||||
else
|
||||
return new cUiDummyQuickAction(quickAction);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider);
|
||||
|
||||
public delegate void UiActionEventHandlerDelegate(object sender, UiActionEventArgs args);
|
||||
|
||||
public static readonly RoutedEvent UiActionClickedEvent = EventManager.RegisterRoutedEvent("UiActionClicked", RoutingStrategy.Bubble, typeof(UiActionEventHandlerDelegate), typeof(UIElement));
|
||||
|
||||
public static void RaiseEvent(cUiActionBase uiAction, UIElement uiElement, object sender)
|
||||
{
|
||||
uiElement.RaiseEvent(new UiActionEventArgs(UiActionClickedEvent, sender) { UiAction = uiAction });
|
||||
}
|
||||
}
|
||||
|
||||
public class UiActionEventArgs : RoutedEventArgs
|
||||
{
|
||||
public cUiActionBase UiAction { get; set; }
|
||||
|
||||
public UiActionEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
207
FasdDesktopUi/Basics/UiActions/UiChainQuickAction.cs
Normal file
207
FasdDesktopUi/Basics/UiActions/UiChainQuickAction.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.MultiLanguage;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiChainQuickAction : cUiQuickAction
|
||||
{
|
||||
private readonly List<cFasdQuickAction> chainedQuickActionConfigs = new List<cFasdQuickAction>();
|
||||
|
||||
public int QuickActionCount { get => chainedQuickActionConfigs?.Count ?? 0; }
|
||||
|
||||
public cF4sdQuickActionChained ChainedQuickAction { get; set; }
|
||||
|
||||
public cUiChainQuickAction(cF4sdQuickActionChained quickAction) : base(quickAction)
|
||||
{
|
||||
ChainedQuickAction = quickAction;
|
||||
|
||||
foreach (var quickActionName in quickAction.QuickActionNames)
|
||||
{
|
||||
if ((cF4SDCockpitXmlConfig.Instance?.QuickActionConfig?.F4SDQuickActions.QuickActions.TryGetValue(quickActionName, out var chainedQuickAction) ?? false))
|
||||
chainedQuickActionConfigs.Add(chainedQuickAction);
|
||||
else
|
||||
LogEntry($"Couldn't find Quick Action with name '{quickActionName}'", C4IT.Logging.LogLevels.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
public async override Task<cQuickActionStatusMonitorModel> GetQuickActionStatusMonitorDataAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var quickActionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>();
|
||||
|
||||
bool requiresUserPermission = false;
|
||||
|
||||
foreach (var quickActionConfig in chainedQuickActionConfigs)
|
||||
{
|
||||
var tempStep = new cQuickActionStatusMonitorModel.cQuickActionStep(quickActionConfig.Names.GetValue(), quickActionConfig.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main);
|
||||
|
||||
var uiAction = cUiActionBase.GetUiAction(quickActionConfig);
|
||||
if (uiAction is cUiQuickAction uiQuickAction)
|
||||
{
|
||||
var statusMonitorData = await uiQuickAction.GetQuickActionStatusMonitorDataAsync();
|
||||
tempStep.SubSteps = statusMonitorData.ActionSteps;
|
||||
|
||||
requiresUserPermission = requiresUserPermission || statusMonitorData.RequiresUserPermission;
|
||||
}
|
||||
|
||||
quickActionSteps.Add(tempStep);
|
||||
|
||||
}
|
||||
|
||||
var output = new cQuickActionStatusMonitorModel()
|
||||
{
|
||||
ActionName = ChainedQuickAction.Names.GetValue(),
|
||||
QuickActionDefinition = ChainedQuickAction,
|
||||
ActionSteps = quickActionSteps,
|
||||
RequiresUserPermission = requiresUserPermission,
|
||||
RunQuickAction = ProcessActionAsync
|
||||
};
|
||||
|
||||
if (chainedQuickActionConfigs.Any(config => config.AdjustableParameters?.Count > 0))
|
||||
output.QuickActionParameters = new Dictionary<string, cAdjustableParameter>();
|
||||
|
||||
foreach (var quickActionConfig in chainedQuickActionConfigs)
|
||||
{
|
||||
if (quickActionConfig.AdjustableParameters is null)
|
||||
continue;
|
||||
|
||||
foreach (var quickActionParam in quickActionConfig.AdjustableParameters)
|
||||
{
|
||||
if (output.QuickActionParameters is null || output.QuickActionParameters.ContainsKey(quickActionParam.Key))
|
||||
continue;
|
||||
|
||||
output.QuickActionParameters.Add(quickActionParam.Key, quickActionParam.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
|
||||
var detailedData = new cDetailedDataModel() { Heading = cMultiLanguageSupport.GetItem("DetailsPage.History") };
|
||||
|
||||
//Get QuickAciton Data
|
||||
detailedData.FullDetailedData = new List<object>() { new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } };
|
||||
if (dataProvider != null)
|
||||
{
|
||||
var quickActionHistory = await dataProvider.QuickActionProtocollHelper.GetQuickActionHistoryAsync(ChainedQuickAction.Name);
|
||||
foreach (var historyLine in quickActionHistory)
|
||||
{
|
||||
detailedData.FullDetailedData.Add(historyLine);
|
||||
}
|
||||
}
|
||||
|
||||
//Get Process Steps of Action
|
||||
var quickActionData = await GetQuickActionStatusMonitorDataAsync();
|
||||
|
||||
//Get Recommendation
|
||||
cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null;
|
||||
|
||||
return new cDataCanvasDataModel() { DetailedData = detailedData, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData };
|
||||
}
|
||||
|
||||
private void CancelRunningActionSteps()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var actionStep in StatusMonitor.QuickActionData.ActionSteps)
|
||||
{
|
||||
if (actionStep.Status is enumQuickActionRevisionStatus.inProgress)
|
||||
actionStep.Status = enumQuickActionRevisionStatus.canceled;
|
||||
|
||||
foreach (var subSteps in actionStep.SubSteps)
|
||||
{
|
||||
if (subSteps.Status is enumQuickActionRevisionStatus.inProgress)
|
||||
subSteps.Status = enumQuickActionRevisionStatus.canceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (chainedQuickActionConfigs?.Count <= 0)
|
||||
return null;
|
||||
|
||||
foreach (var quickActionConfig in chainedQuickActionConfigs)
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
var uiAction = GetUiAction(quickActionConfig);
|
||||
|
||||
if (uiAction is null)
|
||||
continue;
|
||||
|
||||
if (!(uiAction is cUiQuickAction uiQuickAction))
|
||||
continue;
|
||||
|
||||
uiQuickAction.DataProvider = DataProvider;
|
||||
uiQuickAction.StatusMonitor = StatusMonitor;
|
||||
|
||||
foreach (var child in StatusMonitor.CompletionStatusPanel.Children)
|
||||
{
|
||||
if (child is System.Windows.Controls.StackPanel childStackPanel)
|
||||
childStackPanel.Visibility = System.Windows.Visibility.Collapsed;
|
||||
|
||||
if (child is System.Windows.FrameworkElement childFrameworkElement)
|
||||
if (childFrameworkElement.Tag?.Equals(quickActionConfig.Name) ?? false)
|
||||
childFrameworkElement.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
|
||||
var result = await uiQuickAction.ProcessActionAsync(token, ParameterDictionary);
|
||||
|
||||
if (result != null && result[0].Equals(cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError")))
|
||||
{
|
||||
CancelRunningActionSteps();
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
}
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
CancelRunningActionSteps();
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
FasdDesktopUi/Basics/UiActions/UiCopyAction.cs
Normal file
70
FasdDesktopUi/Basics/UiActions/UiCopyAction.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using C4IT.FASD.Base;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiCopyAction : cUiActionBase
|
||||
{
|
||||
public cCopyTemplate CopyTemplate { get; set; }
|
||||
|
||||
public cUiCopyAction(cCopyTemplate copyTemplate)
|
||||
{
|
||||
CopyTemplate = copyTemplate;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (dataProvider == null || dataProvider.NamedParameterEntries.Count == 0 || CopyTemplate == null)
|
||||
return false;
|
||||
|
||||
var ClData = new DataObject();
|
||||
foreach (var Entry in CopyTemplate.CopyContentList.Values)
|
||||
SetCopyContent(ClData, Entry, dataProvider);
|
||||
|
||||
System.Windows.Forms.Clipboard.SetDataObject(ClData, true);
|
||||
|
||||
if (sender is CustomMenuItem senderElement)
|
||||
await cUtility.ChangeIconToCheckAsync(senderElement.MenuItemIcon);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetCopyContent(DataObject ClData, cCopyContent Content, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
var clipboardText = Content.Content;
|
||||
|
||||
clipboardText = dataProvider.HealthCardDataHelper.ReplaceNamedParameters(clipboardText, Content.Format == enumCopyContentFormat.HTML);
|
||||
|
||||
var textFormat = TextDataFormat.UnicodeText;
|
||||
if (Content.Format == enumCopyContentFormat.HTML)
|
||||
{
|
||||
clipboardText = cUtility.GetHtmlFrame(clipboardText);
|
||||
textFormat = TextDataFormat.Html;
|
||||
}
|
||||
|
||||
ClData.SetText(clipboardText, textFormat);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
179
FasdDesktopUi/Basics/UiActions/UiCopyDetailsTableContent.cs
Normal file
179
FasdDesktopUi/Basics/UiActions/UiCopyDetailsTableContent.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using C4IT.Logging;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using C4IT.MultiLanguage;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
abstract public class cUiCopyDetailsTableContentBase : cUiActionBase
|
||||
{
|
||||
private cDetailedDataModel Data;
|
||||
|
||||
public cUiCopyDetailsTableContentBase(cDetailedDataModel Data)
|
||||
{
|
||||
this.Data = Data;
|
||||
}
|
||||
|
||||
internal String getContentString(bool csv)
|
||||
{
|
||||
try
|
||||
{
|
||||
string retVal = String.Empty;
|
||||
char separator = csv ? ';' : '\t';
|
||||
|
||||
if (!Data.HasColumnHeaders)
|
||||
retVal = Data.Heading;
|
||||
|
||||
foreach (var row in Data.FullDetailedData)
|
||||
{
|
||||
if (!(row is List<object> _lst))
|
||||
continue;
|
||||
|
||||
var line = String.Empty;
|
||||
foreach (var cell in _lst)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(line))
|
||||
line += separator;
|
||||
|
||||
var item = cell.ToString();
|
||||
if (csv && item.Contains(separator.ToString()))
|
||||
{
|
||||
item = item.Replace("\"", "\"\"");
|
||||
item = "\"" + item + "\"";
|
||||
}
|
||||
|
||||
line += item;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(line))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(retVal))
|
||||
retVal += "\n";
|
||||
retVal += line;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class cUiCopyDetailsTableContent : cUiCopyDetailsTableContentBase
|
||||
{
|
||||
public cUiCopyDetailsTableContent (cDetailedDataModel Data) : base(Data)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, System.Windows.UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var strCipboard = getContentString(false);
|
||||
if (string.IsNullOrEmpty(strCipboard))
|
||||
return true;
|
||||
|
||||
strCipboard += "\n";
|
||||
System.Windows.Forms.Clipboard.SetText(strCipboard);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cUiSaveDetailsTableContent : cUiCopyDetailsTableContentBase
|
||||
{
|
||||
public cUiSaveDetailsTableContent(cDetailedDataModel Data) : base(Data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out string pszPath);
|
||||
|
||||
public static readonly Guid DownloadsFolderID = new Guid("374DE290-123F-4565-9164-39C4925E467B");
|
||||
|
||||
public static string GetSpecialWindowsFolder(Guid FolderID)
|
||||
{
|
||||
try
|
||||
{
|
||||
string _folder;
|
||||
if (SHGetKnownFolderPath(FolderID, 0, IntPtr.Zero, out _folder) == 0)
|
||||
return _folder;
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, System.Windows.UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var strContent = getContentString(false);
|
||||
|
||||
if (string.IsNullOrEmpty(strContent))
|
||||
return true;
|
||||
|
||||
var LastDirectory = cFasdCockpitConfig.Instance.LastDownloadPath;
|
||||
if (string.IsNullOrEmpty(LastDirectory))
|
||||
LastDirectory = GetSpecialWindowsFolder(DownloadsFolderID);
|
||||
|
||||
SaveFileDialog saveFileDialog = new SaveFileDialog()
|
||||
{
|
||||
Filter = "Tab-separated file (*.txt)|*.txt|Comma-serarated file (*.csv)|*.csv",
|
||||
Title = cMultiLanguageSupport.GetItem("DetailsPage.DetailTable.ContentDownload"),
|
||||
InitialDirectory = LastDirectory
|
||||
};
|
||||
|
||||
if (saveFileDialog.ShowDialog() != true)
|
||||
return true;
|
||||
|
||||
if (Path.GetExtension(saveFileDialog.FileName).ToLower() == ".csv")
|
||||
strContent = getContentString(true);
|
||||
|
||||
File.WriteAllText(saveFileDialog.FileName, strContent, Encoding.UTF8);
|
||||
|
||||
cFasdCockpitConfig.Instance.LastDownloadPath = Path.GetDirectoryName(saveFileDialog.FileName);
|
||||
cFasdCockpitConfig.Instance.Save("LastDownloadPath");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
147
FasdDesktopUi/Basics/UiActions/UiDemoQuickAction.cs
Normal file
147
FasdDesktopUi/Basics/UiActions/UiDemoQuickAction.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
|
||||
using FasdCockpitBase.Models;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiDemoQuickAction : cUiQuickAction
|
||||
{
|
||||
public cF4sdQuickActionDemo quickActionDemo { get; private set; }
|
||||
|
||||
public cUiDemoQuickAction(cF4sdQuickActionDemo QuickActionConfig) : base(QuickActionConfig)
|
||||
{
|
||||
quickActionDemo = QuickActionConfig;
|
||||
Name = QuickActionConfig.Name;
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
DataProvider = dataProvider;
|
||||
|
||||
var detailedData = new cDetailedDataModel() { Heading = "Demo QuickAction" };
|
||||
|
||||
//Get QuickAciton Data
|
||||
detailedData.FullDetailedData = new List<object>()
|
||||
{
|
||||
new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime")},
|
||||
new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow.AddMinutes(-5), RawValueType.DATETIME)},
|
||||
new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow.AddMinutes(-38), RawValueType.DATETIME) },
|
||||
new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow.AddHours(-2).AddMinutes(12), RawValueType.DATETIME) },
|
||||
new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow.AddDays(-1).AddHours(4).AddMinutes(-32), RawValueType.DATETIME) },
|
||||
new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow.AddDays(-1).AddHours(4).AddMinutes(-34), RawValueType.DATETIME) }
|
||||
};
|
||||
|
||||
//Get Process Steps of Action
|
||||
var quickActionData = new cQuickActionStatusMonitorModel()
|
||||
{
|
||||
ActionName = Name,
|
||||
QuickActionDefinition = quickActionDemo,
|
||||
ActionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>(),
|
||||
QuickActionParameters = quickActionDemo.AdjustableParameters,
|
||||
RunQuickAction = ProcessActionAsync
|
||||
};
|
||||
|
||||
if (quickActionDemo.QuickActionType == enumQuickActionExecutionType.LocalScript)
|
||||
{
|
||||
quickActionData.ActionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Local.Load"), quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quickActionDemo.SimulatedClientConnect > 0)
|
||||
quickActionData.ActionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Connect"), quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.connectingToClient));
|
||||
if (quickActionDemo.SimulatedRuntime > 0)
|
||||
quickActionData.ActionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Running"), quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running));
|
||||
}
|
||||
|
||||
cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null;
|
||||
|
||||
return new cDataCanvasDataModel() { DetailedData = detailedData, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData };
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
var _finshedStatus = enumQuickActionRevisionStatus.finishedSuccessfull;
|
||||
if (quickActionDemo.SimulatedClientConnect > 0)
|
||||
{
|
||||
try { await Task.Delay(quickActionDemo.SimulatedClientConnect * 1000, token); }
|
||||
catch (TaskCanceledException) { }
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
_finshedStatus = enumQuickActionRevisionStatus.canceled;
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.connectingToClient, _finshedStatus);
|
||||
}
|
||||
|
||||
if (quickActionDemo.SimulatedRuntime > 0)
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
try { await Task.Delay(quickActionDemo.SimulatedRuntime * 1000, token); }
|
||||
catch (TaskCanceledException) { }
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
_finshedStatus = enumQuickActionRevisionStatus.canceled;
|
||||
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, _finshedStatus);
|
||||
}
|
||||
|
||||
string _msg;
|
||||
if (_finshedStatus == enumQuickActionRevisionStatus.canceled)
|
||||
{
|
||||
_msg = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled");
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quickActionDemo?.QuickActionMeasureResults?.Count > 0 && quickActionDemo.QuickActionMeasures?.Count > 0)
|
||||
{
|
||||
var measureValues = cUiRemoteQuickAction.GetStatusMonitorMeasureValues(quickActionDemo.QuickActionMeasureResults.Values.ToList(), quickActionDemo.QuickActionMeasures);
|
||||
if (measureValues?.Count > 0)
|
||||
StatusMonitor.MeasureValues = measureValues;
|
||||
}
|
||||
|
||||
cQuickActionOutput quickActionOutput = null;
|
||||
var _ref = new cF4sdQuickActionRevision();
|
||||
|
||||
if (!string.IsNullOrEmpty(quickActionDemo?.DemoResult))
|
||||
try
|
||||
{
|
||||
dynamic retValue = Newtonsoft.Json.JsonConvert.DeserializeObject(quickActionDemo?.DemoResult);
|
||||
var _output = new cF4sdQuickActionRevision.cOutput()
|
||||
{
|
||||
ResultCode = quickActionDemo.QuickActionSuccess,
|
||||
Values = retValue
|
||||
};
|
||||
|
||||
_ref.OutputText = Newtonsoft.Json.JsonConvert.SerializeObject(_output);
|
||||
}
|
||||
catch { }
|
||||
|
||||
StatusMonitor.QuickActionOutputs.Add(_ref.Output);
|
||||
quickActionOutput = QuickActionStatusMonitor.cQuickActionOutput.GetQuickActionOutput(_ref.Output, DataProvider);
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(quickActionDemo, DataProvider, true, quickActionOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(quickActionDemo, copyData));
|
||||
|
||||
_msg = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull");
|
||||
}
|
||||
|
||||
return new List<object>() { _msg, _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
}
|
||||
}
|
||||
47
FasdDesktopUi/Basics/UiActions/UiDummyQuickAction.cs
Normal file
47
FasdDesktopUi/Basics/UiActions/UiDummyQuickAction.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiDummyQuickAction : cUiQuickAction
|
||||
{
|
||||
public cUiDummyQuickAction(cFasdQuickAction quickAction)
|
||||
: base(null)
|
||||
{
|
||||
Name = quickAction.Name;
|
||||
Description = quickAction.Descriptions.GetValue();
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider = null, bool isDetailedLayout = false)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return new cDataCanvasDataModel();
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
List<object> result = new List<object> { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<QuickActionStatusMonitor.cQuickActionMeasureValue> GetStatusMonitorMeasureValues(List<cF4sdQuickActionRevision.cMeasure> measures)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
246
FasdDesktopUi/Basics/UiActions/UiLocalQuickAction.cs
Normal file
246
FasdDesktopUi/Basics/UiActions/UiLocalQuickAction.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using Newtonsoft.Json;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiLocalQuickAction : cUiQuickAction
|
||||
{
|
||||
public cFasdQuickActionLocal LocalQuickAction { get; set; }
|
||||
|
||||
public cUiLocalQuickAction(cFasdQuickActionLocal quickAction) : base(quickAction)
|
||||
{
|
||||
LocalQuickAction = quickAction;
|
||||
Name = quickAction.Name;
|
||||
}
|
||||
|
||||
public override async Task<cQuickActionStatusMonitorModel> GetQuickActionStatusMonitorDataAsync()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new cQuickActionStatusMonitorModel()
|
||||
{
|
||||
ActionName = LocalQuickAction.Names.GetValue(),
|
||||
QuickActionDefinition = LocalQuickAction,
|
||||
ActionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>()
|
||||
{
|
||||
new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Local.Load"), LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running)
|
||||
},
|
||||
QuickActionParameters = LocalQuickAction.AdjustableParameters,
|
||||
RunQuickAction = ProcessActionAsync
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
|
||||
var detailedDataQuickActionHistory = new cDetailedDataModel()
|
||||
{
|
||||
Heading = cMultiLanguageSupport.GetItem("DetailsPage.History"),
|
||||
FullDetailedData = new List<object>() { new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } }
|
||||
};
|
||||
|
||||
//Get QuickAciton Data
|
||||
if (dataProvider != null)
|
||||
{
|
||||
var quickActionHistory = await dataProvider.QuickActionProtocollHelper.GetQuickActionHistoryAsync(LocalQuickAction.Name);
|
||||
|
||||
if (quickActionHistory != null)
|
||||
detailedDataQuickActionHistory.FullDetailedData.AddRange(quickActionHistory);
|
||||
}
|
||||
|
||||
|
||||
//Get Process Steps of Action
|
||||
var quickActionData = await GetQuickActionStatusMonitorDataAsync();
|
||||
|
||||
//Get Recommendation
|
||||
cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null;
|
||||
|
||||
return new cDataCanvasDataModel() { DetailedData = detailedDataQuickActionHistory, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData };
|
||||
}
|
||||
|
||||
private cF4sdQuickActionRevision GetRevisionOutput(cExternalToolExecutorEnh.cProcessResult _result)
|
||||
{
|
||||
var retVal = new cF4sdQuickActionRevision() { Status = enumQuickActionRevisionStatus.unknown };
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_result.StandardOutput))
|
||||
{
|
||||
retVal.OutputText = _result.StandardOutput;
|
||||
if (retVal.Output != null)
|
||||
{
|
||||
if (retVal.Output.ErrorCode is null || retVal.Output.ErrorCode == 0)
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedSuccessfull;
|
||||
else
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedWithError;
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal.Status == enumQuickActionRevisionStatus.unknown)
|
||||
{
|
||||
if (_result.ReturnCode != 0 || !string.IsNullOrEmpty(_result.StandardError))
|
||||
{
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedWithError;
|
||||
retVal.Output = new cF4sdQuickActionRevision.cOutput()
|
||||
{
|
||||
ErrorCode = _result.ReturnCode,
|
||||
ErrorDescription = _result.StandardError
|
||||
};
|
||||
}
|
||||
else
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedSuccessfull;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
|
||||
var _actionResult = await cExternalToolExecutorEnh.StartLocalActionAsync(LocalQuickAction, DataProvider.NamedParameterEntries.ToInterfaceDictionary(), cMultiLanguageSupport.GetItem("RemoteTool.Credentials.PasswordRequest"), ParameterDictionary);
|
||||
|
||||
cQuickActionOutput quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown });
|
||||
cQuickActionOutput protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown });
|
||||
|
||||
List<object> output = new List<object>();
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
var ResultRevision = GetRevisionOutput(_actionResult);
|
||||
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
|
||||
if (ResultRevision.Output == null)
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
else
|
||||
{
|
||||
StatusMonitor.QuickActionOutputs.Add(ResultRevision.Output);
|
||||
quickActionOutput = cQuickActionOutput.GetQuickActionOutput(ResultRevision.Output, DataProvider);
|
||||
}
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
if (ResultRevision.Output == null)
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
else
|
||||
protocollOutput = cQuickActionOutput.GetQuickActionOutput(ResultRevision.Output, DataProvider);
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(LocalQuickAction, copyData));
|
||||
|
||||
|
||||
string quickActionStatus;
|
||||
switch (ResultRevision.Status)
|
||||
{
|
||||
case enumQuickActionRevisionStatus.inProgress:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.InProgress");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedSuccessfull:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedWithError:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.unknown:
|
||||
default:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
output = new List<object>() { quickActionStatus, _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
else
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.canceled);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.canceled);
|
||||
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(LocalQuickAction, copyData));
|
||||
|
||||
output = new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Guid? userId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User)?.Id;
|
||||
Guid? computerId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Computer)?.Id;
|
||||
|
||||
var reportQuickActionParameter = new cF4SDQuickActionParameters()
|
||||
{
|
||||
CaseId = DataProvider.CaseId,
|
||||
QuickActionId = LocalQuickAction.Id,
|
||||
QuickActionName = LocalQuickAction.Name,
|
||||
Paramaters = ParameterDictionary is null ? null : JsonConvert.SerializeObject(ParameterDictionary, Formatting.None),
|
||||
Result = JsonConvert.SerializeObject(quickActionOutput.ResultCode.GetValueOrDefault().ToString(), Formatting.None),
|
||||
ErrorCode = quickActionOutput.ErrorCode,
|
||||
ErrorDescription = quickActionOutput.ErrorDescription,
|
||||
Start = startTime,
|
||||
Finish = DateTime.UtcNow,
|
||||
UserId = userId,
|
||||
DeviceId = computerId,
|
||||
ExecutionType = LocalQuickAction.ExecutionType,
|
||||
ResultType = LocalQuickAction.ResultType
|
||||
};
|
||||
|
||||
var reportedQuickActionSuccessfully = await cFasdCockpitCommunicationBase.Instance.ReportQuickAction(reportQuickActionParameter);
|
||||
|
||||
if (reportedQuickActionSuccessfully is false)
|
||||
LogEntry($"Failed to report QuickAction '{LocalQuickAction.Name}' for case '{reportQuickActionParameter.CaseId}' to Analytics.", LogLevels.Warning);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
161
FasdDesktopUi/Basics/UiActions/UiLocalWebRequestQuickAction.cs
Normal file
161
FasdDesktopUi/Basics/UiActions/UiLocalWebRequestQuickAction.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiLocalWebRequestQuickAction : cUiLocalQuickAction
|
||||
{
|
||||
public cF4sdQuickActionLocalWebRequest WebRequestQuickAction { get; set; }
|
||||
|
||||
public cUiLocalWebRequestQuickAction(cF4sdQuickActionLocalWebRequest webRequestQuickAction) : base(webRequestQuickAction)
|
||||
{
|
||||
WebRequestQuickAction = webRequestQuickAction;
|
||||
}
|
||||
|
||||
|
||||
private string GetUrl()
|
||||
{
|
||||
string output = string.Empty;
|
||||
try
|
||||
{
|
||||
if (WebRequestQuickAction?.QueryString is null)
|
||||
return output;
|
||||
|
||||
if (!string.IsNullOrEmpty(WebRequestQuickAction.QueryString.ConstValue))
|
||||
{
|
||||
output = WebRequestQuickAction.QueryString.ConstValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var queryStringParameterName = WebRequestQuickAction.QueryString.ParameterName;
|
||||
if (!string.IsNullOrEmpty(queryStringParameterName))
|
||||
if (DataProvider.NamedParameterEntries.TryGetValue(queryStringParameterName, out var namedParameterEntry))
|
||||
output = namedParameterEntry.GetValue();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(output))
|
||||
return output;
|
||||
|
||||
if (WebRequestQuickAction.QueryParameters?.Count <= 0)
|
||||
return output;
|
||||
|
||||
foreach (var queryParameter in WebRequestQuickAction.QueryParameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryParameter.QueryParameterName))
|
||||
continue;
|
||||
|
||||
var replacementString = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(queryParameter.ConstValue))
|
||||
{
|
||||
replacementString = queryParameter.ConstValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var queryStringParameterName = queryParameter.ParameterName;
|
||||
if (!string.IsNullOrEmpty(queryStringParameterName))
|
||||
if (DataProvider.NamedParameterEntries.TryGetValue(queryStringParameterName, out var namedParameterEntry))
|
||||
replacementString = queryParameter.UseHtmlValue ? namedParameterEntry.GetHtmlValue() : namedParameterEntry.GetHtmlValue();
|
||||
}
|
||||
|
||||
output = output.Replace(queryParameter.QueryParameterName, replacementString);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//todo: use ParameterDictionary if request has Parameters
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
cBrowsers browsers = new cBrowsers();
|
||||
string webRequestUrl = GetUrl();
|
||||
|
||||
browsers.Start(WebRequestQuickAction.BrowserName, webRequestUrl);
|
||||
|
||||
if (string.IsNullOrEmpty(webRequestUrl))
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.canceled);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.canceled);
|
||||
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
cQuickActionOutput quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown }); ;
|
||||
cQuickActionOutput protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown }); ;
|
||||
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(LocalQuickAction, copyData));
|
||||
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
else
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.canceled);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, LocalQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.canceled);
|
||||
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(LocalQuickAction, copyData));
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
internal class cUiProcessSearchHistoryEntry : cUiActionBase
|
||||
{
|
||||
public cSearchHistoryEntryBase HistoryEntry { get; private set; }
|
||||
|
||||
public cUiProcessSearchHistoryEntry(cSearchHistoryEntryBase historyEntry)
|
||||
{
|
||||
HistoryEntry = historyEntry;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
cSearchManager.Instance.ReplaceEntry(HistoryEntry, HistoryEntry);
|
||||
HistoryEntry.SearchUiProvider.SetSearchHistoryVisibility(false);
|
||||
if (HistoryEntry.ShouldRefresh())
|
||||
{
|
||||
HistoryEntry.SearchUiProvider.ShowLoadingTextItem(cMultiLanguageSupport.GetItem("Searchbar.Refresh.Relations"));
|
||||
await HistoryEntry.RefreshAsync();
|
||||
}
|
||||
|
||||
// todo set relationService
|
||||
IRelationService relationService = new RelationService();
|
||||
|
||||
switch (HistoryEntry)
|
||||
{
|
||||
case cSearchHistorySearchResultEntry SearchEntry:
|
||||
HistoryEntry.SearchUiProvider.SetSearchHistoryVisibility(true);
|
||||
HistoryEntry.SearchUiProvider.ShowSearchRelations(SearchEntry, relationService, HistoryEntry.SearchUiProvider);
|
||||
return true;
|
||||
case cSearchHistoryRelationEntry RelationEntry:
|
||||
string caseObjectName = RelationEntry.SelectedRelation.DisplayName;
|
||||
string loadingStatusText = string.Format(cMultiLanguageSupport.GetItem("Searchbar.Loading.CaseData"), caseObjectName);
|
||||
RelationEntry.SearchUiProvider.ShowLoadingTextItem(loadingStatusText);
|
||||
|
||||
// check, if have an active support case
|
||||
var supportCaseActive = dataProvider?.IsActive ?? false;
|
||||
if (supportCaseActive)
|
||||
{
|
||||
if (!await cSupportCaseDataProvider.SupportTicketActiveNoticeAsync())
|
||||
{
|
||||
HistoryEntry.isSeen = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
HistoryEntry.isSeen = true;
|
||||
dataProvider = await cSupportCaseDataProvider.GetDataProviderForAsync(RelationEntry.Relations, RelationEntry.SelectedRelation, relationService);
|
||||
if (dataProvider is null)
|
||||
{
|
||||
Debug.Assert(true, "Could not start a data provider for the selected criterias.");
|
||||
LogEntry("Could not start a data provider for the selected criterias.", LogLevels.Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
110
FasdDesktopUi/Basics/UiActions/UiProcessSearchRelationAction.cs
Normal file
110
FasdDesktopUi/Basics/UiActions/UiProcessSearchRelationAction.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiProcessSearchRelationAction : cUiActionBase
|
||||
{
|
||||
private readonly List<cFasdApiSearchResultEntry> _selectedSearchResult;
|
||||
private readonly List<cF4sdApiSearchResultRelation> _relations;
|
||||
private readonly cF4sdApiSearchResultRelation _selectedRelation;
|
||||
private readonly IRelationService _relationService;
|
||||
private readonly ISearchUiProvider _searchUiProvider;
|
||||
private readonly cSearchHistoryEntryBase _searchHistoryEntry;
|
||||
|
||||
public cUiProcessSearchRelationAction(cSearchHistorySearchResultEntry searchHistoryEntry, cF4sdApiSearchResultRelation selectedRelation, IRelationService relationService, ISearchUiProvider searchUiProvider)
|
||||
{
|
||||
Name = $"{searchHistoryEntry.HeaderText} → {selectedRelation.DisplayName}";
|
||||
_selectedSearchResult = searchHistoryEntry.SelectedSearchResult;
|
||||
_relations = searchHistoryEntry.Relations;
|
||||
_selectedRelation = selectedRelation;
|
||||
_relationService = relationService;
|
||||
_searchUiProvider = searchUiProvider;
|
||||
_searchHistoryEntry = searchHistoryEntry;
|
||||
}
|
||||
|
||||
public cUiProcessSearchRelationAction(string name, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, cF4sdApiSearchResultRelation selectedRelation, ISearchUiProvider searchUiProvider, cSearchHistoryEntryBase searchHistoryEntry)
|
||||
{
|
||||
Name = name;
|
||||
_selectedSearchResult = selectedSearchResult;
|
||||
_relations = relations;
|
||||
_selectedRelation = selectedRelation;
|
||||
_searchUiProvider = searchUiProvider;
|
||||
_searchHistoryEntry = searchHistoryEntry;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
// return false: The search action has finished, the search could be canceled
|
||||
// return true: The search action is ongoing
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (dataProvider != null)
|
||||
{
|
||||
Debug.Assert(true, "At this moment, we want to create a new support call, so we must not have a dataProvider");
|
||||
LogEntry("At this moment, we want to create a new support call, so we must not have a dataProvider", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_selectedRelation == null)
|
||||
{
|
||||
Debug.Assert(true, "A new support case can't be opend, if we have no selected relation or seach result");
|
||||
LogEntry("A new support case can't be opend, if we have no sselected relation or seach result", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check, if have an active support case
|
||||
var supportCaseActive = dataProvider?.IsActive ?? false;
|
||||
|
||||
// create the search histroy entry
|
||||
var _seachHistoryEntry = new cSearchHistoryRelationEntry(Name, _selectedSearchResult, _relations, _selectedRelation, _searchUiProvider);
|
||||
cSearchManager.Instance.ReplaceEntry(_seachHistoryEntry, _searchHistoryEntry);
|
||||
|
||||
// show the loading information
|
||||
string caseObjectName = _selectedRelation.DisplayName;
|
||||
string loadingStatusText = string.Format(cMultiLanguageSupport.GetItem("Searchbar.Loading.CaseData"), caseObjectName);
|
||||
_searchUiProvider.ShowLoadingTextItem(loadingStatusText);
|
||||
|
||||
// if we have an opened support case, close it immediately
|
||||
if (supportCaseActive)
|
||||
{
|
||||
if (!await cSupportCaseDataProvider.SupportTicketActiveNoticeAsync())
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the new result menu properies for loading ....
|
||||
_seachHistoryEntry.isSeen = true;
|
||||
// get the new data provider for the support call informations (get it from the cache or create a new one)
|
||||
dataProvider = await cSupportCaseDataProvider.GetDataProviderForAsync(_relations, _selectedRelation, _relationService);
|
||||
|
||||
if (dataProvider is null)
|
||||
{
|
||||
Debug.Assert(true, "Could not start a data provider for the selected criterias.");
|
||||
LogEntry("Could not start a data provider for the selected criterias.", LogLevels.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
176
FasdDesktopUi/Basics/UiActions/UiProcessSearchResultAction.cs
Normal file
176
FasdDesktopUi/Basics/UiActions/UiProcessSearchResultAction.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using FasdDesktopUi.Basics.Services.RelationService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiProcessSearchResultAction : cUiActionBase
|
||||
{
|
||||
private readonly ISearchUiProvider _searchUiProvider;
|
||||
private readonly List<cFasdApiSearchResultEntry> _searchResults;
|
||||
|
||||
private readonly List<cF4sdApiSearchResultRelation> _loadedRelations = new List<cF4sdApiSearchResultRelation>();
|
||||
private readonly TaskCompletionSource<bool> _isSearchUnambigous = new TaskCompletionSource<bool>();
|
||||
|
||||
public cF4sdApiSearchResultRelation PreSelectedSearchRelation { get; set; } = null;
|
||||
|
||||
public cUiProcessSearchResultAction(string name, ISearchUiProvider searchUiProvider, List<cFasdApiSearchResultEntry> searchResults)
|
||||
{
|
||||
Name = name;
|
||||
_searchUiProvider = searchUiProvider;
|
||||
_searchResults = searchResults;
|
||||
|
||||
_searchUiProvider.SearchService.RelationsFound += HandleRelationsFound;
|
||||
}
|
||||
|
||||
~cUiProcessSearchResultAction()
|
||||
{
|
||||
_searchUiProvider.SearchService.RelationsFound -= HandleRelationsFound;
|
||||
}
|
||||
|
||||
/// <returns>If the search is unfinished.
|
||||
/// False: search is finished.
|
||||
/// True: search is ongoing.</returns>
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement uiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (dataProvider != null)
|
||||
{
|
||||
Debug.Assert(true, "At this moment, we want to create a new support call, so we must not have a dataProvider");
|
||||
LogEntry("At this moment, we want to create a new support call, so we must not have a dataProvider", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return await ProcessSearchResultDefaultAsync(CancellationToken.None);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <returns>If the search is unfinished.
|
||||
/// False: search is finished.
|
||||
/// True: search is ongoing.</returns>
|
||||
private async Task<bool> ProcessSearchResultDefaultAsync(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_searchResults is null || _searchResults.Count <= 0)
|
||||
return false;
|
||||
_searchUiProvider.ShowLoadingTextItem(cMultiLanguageSupport.GetItem("Searchbar.Loading.Relations"));
|
||||
|
||||
cF4sdStagedSearchResultRelationTaskId gatherRelationTask = await _searchUiProvider.SearchService.LoadRelationsAsync(_searchResults, token);
|
||||
|
||||
HashSet<enumFasdInformationClass> orderedPendingInfoClasses
|
||||
= GetInformationClassOrderedByPriority(gatherRelationTask.PendingInformationClasses, cF4sdIdentityEntry.GetFromSearchResult(_searchResults.FirstOrDefault()?.Type ?? enumF4sdSearchResultClass.Unknown));
|
||||
_searchUiProvider.SetPendingInformationClasses(orderedPendingInfoClasses);
|
||||
|
||||
Mouse.OverrideCursor = null;
|
||||
|
||||
if (MatchPreselectedSearchRelation(_loadedRelations))
|
||||
return await ProcessSearchResultRelationAsync(_searchResults.First().Name, _loadedRelations, PreSelectedSearchRelation);
|
||||
|
||||
if (await _isSearchUnambigous.Task)
|
||||
return await ProcessSearchResultRelationAsync(_searchResults.First().Name, _loadedRelations, _loadedRelations.FirstOrDefault());
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
bool MatchPreselectedSearchRelation(IEnumerable<cF4sdApiSearchResultRelation> relations)
|
||||
{
|
||||
if (PreSelectedSearchRelation is null || relations is null)
|
||||
return false;
|
||||
return relations.Any(entry => entry.Type == PreSelectedSearchRelation.Type && entry.id == PreSelectedSearchRelation.id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> ProcessSearchResultRelationAsync(string name, List<cF4sdApiSearchResultRelation> caseRelations, cF4sdApiSearchResultRelation selectedRelation)
|
||||
{
|
||||
var relationSearchResult = new cSearchHistorySearchResultEntry(_searchResults.FirstOrDefault().DisplayName, _searchResults.FirstOrDefault().DisplayName, _searchResults, caseRelations, _searchUiProvider);
|
||||
string displayName = selectedRelation != null ? $"{name} → {selectedRelation.Name}" : name;
|
||||
|
||||
cUiProcessSearchRelationAction action
|
||||
= new cUiProcessSearchRelationAction(displayName, _searchResults, caseRelations, caseRelations.FirstOrDefault(), _searchUiProvider, relationSearchResult)
|
||||
{
|
||||
DisplayType = enumActionDisplayType.enabled,
|
||||
};
|
||||
|
||||
return await action.RunUiActionAsync(this, null, false, null);
|
||||
}
|
||||
|
||||
private HashSet<enumFasdInformationClass> GetInformationClassOrderedByPriority(HashSet<enumFasdInformationClass> informationClasses, enumFasdInformationClass? excludedInformationClass = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var informationClassPrio = cFasdCockpitConfig.Instance.Global.InformationClassSearchPriority;
|
||||
|
||||
if (excludedInformationClass.HasValue)
|
||||
informationClasses.Remove(excludedInformationClass.Value);
|
||||
|
||||
if (informationClassPrio is null || informationClassPrio.Count == 0)
|
||||
return informationClasses;
|
||||
|
||||
return informationClasses
|
||||
.OrderBy(infoClass => informationClassPrio.Contains(infoClass) ? informationClassPrio.IndexOf(infoClass) : int.MaxValue)
|
||||
.ToHashSet();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
return informationClasses;
|
||||
}
|
||||
|
||||
private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_loadedRelations.AddRange(e.StagedResultRelations.Relations);
|
||||
|
||||
if (!e.StagedResultRelations.IsComplete)
|
||||
return;
|
||||
|
||||
bool isSearchResultUnambigous = _loadedRelations.Count <= 1;
|
||||
|
||||
if (_loadedRelations.Count == 0)
|
||||
_loadedRelations.Add(new cF4sdApiSearchResultRelation(_searchResults.FirstOrDefault()));
|
||||
|
||||
_isSearchUnambigous.TrySetResult(isSearchResultUnambigous);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
117
FasdDesktopUi/Basics/UiActions/UiQuickAction.cs
Normal file
117
FasdDesktopUi/Basics/UiActions/UiQuickAction.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using C4IT.Logging;
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public abstract class cUiQuickAction : cUiActionBase
|
||||
{
|
||||
private readonly bool shouldRunImmidiate = false;
|
||||
|
||||
protected readonly IRawValueFormatter _rawValueFormatter = new RawValueFormatter();
|
||||
|
||||
public cFasdQuickAction QuickActionConfig { get; private set; }
|
||||
|
||||
public cSupportCaseDataProvider DataProvider { get; set; }
|
||||
|
||||
public QuickActionStatusMonitor StatusMonitor { get; set; }
|
||||
|
||||
public cRecommendationDataModel QuickActionRecommendation { get; set; }
|
||||
|
||||
|
||||
public cUiQuickAction(cFasdQuickAction QuickActionConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (QuickActionConfig is null)
|
||||
return;
|
||||
|
||||
_rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
||||
|
||||
shouldRunImmidiate = QuickActionConfig.RunImmediate;
|
||||
Description = QuickActionConfig.Descriptions?.GetValue(Default: null);
|
||||
AlternativeDescription = QuickActionConfig.AlternativeDescriptions?.GetValue(Default: null);
|
||||
this.QuickActionConfig = QuickActionConfig;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task<cQuickActionStatusMonitorModel> GetQuickActionStatusMonitorDataAsync()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return new cQuickActionStatusMonitorModel();
|
||||
}
|
||||
|
||||
public abstract Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout);
|
||||
|
||||
public abstract Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null);
|
||||
|
||||
private void DrawUiActionControls(cDataCanvasDataModel quickActionData, UIElement UiLocation, bool isDetailedLayout)
|
||||
{
|
||||
if (!(UiLocation is Decorator decorator))
|
||||
return;
|
||||
|
||||
if (decorator.Child is DataCanvas existinDataCanvas)
|
||||
{
|
||||
existinDataCanvas.DataCanvasData = quickActionData;
|
||||
existinDataCanvas.DataProvider = DataProvider;
|
||||
existinDataCanvas.IsDetailedLayout = isDetailedLayout;
|
||||
StatusMonitor = existinDataCanvas.QuickActionStatusUc;
|
||||
existinDataCanvas.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataCanvas dataCanvas = new DataCanvas(isDetailedLayout) { DataCanvasData = quickActionData, IsDetailedLayout = isDetailedLayout, DataProvider = DataProvider };
|
||||
decorator.Child = dataCanvas;
|
||||
StatusMonitor = dataCanvas.QuickActionStatusUc;
|
||||
}
|
||||
|
||||
StatusMonitor.ExecuteButton.IsHitTestVisible = true;
|
||||
decorator.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
var quickActionData = await GetQuickActionDataAsync(dataProvider, isDetailedLayout);
|
||||
DrawUiActionControls(quickActionData, UiLocation, isDetailedLayout);
|
||||
|
||||
if (shouldRunImmidiate)
|
||||
if (UiLocation is Decorator uiDecorator)
|
||||
if (uiDecorator.Child is DataCanvas dataCanvas)
|
||||
await dataCanvas.QuickActionStatusUc.RunQuickActionAsync();
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
147
FasdDesktopUi/Basics/UiActions/UiQuickTipAction.cs
Normal file
147
FasdDesktopUi/Basics/UiActions/UiQuickTipAction.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using C4IT.FASD.Base;
|
||||
using F4SD_AdaptableIcon;
|
||||
using FasdDesktopUi.Basics.Converter;
|
||||
using FasdDesktopUi.Basics.Enums;
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls.QuickTip;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiQuickTipAction : cUiActionBase
|
||||
{
|
||||
public cSupportCaseDataProvider DataProvider { get; set; }
|
||||
|
||||
private readonly cFasdQuickTip _quickTip;
|
||||
|
||||
private readonly List<cUiQuickTipElement> _quickTipElements = new List<cUiQuickTipElement>();
|
||||
|
||||
public cUiQuickTipAction(cFasdQuickTip quickTip)
|
||||
{
|
||||
_quickTip = quickTip;
|
||||
}
|
||||
|
||||
public override Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is QuickTipStatusMonitor quickTipStatusMonitor))
|
||||
return Task.FromResult(false);
|
||||
|
||||
DataProvider = dataProvider;
|
||||
|
||||
CreateElementData();
|
||||
|
||||
quickTipStatusMonitor.QuickTipElementData = _quickTipElements;
|
||||
|
||||
quickTipStatusMonitor.QuickTipName = _quickTip.Names.GetValue();
|
||||
|
||||
if (_quickTip.Icon is null)
|
||||
quickTipStatusMonitor.QuickTipIcon = new IconData(MaterialIcons.MaterialIconType.ic_lightbulb_outline);
|
||||
else
|
||||
quickTipStatusMonitor.QuickTipIcon = IconDataConverter.Convert(_quickTip.Icon);
|
||||
|
||||
quickTipStatusMonitor.Visibility = Visibility.Visible;
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
private void CreateElementData()
|
||||
{
|
||||
_quickTipElements.Clear();
|
||||
|
||||
foreach (cQuickTipElement element in _quickTip.QuickTipElements)
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case cManualStep manualStep:
|
||||
_quickTipElements.Add(new cUiQuickTipElement(manualStep, enumQuickTipElementType.Manual, DataProvider));
|
||||
break;
|
||||
case cAutomatedStep automatedStep:
|
||||
_quickTipElements.Add(new cUiQuickTipElement(automatedStep, enumQuickTipElementType.Automated, DataProvider));
|
||||
break;
|
||||
case cTextElement textElement:
|
||||
_quickTipElements.Add(new cUiQuickTipElement(textElement, enumQuickTipElementType.Text, DataProvider));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cUiQuickTipElement
|
||||
{
|
||||
public enumQuickTipElementType ElementType { get; set; }
|
||||
|
||||
public string ElementName { get; set; }
|
||||
|
||||
public string TextBlock { get; set; }
|
||||
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
public IconData Icon { get; set; }
|
||||
|
||||
public cQuickTipElement QuickTipElementDefinition { get; set; }
|
||||
|
||||
public cUiActionBase StepUiAction { get; set; }
|
||||
|
||||
public cSupportCaseDataProvider DataProvider { get; set; }
|
||||
|
||||
public cUiQuickTipElement(cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
}
|
||||
|
||||
public cUiQuickTipElement(cQuickTipElement element, enumQuickTipElementType type, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
ElementType = type;
|
||||
QuickTipElementDefinition = element;
|
||||
ElementName = element.Names.GetValue();
|
||||
TextBlock = element.TextBlocks.GetValue();
|
||||
IsRequired = element.IsRequired;
|
||||
|
||||
if (element is cTextElement)
|
||||
return;
|
||||
|
||||
if (element is cAutomatedStep automatedStep)
|
||||
SetValues(automatedStep);
|
||||
|
||||
if (element is cManualStep manualStep)
|
||||
SetValues(manualStep);
|
||||
}
|
||||
|
||||
private void SetValues(cAutomatedStep automatedStep)
|
||||
{
|
||||
cF4SDCockpitXmlConfig.Instance.MenuItems.TryGetValue(automatedStep.QuickAction, out cFasdBaseConfigMenuItem test);
|
||||
|
||||
MenuItemDataProvider _menuDataProvider = new MenuItemDataProvider(DataProvider);
|
||||
|
||||
cMenuDataBase uiAction = _menuDataProvider.GetMenuItemData()
|
||||
.Where(data => automatedStep.QuickAction == data.UiAction.Name && data.UiAction.DisplayType != enumActionDisplayType.hidden)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (uiAction != null && uiAction.UiAction is cUiQuickAction elementQuickAction)
|
||||
StepUiAction = elementQuickAction;
|
||||
}
|
||||
|
||||
private void SetValues(cManualStep manualStep)
|
||||
{
|
||||
StepUiAction = new cShowRecommendationAction(ElementName, manualStep.Summaries.GetValue());
|
||||
Icon = IconDataConverter.Convert(manualStep.Icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
336
FasdDesktopUi/Basics/UiActions/UiRemoteQuickAction.cs
Normal file
336
FasdDesktopUi/Basics/UiActions/UiRemoteQuickAction.cs
Normal file
@@ -0,0 +1,336 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
using static FasdDesktopUi.Basics.Models.cQuickActionStatusMonitorModel.cQuickActionStep;
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiRemoteQuickAction : cUiQuickAction
|
||||
{
|
||||
public cF4sdQuickActionRemote RemoteQuickAction { get; set; }
|
||||
|
||||
public cUiRemoteQuickAction(cF4sdQuickActionRemote quickAction) : base(quickAction)
|
||||
{
|
||||
RemoteQuickAction = quickAction;
|
||||
}
|
||||
|
||||
public async override Task<cQuickActionStatusMonitorModel> GetQuickActionStatusMonitorDataAsync()
|
||||
{
|
||||
var scriptInfos = await cFasdCockpitCommunicationBase.Instance.GetQuickActionOfAgent(RemoteQuickAction.AgentScriptId);
|
||||
|
||||
var actionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>() { new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Connect"), RemoteQuickAction.Name, enumActionStepType.connectingToClient) };
|
||||
if (scriptInfos.UserPermissionRequired)
|
||||
actionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.UserAcceptance"), RemoteQuickAction.Name, enumActionStepType.waitingForUserAcceptance));
|
||||
|
||||
actionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Running"), RemoteQuickAction.Name, enumActionStepType.running));
|
||||
|
||||
return new cQuickActionStatusMonitorModel()
|
||||
{
|
||||
ActionName = RemoteQuickAction.Names.GetValue(),
|
||||
QuickActionDefinition = RemoteQuickAction,
|
||||
RequiresUserPermission = scriptInfos != null && scriptInfos.UserPermissionRequired,
|
||||
ActionSteps = actionSteps,
|
||||
QuickActionParameters = RemoteQuickAction.AdjustableParameters,
|
||||
RunQuickAction = ProcessActionAsync
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
|
||||
var detailedData = new cDetailedDataModel() { Heading = cMultiLanguageSupport.GetItem("DetailsPage.History") };
|
||||
|
||||
//Get QuickAciton Data
|
||||
if (isDetailedLayout)
|
||||
{
|
||||
detailedData.FullDetailedData = new List<object>() { new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } };
|
||||
var quickActionHistory = await dataProvider.QuickActionProtocollHelper.GetQuickActionHistoryAsync(RemoteQuickAction.Name);
|
||||
foreach (var quickActionLine in quickActionHistory)
|
||||
{
|
||||
quickActionLine[1] = _rawValueFormatter.GetDisplayValue(quickActionLine[1], RawValueType.DATETIME);
|
||||
detailedData.FullDetailedData.Add(quickActionLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
detailedData.FullDetailedData = new List<object>();
|
||||
|
||||
//Get Process Steps of Action
|
||||
var quickActionData = await GetQuickActionStatusMonitorDataAsync();
|
||||
|
||||
//Get Recommendation
|
||||
cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null;
|
||||
|
||||
return new cDataCanvasDataModel() { DetailedData = detailedData, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData };
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
int agentDeviceId = int.MinValue;
|
||||
int? agentUserIdNullable = null;
|
||||
var startTime = DateTime.UtcNow;
|
||||
|
||||
if (DataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter))
|
||||
_ = int.TryParse(agentDeviceIdParameter.GetValue(), out agentDeviceId);
|
||||
|
||||
if (RemoteQuickAction.InformationClasses.Contains(enumFasdInformationClass.User))
|
||||
if (DataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter))
|
||||
if (int.TryParse(agentUserIdParameter.GetValue(), out int agentUserId))
|
||||
agentUserIdNullable = agentUserId;
|
||||
|
||||
//todo: task of DataProviderBase?
|
||||
var QuickActionResult = new cF4sdQuickActionRevision();
|
||||
if (cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode != null)
|
||||
{
|
||||
var parameters = cExternalToolExecutorEnh.ReplaceParameters(RemoteQuickAction.Parameters, DataProvider.NamedParameterEntries.ToInterfaceDictionary(), false, ParameterDictionary);
|
||||
|
||||
var scriptInformation = await cFasdCockpitCommunicationBase.Instance.RunAgentScript(RemoteQuickAction, cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode.Value, agentDeviceId, agentUserIdNullable, parameters);
|
||||
await UpdateQuickActionStatusAsync(scriptInformation.TaskId, token);
|
||||
QuickActionResult = await GetRevisionForStatusMonitorAsync(scriptInformation.RevisionId, scriptInformation.TaskId, token);
|
||||
|
||||
if (QuickActionResult != null && QuickActionResult.Status is enumQuickActionRevisionStatus.finishedWithError)
|
||||
{
|
||||
if (QuickActionResult.Output == null)
|
||||
QuickActionResult.Output = new cF4sdQuickActionRevision.cOutput() { ErrorCode = 1, ErrorDescription = QuickActionResult.OutputText };
|
||||
if (QuickActionResult.Output.ErrorCode == null && QuickActionResult.Output.ResultCode == 0 && QuickActionResult.Output.ErrorDescription == null && !string.IsNullOrEmpty(QuickActionResult.OutputText))
|
||||
QuickActionResult.Output.ErrorDescription = QuickActionResult.OutputText;
|
||||
}
|
||||
}
|
||||
|
||||
if (QuickActionResult == null)
|
||||
QuickActionResult = new cF4sdQuickActionRevision() { Status = enumQuickActionRevisionStatus.finishedWithError, OutputText = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled") };
|
||||
|
||||
if (QuickActionResult.Measures?.Count > 0)
|
||||
{
|
||||
var StatusMonitorMeasureValues = GetStatusMonitorMeasureValues(QuickActionResult.Measures, RemoteQuickAction.QuickActionMeasures);
|
||||
|
||||
if (StatusMonitorMeasureValues?.Count > 0)
|
||||
StatusMonitor.MeasureValues = StatusMonitorMeasureValues;
|
||||
}
|
||||
|
||||
var quickActionOutput = cQuickActionOutput.GetQuickActionOutput(QuickActionResult.Output, DataProvider);
|
||||
var protocollOutput = cQuickActionOutput.GetQuickActionOutput(QuickActionResult.Output, DataProvider);
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
StatusMonitor.QuickActionOutputs.Add(QuickActionResult.Output);
|
||||
var status = quickActionOutput?.IsError == true ? enumQuickActionRevisionStatus.finishedWithError : QuickActionResult.Status;
|
||||
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, enumActionStepType.running, status);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, enumActionStepType.main, status);
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(RemoteQuickAction, DataProvider, true, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(RemoteQuickAction, copyData));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps);
|
||||
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(RemoteQuickAction, DataProvider, true, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(RemoteQuickAction, copyData));
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
string quickActionStatus;
|
||||
switch (QuickActionResult.Status)
|
||||
{
|
||||
case enumQuickActionRevisionStatus.inProgress:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.InProgress");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedSuccessfull:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedWithError:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.unknown:
|
||||
default:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Guid? userId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User)?.Id;
|
||||
Guid? computerId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Computer)?.Id;
|
||||
|
||||
var reportQuickActionParameter = new cF4SDQuickActionParameters()
|
||||
{
|
||||
CaseId = DataProvider.CaseId,
|
||||
QuickActionId = RemoteQuickAction.Id,
|
||||
QuickActionName = RemoteQuickAction.Name,
|
||||
Paramaters = ParameterDictionary is null ? null : JsonConvert.SerializeObject(ParameterDictionary, Formatting.None),
|
||||
Result = QuickActionResult.Output.Values is null ? null : JsonConvert.SerializeObject(QuickActionResult.Output.Values, Formatting.None),
|
||||
ErrorCode = QuickActionResult.Output.ErrorCode,
|
||||
ErrorDescription = QuickActionResult.Output.ErrorDescription,
|
||||
Start = startTime,
|
||||
Finish = DateTime.UtcNow,
|
||||
UserId = userId,
|
||||
DeviceId = computerId,
|
||||
ExecutionType = RemoteQuickAction.ExecutionType,
|
||||
ResultType = RemoteQuickAction.ResultType
|
||||
};
|
||||
|
||||
var reportedQuickActionSuccessfully = await cFasdCockpitCommunicationBase.Instance.ReportQuickAction(reportQuickActionParameter);
|
||||
|
||||
if (reportedQuickActionSuccessfully is false)
|
||||
LogEntry($"Failed to report QuickAction '{RemoteQuickAction.Name}' for case '{reportQuickActionParameter.CaseId}' to Analytics.", LogLevels.Warning);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
});
|
||||
|
||||
return new List<object>() { quickActionStatus, _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static List<cQuickActionMeasureValue> GetStatusMonitorMeasureValues(List<cF4sdQuickActionRevision.cMeasure> measures, Dictionary<int, cF4sdQuickActionMeasure> QuickActionMeasures)
|
||||
{
|
||||
try
|
||||
{
|
||||
var output = new List<cQuickActionMeasureValue>();
|
||||
|
||||
if (QuickActionMeasures == null || measures == null)
|
||||
return null;
|
||||
|
||||
foreach (var measure in measures)
|
||||
{
|
||||
if (!QuickActionMeasures.TryGetValue(measure.Id, out var measureDefinition))
|
||||
continue;
|
||||
|
||||
output.Add(new cQuickActionMeasureValue()
|
||||
{
|
||||
Id = measure.Id,
|
||||
Names = measureDefinition.Names,
|
||||
Display = cUtility.GetRawValueType(measureDefinition.Display),
|
||||
Value = measure.Value,
|
||||
PostValue = measure.PostValue
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task UpdateQuickActionStatusAsync(int taskId, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
const int pollDelayInMilliseconds = 250;
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
var quickActionStatus = await cFasdCockpitCommunicationBase.Instance.GetAgentQuickActionStatus(taskId);
|
||||
|
||||
if (quickActionStatus == enumQuickActionStatus.Unknown)
|
||||
break;
|
||||
|
||||
List<enumActionStepType> actionStepsToUpdate = new List<enumActionStepType>();
|
||||
|
||||
switch (quickActionStatus)
|
||||
{
|
||||
case enumQuickActionStatus.ConnectingToClient:
|
||||
break;
|
||||
case enumQuickActionStatus.WaitingForUserAcceptance:
|
||||
actionStepsToUpdate = new List<enumActionStepType>() { enumActionStepType.connectingToClient };
|
||||
break;
|
||||
case enumQuickActionStatus.Running:
|
||||
case enumQuickActionStatus.Finished:
|
||||
actionStepsToUpdate = new List<enumActionStepType>() { enumActionStepType.connectingToClient, enumActionStepType.waitingForUserAcceptance };
|
||||
break;
|
||||
case enumQuickActionStatus.Cancelled:
|
||||
var remainingSteps = StatusMonitor.QuickActionData.ActionSteps.Where(step => step.Status != enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
|
||||
foreach (var remainingStep in remainingSteps)
|
||||
{
|
||||
remainingStep.Status = enumQuickActionRevisionStatus.canceled;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var actionStepToUpdate in actionStepsToUpdate)
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, actionStepToUpdate, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
}
|
||||
|
||||
if (quickActionStatus == enumQuickActionStatus.Finished || quickActionStatus == enumQuickActionStatus.Cancelled)
|
||||
break;
|
||||
|
||||
await Task.Delay(pollDelayInMilliseconds);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<cF4sdQuickActionRevision> GetRevisionForStatusMonitorAsync(int revisionId, int taskId, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
var revision = await cFasdCockpitCommunicationBase.Instance.GetAgentRevision(revisionId, cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode.Value);
|
||||
return revision;
|
||||
}
|
||||
else
|
||||
await cFasdCockpitCommunicationBase.Instance.CancelAgentTask(taskId);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
261
FasdDesktopUi/Basics/UiActions/UiServerQuickAction.cs
Normal file
261
FasdDesktopUi/Basics/UiActions/UiServerQuickAction.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using C4IT.F4SD.DisplayFormatting;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Cockpit.Communication;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdCockpitBase.Models;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiServerQuickAction : cUiQuickAction
|
||||
{
|
||||
public cF4sdQuickActionServer ServerQuickAction { get; set; }
|
||||
|
||||
public cUiServerQuickAction(cF4sdQuickActionServer quickAction) : base(quickAction)
|
||||
{
|
||||
ServerQuickAction = quickAction;
|
||||
Name = quickAction.Names.GetValue();
|
||||
}
|
||||
|
||||
public override async Task<cQuickActionStatusMonitorModel> GetQuickActionStatusMonitorDataAsync()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new cQuickActionStatusMonitorModel()
|
||||
{
|
||||
ActionName = ServerQuickAction.Names.GetValue(),
|
||||
QuickActionDefinition = ServerQuickAction,
|
||||
ActionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>()
|
||||
{
|
||||
new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Running"), ServerQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running)
|
||||
},
|
||||
QuickActionParameters = ServerQuickAction.AdjustableParameters,
|
||||
RunQuickAction = ProcessActionAsync
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
|
||||
{
|
||||
DataProvider = dataProvider;
|
||||
|
||||
var detailedDataQuickActionHistory = new cDetailedDataModel()
|
||||
{
|
||||
Heading = cMultiLanguageSupport.GetItem("DetailsPage.History"),
|
||||
FullDetailedData = new List<object>() { new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } }
|
||||
};
|
||||
|
||||
//Get QuickAciton Data
|
||||
if (dataProvider != null)
|
||||
{
|
||||
var quickActionHistory = await dataProvider.QuickActionProtocollHelper.GetQuickActionHistoryAsync(ServerQuickAction.Name);
|
||||
|
||||
if (quickActionHistory != null)
|
||||
detailedDataQuickActionHistory.FullDetailedData.AddRange(quickActionHistory);
|
||||
}
|
||||
|
||||
|
||||
//Get Process Steps of Action
|
||||
var quickActionData = await GetQuickActionStatusMonitorDataAsync();
|
||||
|
||||
//Get Recommendation
|
||||
cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null;
|
||||
|
||||
return new cDataCanvasDataModel() { DetailedData = detailedDataQuickActionHistory, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData };
|
||||
}
|
||||
|
||||
private cF4sdQuickActionRevision GetRevisionOutput(cExternalToolExecutorEnh.cProcessResult _result)
|
||||
{
|
||||
var retVal = new cF4sdQuickActionRevision() { Status = enumQuickActionRevisionStatus.unknown };
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_result.StandardOutput))
|
||||
{
|
||||
retVal.OutputText = _result.StandardOutput;
|
||||
if (retVal.Output != null)
|
||||
{
|
||||
if (retVal.Output.ErrorCode is null || retVal.Output.ErrorCode == 0)
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedSuccessfull;
|
||||
else
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedWithError;
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal.Status == enumQuickActionRevisionStatus.unknown)
|
||||
{
|
||||
if (_result.ReturnCode != 0 || !string.IsNullOrEmpty(_result.StandardError))
|
||||
{
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedWithError;
|
||||
retVal.Output = new cF4sdQuickActionRevision.cOutput()
|
||||
{
|
||||
ErrorCode = _result.ReturnCode,
|
||||
ErrorDescription = _result.StandardError
|
||||
};
|
||||
}
|
||||
else
|
||||
retVal.Status = enumQuickActionRevisionStatus.finishedSuccessfull;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
|
||||
var _actionResult = await Task.Run(async () => { return await cExternalToolExecutorEnh.StartServerActionAsync(ServerQuickAction, DataProvider, cMultiLanguageSupport.GetItem("RemoteTool.Credentials.PasswordRequest"), ParameterDictionary); });
|
||||
|
||||
cQuickActionOutput quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown }); ;
|
||||
cQuickActionOutput protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.unknown }); ;
|
||||
|
||||
List<object> output = new List<object>();
|
||||
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
var ResultRevision = GetRevisionOutput(_actionResult);
|
||||
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, ServerQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, ServerQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.finishedSuccessfull);
|
||||
|
||||
if (!string.IsNullOrEmpty(_actionResult.StandardOutput))
|
||||
try
|
||||
{
|
||||
dynamic retValue = Newtonsoft.Json.JsonConvert.DeserializeObject(_actionResult.StandardOutput);
|
||||
var _output = new cF4sdQuickActionRevision.cOutput()
|
||||
{
|
||||
ResultCode = enumQuickActionSuccess.finished,
|
||||
Values = retValue
|
||||
};
|
||||
|
||||
ResultRevision.OutputText = JsonConvert.SerializeObject(_output);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (ResultRevision.Output == null)
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
else
|
||||
{
|
||||
StatusMonitor.QuickActionOutputs.Add(ResultRevision.Output);
|
||||
|
||||
quickActionOutput = cQuickActionOutput.GetQuickActionOutput(ResultRevision.Output, DataProvider);
|
||||
}
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
if (ResultRevision.Output == null)
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
|
||||
else
|
||||
protocollOutput = cQuickActionOutput.GetQuickActionOutput(ResultRevision.Output, DataProvider);
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(ServerQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(ServerQuickAction, copyData));
|
||||
|
||||
string quickActionStatus;
|
||||
switch (ResultRevision.Status)
|
||||
{
|
||||
case enumQuickActionRevisionStatus.inProgress:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.InProgress");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedSuccessfull:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.finishedWithError:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError");
|
||||
break;
|
||||
case enumQuickActionRevisionStatus.unknown:
|
||||
default:
|
||||
quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
output = new List<object>() { quickActionStatus, _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
else
|
||||
{
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, ServerQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.main, enumQuickActionRevisionStatus.canceled);
|
||||
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, ServerQuickAction.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.canceled);
|
||||
|
||||
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
|
||||
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null)
|
||||
{
|
||||
string tempLang = cMultiLanguageSupport.CurrentLanguage;
|
||||
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage;
|
||||
protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
|
||||
cMultiLanguageSupport.CurrentLanguage = tempLang;
|
||||
}
|
||||
|
||||
cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(ServerQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
|
||||
F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(ServerQuickAction, copyData));
|
||||
|
||||
output = new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Guid? userId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User)?.Id;
|
||||
Guid? computerId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Computer)?.Id;
|
||||
|
||||
var reportQuickActionParameter = new cF4SDQuickActionParameters()
|
||||
{
|
||||
CaseId = DataProvider.CaseId,
|
||||
QuickActionId = ServerQuickAction.Id,
|
||||
QuickActionName = ServerQuickAction.Name,
|
||||
Paramaters = ParameterDictionary is null ? null : JsonConvert.SerializeObject(ParameterDictionary, Formatting.None),
|
||||
Result = JsonConvert.SerializeObject(quickActionOutput.ResultCode.GetValueOrDefault().ToString(), Formatting.None),
|
||||
ErrorCode = quickActionOutput.ErrorCode,
|
||||
ErrorDescription = quickActionOutput.ErrorDescription,
|
||||
Start = startTime,
|
||||
Finish = DateTime.UtcNow,
|
||||
UserId = userId,
|
||||
DeviceId = computerId,
|
||||
ExecutionType = ServerQuickAction.ExecutionType,
|
||||
ResultType = ServerQuickAction.ResultType
|
||||
};
|
||||
|
||||
var reportedQuickActionSuccessfully = await cFasdCockpitCommunicationBase.Instance.ReportQuickAction(reportQuickActionParameter);
|
||||
|
||||
if (reportedQuickActionSuccessfully is false)
|
||||
LogEntry($"Failed to report QuickAction '{ServerQuickAction.Name}' for case '{reportQuickActionParameter.CaseId}' to Analytics.", LogLevels.Warning);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), _rawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
FasdDesktopUi/Basics/UiActions/UiSystemDefaultQuickAction.cs
Normal file
51
FasdDesktopUi/Basics/UiActions/UiSystemDefaultQuickAction.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UserControls;
|
||||
using FasdDesktopUi.Pages.CustomMessageBox;
|
||||
using FasdDesktopUi.Pages.DetailsPage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UiActions
|
||||
{
|
||||
public class cUiShowNotepadQuickAction : cUiActionBase
|
||||
{
|
||||
|
||||
public cUiShowNotepadQuickAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override async Task<bool> RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(UiLocation is DetailsPageView detailsPage))
|
||||
return false;
|
||||
|
||||
detailsPage.NotepadChangeVisibilityAction(this, true);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
14
FasdDesktopUi/Basics/UserControls/BlurInvokerContainer.xaml
Normal file
14
FasdDesktopUi/Basics/UserControls/BlurInvokerContainer.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.BlurInvokerContainer"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
IsVisibleChanged="BlurInvoker_IsActiveChanged">
|
||||
<Decorator x:Name="MainDecorator">
|
||||
|
||||
</Decorator>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,65 @@
|
||||
using C4IT.Logging;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
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.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UserControls
|
||||
{
|
||||
public partial class BlurInvokerContainer : UserControl, IBlurInvoker
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public UIElement Child
|
||||
{
|
||||
get { return (UIElement)GetValue(ChildProperty); }
|
||||
set { SetValue(ChildProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ChildProperty =
|
||||
DependencyProperty.Register("Child", typeof(UIElement), typeof(BlurInvokerContainer), new PropertyMetadata(null, new PropertyChangedCallback(ChildChanged)));
|
||||
|
||||
private static void ChildChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(d is BlurInvokerContainer _me))
|
||||
return;
|
||||
|
||||
_me.MainDecorator.Child = _me.Child;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public BlurInvokerContainer()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
|
||||
}
|
||||
|
||||
public bool BlurInvoker_IsActive => IsVisible;
|
||||
|
||||
}
|
||||
}
|
||||
212
FasdDesktopUi/Basics/UserControls/ComboBoxPageable.xaml
Normal file
212
FasdDesktopUi/Basics/UserControls/ComboBoxPageable.xaml
Normal file
@@ -0,0 +1,212 @@
|
||||
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.ComboBoxPageable"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
|
||||
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
|
||||
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
|
||||
mc:Ignorable="d"
|
||||
x:Name="ComboBoxPagableUc"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
|
||||
<UserControl.Resources>
|
||||
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
|
||||
|
||||
<ControlTemplate x:Key="ComboBoxPagableTemplate"
|
||||
TargetType="{x:Type ComboBox}">
|
||||
|
||||
<Grid x:Name="templateRoot"
|
||||
SnapsToDevicePixels="true">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
|
||||
Width="0" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Popup x:Name="PART_Popup"
|
||||
AllowsTransparency="true"
|
||||
Grid.ColumnSpan="2"
|
||||
IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Margin="1"
|
||||
Placement="Bottom"
|
||||
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<TextBox x:Name="SearchTextBox"
|
||||
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
|
||||
Background="{TemplateBinding Background}"
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
Padding="27 5 5 5"
|
||||
Margin="0"
|
||||
TextChanged="SearchTextBox_TextChanged" />
|
||||
|
||||
<ico:AdaptableIcon SelectedInternIcon="menuBar_search"
|
||||
HorizontalAlignment="Left"
|
||||
BorderPadding="5 5 5 7"
|
||||
Margin="0"
|
||||
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Base}" />
|
||||
|
||||
<TextBlock IsHitTestVisible="False"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="30 0 0 0"
|
||||
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Date}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Text, ElementName=SearchTextBox}"
|
||||
Value="">
|
||||
<Setter Property="Text"
|
||||
Value="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<Border CornerRadius="7.5"
|
||||
Padding="10 0"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{TemplateBinding Background}">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Background="#01010101">
|
||||
|
||||
<ico:AdaptableIcon x:Name="PageBackButton"
|
||||
SelectedInternIcon="misc_chevron_left"
|
||||
Style="{DynamicResource SettingsPage.Close.Icon}"
|
||||
MouseLeftButtonUp="PageBackButton_MouseLeftButtonUp"
|
||||
TouchDown="PageBackButton_TouchDown"
|
||||
BorderPadding="7.5"
|
||||
IconHeight="30"
|
||||
IconWidth="30" />
|
||||
|
||||
<TextBlock x:Name="PageTrackerTextBlock"
|
||||
VerticalAlignment="Center" />
|
||||
|
||||
<ico:AdaptableIcon x:Name="PageForButton"
|
||||
SelectedInternIcon="misc_chevron_right"
|
||||
Style="{DynamicResource SettingsPage.Close.Icon}"
|
||||
MouseLeftButtonUp="PageForButton_MouseLeftButtonUp"
|
||||
TouchDown="PageForButton_TouchDown"
|
||||
BorderPadding="7.5"
|
||||
IconHeight="30"
|
||||
IconWidth="30" />
|
||||
<CheckBox x:Name="ResetFilterCheckbox"
|
||||
Style="{DynamicResource ToggleSwitch}"
|
||||
Margin="20 0 0 0"
|
||||
HorizontalAlignment="Left"
|
||||
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=ResetFilter, Mode=TwoWay}"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="Hand"
|
||||
>
|
||||
</CheckBox>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=ResetFilterLabel, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border MinWidth="{Binding ActualWidth, ElementName=templateRoot}"
|
||||
MaxHeight="{TemplateBinding MaxDropDownHeight}">
|
||||
<Border x:Name="dropDownBorder"
|
||||
CornerRadius="7.5"
|
||||
Background="{DynamicResource BackgroundColor.Menu.SubCategory}">
|
||||
<ScrollViewer x:Name="DropDownScrollViewer">
|
||||
<Grid x:Name="grid"
|
||||
RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas x:Name="canvas"
|
||||
HorizontalAlignment="Left"
|
||||
Height="0"
|
||||
VerticalAlignment="Top"
|
||||
Width="0">
|
||||
<Border x:Name="opaqueRect"
|
||||
CornerRadius="7.5"
|
||||
Background="{Binding Background, ElementName=dropDownBorder}"
|
||||
Height="{Binding ActualHeight, ElementName=dropDownBorder}"
|
||||
Width="{Binding ActualWidth, ElementName=dropDownBorder}" />
|
||||
</Canvas>
|
||||
<ItemsPresenter x:Name="ItemsPresenter"
|
||||
KeyboardNavigation.DirectionalNavigation="Contained"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Popup>
|
||||
<ToggleButton x:Name="toggleButton"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Grid.ColumnSpan="2"
|
||||
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Style="{StaticResource ComboBoxToggleButton}" />
|
||||
<ContentPresenter x:Name="contentPresenter"
|
||||
ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
|
||||
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
|
||||
Content="{TemplateBinding SelectionBoxItem}"
|
||||
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
IsHitTestVisible="false"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="false">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.7" />
|
||||
</Trigger>
|
||||
<Trigger Property="HasDropShadow"
|
||||
SourceName="PART_Popup"
|
||||
Value="true">
|
||||
</Trigger>
|
||||
<Trigger Property="HasItems"
|
||||
Value="false">
|
||||
<Setter Property="Height"
|
||||
TargetName="dropDownBorder"
|
||||
Value="95" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsGrouping"
|
||||
Value="true" />
|
||||
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping"
|
||||
Value="false" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="ScrollViewer.CanContentScroll"
|
||||
Value="false" />
|
||||
</MultiTrigger>
|
||||
<Trigger Property="ScrollViewer.CanContentScroll"
|
||||
SourceName="DropDownScrollViewer"
|
||||
Value="false">
|
||||
<Setter Property="Canvas.Top"
|
||||
TargetName="opaqueRect"
|
||||
Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}" />
|
||||
<Setter Property="Canvas.Left"
|
||||
TargetName="opaqueRect"
|
||||
Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<ComboBox x:Name="ComboBoxControl"
|
||||
DropDownOpened="ComboBoxControl_DropDownOpened"
|
||||
DropDownClosed="ComboBoxControl_DropDownClosed"
|
||||
Background="{Binding ElementName=ComboBoxPagableUc, Path=ComboBoxBackground}"
|
||||
BorderBrush="{Binding ElementName=ComboBoxPagableUc, Path=BorderBrush}"
|
||||
ItemsSource="{Binding ElementName=ComboBoxPagableUc, Path=ItemData}"
|
||||
SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=SelectedItem, Mode=TwoWay}"
|
||||
DisplayMemberPath="Key"
|
||||
Template="{StaticResource ComboBoxPagableTemplate}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
396
FasdDesktopUi/Basics/UserControls/ComboBoxPageable.xaml.cs
Normal file
396
FasdDesktopUi/Basics/UserControls/ComboBoxPageable.xaml.cs
Normal file
@@ -0,0 +1,396 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.MultiLanguage;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Navigation;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UserControls
|
||||
{
|
||||
public partial class ComboBoxPageable : UserControl, IFocusInvoker
|
||||
{
|
||||
#region Fields & Properties
|
||||
|
||||
private const int itemsPerPage = 10;
|
||||
private const double searchDelayInMilliseconds = 350;
|
||||
|
||||
private int pageIndex = 0;
|
||||
private int pageCount = 1;
|
||||
private readonly Timer timer = new Timer(searchDelayInMilliseconds);
|
||||
|
||||
private readonly cF4sdHealthSelectionDataRequest searchData = new cF4sdHealthSelectionDataRequest() { Search = string.Empty, Page = 0, PageSize = itemsPerPage };
|
||||
|
||||
public int? ParentIndex { get; set; }
|
||||
public UIElement ParentElement { get; set; }
|
||||
|
||||
|
||||
public string ResetFilterLabel
|
||||
{
|
||||
get { return (string)GetValue(ResetFilterLabelProperty); }
|
||||
set { SetValue(ResetFilterLabelProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResetFilterLabelProperty =
|
||||
DependencyProperty.Register("ResetFilterLabel", typeof(string), typeof(ComboBoxPageable), new PropertyMetadata(cMultiLanguageSupport.GetItem("Dialog.CloseCase.ResetFilter")));
|
||||
|
||||
public bool ResetFilter
|
||||
{
|
||||
get { return (bool)GetValue(ResetFilterProperty); }
|
||||
set { SetValue(ResetFilterProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResetFilterProperty =
|
||||
DependencyProperty.Register("ResetFilter", typeof(bool), typeof(ComboBoxPageable), new PropertyMetadata(false, new PropertyChangedCallback(ResetFilterChanged)));
|
||||
|
||||
private static void ResetFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(d is ComboBoxPageable me))
|
||||
return;
|
||||
|
||||
me.searchData.ResetFilter = me.ResetFilter;
|
||||
me.InvokeSearchValueChanged();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region TotalItemCount
|
||||
|
||||
public int TotalItemCount
|
||||
{
|
||||
get { return (int)GetValue(TotalItemCountProperty); }
|
||||
set { SetValue(TotalItemCountProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TotalItemCountProperty =
|
||||
DependencyProperty.Register("TotalItemCount", typeof(int), typeof(ComboBoxPageable), new PropertyMetadata(0, new PropertyChangedCallback(TotalItemCountChanged)));
|
||||
|
||||
private static void TotalItemCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
if (!(d is ComboBoxPageable me))
|
||||
return;
|
||||
|
||||
me.pageCount = me.TotalItemCount % itemsPerPage == 0 ? me.TotalItemCount / itemsPerPage : (me.TotalItemCount / itemsPerPage) + 1;
|
||||
me.UpdatePageTracker();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
|
||||
"SelectedItem",
|
||||
typeof(object),
|
||||
typeof(ComboBoxPageable),
|
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||
|
||||
public object SelectedItem
|
||||
{
|
||||
get { return GetValue(SelectedItemProperty); }
|
||||
set { SetValue(SelectedItemProperty, value); }
|
||||
}
|
||||
|
||||
#region SearchDataChanged
|
||||
|
||||
public EventHandler<cF4sdHealthSelectionDataRequest> SearchDataChanged
|
||||
{
|
||||
get { return (EventHandler<cF4sdHealthSelectionDataRequest>)GetValue(SearchDataChangedProperty); }
|
||||
set { SetValue(SearchDataChangedProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public static readonly DependencyProperty SearchDataChangedProperty =
|
||||
DependencyProperty.Register("SearchDataChanged", typeof(EventHandler<cF4sdHealthSelectionDataRequest>), typeof(ComboBoxPageable), new PropertyMetadata(null));
|
||||
|
||||
#endregion
|
||||
|
||||
#region ItemData
|
||||
|
||||
public ObservableCollection<KeyValuePair<string, object>> ItemData
|
||||
{
|
||||
get { return (ObservableCollection<KeyValuePair<string, object>>)GetValue(ItemDataProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(ItemDataProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemDataProperty =
|
||||
DependencyProperty.Register("ItemData", typeof(ObservableCollection<KeyValuePair<string, object>>), typeof(ComboBoxPageable), new PropertyMetadata(null));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styles
|
||||
|
||||
public Brush ComboBoxBackground
|
||||
{
|
||||
get { return (Brush)GetValue(ComboBoxBackgroundProperty); }
|
||||
set { SetValue(ComboBoxBackgroundProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ComboBoxBackgroundProperty =
|
||||
DependencyProperty.Register("ComboBoxBackground", typeof(Brush), typeof(ComboBoxPageable), new PropertyMetadata(Brushes.Transparent));
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public ComboBoxPageable()
|
||||
{
|
||||
InitializeComponent();
|
||||
timer.Elapsed += TimerElapsed;
|
||||
}
|
||||
|
||||
private void TimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
timer.Stop();
|
||||
Dispatcher.Invoke(InvokeSearchValueChanged);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
private void InvokeSearchValueChanged()
|
||||
{
|
||||
try
|
||||
{
|
||||
searchData.Page = pageIndex;
|
||||
|
||||
if (SearchDataChanged != null)
|
||||
SearchDataChanged.Invoke(this, searchData);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValuePair<string, object>? GetSelectedValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ComboBoxControl.SelectedItem is KeyValuePair<string, object> selectedItem)
|
||||
return selectedItem;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Paging Events
|
||||
|
||||
#region PageBack
|
||||
|
||||
private void PageBackButton_Click(RoutedEventArgs e)
|
||||
{
|
||||
if (pageIndex <= 0)
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
pageIndex--;
|
||||
InvokeSearchValueChanged();
|
||||
UpdatePageTracker();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void PageBackButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
PageBackButton_Click(e);
|
||||
}
|
||||
|
||||
private void PageBackButton_TouchDown(object sender, TouchEventArgs e)
|
||||
{
|
||||
PageBackButton_Click(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PageFor
|
||||
|
||||
private void PageForButton_Click(RoutedEventArgs e)
|
||||
{
|
||||
if (pageIndex + 1 >= pageCount)
|
||||
return;
|
||||
|
||||
pageIndex++;
|
||||
InvokeSearchValueChanged();
|
||||
UpdatePageTracker();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void PageForButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
PageForButton_Click(e);
|
||||
}
|
||||
|
||||
private void PageForButton_TouchDown(object sender, TouchEventArgs e)
|
||||
{
|
||||
PageForButton_Click(e);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
private void UpdatePageTracker()
|
||||
{
|
||||
try
|
||||
{
|
||||
var pageTrackerElement = ComboBoxControl.Template.FindName("PageTrackerTextBlock", ComboBoxControl);
|
||||
|
||||
if (!(pageTrackerElement is TextBlock pageTrackerTextBlock))
|
||||
return;
|
||||
|
||||
pageTrackerTextBlock.Text = $"{pageIndex + 1} / {pageCount}";
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(sender is TextBox searchTextBox))
|
||||
return;
|
||||
|
||||
pageIndex = 0;
|
||||
searchData.Search = searchTextBox.Text;
|
||||
UpdatePageTracker();
|
||||
|
||||
timer.Stop();
|
||||
timer.Start();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBoxControl_DropDownClosed(object sender, EventArgs e)
|
||||
{
|
||||
timer.Stop();
|
||||
cFocusInvoker.InvokeLostFocus(this, e);
|
||||
}
|
||||
|
||||
private void ComboBoxControl_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Elterninfo nur setzen, wenn (noch) nicht sinnvoll vorhanden
|
||||
bool invalidIndex = false;
|
||||
if (ParentElement is Panel p && (ParentIndex == null || ParentIndex < 0 || ParentIndex > p.Children.Count))
|
||||
invalidIndex = true;
|
||||
|
||||
if (ParentElement == null || invalidIndex)
|
||||
{
|
||||
ParentElement = this.Parent as UIElement;
|
||||
|
||||
if (this.Parent is Panel panel)
|
||||
ParentIndex = panel.Children.IndexOf(this);
|
||||
else
|
||||
ParentIndex = null;
|
||||
}
|
||||
|
||||
|
||||
cFocusInvoker.InvokeGotFocus(this, e);
|
||||
InvokeSearchValueChanged();
|
||||
|
||||
|
||||
#region Focus auf Textfeld setzen beim Öffnen der Combobox
|
||||
if (!(sender is ComboBox comboBox)) return;
|
||||
|
||||
// Zugriff auf das Popup-Element
|
||||
Popup partPopup = comboBox.Template.FindName("PART_Popup", comboBox) as Popup;
|
||||
if (partPopup == null) return;
|
||||
|
||||
// Verzögerter Fokus
|
||||
var _h = Dispatcher.BeginInvoke((Action)(() =>
|
||||
{
|
||||
if (partPopup.IsOpen)
|
||||
{
|
||||
// Suchen des SearchTextBox-Element innerhalb des Popups
|
||||
TextBox searchTextBox = FindVisualChild<TextBox>(partPopup.Child, "SearchTextBox");
|
||||
if (searchTextBox != null)
|
||||
{
|
||||
// Setzen des Fokus auf TextBox
|
||||
searchTextBox.Focus();
|
||||
}
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
||||
#endregion
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private static T FindVisualChild<T>(DependencyObject parent, string childName) where T : DependencyObject
|
||||
{
|
||||
if (parent == null) return null;
|
||||
|
||||
T foundChild = null;
|
||||
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
|
||||
for (int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
var childType = child as T;
|
||||
if (childType == null)
|
||||
{
|
||||
foundChild = FindVisualChild<T>(child, childName);
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(childName))
|
||||
{
|
||||
var frameworkElement = child as FrameworkElement;
|
||||
if (frameworkElement != null && frameworkElement.Name == childName)
|
||||
{
|
||||
return (T)child;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (T)child;
|
||||
}
|
||||
}
|
||||
return foundChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
FasdDesktopUi/Basics/UserControls/CustomDialog.xaml
Normal file
50
FasdDesktopUi/Basics/UserControls/CustomDialog.xaml
Normal file
@@ -0,0 +1,50 @@
|
||||
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
|
||||
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:Name="YesNoControl">
|
||||
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
<vc:BoolOrToVisibilityConverter x:Key="BoolOrToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Padding="10"
|
||||
CornerRadius="10"
|
||||
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Value}">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<ico:AdaptableIcon SelectedInternIcon="window_close"
|
||||
DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Right"
|
||||
Style="{DynamicResource SettingsPage.Close.Icon}" />
|
||||
|
||||
<local:YesNoButton HasYesNoButtons="{Binding ElementName=YesNoControl, Path=HasYesNoButtons}"
|
||||
HasYesNoText="{Binding ElementName=YesNoControl, Path=HasYesNoText}"
|
||||
DockPanel.Dock="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
ButtonHasBeenClicked="YesNoButton_ButtonHasBeenClicked">
|
||||
<local:YesNoButton.Visibility>
|
||||
<MultiBinding Converter="{StaticResource BoolOrToVisibilityConverter}">
|
||||
<Binding Path="HasYesNoButtons" ElementName="YesNoControl"/>
|
||||
<Binding Path="HasYesNoText" ElementName="YesNoControl"/>
|
||||
</MultiBinding>
|
||||
</local:YesNoButton.Visibility>
|
||||
</local:YesNoButton>
|
||||
|
||||
<StackPanel x:Name="MainStack" />
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Border>
|
||||
|
||||
</UserControl>
|
||||
110
FasdDesktopUi/Basics/UserControls/CustomDialog.xaml.cs
Normal file
110
FasdDesktopUi/Basics/UserControls/CustomDialog.xaml.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using FasdDesktopUi.Basics.CustomEvents;
|
||||
using FasdDesktopUi.Basics.Helper;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UserControls
|
||||
{
|
||||
public partial class CustomDialog : UserControl, IFocusInvoker
|
||||
{
|
||||
|
||||
#region Proeprties and Fields
|
||||
|
||||
public int? ParentIndex { get; set; }
|
||||
public UIElement ParentElement { get; set; }
|
||||
|
||||
#region HasYesNoButtons
|
||||
|
||||
public bool HasYesNoButtons
|
||||
{
|
||||
get { return (bool)GetValue(HasYesNoButtonsProperty); }
|
||||
set { SetValue(HasYesNoButtonsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HasYesNoButtonsProperty =
|
||||
DependencyProperty.Register("HasYesNoButtons", typeof(bool), typeof(CustomDialog), new PropertyMetadata(true));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region HasYesNoText
|
||||
|
||||
public bool HasYesNoText
|
||||
{
|
||||
get { return (bool)GetValue(HasYesNoTextProperty); }
|
||||
set { SetValue(HasYesNoTextProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HasYesNoTextProperty =
|
||||
DependencyProperty.Register("HasYesNoText", typeof(bool), typeof(CustomDialog), new PropertyMetadata(true));
|
||||
|
||||
#endregion
|
||||
|
||||
#region ContainerData
|
||||
|
||||
public cContainerData ContainerData
|
||||
{
|
||||
get { return (cContainerData)GetValue(ContainerDataProperty); }
|
||||
set { SetValue(ContainerDataProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContainerDataProperty =
|
||||
DependencyProperty.Register("ContainerData", typeof(cContainerData), typeof(CustomDialog), new PropertyMetadata(new cContainerData(), new PropertyChangedCallback(ContainerDataHasChanged)));
|
||||
|
||||
private static void ContainerDataHasChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(d is CustomDialog _me))
|
||||
return;
|
||||
|
||||
_me.UpdateDialogContent();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public CustomDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void UpdateDialogContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ContainerData is null)
|
||||
return;
|
||||
|
||||
MainStack.Children.Clear();
|
||||
|
||||
foreach (var dialogComponentData in ContainerData)
|
||||
{
|
||||
if (cUiElementHelper.DrawCustomizableContainerComponent(dialogComponentData, this, out var createdControl))
|
||||
{
|
||||
createdControl.Margin = new Thickness(0, 5, 0, 5);
|
||||
MainStack.Children.Add(createdControl);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
private void YesNoButton_ButtonHasBeenClicked(object sender, BooleanEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
20
FasdDesktopUi/Basics/UserControls/CustomMenu.xaml
Normal file
20
FasdDesktopUi/Basics/UserControls/CustomMenu.xaml
Normal file
@@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
|
||||
Name="CustomMenuUc"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
|
||||
<Grid x:Name="MainGrid">
|
||||
|
||||
<ScrollViewer x:Name="MainScrollViewer"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel x:Name="MainStackPanel" />
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
230
FasdDesktopUi/Basics/UserControls/CustomMenu.xaml.cs
Normal file
230
FasdDesktopUi/Basics/UserControls/CustomMenu.xaml.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using FasdDesktopUi.Basics.CustomEvents;
|
||||
using FasdDesktopUi.Basics.Models;
|
||||
using FasdDesktopUi.Basics.UiActions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace FasdDesktopUi.Basics.UserControls
|
||||
{
|
||||
public partial class CustomMenu : UserControl
|
||||
{
|
||||
#region Properties
|
||||
|
||||
#region MenuDataList DependencyPoperty
|
||||
|
||||
private static void MenuDataListChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (!(d is CustomMenu _me))
|
||||
return;
|
||||
|
||||
_me.ClearControl();
|
||||
_me.AddCustomMenuItems();
|
||||
_me.UpdateCornerRadius();
|
||||
|
||||
if (_me.IsKeyboardNavigatable)
|
||||
_me.IndexOfSelectedMenuItem = 0;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MenuDataListProperty =
|
||||
DependencyProperty.Register("MenuDataList", typeof(List<cMenuDataBase>), typeof(CustomMenu), new PropertyMetadata(new List<cMenuDataBase>(), new PropertyChangedCallback(MenuDataListChangedCallback)));
|
||||
|
||||
public List<cMenuDataBase> MenuDataList
|
||||
{
|
||||
get { return (List<cMenuDataBase>)GetValue(MenuDataListProperty); }
|
||||
set { SetValue(MenuDataListProperty, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IndexOfSelectedMenuItem DependencyProperty
|
||||
|
||||
private static void IndexOfSelectedMenuItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (!(d is CustomMenu _me && e.NewValue is int index))
|
||||
return;
|
||||
|
||||
if (!_me.IsKeyboardNavigatable)
|
||||
return;
|
||||
|
||||
foreach (CustomMenuItem menuItem in _me.MainStackPanel.Children)
|
||||
{
|
||||
menuItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory");
|
||||
|
||||
if (index < 0 || index > _me.MainStackPanel.Children.Count)
|
||||
continue;
|
||||
|
||||
if (_me.MainStackPanel.Children.IndexOf(menuItem) == index)
|
||||
menuItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.Hover");
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IndexOfSelectedMenuItemProperty =
|
||||
DependencyProperty.Register("IndexOfSelectedMenuItem", typeof(int), typeof(CustomMenu), new PropertyMetadata(-1, new PropertyChangedCallback(IndexOfSelectedMenuItemChanged)));
|
||||
|
||||
public int IndexOfSelectedMenuItem
|
||||
{
|
||||
get { return (int)GetValue(IndexOfSelectedMenuItemProperty); }
|
||||
set { SetValue(IndexOfSelectedMenuItemProperty, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsKeyboardNavigatable
|
||||
|
||||
public static readonly DependencyProperty IsKeyboardNavigatableProperty =
|
||||
DependencyProperty.Register("IsKeyboardNavigatable", typeof(bool), typeof(CustomMenuItem), new PropertyMetadata(false));
|
||||
|
||||
public bool IsKeyboardNavigatable
|
||||
{
|
||||
get { return (bool)GetValue(IsKeyboardNavigatableProperty); }
|
||||
set { SetValue(IsKeyboardNavigatableProperty, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public CustomMenu()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public CustomMenu(bool drawWithBorder = false)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if (drawWithBorder)
|
||||
DrawControlWithBorder();
|
||||
}
|
||||
|
||||
private void DrawControlWithBorder()
|
||||
{
|
||||
var tempBorder = new Border() { Padding = new Thickness(10), CornerRadius = new CornerRadius(10) };
|
||||
tempBorder.SetResourceReference(BackgroundProperty, "BackgroundColor.Menu.Categories");
|
||||
|
||||
var tempControl = MainScrollViewer;
|
||||
MainGrid.Children.Remove(tempControl);
|
||||
|
||||
MainGrid.Children.Add(tempBorder);
|
||||
tempBorder.Child = tempControl;
|
||||
}
|
||||
|
||||
private void ClearControl()
|
||||
{
|
||||
MainStackPanel.Children.Clear();
|
||||
IndexOfSelectedMenuItem = -1;
|
||||
}
|
||||
|
||||
private void AddCustomMenuItems()
|
||||
{
|
||||
if (MenuDataList == null)
|
||||
return;
|
||||
|
||||
foreach (var menuItemData in MenuDataList)
|
||||
{
|
||||
var menuItem = new CustomMenuItem(false) { MenuData = menuItemData };
|
||||
menuItem.MouseEnter += MenuItem_MouseEnter;
|
||||
MainStackPanel.Children.Add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCornerRadius()
|
||||
{
|
||||
const double cornerRadius = 10;
|
||||
|
||||
if (MainStackPanel.Children.Count <= 0)
|
||||
return;
|
||||
|
||||
if (MainStackPanel.Children[0] is CustomMenuItem menuItemFirst)
|
||||
{
|
||||
var tempCornerRadius = menuItemFirst.MenuItemBorder.CornerRadius;
|
||||
tempCornerRadius.TopLeft = cornerRadius;
|
||||
tempCornerRadius.TopRight = cornerRadius;
|
||||
menuItemFirst.MenuItemBorder.CornerRadius = tempCornerRadius;
|
||||
}
|
||||
|
||||
if (MainStackPanel.Children[MainStackPanel.Children.Count - 1] is CustomMenuItem menuItemLast)
|
||||
{
|
||||
var tempCornerRadiusLast = menuItemLast.MenuItemBorder.CornerRadius;
|
||||
tempCornerRadiusLast.BottomLeft = cornerRadius;
|
||||
tempCornerRadiusLast.BottomRight = cornerRadius;
|
||||
menuItemLast.MenuItemBorder.CornerRadius = tempCornerRadiusLast;
|
||||
}
|
||||
}
|
||||
|
||||
private void MenuItem_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!(sender is CustomMenuItem menuItem))
|
||||
return;
|
||||
|
||||
CustomEventManager.RaiseIndexChangedEvent(this, -1, MainStackPanel.Children.IndexOf(menuItem));
|
||||
}
|
||||
|
||||
internal void ShowDetailHeading(bool showDetailHeadings)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var resultItem in MainStackPanel.Children.OfType<CustomMenuItem>())
|
||||
{
|
||||
resultItem.ShowDetailHeadings(showDetailHeadings);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal void HightlightItemAt(int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (CustomMenuItem resultItem in MainStackPanel.Children)
|
||||
{
|
||||
if (MainStackPanel.Children.IndexOf(resultItem) == index)
|
||||
{
|
||||
resultItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.Hover");
|
||||
CustomEventManager.RaiseMenuDataChangedEvent(this, resultItem.MenuData);
|
||||
}
|
||||
else
|
||||
resultItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SelectItemAt(int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (MenuDataList is null)
|
||||
return;
|
||||
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
if (MenuDataList.Count == 0 || MenuDataList.Count <= index)
|
||||
return;
|
||||
|
||||
cUiActionBase uiAction = MenuDataList[index].UiAction;
|
||||
|
||||
if (uiAction is null || uiAction.DisplayType == Enums.enumActionDisplayType.disabled)
|
||||
return;
|
||||
|
||||
cUiActionBase.RaiseEvent(uiAction, this, this);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user