This commit is contained in:
Meik
2025-11-11 11:03:42 +01:00
commit dc3e8a2e4c
582 changed files with 191465 additions and 0 deletions

32
FasdDesktopUi/App.config Normal file
View 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
View 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
View 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
View 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
}
}

View 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));
}
}
}

View 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;
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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
}
}

View 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;
}
}
}

View 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();
}
}
}
}

View 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;
}
}
}

View File

@@ -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();
}
}
}

View 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;
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();
}
}
}

View 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;
}
}
}

View File

@@ -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();
}
}
}

View 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;
}
}
}

View 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 });
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View File

@@ -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)
{
}
}
}

View 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
}
}

View File

@@ -0,0 +1,8 @@
namespace FasdDesktopUi.Basics.Enums
{
public enum enumAppColorMode
{
DarkMode,
LightMode
}
}

View File

@@ -0,0 +1,11 @@
namespace FasdDesktopUi.Basics.Enums
{
public enum enumHighlightColor
{
none = 0,
blue = 1,
green = 2,
orange = 3,
red = 4
}
}

View 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
}
}

View 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);
}
}
}

View 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;
}
}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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
}
}
}

View 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);
}
}
}

View 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
}

View 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; }
}
}

View 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; }
}
}

View 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
{
}
}

View 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; }
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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; }
}
}

View 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;
}
}

View 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
}
}

View File

@@ -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;
}
}
}

View 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;
}
}

View 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);
}
}
}
}
}

View 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");
}
}
}

View 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;
}
}
}
}
}

View File

@@ -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
}
}

View 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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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; }
}
}

View File

@@ -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;
}
}

View File

@@ -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; }
}
}

View 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;
}
}

View 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();
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View 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);
}
}
}

View 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
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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)
{
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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) };
}
}
}

View 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;
}
}
}

View 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) };
}
}
}
}

View 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
{
}
}
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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) };
}
}
}
}

View 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;
}
}
}

View 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>

View File

@@ -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;
}
}

View 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>

View 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;
}
}
}

View 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>

View 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)
{
}
}
}

View 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>

View 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